From d1d6ad1c2a00f86f5369a4867bb7ca6729997e20 Mon Sep 17 00:00:00 2001 From: Roman <1325980292@qq.com> Date: Mon, 18 Jul 2022 23:15:27 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=AF=BC=E5=85=A5=E9=A9=AC=E9=AA=A8=E9=AA=BC?= =?UTF-8?q?=202.=E6=B5=8B=E8=AF=95IK=E6=88=90=E5=8A=9F=203.=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E5=BF=85=E8=A6=81=E7=9A=84=E6=8F=92=E4=BB=B6=EF=BC=9A?= =?UTF-8?q?InputSystem=E3=80=81CinemaMachine=E3=80=81Dotween=E3=80=81ASE?= =?UTF-8?q?=E3=80=81Odin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 好累啊,下班 --- .../{Scenes.meta => AmplifyShaderEditor.meta} | 2 +- .../AmplifyShaderEditor.asmdef | 15 + .../AmplifyShaderEditor.asmdef.meta | 7 + Assets/AmplifyShaderEditor/ChangeLog.txt | 4744 +++++++ Assets/AmplifyShaderEditor/ChangeLog.txt.meta | 8 + .../CreatingTerrainsWithASE.txt | 58 + .../CreatingTerrainsWithASE.txt.meta | 8 + Assets/AmplifyShaderEditor/Examples.meta | 9 + .../Built-In Samples.unitypackage.meta | 8 + .../AmplifyShaderEditor/Examples/Credits.txt | 8 + .../Examples/Credits.txt.meta | 8 + .../Examples/DownloadSamplesInstructions.txt | 8 + .../DownloadSamplesInstructions.txt.meta | 8 + .../HDRP Samples (Legacy).unitypackage.meta | 8 + .../Examples/HDRP Samples.unitypackage.meta | 8 + .../LWRP Samples (Legacy).unitypackage.meta | 8 + .../Examples/LWRP Samples.unitypackage.meta | 8 + .../Examples/README Samples.txt | 12 + .../Examples/README Samples.txt.meta | 8 + .../Sample Resources.unitypackage.meta | 8 + .../Examples/URP Samples.unitypackage.meta | 8 + Assets/AmplifyShaderEditor/Plugins.meta | 9 + .../AmplifyShaderEditor/Plugins/Editor.meta | 9 + .../Plugins/Editor/Actions.meta | 9 + .../Plugins/Editor/Actions/ActionData.cs | 336 + .../Plugins/Editor/Actions/ActionData.cs.meta | 12 + .../Plugins/Editor/Actions/ActionLog.cs | 58 + .../Plugins/Editor/Actions/ActionLog.cs.meta | 12 + .../Plugins/Editor/Actions/ActionSequence.cs | 39 + .../Editor/Actions/ActionSequence.cs.meta | 12 + .../Plugins/Editor/Constants.cs | 690 + .../Plugins/Editor/Constants.cs.meta | 12 + .../Plugins/Editor/CustomDrawers.meta | 9 + .../Editor/CustomDrawers/ASEBeginDecorator.cs | 32 + .../CustomDrawers/ASEBeginDecorator.cs.meta | 11 + .../Editor/CustomDrawers/ASEEndDecorator.cs | 36 + .../CustomDrawers/ASEEndDecorator.cs.meta | 11 + .../Editor/CustomDrawers/EditableIf.cs | 294 + .../Editor/CustomDrawers/EditableIf.cs.meta | 12 + .../Editor/CustomDrawers/NoKeywordToggle.cs | 25 + .../CustomDrawers/NoKeywordToggle.cs.meta | 12 + .../Editor/CustomDrawers/RemapSliders.cs | 36 + .../Editor/CustomDrawers/RemapSliders.cs.meta | 11 + .../Editor/CustomDrawers/RemapSlidersFull.cs | 36 + .../CustomDrawers/RemapSlidersFull.cs.meta | 11 + .../Editor/CustomDrawers/SingleLineTexture.cs | 23 + .../CustomDrawers/SingleLineTexture.cs.meta | 11 + .../Plugins/Editor/DoCreateFunction.cs | 17 + .../Plugins/Editor/DoCreateFunction.cs.meta | 12 + .../Plugins/Editor/DoCreateShader.cs | 48 + .../Plugins/Editor/DoCreateShader.cs.meta | 12 + .../Plugins/Editor/EditorOptions.cs | 67 + .../Plugins/Editor/EditorOptions.cs.meta | 12 + .../Plugins/Editor/Graphs.meta | 9 + .../Plugins/Editor/Graphs/NodeGrid.cs | 283 + .../Plugins/Editor/Graphs/NodeGrid.cs.meta | 12 + .../Plugins/Editor/Graphs/ParentGraph.cs | 4060 ++++++ .../Plugins/Editor/Graphs/ParentGraph.cs.meta | 12 + .../Plugins/Editor/Menu.meta | 9 + .../Editor/Menu/AmplifyShaderEditorWindow.cs | 6110 +++++++++ .../Menu/AmplifyShaderEditorWindow.cs.meta | 12 + .../Editor/Menu/AmplifyShaderFunction.cs | 189 + .../Editor/Menu/AmplifyShaderFunction.cs.meta | 12 + .../Menu/AmplifyShaderFunctionEditor.cs | 168 + .../Menu/AmplifyShaderFunctionEditor.cs.meta | 12 + .../Plugins/Editor/Menu/AutoPanData.cs | 94 + .../Plugins/Editor/Menu/AutoPanData.cs.meta | 12 + .../Plugins/Editor/Menu/Clipboard.cs | 262 + .../Plugins/Editor/Menu/Clipboard.cs.meta | 12 + .../Plugins/Editor/Menu/ConfirmationWindow.cs | 120 + .../Editor/Menu/ConfirmationWindow.cs.meta | 12 + .../Plugins/Editor/Menu/ConsoleLogWindow.cs | 309 + .../Editor/Menu/ConsoleLogWindow.cs.meta | 12 + .../Plugins/Editor/Menu/ContextMenuItem.cs | 81 + .../Editor/Menu/ContextMenuItem.cs.meta | 12 + .../Editor/Menu/CustomStylesContainer.cs | 53 + .../Editor/Menu/CustomStylesContainer.cs.meta | 12 + .../Plugins/Editor/Menu/DebugConsoleWindow.cs | 203 + .../Editor/Menu/DebugConsoleWindow.cs.meta | 12 + .../Plugins/Editor/Menu/DragAndDropTool.cs | 47 + .../Editor/Menu/DragAndDropTool.cs.meta | 12 + .../Editor/Menu/DuplicatePreventionBuffer.cs | 375 + .../Menu/DuplicatePreventionBuffer.cs.meta | 12 + .../Plugins/Editor/Menu/GraphContextMenu.cs | 393 + .../Editor/Menu/GraphContextMenu.cs.meta | 12 + .../Plugins/Editor/Menu/MenuParent.cs | 451 + .../Plugins/Editor/Menu/MenuParent.cs.meta | 12 + .../Editor/Menu/NodeParametersWindow.cs | 557 + .../Editor/Menu/NodeParametersWindow.cs.meta | 12 + .../Editor/Menu/NodeWireReferencesUtils.cs | 56 + .../Menu/NodeWireReferencesUtils.cs.meta | 12 + .../Plugins/Editor/Menu/Palette.meta | 9 + .../Editor/Menu/Palette/ContextPalette.cs | 101 + .../Menu/Palette/ContextPalette.cs.meta | 12 + .../Editor/Menu/Palette/PaletteParent.cs | 573 + .../Editor/Menu/Palette/PaletteParent.cs.meta | 12 + .../Editor/Menu/Palette/PalettePopUp.cs | 73 + .../Editor/Menu/Palette/PalettePopUp.cs.meta | 12 + .../Editor/Menu/Palette/PaletteWindow.cs | 33 + .../Editor/Menu/Palette/PaletteWindow.cs.meta | 12 + .../Plugins/Editor/Menu/PortLegendInfo.cs | 469 + .../Editor/Menu/PortLegendInfo.cs.meta | 12 + .../Plugins/Editor/Menu/SceneSaveCallback.cs | 40 + .../Editor/Menu/SceneSaveCallback.cs.meta | 12 + .../Editor/Menu/ShaderEditorModeWindow.cs | 192 + .../Menu/ShaderEditorModeWindow.cs.meta | 12 + .../Plugins/Editor/Menu/ShaderLibrary.cs | 91 + .../Plugins/Editor/Menu/ShaderLibrary.cs.meta | 12 + .../Plugins/Editor/Menu/Tools.meta | 9 + .../Editor/Menu/Tools/ToolsMenuButton.cs | 249 + .../Editor/Menu/Tools/ToolsMenuButton.cs.meta | 12 + .../Menu/Tools/ToolsMenuButtonParent.cs | 75 + .../Menu/Tools/ToolsMenuButtonParent.cs.meta | 12 + .../Editor/Menu/Tools/ToolsMenuButtonSep.cs | 41 + .../Menu/Tools/ToolsMenuButtonSep.cs.meta | 12 + .../Plugins/Editor/Menu/Tools/ToolsWindow.cs | 632 + .../Editor/Menu/Tools/ToolsWindow.cs.meta | 12 + .../Plugins/Editor/Native.meta | 9 + .../Plugins/Editor/Native/FallbackColor.cs | 55 + .../Editor/Native/FallbackColor.cs.meta | 12 + .../Plugins/Editor/Native/FallbackFloat.cs | 56 + .../Editor/Native/FallbackFloat.cs.meta | 12 + .../Plugins/Editor/Native/FallbackInt.cs | 56 + .../Plugins/Editor/Native/FallbackInt.cs.meta | 12 + .../Editor/Native/FallbackMatrix4x4.cs | 55 + .../Editor/Native/FallbackMatrix4x4.cs.meta | 12 + .../Plugins/Editor/Native/FallbackString.cs | 56 + .../Editor/Native/FallbackString.cs.meta | 12 + .../Plugins/Editor/Native/FallbackTexture.cs | 55 + .../Editor/Native/FallbackTexture.cs.meta | 12 + .../Plugins/Editor/Native/FallbackVariable.cs | 36 + .../Editor/Native/FallbackVariable.cs.meta | 12 + .../Plugins/Editor/Native/FallbackVector2.cs | 56 + .../Editor/Native/FallbackVector2.cs.meta | 12 + .../Plugins/Editor/Native/FallbackVector3.cs | 56 + .../Editor/Native/FallbackVector3.cs.meta | 12 + .../Plugins/Editor/Native/FallbackVector4.cs | 48 + .../Editor/Native/FallbackVector4.cs.meta | 12 + .../Plugins/Editor/Native/IFallbackVars.cs | 10 + .../Editor/Native/IFallbackVars.cs.meta | 12 + .../Plugins/Editor/Nodes.meta | 9 + .../Plugins/Editor/Nodes/CommentaryNode.cs | 692 + .../Editor/Nodes/CommentaryNode.cs.meta | 12 + .../Plugins/Editor/Nodes/Constants.meta | 9 + .../Editor/Nodes/Constants/ColorNode.cs | 507 + .../Editor/Nodes/Constants/ColorNode.cs.meta | 12 + .../Editor/Nodes/Constants/GlobalArrayNode.cs | 489 + .../Nodes/Constants/GlobalArrayNode.cs.meta | 12 + .../Editor/Nodes/Constants/GradientNode.cs | 230 + .../Nodes/Constants/GradientNode.cs.meta | 12 + .../Plugins/Editor/Nodes/Constants/IntNode.cs | 300 + .../Editor/Nodes/Constants/IntNode.cs.meta | 12 + .../Editor/Nodes/Constants/Matrix3X3Node.cs | 261 + .../Nodes/Constants/Matrix3X3Node.cs.meta | 12 + .../Editor/Nodes/Constants/Matrix4X4Node.cs | 248 + .../Nodes/Constants/Matrix4X4Node.cs.meta | 12 + .../Nodes/Constants/MatrixParentNode.cs | 86 + .../Nodes/Constants/MatrixParentNode.cs.meta | 12 + .../Plugins/Editor/Nodes/Constants/PiNode.cs | 63 + .../Editor/Nodes/Constants/PiNode.cs.meta | 12 + .../Editor/Nodes/Constants/PropertyNode.cs | 1926 +++ .../Nodes/Constants/PropertyNode.cs.meta | 12 + .../Editor/Nodes/Constants/RangedFloatNode.cs | 535 + .../Nodes/Constants/RangedFloatNode.cs.meta | 12 + .../Nodes/Constants/ShaderVariables.meta | 9 + .../ShaderVariables/CameraAndScreen.meta | 9 + .../CameraAndScreen/CameraProjectionNode.cs | 100 + .../CameraProjectionNode.cs.meta | 12 + .../CameraAndScreen/CameraWorldClipPlanes.cs | 115 + .../CameraWorldClipPlanes.cs.meta | 12 + .../CameraAndScreen/OrthoParams.cs | 38 + .../CameraAndScreen/OrthoParams.cs.meta | 12 + .../CameraAndScreen/ProjectionParams.cs | 32 + .../CameraAndScreen/ProjectionParams.cs.meta | 12 + .../CameraAndScreen/ScreenParams.cs | 32 + .../CameraAndScreen/ScreenParams.cs.meta | 12 + .../CameraAndScreen/WorldSpaceCameraPos.cs | 28 + .../WorldSpaceCameraPos.cs.meta | 12 + .../CameraAndScreen/ZBufferParams.cs | 31 + .../CameraAndScreen/ZBufferParams.cs.meta | 12 + .../ShaderVariables/ConstVecShaderVariable.cs | 39 + .../ConstVecShaderVariable.cs.meta | 12 + .../ShaderVariables/ConstantShaderVariable.cs | 35 + .../ConstantShaderVariable.cs.meta | 12 + .../ShaderVariables/FogAndAmbient.meta | 9 + .../FogAndAmbient/FogAndAmbientColorsNode.cs | 126 + .../FogAndAmbientColorsNode.cs.meta | 12 + .../FogAndAmbient/FogParamsNode.cs | 32 + .../FogAndAmbient/FogParamsNode.cs.meta | 12 + .../Constants/ShaderVariables/Lighting.meta | 9 + .../Lighting/CustomStandardSurface.cs | 197 + .../Lighting/CustomStandardSurface.cs.meta | 12 + .../Lighting/IndirectDiffuseLighting.cs | 367 + .../Lighting/IndirectDiffuseLighting.cs.meta | 12 + .../Lighting/IndirectSpecularLight.cs | 268 + .../Lighting/IndirectSpecularLight.cs.meta | 12 + .../Lighting/LightAttenuation.cs | 134 + .../Lighting/LightAttenuation.cs.meta | 12 + .../Lighting/LightColorNode.cs | 90 + .../Lighting/LightColorNode.cs.meta | 12 + .../Lighting/WorldSpaceLightPos.cs | 93 + .../Lighting/WorldSpaceLightPos.cs.meta | 12 + .../ShaderVariables/ShaderVariablesNode.cs | 27 + .../ShaderVariablesNode.cs.meta | 12 + .../Nodes/Constants/ShaderVariables/Time.meta | 9 + .../Constants/ShaderVariables/Time/CosTime.cs | 55 + .../ShaderVariables/Time/CosTime.cs.meta | 12 + .../ShaderVariables/Time/DeltaTime.cs | 33 + .../ShaderVariables/Time/DeltaTime.cs.meta | 12 + .../ShaderVariables/Time/SimpleTimeNode.cs | 48 + .../Time/SimpleTimeNode.cs.meta | 12 + .../ShaderVariables/Time/SinTimeNode.cs | 58 + .../ShaderVariables/Time/SinTimeNode.cs.meta | 12 + .../ShaderVariables/Time/TimeNode.cs | 55 + .../ShaderVariables/Time/TimeNode.cs.meta | 12 + .../Constants/ShaderVariables/Transform.meta | 9 + .../Transform/CameraToWorldMatrix.cs | 24 + .../Transform/CameraToWorldMatrix.cs.meta | 12 + .../Transform/InverseProjectionMatrixNode.cs | 46 + .../InverseProjectionMatrixNode.cs.meta | 11 + .../Transform/InverseTranspMVMatrixNode.cs | 18 + .../InverseTranspMVMatrixNode.cs.meta | 12 + .../Transform/InverseViewMatrixNode.cs | 19 + .../Transform/InverseViewMatrixNode.cs.meta | 12 + .../InverseViewProjectionMatrixNode.cs | 46 + .../InverseViewProjectionMatrixNode.cs.meta | 11 + .../ShaderVariables/Transform/MMatrixNode.cs | 18 + .../Transform/MMatrixNode.cs.meta | 12 + .../ShaderVariables/Transform/MVMatrixNode.cs | 18 + .../Transform/MVMatrixNode.cs.meta | 12 + .../Transform/MVPMatrixNode.cs | 18 + .../Transform/MVPMatrixNode.cs.meta | 12 + .../Transform/ObjectToWorldMatrixNode.cs | 19 + .../Transform/ObjectToWorldMatrixNode.cs.meta | 12 + .../Transform/ProjectionMatrixNode.cs | 19 + .../Transform/ProjectionMatrixNode.cs.meta | 12 + .../Transform/Texture0MatrixNode.cs | 18 + .../Transform/Texture0MatrixNode.cs.meta | 12 + .../Transform/Texture1MatrixNode.cs | 18 + .../Transform/Texture1MatrixNode.cs.meta | 12 + .../Transform/Texture2MatrixNode.cs | 18 + .../Transform/Texture2MatrixNode.cs.meta | 12 + .../Transform/Texture3MatrixNode.cs | 18 + .../Transform/Texture3MatrixNode.cs.meta | 12 + .../Transform/TransformDirectionNode.cs | 579 + .../Transform/TransformDirectionNode.cs.meta | 12 + .../Transform/TransformPositionNode.cs | 626 + .../Transform/TransformPositionNode.cs.meta | 12 + .../Transform/TransformVariables.cs | 166 + .../Transform/TransformVariables.cs.meta | 12 + .../Transform/TransposeMVMatrix.cs | 18 + .../Transform/TransposeMVMatrix.cs.meta | 12 + .../Transform/UnityProjectorClipMatrixNode.cs | 23 + .../UnityProjectorClipMatrixNode.cs.meta | 12 + .../Transform/UnityProjectorMatrixNode.cs | 23 + .../UnityProjectorMatrixNode.cs.meta | 12 + .../Transform/UnityScaleMatrix.cs | 18 + .../Transform/UnityScaleMatrix.cs.meta | 12 + .../Transform/ViewMatrixNode.cs | 19 + .../Transform/ViewMatrixNode.cs.meta | 12 + .../Transform/ViewProjectionMatrixNode.cs | 18 + .../ViewProjectionMatrixNode.cs.meta | 12 + .../Transform/WorldToCameraMatrix.cs | 23 + .../Transform/WorldToCameraMatrix.cs.meta | 12 + .../Transform/WorldToObjectMatrix.cs | 20 + .../Transform/WorldToObjectMatrix.cs.meta | 12 + .../Transform/WorldToTangentMatrix.cs | 47 + .../Transform/WorldToTangentMatrix.cs.meta | 12 + .../Constants/ShaderVariables/Various.meta | 9 + .../Various/ColorSpaceDouble.cs | 37 + .../Various/ColorSpaceDouble.cs.meta | 12 + .../Various/FaceVariableNode.cs | 53 + .../Various/FaceVariableNode.cs.meta | 12 + .../ShaderVariables/Various/InstanceIdNode.cs | 43 + .../Various/InstanceIdNode.cs.meta | 12 + .../ShaderVariables/Various/LODFadeNode.cs | 107 + .../Various/LODFadeNode.cs.meta | 12 + .../Various/PrimitiveIdVariableNode.cs | 38 + .../Various/PrimitiveIdVariableNode.cs.meta | 12 + .../Various/SwitchByFaceNode.cs | 70 + .../Various/SwitchByFaceNode.cs.meta | 12 + .../Various/VertexIdVariableNode.cs | 54 + .../Various/VertexIdVariableNode.cs.meta | 12 + .../Various/WorldTransformParams.cs | 32 + .../Various/WorldTransformParams.cs.meta | 12 + .../Editor/Nodes/Constants/StaticSwitch.cs | 1240 ++ .../Nodes/Constants/StaticSwitch.cs.meta | 12 + .../Plugins/Editor/Nodes/Constants/TauNode.cs | 32 + .../Editor/Nodes/Constants/TauNode.cs.meta | 12 + .../Nodes/Constants/TextureArrayNode.cs | 990 ++ .../Nodes/Constants/TextureArrayNode.cs.meta | 12 + .../Editor/Nodes/Constants/Vector2Node.cs | 301 + .../Nodes/Constants/Vector2Node.cs.meta | 12 + .../Editor/Nodes/Constants/Vector3Node.cs | 315 + .../Nodes/Constants/Vector3Node.cs.meta | 12 + .../Editor/Nodes/Constants/Vector4Node.cs | 321 + .../Nodes/Constants/Vector4Node.cs.meta | 12 + .../Plugins/Editor/Nodes/CustomAddNode.cs | 19 + .../Editor/Nodes/CustomAddNode.cs.meta | 12 + .../Plugins/Editor/Nodes/CustomNode.cs | 183 + .../Plugins/Editor/Nodes/CustomNode.cs.meta | 12 + .../Plugins/Editor/Nodes/DrawInfo.cs | 19 + .../Plugins/Editor/Nodes/DrawInfo.cs.meta | 12 + .../Plugins/Editor/Nodes/DynamicTypeNode.cs | 521 + .../Editor/Nodes/DynamicTypeNode.cs.meta | 12 + .../Plugins/Editor/Nodes/HelperFuncs.meta | 9 + .../Nodes/HelperFuncs/CameraDepthFade.cs | 130 + .../Nodes/HelperFuncs/CameraDepthFade.cs.meta | 12 + .../ComputeGrabScreenPosHlpNode.cs | 54 + .../ComputeGrabScreenPosHlpNode.cs.meta | 12 + .../HelperFuncs/ComputeScreenPosHlpNode.cs | 76 + .../ComputeScreenPosHlpNode.cs.meta | 12 + .../HelperFuncs/DecodeDepthNormalNode.cs | 46 + .../HelperFuncs/DecodeDepthNormalNode.cs.meta | 12 + .../HelperFuncs/DecodeFloatRGBAHlpNode.cs | 27 + .../DecodeFloatRGBAHlpNode.cs.meta | 12 + .../Nodes/HelperFuncs/DecodeFloatRGHlpNode.cs | 27 + .../HelperFuncs/DecodeFloatRGHlpNode.cs.meta | 12 + .../HelperFuncs/DecodeLightmapHlpNode.cs | 109 + .../HelperFuncs/DecodeLightmapHlpNode.cs.meta | 12 + .../DecodeViewNormalStereoHlpNode.cs | 27 + .../DecodeViewNormalStereoHlpNode.cs.meta | 12 + .../Editor/Nodes/HelperFuncs/DepthFade.cs | 168 + .../Nodes/HelperFuncs/DepthFade.cs.meta | 12 + .../DiffuseAndSpecularFromMetallicNode.cs | 59 + ...DiffuseAndSpecularFromMetallicNode.cs.meta | 12 + .../Editor/Nodes/HelperFuncs/DitheringNode.cs | 311 + .../Nodes/HelperFuncs/DitheringNode.cs.meta | 12 + .../HelperFuncs/EncodeDepthNormalNode.cs | 34 + .../HelperFuncs/EncodeDepthNormalNode.cs.meta | 12 + .../HelperFuncs/EncodeFloatRGBAHlpNode.cs | 27 + .../EncodeFloatRGBAHlpNode.cs.meta | 12 + .../Nodes/HelperFuncs/EncodeFloatRGHlpNode.cs | 27 + .../HelperFuncs/EncodeFloatRGHlpNode.cs.meta | 12 + .../EncodeViewNormalStereoHlpNode.cs | 27 + .../EncodeViewNormalStereoHlpNode.cs.meta | 12 + .../Nodes/HelperFuncs/GammaToLinearNode.cs | 122 + .../HelperFuncs/GammaToLinearNode.cs.meta | 12 + .../Nodes/HelperFuncs/HelperParentNode.cs | 93 + .../HelperFuncs/HelperParentNode.cs.meta | 12 + .../Nodes/HelperFuncs/LinearToGammaNode.cs | 127 + .../HelperFuncs/LinearToGammaNode.cs.meta | 12 + .../Nodes/HelperFuncs/LuminanceHlpNode.cs | 26 + .../HelperFuncs/LuminanceHlpNode.cs.meta | 12 + .../HelperFuncs/ObjSpaceLightDirHlpNode.cs | 43 + .../ObjSpaceLightDirHlpNode.cs.meta | 12 + .../HelperFuncs/ObjSpaceViewDirHlpNode.cs | 34 + .../ObjSpaceViewDirHlpNode.cs.meta | 12 + .../Nodes/HelperFuncs/ParallaxMappingNode.cs | 148 + .../HelperFuncs/ParallaxMappingNode.cs.meta | 12 + .../ParallaxOcclusionMappingNode.cs | 650 + .../ParallaxOcclusionMappingNode.cs.meta | 12 + .../HelperFuncs/ParallaxOffsetHlpNode.cs | 47 + .../HelperFuncs/ParallaxOffsetHlpNode.cs.meta | 12 + .../HelperFuncs/ShadeVertexLightsHlpNode.cs | 105 + .../ShadeVertexLightsHlpNode.cs.meta | 12 + .../Nodes/HelperFuncs/SurfaceDepthNode.cs | 184 + .../HelperFuncs/SurfaceDepthNode.cs.meta | 12 + .../Editor/Nodes/HelperFuncs/TriplanarNode.cs | 1536 +++ .../Nodes/HelperFuncs/TriplanarNode.cs.meta | 12 + .../HelperFuncs/UnityObjToClipPosHlpNode.cs | 34 + .../UnityObjToClipPosHlpNode.cs.meta | 12 + .../HelperFuncs/UnityObjToViewPosHlpNode.cs | 33 + .../UnityObjToViewPosHlpNode.cs.meta | 12 + .../HelperFuncs/WorldSpaceLightDirHlpNode.cs | 78 + .../WorldSpaceLightDirHlpNode.cs.meta | 12 + .../HelperFuncs/WorldSpaceViewDirHlpNode.cs | 34 + .../WorldSpaceViewDirHlpNode.cs.meta | 12 + .../Plugins/Editor/Nodes/ISignalGenerator.cs | 11 + .../Editor/Nodes/ISignalGenerator.cs.meta | 12 + .../Plugins/Editor/Nodes/ImageEffects.meta | 9 + .../Editor/Nodes/ImageEffects/BlendOpsNode.cs | 445 + .../Nodes/ImageEffects/BlendOpsNode.cs.meta | 12 + .../Nodes/ImageEffects/DesaturateOpNode.cs | 57 + .../ImageEffects/DesaturateOpNode.cs.meta | 12 + .../Editor/Nodes/ImageEffects/HSVToRGBNode.cs | 87 + .../Nodes/ImageEffects/HSVToRGBNode.cs.meta | 12 + .../Nodes/ImageEffects/LuminanceNode.cs | 32 + .../Nodes/ImageEffects/LuminanceNode.cs.meta | 12 + .../Nodes/ImageEffects/NoiseGeneratorNode.cs | 466 + .../ImageEffects/NoiseGeneratorNode.cs.meta | 12 + .../Nodes/ImageEffects/PosterizeNode.cs | 98 + .../Nodes/ImageEffects/PosterizeNode.cs.meta | 12 + .../Editor/Nodes/ImageEffects/RGBToHSVNode.cs | 93 + .../Nodes/ImageEffects/RGBToHSVNode.cs.meta | 12 + .../ImageEffects/SimpleContrastOpNode.cs | 55 + .../ImageEffects/SimpleContrastOpNode.cs.meta | 12 + .../Nodes/ImageEffects/SimplexNoiseNode.cs | 104 + .../ImageEffects/SimplexNoiseNode.cs.meta | 12 + .../Nodes/ImageEffects/TFHCGrayscale.cs | 116 + .../Nodes/ImageEffects/TFHCGrayscale.cs.meta | 12 + .../Editor/Nodes/ImageEffects/VoronoiNode.cs | 618 + .../Nodes/ImageEffects/VoronoiNode.cs.meta | 12 + .../Editor/Nodes/LogicalOperators.meta | 9 + .../Editor/Nodes/LogicalOperators/Compare.cs | 293 + .../Nodes/LogicalOperators/Compare.cs.meta | 12 + .../LogicalOperators/ConditionalIfNode.cs | 297 + .../ConditionalIfNode.cs.meta | 12 + .../LogicalOperators/KeywordSwitchNode.cs | 133 + .../KeywordSwitchNode.cs.meta | 12 + .../LogicalOperators/TFHCCompareEqual.cs | 35 + .../LogicalOperators/TFHCCompareEqual.cs.meta | 12 + .../LogicalOperators/TFHCCompareGreater.cs | 36 + .../TFHCCompareGreater.cs.meta | 12 + .../TFHCCompareGreaterEqual.cs | 37 + .../TFHCCompareGreaterEqual.cs.meta | 12 + .../LogicalOperators/TFHCCompareLower.cs | 35 + .../LogicalOperators/TFHCCompareLower.cs.meta | 12 + .../LogicalOperators/TFHCCompareLowerEqual.cs | 35 + .../TFHCCompareLowerEqual.cs.meta | 12 + .../LogicalOperators/TFHCCompareNotEqual.cs | 35 + .../TFHCCompareNotEqual.cs.meta | 12 + .../LogicalOperators/TFHCCompareWithRange.cs | 122 + .../TFHCCompareWithRange.cs.meta | 12 + .../Editor/Nodes/LogicalOperators/TFHCIf.cs | 133 + .../Nodes/LogicalOperators/TFHCIf.cs.meta | 12 + .../Editor/Nodes/LogicalOperators/TFHCStub.cs | 103 + .../Nodes/LogicalOperators/TFHCStub.cs.meta | 12 + .../Plugins/Editor/Nodes/Master.meta | 9 + .../Nodes/Master/AdditionalDefinesHelper.cs | 140 + .../Master/AdditionalDefinesHelper.cs.meta | 12 + .../Nodes/Master/AdditionalIncludesHelper.cs | 154 + .../Master/AdditionalIncludesHelper.cs.meta | 12 + .../Nodes/Master/AdditionalPragmasHelper.cs | 141 + .../Master/AdditionalPragmasHelper.cs.meta | 12 + .../Master/AdditionalSurfaceOptionsHelper.cs | 153 + .../AdditionalSurfaceOptionsHelper.cs.meta | 12 + .../Editor/Nodes/Master/BillboardOpHelper.cs | 273 + .../Nodes/Master/BillboardOpHelper.cs.meta | 12 + .../Editor/Nodes/Master/BlendOpsHelper.cs | 447 + .../Nodes/Master/BlendOpsHelper.cs.meta | 12 + .../Editor/Nodes/Master/CodeGenerationData.cs | 24 + .../Nodes/Master/CodeGenerationData.cs.meta | 12 + .../Editor/Nodes/Master/ColorMaskHelper.cs | 107 + .../Nodes/Master/ColorMaskHelper.cs.meta | 12 + .../Editor/Nodes/Master/CustomTagsHelper.cs | 482 + .../Nodes/Master/CustomTagsHelper.cs.meta | 12 + .../Editor/Nodes/Master/DependenciesHelper.cs | 210 + .../Nodes/Master/DependenciesHelper.cs.meta | 12 + .../Nodes/Master/FallbackPickerHelper.cs | 119 + .../Nodes/Master/FallbackPickerHelper.cs.meta | 12 + .../Editor/Nodes/Master/FunctionInput.cs | 527 + .../Editor/Nodes/Master/FunctionInput.cs.meta | 12 + .../Editor/Nodes/Master/FunctionNode.cs | 1246 ++ .../Editor/Nodes/Master/FunctionNode.cs.meta | 12 + .../Editor/Nodes/Master/FunctionOutput.cs | 318 + .../Nodes/Master/FunctionOutput.cs.meta | 12 + .../Editor/Nodes/Master/FunctionSubtitle.cs | 124 + .../Nodes/Master/FunctionSubtitle.cs.meta | 12 + .../Editor/Nodes/Master/FunctionSwitch.cs | 885 ++ .../Nodes/Master/FunctionSwitch.cs.meta | 12 + .../Nodes/Master/FunctionSwitchByPipeline.cs | 102 + .../Master/FunctionSwitchByPipeline.cs.meta | 12 + .../Plugins/Editor/Nodes/Master/LogNode.cs | 80 + .../Editor/Nodes/Master/LogNode.cs.meta | 12 + .../Plugins/Editor/Nodes/Master/MasterNode.cs | 1031 ++ .../Editor/Nodes/Master/MasterNode.cs.meta | 12 + .../Nodes/Master/MasterNodeDataCollector.cs | 2311 ++++ .../Master/MasterNodeDataCollector.cs.meta | 12 + .../Editor/Nodes/Master/OutlineOpHelper.cs | 633 + .../Nodes/Master/OutlineOpHelper.cs.meta | 12 + .../Plugins/Editor/Nodes/Master/OutputNode.cs | 90 + .../Editor/Nodes/Master/OutputNode.cs.meta | 12 + .../Nodes/Master/RenderingOptionsOpHelper.cs | 227 + .../Master/RenderingOptionsOpHelper.cs.meta | 12 + .../Master/RenderingPlatformsOpHelper.cs | 373 + .../Master/RenderingPlatformsOpHelper.cs.meta | 12 + .../Editor/Nodes/Master/StandardSurface.cs | 3342 +++++ .../Nodes/Master/StandardSurface.cs.meta | 12 + .../Nodes/Master/StencilBufferOpHelper.cs | 304 + .../Master/StencilBufferOpHelper.cs.meta | 12 + .../Master/TerrainDrawInstancedHelper.cs | 375 + .../Master/TerrainDrawInstancedHelper.cs.meta | 12 + .../Nodes/Master/TessellationOpHelper.cs | 654 + .../Nodes/Master/TessellationOpHelper.cs.meta | 12 + .../Editor/Nodes/Master/UsePassHelper.cs | 360 + .../Editor/Nodes/Master/UsePassHelper.cs.meta | 12 + .../Editor/Nodes/Master/ZBufferOpHelper.cs | 272 + .../Nodes/Master/ZBufferOpHelper.cs.meta | 12 + .../Plugins/Editor/Nodes/Misc.meta | 9 + .../Plugins/Editor/Nodes/Misc/AppendNode.cs | 254 + .../Editor/Nodes/Misc/AppendNode.cs.meta | 12 + .../Nodes/Misc/BreakToComponentsNode.cs | 290 + .../Nodes/Misc/BreakToComponentsNode.cs.meta | 12 + .../Editor/Nodes/Misc/CustomExpressionNode.cs | 1839 +++ .../Nodes/Misc/CustomExpressionNode.cs.meta | 12 + .../Editor/Nodes/Misc/DynamicAppendNode.cs | 475 + .../Nodes/Misc/DynamicAppendNode.cs.meta | 12 + .../Plugins/Editor/Nodes/Misc/FresnelNode.cs | 393 + .../Editor/Nodes/Misc/FresnelNode.cs.meta | 12 + .../Editor/Nodes/Misc/GetLocalVarNode.cs | 430 + .../Editor/Nodes/Misc/GetLocalVarNode.cs.meta | 12 + .../Editor/Nodes/Misc/LayeredBlendNode.cs | 61 + .../Nodes/Misc/LayeredBlendNode.cs.meta | 12 + .../Editor/Nodes/Misc/LinearDepthNode.cs | 109 + .../Editor/Nodes/Misc/LinearDepthNode.cs.meta | 12 + .../Editor/Nodes/Misc/MatrixFromVectors.cs | 215 + .../Nodes/Misc/MatrixFromVectors.cs.meta | 12 + .../Nodes/Misc/PosFromTransformMatrix.cs | 34 + .../Nodes/Misc/PosFromTransformMatrix.cs.meta | 12 + .../Editor/Nodes/Misc/RegisterLocalVarNode.cs | 352 + .../Nodes/Misc/RegisterLocalVarNode.cs.meta | 12 + .../Plugins/Editor/Nodes/Misc/RelayNode.cs | 38 + .../Editor/Nodes/Misc/RelayNode.cs.meta | 12 + .../Editor/Nodes/Misc/RotateAboutAxisNode.cs | 95 + .../Nodes/Misc/RotateAboutAxisNode.cs.meta | 12 + .../Editor/Nodes/Misc/SummedBlendNode.cs | 56 + .../Editor/Nodes/Misc/SummedBlendNode.cs.meta | 12 + .../Plugins/Editor/Nodes/Misc/SwitchNode.cs | 230 + .../Editor/Nodes/Misc/SwitchNode.cs.meta | 12 + .../Plugins/Editor/Nodes/Misc/SwizzleNode.cs | 441 + .../Editor/Nodes/Misc/SwizzleNode.cs.meta | 12 + .../Editor/Nodes/Misc/ToggleSwitchNode.cs | 311 + .../Nodes/Misc/ToggleSwitchNode.cs.meta | 12 + .../Editor/Nodes/Misc/Transformation.meta | 9 + .../Transformation/ObjectToWorldTransfNode.cs | 30 + .../ObjectToWorldTransfNode.cs.meta | 12 + .../Misc/Transformation/ParentTransfNode.cs | 53 + .../Transformation/ParentTransfNode.cs.meta | 12 + .../Transformation/WorldToObjectTransfNode.cs | 54 + .../WorldToObjectTransfNode.cs.meta | 12 + .../Editor/Nodes/Misc/VectorFromMatrixNode.cs | 131 + .../Nodes/Misc/VectorFromMatrixNode.cs.meta | 12 + .../Editor/Nodes/Misc/WeightedAvgNode.cs | 182 + .../Editor/Nodes/Misc/WeightedAvgNode.cs.meta | 12 + .../Editor/Nodes/Misc/WeightedBlendNode.cs | 58 + .../Nodes/Misc/WeightedBlendNode.cs.meta | 12 + .../Plugins/Editor/Nodes/Misc/WireNode.cs | 484 + .../Editor/Nodes/Misc/WireNode.cs.meta | 12 + .../Plugins/Editor/Nodes/NodeAttributes.cs | 97 + .../Editor/Nodes/NodeAttributes.cs.meta | 12 + .../Plugins/Editor/Nodes/NodeRestrictions.cs | 119 + .../Editor/Nodes/NodeRestrictions.cs.meta | 12 + .../Plugins/Editor/Nodes/NodeUsageRegister.cs | 203 + .../Editor/Nodes/NodeUsageRegister.cs.meta | 12 + .../Plugins/Editor/Nodes/NodeUtils.cs | 293 + .../Plugins/Editor/Nodes/NodeUtils.cs.meta | 12 + .../Plugins/Editor/Nodes/Operators.meta | 9 + .../Editor/Nodes/Operators/ACosOpNode.cs | 26 + .../Editor/Nodes/Operators/ACosOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/ASinOpNode.cs | 26 + .../Editor/Nodes/Operators/ASinOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/ATan2OpNode.cs | 28 + .../Nodes/Operators/ATan2OpNode.cs.meta | 12 + .../Editor/Nodes/Operators/ATanOpNode.cs | 26 + .../Editor/Nodes/Operators/ATanOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/AbsOpNode.cs | 26 + .../Editor/Nodes/Operators/AbsOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/CeilOpNode.cs | 26 + .../Editor/Nodes/Operators/CeilOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/ClampOpNode.cs | 103 + .../Nodes/Operators/ClampOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/ClipNode.cs | 123 + .../Editor/Nodes/Operators/ClipNode.cs.meta | 12 + .../Nodes/Operators/ComponentMaskNode.cs | 382 + .../Nodes/Operators/ComponentMaskNode.cs.meta | 12 + .../Editor/Nodes/Operators/CosOpNode.cs | 26 + .../Editor/Nodes/Operators/CosOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/CoshOpNode.cs | 26 + .../Editor/Nodes/Operators/CoshOpNode.cs.meta | 12 + .../Nodes/Operators/CrossProductOpNode.cs | 35 + .../Operators/CrossProductOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/DdxOpNode.cs | 32 + .../Editor/Nodes/Operators/DdxOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/DdyOpNode.cs | 32 + .../Editor/Nodes/Operators/DdyOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/DegreesOpNode.cs | 26 + .../Nodes/Operators/DegreesOpNode.cs.meta | 12 + .../Nodes/Operators/DeterminantOpNode.cs | 25 + .../Nodes/Operators/DeterminantOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/DistanceOpNode.cs | 32 + .../Nodes/Operators/DistanceOpNode.cs.meta | 12 + .../Nodes/Operators/DotProductOpNode.cs | 34 + .../Nodes/Operators/DotProductOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/Exp2OpNode.cs | 26 + .../Editor/Nodes/Operators/Exp2OpNode.cs.meta | 12 + .../Editor/Nodes/Operators/ExpOpNode.cs | 26 + .../Editor/Nodes/Operators/ExpOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/FWidthOpNode.cs | 38 + .../Nodes/Operators/FWidthOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/FloorOpNode.cs | 24 + .../Nodes/Operators/FloorOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/FmodOpNode.cs | 36 + .../Editor/Nodes/Operators/FmodOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/FractNode.cs | 26 + .../Editor/Nodes/Operators/FractNode.cs.meta | 12 + .../Nodes/Operators/GradientSampleNode.cs | 207 + .../Operators/GradientSampleNode.cs.meta | 12 + .../Editor/Nodes/Operators/InverseOpNode.cs | 138 + .../Nodes/Operators/InverseOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/LengthOpNode.cs | 41 + .../Nodes/Operators/LengthOpNode.cs.meta | 12 + .../Plugins/Editor/Nodes/Operators/LerpOp.cs | 116 + .../Editor/Nodes/Operators/LerpOp.cs.meta | 12 + .../Editor/Nodes/Operators/Log10OpNode.cs | 26 + .../Nodes/Operators/Log10OpNode.cs.meta | 12 + .../Editor/Nodes/Operators/Log2OpNode.cs | 26 + .../Editor/Nodes/Operators/Log2OpNode.cs.meta | 12 + .../Editor/Nodes/Operators/LogOpNode.cs | 26 + .../Editor/Nodes/Operators/LogOpNode.cs.meta | 12 + .../Nodes/Operators/MultipleInputOpNode.cs | 3 + .../Operators/MultipleInputOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/NegateNode.cs | 46 + .../Editor/Nodes/Operators/NegateNode.cs.meta | 12 + .../Editor/Nodes/Operators/NormalizeNode.cs | 87 + .../Nodes/Operators/NormalizeNode.cs.meta | 12 + .../Editor/Nodes/Operators/OneMinusNode.cs | 45 + .../Nodes/Operators/OneMinusNode.cs.meta | 12 + .../Editor/Nodes/Operators/PowerNode.cs | 93 + .../Editor/Nodes/Operators/PowerNode.cs.meta | 12 + .../Editor/Nodes/Operators/RSqrtOpNode.cs | 26 + .../Nodes/Operators/RSqrtOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/RadiansOpNode.cs | 26 + .../Nodes/Operators/RadiansOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/ReflectOpNode.cs | 33 + .../Nodes/Operators/ReflectOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/RefractOpVec.cs | 92 + .../Nodes/Operators/RefractOpVec.cs.meta | 12 + .../Editor/Nodes/Operators/RoundOpNode.cs | 26 + .../Nodes/Operators/RoundOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/SaturateNode.cs | 26 + .../Nodes/Operators/SaturateNode.cs.meta | 12 + .../Nodes/Operators/ScaleAndOffsetNode.cs | 78 + .../Operators/ScaleAndOffsetNode.cs.meta | 12 + .../Editor/Nodes/Operators/ScaleNode.cs | 152 + .../Editor/Nodes/Operators/ScaleNode.cs.meta | 12 + .../Editor/Nodes/Operators/SignOpNode.cs | 26 + .../Editor/Nodes/Operators/SignOpNode.cs.meta | 12 + .../Nodes/Operators/SimplifiedFModOpNode.cs | 32 + .../Operators/SimplifiedFModOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/SinOpNode.cs | 26 + .../Editor/Nodes/Operators/SinOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/SingleInputOp.cs | 67 + .../Nodes/Operators/SingleInputOp.cs.meta | 12 + .../Editor/Nodes/Operators/SinhOpNode.cs | 26 + .../Editor/Nodes/Operators/SinhOpNode.cs.meta | 12 + .../Nodes/Operators/SmoothstepOpNode.cs | 122 + .../Nodes/Operators/SmoothstepOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/SqrtOpNode.cs | 26 + .../Editor/Nodes/Operators/SqrtOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/StepOpNode.cs | 24 + .../Editor/Nodes/Operators/StepOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/TFHCRemapNode.cs | 74 + .../Nodes/Operators/TFHCRemapNode.cs.meta | 12 + .../Editor/Nodes/Operators/TanOpNode.cs | 26 + .../Editor/Nodes/Operators/TanOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/TanhOpNode.cs | 26 + .../Editor/Nodes/Operators/TanhOpNode.cs.meta | 12 + .../Nodes/Operators/TransformVectorOpNode.cs | 160 + .../Operators/TransformVectorOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/TransposeOpNode.cs | 23 + .../Nodes/Operators/TransposeOpNode.cs.meta | 12 + .../Editor/Nodes/Operators/TruncOpNode.cs | 26 + .../Nodes/Operators/TruncOpNode.cs.meta | 12 + .../Nodes/Operators/VariablePortTypeOpNode.cs | 76 + .../Operators/VariablePortTypeOpNode.cs.meta | 12 + .../Plugins/Editor/Nodes/ParentNode.cs | 3801 ++++++ .../Plugins/Editor/Nodes/ParentNode.cs.meta | 12 + .../Plugins/Editor/Nodes/ReordenatorNode.cs | 170 + .../Editor/Nodes/ReordenatorNode.cs.meta | 12 + .../Plugins/Editor/Nodes/SRP.meta | 9 + .../Plugins/Editor/Nodes/SRP/BakedGINode.cs | 107 + .../Editor/Nodes/SRP/BakedGINode.cs.meta | 11 + .../Plugins/Editor/Nodes/SRP/HD.meta | 8 + .../Editor/Nodes/SRP/HD/HDEmissionNode.cs | 175 + .../Nodes/SRP/HD/HDEmissionNode.cs.meta | 11 + .../Editor/Nodes/SRP/MaterialQualityNode.cs | 85 + .../Nodes/SRP/MaterialQualityNode.cs.meta | 12 + .../Plugins/Editor/Nodes/SRP/URP.meta | 9 + .../Nodes/SRP/URP/ReflectionProbeNode.cs | 66 + .../Nodes/SRP/URP/ReflectionProbeNode.cs.meta | 12 + .../Editor/Nodes/SignalGeneratorNode.cs | 41 + .../Editor/Nodes/SignalGeneratorNode.cs.meta | 12 + .../Plugins/Editor/Nodes/SimpleNodes.meta | 9 + .../Nodes/SimpleNodes/SimpleAddOpNode.cs | 58 + .../Nodes/SimpleNodes/SimpleAddOpNode.cs.meta | 12 + .../Nodes/SimpleNodes/SimpleDivideOpNode.cs | 45 + .../SimpleNodes/SimpleDivideOpNode.cs.meta | 12 + .../Nodes/SimpleNodes/SimpleMaxOpNode.cs | 24 + .../Nodes/SimpleNodes/SimpleMaxOpNode.cs.meta | 12 + .../Nodes/SimpleNodes/SimpleMinOpNode.cs | 24 + .../Nodes/SimpleNodes/SimpleMinOpNode.cs.meta | 12 + .../Nodes/SimpleNodes/SimpleMultiplyOpNode.cs | 175 + .../SimpleNodes/SimpleMultiplyOpNode.cs.meta | 12 + .../Nodes/SimpleNodes/SimpleRemainderNode.cs | 66 + .../SimpleNodes/SimpleRemainderNode.cs.meta | 12 + .../Nodes/SimpleNodes/SimpleSubtractOpNode.cs | 39 + .../SimpleNodes/SimpleSubtractOpNode.cs.meta | 12 + .../Plugins/Editor/Nodes/StickyNoteNode .cs | 502 + .../Editor/Nodes/StickyNoteNode .cs.meta | 12 + .../Editor/Nodes/SurfaceShaderInputs.meta | 9 + .../SurfaceShaderInputs/ColorInputsNode.cs | 17 + .../ColorInputsNode.cs.meta | 12 + .../SurfaceShaderInputs/GrabScreenPosition.cs | 118 + .../GrabScreenPosition.cs.meta | 12 + .../SurfaceShaderInputs/LocalVertexPosNode.cs | 50 + .../LocalVertexPosNode.cs.meta | 12 + .../SurfaceShaderInputs/ScreenColorNode.cs | 716 + .../ScreenColorNode.cs.meta | 12 + .../SurfaceShaderInputs/ScreenDepthNode.cs | 173 + .../ScreenDepthNode.cs.meta | 12 + .../ScreenPosInputsNode.cs | 155 + .../ScreenPosInputsNode.cs.meta | 12 + .../SurfaceShaderINParentNode.cs | 122 + .../SurfaceShaderINParentNode.cs.meta | 12 + .../SurfaceShaderInputs/TexelSizeNode.cs | 325 + .../SurfaceShaderInputs/TexelSizeNode.cs.meta | 12 + .../SurfaceShaderInputs/UVCoordsParentNode.cs | 112 + .../UVCoordsParentNode.cs.meta | 12 + .../ViewDirInputsCoordNode.cs | 167 + .../ViewDirInputsCoordNode.cs.meta | 12 + .../WorldNormalInputsNode.cs | 119 + .../WorldNormalInputsNode.cs.meta | 12 + .../SurfaceShaderInputs/WorldNormalVector.cs | 178 + .../WorldNormalVector.cs.meta | 12 + .../SurfaceShaderInputs/WorldPosInputsNode.cs | 37 + .../WorldPosInputsNode.cs.meta | 12 + .../WorldReflInputsNode.cs | 18 + .../WorldReflInputsNode.cs.meta | 12 + .../WorldReflectionVector.cs | 215 + .../WorldReflectionVector.cs.meta | 12 + .../Plugins/Editor/Nodes/Textures.meta | 9 + .../Editor/Nodes/Textures/BlendNormalsNode.cs | 104 + .../Nodes/Textures/BlendNormalsNode.cs.meta | 12 + .../Nodes/Textures/HeightMapBlendNode.cs | 81 + .../Nodes/Textures/HeightMapBlendNode.cs.meta | 12 + .../Editor/Nodes/Textures/PannerNode.cs | 110 + .../Editor/Nodes/Textures/PannerNode.cs.meta | 12 + .../Editor/Nodes/Textures/RotatorNode.cs | 96 + .../Editor/Nodes/Textures/RotatorNode.cs.meta | 12 + .../Editor/Nodes/Textures/SamplerNode.cs | 2325 ++++ .../Editor/Nodes/Textures/SamplerNode.cs.meta | 12 + .../Editor/Nodes/Textures/SamplerStateNode.cs | 378 + .../Nodes/Textures/SamplerStateNode.cs.meta | 12 + .../Nodes/Textures/SubstanceSamplerNode.cs | 1360 ++ .../Textures/SubstanceSamplerNode.cs.meta | 12 + .../Nodes/Textures/TFHCFlipBookUVAnimation.cs | 238 + .../Textures/TFHCFlipBookUVAnimation.cs.meta | 12 + .../Editor/Nodes/Textures/TFHCPixelate.cs | 54 + .../Nodes/Textures/TFHCPixelate.cs.meta | 12 + .../Nodes/Textures/TextureCoordinatesNode.cs | 628 + .../Textures/TextureCoordinatesNode.cs.meta | 12 + .../Nodes/Textures/TexturePropertyNode.cs | 1138 ++ .../Textures/TexturePropertyNode.cs.meta | 12 + .../Nodes/Textures/TextureTransformNode.cs | 364 + .../Textures/TextureTransformNode.cs.meta | 12 + .../Nodes/Textures/UnpackScaleNormalNode.cs | 68 + .../Textures/UnpackScaleNormalNode.cs.meta | 12 + .../Nodes/Textures/VirtualTextureObject.cs | 296 + .../Textures/VirtualTextureObject.cs.meta | 12 + .../Plugins/Editor/Nodes/UndoParentNode.cs | 722 + .../Editor/Nodes/UndoParentNode.cs.meta | 12 + .../Plugins/Editor/Nodes/Vertex.meta | 9 + .../Editor/Nodes/Vertex/BillboardNode.cs | 124 + .../Editor/Nodes/Vertex/BillboardNode.cs.meta | 12 + .../Nodes/Vertex/BitangentVertexDataNode.cs | 37 + .../Vertex/BitangentVertexDataNode.cs.meta | 12 + .../Editor/Nodes/Vertex/BlendIndicesNode.cs | 69 + .../Nodes/Vertex/BlendIndicesNode.cs.meta | 11 + .../Editor/Nodes/Vertex/BlendWeightsNode.cs | 65 + .../Nodes/Vertex/BlendWeightsNode.cs.meta | 11 + .../Nodes/Vertex/ColorVertexDataNode.cs | 18 + .../Nodes/Vertex/ColorVertexDataNode.cs.meta | 12 + .../Nodes/Vertex/NormalVertexDataNode.cs | 44 + .../Nodes/Vertex/NormalVertexDataNode.cs.meta | 12 + .../Editor/Nodes/Vertex/ObjectScaleNode.cs | 75 + .../Nodes/Vertex/ObjectScaleNode.cs.meta | 12 + .../Editor/Nodes/Vertex/OutlineNode.cs | 392 + .../Editor/Nodes/Vertex/OutlineNode.cs.meta | 12 + .../Editor/Nodes/Vertex/PosVertexDataNode.cs | 138 + .../Nodes/Vertex/PosVertexDataNode.cs.meta | 12 + .../Nodes/Vertex/TangentSignVertexDataNode.cs | 23 + .../Vertex/TangentSignVertexDataNode.cs.meta | 12 + .../Nodes/Vertex/TangentVertexDataNode.cs | 120 + .../Vertex/TangentVertexDataNode.cs.meta | 12 + .../Editor/Nodes/Vertex/Tessellation.meta | 9 + .../Tessellation/DistanceBasedTessNode.cs | 30 + .../DistanceBasedTessNode.cs.meta | 12 + .../Tessellation/EdgeLengthCullTessNode.cs | 27 + .../EdgeLengthCullTessNode.cs.meta | 12 + .../Vertex/Tessellation/EdgeLengthTessNode.cs | 23 + .../Tessellation/EdgeLengthTessNode.cs.meta | 12 + .../Tessellation/TessellationParentNode.cs | 29 + .../TessellationParentNode.cs.meta | 12 + .../Nodes/Vertex/TexCoord1VertexDataNode.cs | 16 + .../Vertex/TexCoord1VertexDataNode.cs.meta | 12 + .../Nodes/Vertex/TexCoordVertexDataNode.cs | 241 + .../Vertex/TexCoordVertexDataNode.cs.meta | 12 + .../Editor/Nodes/Vertex/VertexBinormalNode.cs | 48 + .../Nodes/Vertex/VertexBinormalNode.cs.meta | 12 + .../Editor/Nodes/Vertex/VertexColorNode.cs | 47 + .../Nodes/Vertex/VertexColorNode.cs.meta | 12 + .../Editor/Nodes/Vertex/VertexDataNode.cs | 50 + .../Nodes/Vertex/VertexDataNode.cs.meta | 12 + .../Editor/Nodes/Vertex/VertexTangentNode.cs | 50 + .../Nodes/Vertex/VertexTangentNode.cs.meta | 12 + .../Nodes/Vertex/VertexToFragmentNode.cs | 187 + .../Nodes/Vertex/VertexToFragmentNode.cs.meta | 12 + .../Plugins/Editor/PreMadeShaders.cs | 47 + .../Plugins/Editor/PreMadeShaders.cs.meta | 12 + .../Plugins/Editor/Templates.meta | 9 + .../TemplateAdditionalDefinesHelper.cs | 31 + .../TemplateAdditionalDefinesHelper.cs.meta | 12 + .../TemplateAdditionalDirectivesHelper.cs | 837 ++ ...TemplateAdditionalDirectivesHelper.cs.meta | 12 + .../TemplateAdditionalIncludesHelper.cs | 31 + .../TemplateAdditionalIncludesHelper.cs.meta | 12 + .../TemplateAdditionalParentHelper.cs | 193 + .../TemplateAdditionalParentHelper.cs.meta | 12 + .../TemplateAdditionalPragmasHelper.cs | 31 + .../TemplateAdditionalPragmasHelper.cs.meta | 12 + .../Templates/TemplateAlphaToMaskModule.cs | 128 + .../TemplateAlphaToMaskModule.cs.meta | 12 + .../Templates/TemplateCodeSnippetBase.cs | 102 + .../Templates/TemplateCodeSnippetBase.cs.meta | 12 + .../Templates/TemplateColorMaskModule.cs | 200 + .../Templates/TemplateColorMaskModule.cs.meta | 12 + .../Templates/TemplateCullModeModule.cs | 128 + .../Templates/TemplateCullModeModule.cs.meta | 12 + .../Editor/Templates/TemplateDBItem.cs | 21 + .../Editor/Templates/TemplateDBItem.cs.meta | 12 + .../Plugins/Editor/Templates/TemplateData.cs | 1183 ++ .../Editor/Templates/TemplateData.cs.meta | 12 + .../Editor/Templates/TemplateDataCollector.cs | 2153 +++ .../Templates/TemplateDataCollector.cs.meta | 12 + .../Editor/Templates/TemplateDataParent.cs | 217 + .../Templates/TemplateDataParent.cs.meta | 12 + .../Editor/Templates/TemplateDepthModule.cs | 397 + .../Templates/TemplateDepthModule.cs.meta | 12 + .../Templates/TemplateFragmentDataNode.cs | 280 + .../TemplateFragmentDataNode.cs.meta | 12 + .../Templates/TemplateHelperFunctions.cs | 2550 ++++ .../Templates/TemplateHelperFunctions.cs.meta | 12 + .../Editor/Templates/TemplateIdManager.cs | 236 + .../Templates/TemplateIdManager.cs.meta | 12 + .../Editor/Templates/TemplateInterpData.cs | 239 + .../Templates/TemplateInterpData.cs.meta | 12 + .../Editor/Templates/TemplateLocalVarData.cs | 59 + .../Templates/TemplateLocalVarData.cs.meta | 12 + .../Editor/Templates/TemplateLocalVarsNode.cs | 264 + .../Templates/TemplateLocalVarsNode.cs.meta | 12 + .../Editor/Templates/TemplateMasterNode.cs | 770 ++ .../Templates/TemplateMasterNode.cs.meta | 12 + .../Editor/Templates/TemplateMenuItems.cs | 55 + .../Templates/TemplateMenuItems.cs.meta | 12 + .../Editor/Templates/TemplateModuleHelper.cs | 788 ++ .../Templates/TemplateModuleHelper.cs.meta | 12 + .../Editor/Templates/TemplateModuleParent.cs | 82 + .../Templates/TemplateModuleParent.cs.meta | 12 + .../Editor/Templates/TemplateModulesData.cs | 819 ++ .../Templates/TemplateModulesData.cs.meta | 12 + .../Editor/Templates/TemplateMultiPass.cs | 1486 +++ .../Templates/TemplateMultiPass.cs.meta | 12 + .../Templates/TemplateMultiPassMasterNode.cs | 3647 ++++++ .../TemplateMultiPassMasterNode.cs.meta | 12 + .../Templates/TemplateMultiPassSwitchNode.cs | 328 + .../TemplateMultiPassSwitchNode.cs.meta | 12 + .../Editor/Templates/TemplateNodeParent.cs | 272 + .../Templates/TemplateNodeParent.cs.meta | 12 + .../Editor/Templates/TemplateOptionsData.cs | 1162 ++ .../Templates/TemplateOptionsData.cs.meta | 12 + .../TemplateOptionsDefinesContainer.cs | 69 + .../TemplateOptionsDefinesContainer.cs.meta | 12 + .../Editor/Templates/TemplateOptionsPort.cs | 174 + .../Templates/TemplateOptionsPort.cs.meta | 12 + .../Editor/Templates/TemplateOptionsUI.cs | 323 + .../Templates/TemplateOptionsUI.cs.meta | 12 + .../Templates/TemplateOptionsUIHelper.cs | 873 ++ .../Templates/TemplateOptionsUIHelper.cs.meta | 12 + .../Plugins/Editor/Templates/TemplatePass.cs | 637 + .../Editor/Templates/TemplatePass.cs.meta | 12 + .../Templates/TemplatePassSelectorHelper.cs | 167 + .../TemplatePassSelectorHelper.cs.meta | 12 + .../Editor/Templates/TemplatePostProcessor.cs | 177 + .../Templates/TemplatePostProcessor.cs.meta | 12 + .../Templates/TemplateRenderPlatformHelper.cs | 80 + .../TemplateRenderPlatformHelper.cs.meta | 12 + .../Editor/Templates/TemplateShaderData.cs | 121 + .../Templates/TemplateShaderData.cs.meta | 12 + .../Templates/TemplateShaderModelModule.cs | 107 + .../TemplateShaderModelModule.cs.meta | 12 + .../Templates/TemplateShaderPropertyData.cs | 52 + .../TemplateShaderPropertyData.cs.meta | 12 + .../Templates/TemplateShaderPropertyNode.cs | 715 + .../TemplateShaderPropertyNode.cs.meta | 12 + .../Editor/Templates/TemplateSubShader.cs | 173 + .../Templates/TemplateSubShader.cs.meta | 12 + .../Editor/Templates/TemplateTagsModule.cs | 465 + .../Templates/TemplateTagsModule.cs.meta | 12 + .../Editor/Templates/TemplateVertexData.cs | 190 + .../Templates/TemplateVertexData.cs.meta | 12 + .../Templates/TemplateVertexDataNode.cs | 278 + .../Templates/TemplateVertexDataNode.cs.meta | 12 + .../Editor/Templates/TemplatesBlendModule.cs | 756 ++ .../Templates/TemplatesBlendModule.cs.meta | 12 + .../Editor/Templates/TemplatesManager.cs | 937 ++ .../Editor/Templates/TemplatesManager.cs.meta | 12 + .../Templates/TemplatesStencilBufferModule.cs | 669 + .../TemplatesStencilBufferModule.cs.meta | 12 + .../Plugins/Editor/Utils.meta | 9 + .../Plugins/Editor/Utils/ASEPPSHelperTool.cs | 464 + .../Editor/Utils/ASEPPSHelperTool.cs.meta | 12 + .../Editor/Utils/ASEPackageManagerHelper.cs | 701 + .../Utils/ASEPackageManagerHelper.cs.meta | 12 + .../Plugins/Editor/Utils/ASEStartScreen.cs | 495 + .../Editor/Utils/ASEStartScreen.cs.meta | 12 + .../Editor/Utils/ASETextureArrayCreator.cs | 813 ++ .../Utils/ASETextureArrayCreator.cs.meta | 12 + .../Editor/Utils/CustomMaterialInspector.cs | 543 + .../Utils/CustomMaterialInspector.cs.meta | 12 + .../Editor/Utils/CustomShaderInspector.cs | 969 ++ .../Utils/CustomShaderInspector.cs.meta | 12 + .../Utils/CustomTexture2DArrayInspector.cs | 132 + .../CustomTexture2DArrayInspector.cs.meta | 12 + .../Editor/Utils/EditorVariablesManager.cs | 254 + .../Utils/EditorVariablesManager.cs.meta | 12 + .../Plugins/Editor/Utils/GeneratorUtils.cs | 1377 ++ .../Editor/Utils/GeneratorUtils.cs.meta | 12 + .../Plugins/Editor/Utils/GenericMessage.cs | 117 + .../Editor/Utils/GenericMessage.cs.meta | 12 + .../Plugins/Editor/Utils/IOUtils.cs | 843 ++ .../Plugins/Editor/Utils/IOUtils.cs.meta | 12 + .../Plugins/Editor/Utils/InlineProperty.cs | 322 + .../Editor/Utils/InlineProperty.cs.meta | 12 + .../Editor/Utils/InvalidDataChecker.cs | 172 + .../Editor/Utils/InvalidDataChecker.cs.meta | 12 + .../Plugins/Editor/Utils/NodeExporterUtils.cs | 284 + .../Editor/Utils/NodeExporterUtils.cs.meta | 12 + .../Plugins/Editor/Utils/Preferences.cs | 192 + .../Plugins/Editor/Utils/Preferences.cs.meta | 11 + .../Plugins/Editor/Utils/RectExtension.cs | 40 + .../Editor/Utils/RectExtension.cs.meta | 12 + .../Editor/Utils/SamplerStateAutoGenerator.cs | 203 + .../Utils/SamplerStateAutoGenerator.cs.meta | 12 + .../Plugins/Editor/Utils/ShortcutsManager.cs | 215 + .../Editor/Utils/ShortcutsManager.cs.meta | 12 + .../Editor/Utils/TextureArrayCreatorAsset.cs | 75 + .../Utils/TextureArrayCreatorAsset.cs.meta | 12 + .../Plugins/Editor/Utils/TipsWindow.cs | 148 + .../Plugins/Editor/Utils/TipsWindow.cs.meta | 12 + .../Plugins/Editor/Utils/UIUtils.cs | 3109 +++++ .../Plugins/Editor/Utils/UIUtils.cs.meta | 12 + .../Plugins/Editor/Utils/UndoUtils.cs | 12 + .../Plugins/Editor/Utils/UndoUtils.cs.meta | 12 + .../Editor/Utils/UpperLeftWidgetHelper.cs | 91 + .../Utils/UpperLeftWidgetHelper.cs.meta | 12 + .../Plugins/Editor/Utils/WindowHelper.cs | 260 + .../Plugins/Editor/Utils/WindowHelper.cs.meta | 12 + .../Plugins/Editor/Utils/WindowsUtil.cs | 148 + .../Plugins/Editor/Utils/WindowsUtil.cs.meta | 12 + .../Plugins/Editor/Version.meta | 9 + .../Plugins/Editor/Version/About.cs | 66 + .../Plugins/Editor/Version/About.cs.meta | 12 + .../Plugins/Editor/Version/VersionInfo.cs | 31 + .../Editor/Version/VersionInfo.cs.meta | 12 + .../Plugins/Editor/Wires.meta | 9 + .../Plugins/Editor/Wires/GLDraw.cs | 156 + .../Plugins/Editor/Wires/GLDraw.cs.meta | 12 + .../Plugins/Editor/Wires/InputPort.cs | 1527 +++ .../Plugins/Editor/Wires/InputPort.cs.meta | 12 + .../Plugins/Editor/Wires/OutputPort.cs | 314 + .../Plugins/Editor/Wires/OutputPort.cs.meta | 12 + .../Editor/Wires/WireBezierReference.cs | 58 + .../Editor/Wires/WireBezierReference.cs.meta | 12 + .../Plugins/Editor/Wires/WirePort.cs | 606 + .../Plugins/Editor/Wires/WirePort.cs.meta | 12 + .../Plugins/Editor/Wires/WireReference.cs | 126 + .../Editor/Wires/WireReference.cs.meta | 12 + .../Plugins/EditorResources.meta | 9 + .../Plugins/EditorResources/GUISkins.meta | 9 + .../EditorResources/GUISkins/MainSkin.guiskin | 5340 ++++++++ .../GUISkins/MainSkin.guiskin.meta | 8 + .../Plugins/EditorResources/Nodes.meta | 9 + .../EditorResources/Nodes/Bezier1X2AA.png | Bin 0 -> 174 bytes .../Nodes/Bezier1X2AA.png.meta | 59 + .../Nodes/GPUInstancingIconOFF.png | Bin 0 -> 19742 bytes .../Nodes/GPUInstancingIconOFF.png.meta | 58 + .../Nodes/GPUInstancingIconON.png | Bin 0 -> 20254 bytes .../Nodes/GPUInstancingIconON.png.meta | 58 + .../EditorResources/Nodes/LinkIcon.png | Bin 0 -> 18334 bytes .../EditorResources/Nodes/LinkIcon.png.meta | 76 + .../Nodes/MasterNodeIconOFF.png | Bin 0 -> 23236 bytes .../Nodes/MasterNodeIconOFF.png.meta | 58 + .../Nodes/MasterNodeIconON.png | Bin 0 -> 23337 bytes .../Nodes/MasterNodeIconON.png.meta | 58 + .../Nodes/TextureReferenceBg.png | Bin 0 -> 788 bytes .../Nodes/TextureReferenceBg.png.meta | 58 + .../Plugins/EditorResources/Previews.meta | 9 + .../Previews/IndirectSpecularPreview.exr | Bin 0 -> 164430 bytes .../Previews/IndirectSpecularPreview.exr.meta | 69 + .../Previews/LinearPreviews.shader | 232 + .../Previews/LinearPreviews.shader.meta | 11 + .../Previews/Preview_ACosOpNode.shader | 25 + .../Previews/Preview_ACosOpNode.shader.meta | 9 + .../Previews/Preview_ASinOpNode.shader | 25 + .../Previews/Preview_ASinOpNode.shader.meta | 9 + .../Previews/Preview_ATan2OpNode.shader | 29 + .../Previews/Preview_ATan2OpNode.shader.meta | 9 + .../Previews/Preview_ATanOpNode.shader | 25 + .../Previews/Preview_ATanOpNode.shader.meta | 9 + .../Previews/Preview_AbsOpNode.shader | 25 + .../Previews/Preview_AbsOpNode.shader.meta | 9 + .../Previews/Preview_AppendNode.shader | 36 + .../Previews/Preview_AppendNode.shader.meta | 9 + .../Previews/Preview_BlendNormalsNode.shader | 82 + .../Preview_BlendNormalsNode.shader.meta | 9 + .../Previews/Preview_BlendOpsNode.shader | 601 + .../Previews/Preview_BlendOpsNode.shader.meta | 9 + .../Preview_BreakToComponentsNode.shader | 73 + .../Preview_BreakToComponentsNode.shader.meta | 9 + .../Previews/Preview_CeilOpNode.shader | 25 + .../Previews/Preview_CeilOpNode.shader.meta | 9 + .../Previews/Preview_ClampOpNode.shader | 33 + .../Previews/Preview_ClampOpNode.shader.meta | 9 + .../Previews/Preview_Clip.shader | 35 + .../Previews/Preview_Clip.shader.meta | 9 + .../Previews/Preview_ClipPlanes.shader | 25 + .../Previews/Preview_ClipPlanes.shader.meta | 9 + .../Previews/Preview_ColorNode.shader | 24 + .../Previews/Preview_ColorNode.shader.meta | 9 + .../Previews/Preview_ColorSpaceDouble.shader | 19 + .../Preview_ColorSpaceDouble.shader.meta | 9 + .../Previews/Preview_Compare.shader | 48 + .../Previews/Preview_Compare.shader.meta | 9 + .../Previews/Preview_ComponentMaskNode.shader | 62 + .../Preview_ComponentMaskNode.shader.meta | 9 + .../Previews/Preview_ComputeScreenPos.shader | 47 + .../Preview_ComputeScreenPos.shader.meta | 9 + .../Previews/Preview_ConditionalIfNode.shader | 47 + .../Preview_ConditionalIfNode.shader.meta | 9 + .../Previews/Preview_CosOpNode.shader | 25 + .../Previews/Preview_CosOpNode.shader.meta | 9 + .../Previews/Preview_CosTime.shader | 25 + .../Previews/Preview_CosTime.shader.meta | 9 + .../Previews/Preview_CoshOpNode.shader | 25 + .../Previews/Preview_CoshOpNode.shader.meta | 9 + .../Preview_CrossProductOpNode.shader | 29 + .../Preview_CrossProductOpNode.shader.meta | 9 + .../Previews/Preview_DdxOpNode.shader | 25 + .../Previews/Preview_DdxOpNode.shader.meta | 9 + .../Previews/Preview_DdyOpNode.shader | 25 + .../Previews/Preview_DdyOpNode.shader.meta | 9 + .../Preview_DecodeDepthNormalNode.shader | 30 + .../Preview_DecodeDepthNormalNode.shader.meta | 9 + .../Preview_DecodeFloatRGBAHlpNode.shader | 27 + ...Preview_DecodeFloatRGBAHlpNode.shader.meta | 9 + .../Preview_DecodeFloatRGHlpNode.shader | 27 + .../Preview_DecodeFloatRGHlpNode.shader.meta | 9 + .../Preview_DecodeLightmapHlpNode.shader | 26 + .../Preview_DecodeLightmapHlpNode.shader.meta | 9 + ...eview_DecodeViewNormalStereoHlpNode.shader | 27 + ..._DecodeViewNormalStereoHlpNode.shader.meta | 9 + .../Previews/Preview_DegreesOpNode.shader | 25 + .../Preview_DegreesOpNode.shader.meta | 9 + .../Previews/Preview_DeltaTime.shader | 26 + .../Previews/Preview_DeltaTime.shader.meta | 9 + .../Previews/Preview_DesaturateNode.shader | 34 + .../Preview_DesaturateNode.shader.meta | 9 + ...view_DiffuseAndSpecularFromMetallic.shader | 32 + ...DiffuseAndSpecularFromMetallic.shader.meta | 9 + .../Previews/Preview_DistanceOpNode.shader | 29 + .../Preview_DistanceOpNode.shader.meta | 9 + .../Previews/Preview_DotProductOpNode.shader | 27 + .../Preview_DotProductOpNode.shader.meta | 9 + .../Previews/Preview_DynamicAppendNode.shader | 135 + .../Preview_DynamicAppendNode.shader.meta | 9 + .../Preview_EncodeFloatRGBAHlpNode.shader | 27 + ...Preview_EncodeFloatRGBAHlpNode.shader.meta | 9 + .../Preview_EncodeFloatRGHlpNode.shader | 27 + .../Preview_EncodeFloatRGHlpNode.shader.meta | 9 + ...eview_EncodeViewNormalStereoHlpNode.shader | 27 + ..._EncodeViewNormalStereoHlpNode.shader.meta | 9 + .../Previews/Preview_Exp2OpNode.shader | 25 + .../Previews/Preview_Exp2OpNode.shader.meta | 9 + .../Previews/Preview_ExpOpNode.shader | 25 + .../Previews/Preview_ExpOpNode.shader.meta | 9 + .../Previews/Preview_FWidthOpNode.shader | 25 + .../Previews/Preview_FWidthOpNode.shader.meta | 9 + .../Previews/Preview_FaceVariableNode.shader | 19 + .../Preview_FaceVariableNode.shader.meta | 9 + .../Previews/Preview_FloorOpNode.shader | 25 + .../Previews/Preview_FloorOpNode.shader.meta | 9 + .../Previews/Preview_FmodOpNode.shader | 29 + .../Previews/Preview_FmodOpNode.shader.meta | 9 + .../Preview_FogAndAmbientColors.shader | 75 + .../Preview_FogAndAmbientColors.shader.meta | 9 + .../Previews/Preview_FogParams.shader | 19 + .../Previews/Preview_FogParams.shader.meta | 9 + .../Previews/Preview_FractNode.shader | 25 + .../Previews/Preview_FractNode.shader.meta | 9 + .../Previews/Preview_FresnelNode.shader | 358 + .../Previews/Preview_FresnelNode.shader.meta | 9 + .../Previews/Preview_FunctionInputNode.shader | 39 + .../Preview_FunctionInputNode.shader.meta | 9 + .../Previews/Preview_FunctionNode.shader | 25 + .../Previews/Preview_FunctionNode.shader.meta | 9 + .../Preview_FunctionOutputNode.shader | 25 + .../Preview_FunctionOutputNode.shader.meta | 9 + .../Previews/Preview_GammaToLinearNode.shader | 27 + .../Preview_GammaToLinearNode.shader.meta | 11 + .../Previews/Preview_GetLocalVarNode.shader | 25 + .../Preview_GetLocalVarNode.shader.meta | 9 + .../Previews/Preview_GradientSample.shader | 123 + .../Preview_GradientSample.shader.meta | 9 + .../Previews/Preview_GrayscaleNode.shader | 62 + .../Preview_GrayscaleNode.shader.meta | 9 + .../Previews/Preview_HSVToRGBNode.shader | 41 + .../Previews/Preview_HSVToRGBNode.shader.meta | 9 + .../Preview_HeightMapTextureBlend.shader | 33 + .../Preview_HeightMapTextureBlend.shader.meta | 9 + .../Preview_IndirectDiffuseLight.shader | 106 + .../Preview_IndirectDiffuseLight.shader.meta | 9 + .../Preview_IndirectSpecularLight.shader | 128 + .../Preview_IndirectSpecularLight.shader.meta | 13 + .../Previews/Preview_InstanceIDNode.shader | 24 + .../Preview_InstanceIDNode.shader.meta | 9 + .../Previews/Preview_IntNode.shader | 24 + .../Previews/Preview_IntNode.shader.meta | 9 + .../Previews/Preview_LODFadeNode.shader | 19 + .../Previews/Preview_LODFadeNode.shader.meta | 9 + .../Previews/Preview_LayeredBlendNode.shader | 90 + .../Preview_LayeredBlendNode.shader.meta | 9 + .../Previews/Preview_LengthOpNode.shader | 73 + .../Previews/Preview_LengthOpNode.shader.meta | 9 + .../Previews/Preview_LerpOp.shader | 32 + .../Previews/Preview_LerpOp.shader.meta | 9 + .../Previews/Preview_LightAttenuation.shader | 26 + .../Preview_LightAttenuation.shader.meta | 9 + .../Previews/Preview_LightColorNode.shader | 56 + .../Preview_LightColorNode.shader.meta | 9 + .../Previews/Preview_LinearDepthNode.shader | 43 + .../Preview_LinearDepthNode.shader.meta | 9 + .../Previews/Preview_LinearToGammaNode.shader | 27 + .../Preview_LinearToGammaNode.shader.meta | 11 + .../Previews/Preview_Log10OpNode.shader | 25 + .../Previews/Preview_Log10OpNode.shader.meta | 9 + .../Previews/Preview_Log2OpNode.shader | 25 + .../Previews/Preview_Log2OpNode.shader.meta | 9 + .../Previews/Preview_LogOpNode.shader | 25 + .../Previews/Preview_LogOpNode.shader.meta | 9 + .../Previews/Preview_LuminanceNode.shader | 26 + .../Preview_LuminanceNode.shader.meta | 9 + .../Previews/Preview_NegateNode.shader | 25 + .../Previews/Preview_NegateNode.shader.meta | 9 + .../Previews/Preview_NodeMasking.shader | 55 + .../Previews/Preview_NodeMasking.shader.meta | 9 + .../Preview_NoiseGeneratorNode.shader | 267 + .../Preview_NoiseGeneratorNode.shader.meta | 9 + .../Preview_NormalVertexDataNode.shader | 22 + .../Preview_NormalVertexDataNode.shader.meta | 9 + .../Previews/Preview_NormalizeNode.shader | 25 + .../Preview_NormalizeNode.shader.meta | 9 + .../Preview_ObjSpaceLightDirHlpNode.shader | 22 + ...review_ObjSpaceLightDirHlpNode.shader.meta | 9 + .../Preview_ObjSpaceViewDirHlpNode.shader | 25 + ...Preview_ObjSpaceViewDirHlpNode.shader.meta | 9 + .../Previews/Preview_ObjectScaleNode.shader | 36 + .../Preview_ObjectScaleNode.shader.meta | 9 + .../Previews/Preview_ObjectToClipPos.shader | 28 + .../Preview_ObjectToClipPos.shader.meta | 9 + .../Previews/Preview_ObjectToViewPos.shader | 29 + .../Preview_ObjectToViewPos.shader.meta | 9 + .../Preview_ObjectToWorldTransfNode.shader | 25 + ...review_ObjectToWorldTransfNode.shader.meta | 9 + .../Previews/Preview_OneMinusNode.shader | 25 + .../Previews/Preview_OneMinusNode.shader.meta | 9 + .../Previews/Preview_OrthoParams.shader | 19 + .../Previews/Preview_OrthoParams.shader.meta | 9 + .../Previews/Preview_PannerNode.shader | 40 + .../Previews/Preview_PannerNode.shader.meta | 9 + .../Preview_ParallaxMappingNode.shader | 44 + .../Preview_ParallaxMappingNode.shader.meta | 9 + .../Previews/Preview_ParallaxOffset.shader | 35 + .../Preview_ParallaxOffset.shader.meta | 9 + .../Previews/Preview_PiNode.shader | 21 + .../Previews/Preview_PiNode.shader.meta | 9 + .../Previews/Preview_PosVertexDataNode.shader | 22 + .../Preview_PosVertexDataNode.shader.meta | 9 + .../Previews/Preview_PosterizeNode.shader | 35 + .../Preview_PosterizeNode.shader.meta | 9 + .../Previews/Preview_PowerNode.shader | 29 + .../Previews/Preview_PowerNode.shader.meta | 9 + .../Preview_PrimitiveIDVariableNode.shader | 19 + ...review_PrimitiveIDVariableNode.shader.meta | 9 + .../Previews/Preview_ProjectionParams.shader | 19 + .../Preview_ProjectionParams.shader.meta | 9 + .../Previews/Preview_RGBToHSVNode.shader | 37 + .../Previews/Preview_RGBToHSVNode.shader.meta | 9 + .../Previews/Preview_RadiansOpNode.shader | 25 + .../Preview_RadiansOpNode.shader.meta | 9 + .../Previews/Preview_RangedFloatNode.shader | 24 + .../Preview_RangedFloatNode.shader.meta | 9 + .../Previews/Preview_ReflectOpNode.shader | 29 + .../Preview_ReflectOpNode.shader.meta | 9 + .../Previews/Preview_RefractOpVec.shader | 32 + .../Previews/Preview_RefractOpVec.shader.meta | 9 + .../Preview_RegisterLocalVarNode.shader | 25 + .../Preview_RegisterLocalVarNode.shader.meta | 9 + .../Previews/Preview_RelayNode.shader | 25 + .../Previews/Preview_RelayNode.shader.meta | 9 + .../Previews/Preview_RotatorNode.shader | 43 + .../Previews/Preview_RotatorNode.shader.meta | 9 + .../Previews/Preview_RoundOpNode.shader | 25 + .../Previews/Preview_RoundOpNode.shader.meta | 9 + .../Previews/Preview_RsqrtOpNode.shader | 25 + .../Previews/Preview_RsqrtOpNode.shader.meta | 9 + .../Previews/Preview_SamplerNode.shader | 143 + .../Previews/Preview_SamplerNode.shader.meta | 9 + .../Previews/Preview_SaturateNode.shader | 25 + .../Previews/Preview_SaturateNode.shader.meta | 9 + .../Preview_ScaleAndOffsetNode.shader | 33 + .../Preview_ScaleAndOffsetNode.shader.meta | 9 + .../Previews/Preview_ScaleNode.shader | 27 + .../Previews/Preview_ScaleNode.shader.meta | 9 + .../Previews/Preview_ScreenParams.shader | 19 + .../Previews/Preview_ScreenParams.shader.meta | 9 + .../Preview_ScreenPosInputsNode.shader | 62 + .../Preview_ScreenPosInputsNode.shader.meta | 9 + .../Previews/Preview_ShadeVertexLights.shader | 34 + .../Preview_ShadeVertexLights.shader.meta | 9 + .../Previews/Preview_SignOpNode.shader | 25 + .../Previews/Preview_SignOpNode.shader.meta | 9 + .../Previews/Preview_SimpleAddOpNode.shader | 66 + .../Preview_SimpleAddOpNode.shader.meta | 9 + .../Preview_SimpleContrastNode.shader | 39 + .../Preview_SimpleContrastNode.shader.meta | 9 + .../Preview_SimpleDivideOpNode.shader | 29 + .../Preview_SimpleDivideOpNode.shader.meta | 9 + .../Previews/Preview_SimpleMaxOp.shader | 29 + .../Previews/Preview_SimpleMaxOp.shader.meta | 9 + .../Previews/Preview_SimpleMinNode.shader | 29 + .../Preview_SimpleMinNode.shader.meta | 9 + .../Preview_SimpleMultiplyOpNode.shader | 272 + .../Preview_SimpleMultiplyOpNode.shader.meta | 9 + .../Preview_SimpleRemainderNode.shader | 29 + .../Preview_SimpleRemainderNode.shader.meta | 9 + .../Preview_SimpleSubtractOpNode.shader | 29 + .../Preview_SimpleSubtractOpNode.shader.meta | 9 + .../Previews/Preview_SimpleTimeNode.shader | 29 + .../Preview_SimpleTimeNode.shader.meta | 9 + .../Preview_SimplifiedFModOpNode.shader | 29 + .../Preview_SimplifiedFModOpNode.shader.meta | 9 + .../Previews/Preview_SinOpNode.shader | 25 + .../Previews/Preview_SinOpNode.shader.meta | 9 + .../Previews/Preview_SinTimeNode.shader | 25 + .../Previews/Preview_SinTimeNode.shader.meta | 9 + .../Previews/Preview_SinhOpNode.shader | 25 + .../Previews/Preview_SinhOpNode.shader.meta | 9 + .../Previews/Preview_SmoothstepOpNode.shader | 32 + .../Preview_SmoothstepOpNode.shader.meta | 9 + .../Previews/Preview_SqrtOpNode.shader | 25 + .../Previews/Preview_SqrtOpNode.shader.meta | 9 + .../Previews/Preview_StaticSwitchNode.shader | 59 + .../Preview_StaticSwitchNode.shader.meta | 9 + .../Previews/Preview_StepOpNode.shader | 29 + .../Previews/Preview_StepOpNode.shader.meta | 9 + .../Preview_SubstanceSamplerNode.shader | 53 + .../Preview_SubstanceSamplerNode.shader.meta | 9 + .../Previews/Preview_SummedBlendNode.shader | 85 + .../Preview_SummedBlendNode.shader.meta | 9 + .../Previews/Preview_SwitchByFaceNode.shader | 29 + .../Preview_SwitchByFaceNode.shader.meta | 9 + .../Previews/Preview_SwitchNode.shader | 59 + .../Previews/Preview_SwitchNode.shader.meta | 9 + .../Previews/Preview_SwizzleNode.shader | 3103 +++++ .../Previews/Preview_SwizzleNode.shader.meta | 9 + .../Previews/Preview_TFHCCompareEqual.shader | 35 + .../Preview_TFHCCompareEqual.shader.meta | 9 + .../Preview_TFHCCompareGreater.shader | 35 + .../Preview_TFHCCompareGreater.shader.meta | 9 + .../Preview_TFHCCompareGreaterEqual.shader | 35 + ...review_TFHCCompareGreaterEqual.shader.meta | 9 + .../Preview_TFHCCompareLessNode.shader | 35 + .../Preview_TFHCCompareLessNode.shader.meta | 9 + .../Preview_TFHCCompareLowerEqual.shader | 35 + .../Preview_TFHCCompareLowerEqual.shader.meta | 9 + .../Preview_TFHCCompareNotEqual.shader | 35 + .../Preview_TFHCCompareNotEqual.shader.meta | 9 + .../Preview_TFHCCompareWithRange.shader | 38 + .../Preview_TFHCCompareWithRange.shader.meta | 9 + .../Preview_TFHCFlipBookUVAnimation.shader | 89 + ...review_TFHCFlipBookUVAnimation.shader.meta | 9 + .../Previews/Preview_TFHCIf.shader | 41 + .../Previews/Preview_TFHCIf.shader.meta | 9 + .../Previews/Preview_TFHCPixelateUV.shader | 35 + .../Preview_TFHCPixelateUV.shader.meta | 9 + .../Previews/Preview_TFHCRemap.shader | 49 + .../Previews/Preview_TFHCRemap.shader.meta | 9 + .../Previews/Preview_TanOpNode.shader | 25 + .../Previews/Preview_TanOpNode.shader.meta | 9 + .../Preview_TangentSignVertexDataNode.shader | 31 + ...view_TangentSignVertexDataNode.shader.meta | 9 + .../Preview_TangentVertexDataNode.shader | 22 + .../Preview_TangentVertexDataNode.shader.meta | 9 + .../Previews/Preview_TanhOpNode.shader | 25 + .../Previews/Preview_TanhOpNode.shader.meta | 9 + .../Previews/Preview_TauNode.shader | 19 + .../Previews/Preview_TauNode.shader.meta | 9 + .../Preview_TemplateShaderProperty.shader | 47 + ...Preview_TemplateShaderProperty.shader.meta | 9 + .../Preview_TexCoordVertexDataNode.shader | 19 + ...Preview_TexCoordVertexDataNode.shader.meta | 9 + .../Previews/Preview_TexelSize.shader | 80 + .../Previews/Preview_TexelSize.shader.meta | 9 + .../Previews/Preview_Texture2D.shader | 19 + .../Previews/Preview_Texture2D.shader.meta | 9 + .../Previews/Preview_TextureArrayNode.shader | 63 + .../Preview_TextureArrayNode.shader.meta | 9 + .../Preview_TextureCoordinatesNode.shader | 29 + ...Preview_TextureCoordinatesNode.shader.meta | 9 + .../Preview_TexturePropertyNode.shader | 84 + .../Preview_TexturePropertyNode.shader.meta | 9 + .../Previews/Preview_TextureTransform.shader | 87 + .../Preview_TextureTransform.shader.meta | 9 + .../Previews/Preview_TimeNode.shader | 25 + .../Previews/Preview_TimeNode.shader.meta | 9 + .../Previews/Preview_ToggleSwitchNode.shader | 30 + .../Preview_ToggleSwitchNode.shader.meta | 9 + .../Previews/Preview_TriplanarNode.shader | 105 + .../Preview_TriplanarNode.shader.meta | 9 + .../Previews/Preview_TruncOpNode.shader | 25 + .../Previews/Preview_TruncOpNode.shader.meta | 9 + .../Preview_UnpackScaleNormalNode.shader | 33 + .../Preview_UnpackScaleNormalNode.shader.meta | 9 + .../Previews/Preview_Vector2Node.shader | 24 + .../Previews/Preview_Vector2Node.shader.meta | 9 + .../Previews/Preview_Vector3Node.shader | 24 + .../Previews/Preview_Vector3Node.shader.meta | 9 + .../Previews/Preview_Vector4Node.shader | 24 + .../Previews/Preview_Vector4Node.shader.meta | 9 + .../Preview_VertexBinormalNode.shader | 31 + .../Preview_VertexBinormalNode.shader.meta | 9 + .../Previews/Preview_VertexColorNode.shader | 19 + .../Preview_VertexColorNode.shader.meta | 9 + .../Preview_VertexIdVariableNode.shader | 39 + .../Preview_VertexIdVariableNode.shader.meta | 9 + .../Previews/Preview_VertexTangentNode.shader | 31 + .../Preview_VertexTangentNode.shader.meta | 9 + .../Preview_ViewDirInputsCoordNode.shader | 57 + ...Preview_ViewDirInputsCoordNode.shader.meta | 9 + .../Previews/Preview_VoronoiNode.shader | 263 + .../Previews/Preview_VoronoiNode.shader.meta | 9 + .../Previews/Preview_WeightedBlendNode.shader | 84 + .../Preview_WeightedBlendNode.shader.meta | 9 + .../Previews/Preview_WireNode.shader | 25 + .../Previews/Preview_WireNode.shader.meta | 9 + .../Previews/Preview_WorldNormalVector.shader | 66 + .../Preview_WorldNormalVector.shader.meta | 9 + .../Preview_WorldPosInputsNode.shader | 23 + .../Preview_WorldPosInputsNode.shader.meta | 9 + .../Preview_WorldReflectionVector.shader | 77 + .../Preview_WorldReflectionVector.shader.meta | 9 + .../Preview_WorldSpaceCameraPos.shader | 20 + .../Preview_WorldSpaceCameraPos.shader.meta | 9 + .../Preview_WorldSpaceLightDirHlpNode.shader | 22 + ...view_WorldSpaceLightDirHlpNode.shader.meta | 9 + .../Preview_WorldSpaceLightPosNode.shader | 33 + ...Preview_WorldSpaceLightPosNode.shader.meta | 9 + .../Preview_WorldSpaceViewDirHlpNode.shader | 25 + ...eview_WorldSpaceViewDirHlpNode.shader.meta | 9 + .../Preview_WorldToObjectTransfNode.shader | 25 + ...review_WorldToObjectTransfNode.shader.meta | 9 + .../Preview_WorldTransformParams.shader | 20 + .../Preview_WorldTransformParams.shader.meta | 9 + .../Previews/Preview_ZBufferParams.shader | 19 + .../Preview_ZBufferParams.shader.meta | 9 + .../Previews/TextureArrayInspector.shader | 30 + .../TextureArrayInspector.shader.meta | 9 + .../EditorResources/ShaderFunctions.meta | 9 + .../EditorResources/ShaderFunctions/And.asset | 39 + .../ShaderFunctions/And.asset.meta | 8 + .../ShaderFunctions/Bacteria.asset | 38 + .../ShaderFunctions/Bacteria.asset.meta | 8 + .../ShaderFunctions/Bicubic Precompute.asset | 57 + .../Bicubic Precompute.asset.meta | 8 + .../ShaderFunctions/Bicubic Sample.asset | 97 + .../ShaderFunctions/Bicubic Sample.asset.meta | 8 + .../Bidirectional Parallax Mapping.asset | 49 + .../Bidirectional Parallax Mapping.asset.meta | 8 + .../Blinn-Phong Half Vector.asset | 23 + .../Blinn-Phong Half Vector.asset.meta | 8 + .../ShaderFunctions/Blinn-Phong Light.asset | 41 + .../Blinn-Phong Light.asset.meta | 8 + .../ShaderFunctions/BlinnPhongLightWrap.asset | 48 + .../BlinnPhongLightWrap.asset.meta | 8 + .../ShaderFunctions/BoxMask.asset | 27 + .../ShaderFunctions/BoxMask.asset.meta | 9 + .../ShaderFunctions/Bricks Pattern.asset | 41 + .../ShaderFunctions/Bricks Pattern.asset.meta | 8 + .../ShaderFunctions/Checkerboard.asset | 56 + .../ShaderFunctions/Checkerboard.asset.meta | 8 + .../ShaderFunctions/Color Mask.asset | 37 + .../ShaderFunctions/Color Mask.asset.meta | 8 + .../ShaderFunctions/ComputeFilterWidth.asset | 22 + .../ComputeFilterWidth.asset.meta | 8 + .../ShaderFunctions/ConstantBiasScale.asset | 26 + .../ConstantBiasScale.asset.meta | 8 + .../ShaderFunctions/CotangentFrame.asset | 37 + .../ShaderFunctions/CotangentFrame.asset.meta | 8 + .../Create Orthogonal Vector.asset | 33 + .../Create Orthogonal Vector.asset.meta | 8 + .../Decode Directional Lighmap.asset | 45 + .../Decode Directional Lighmap.asset.meta | 8 + .../DepthMaskedRefraction.asset | 52 + .../DepthMaskedRefraction.asset.meta | 8 + .../Derive Tangent Basis.asset | 64 + .../Derive Tangent Basis.asset.meta | 8 + .../ShaderFunctions/Detail Albedo.asset | 30 + .../ShaderFunctions/Detail Albedo.asset.meta | 8 + .../ShaderFunctions/Dots Pattern.asset | 42 + .../ShaderFunctions/Dots Pattern.asset.meta | 8 + .../ShaderFunctions/Ellipse.asset | 40 + .../ShaderFunctions/Ellipse.asset.meta | 8 + .../ShaderFunctions/FetchHDColorPyramid.asset | 40 + .../FetchHDColorPyramid.asset.meta | 8 + .../ShaderFunctions/FetchLightmapValue.asset | 48 + .../FetchLightmapValue.asset.meta | 9 + .../ShaderFunctions/Flipbook.asset | 36 + .../ShaderFunctions/Flipbook.asset.meta | 8 + .../ShaderFunctions/Flow.asset | 50 + .../ShaderFunctions/Flow.asset.meta | 8 + .../Four Splats First Pass Terrain.asset | 101 + .../Four Splats First Pass Terrain.asset.meta | 8 + .../ShaderFunctions/Grid.asset | 38 + .../ShaderFunctions/Grid.asset.meta | 8 + .../ShaderFunctions/Half Lambert Term.asset | 25 + .../Half Lambert Term.asset.meta | 8 + .../Height-based Blending.asset | 44 + .../Height-based Blending.asset.meta | 8 + .../ShaderFunctions/Herringbone.asset | 38 + .../ShaderFunctions/Herringbone.asset.meta | 8 + .../ShaderFunctions/Hex Lattice.asset | 40 + .../ShaderFunctions/Hex Lattice.asset.meta | 8 + .../ShaderFunctions/Houndstooth.asset | 39 + .../ShaderFunctions/Houndstooth.asset.meta | 8 + .../ShaderFunctions/Inverse Lerp.asset | 41 + .../ShaderFunctions/Inverse Lerp.asset.meta | 8 + .../ShaderFunctions/Lerp White To.asset | 26 + .../ShaderFunctions/Lerp White To.asset.meta | 8 + .../ShaderFunctions/Midtones Control.asset | 35 + .../Midtones Control.asset.meta | 8 + .../ShaderFunctions/Noise Sine Wave.asset | 43 + .../Noise Sine Wave.asset.meta | 8 + .../Non Stereo Screen Pos.asset | 42 + .../Non Stereo Screen Pos.asset.meta | 8 + .../ShaderFunctions/Normal From Height.asset | 47 + .../Normal From Height.asset.meta | 8 + .../ShaderFunctions/Normal From Texture.asset | 82 + .../Normal From Texture.asset.meta | 8 + .../ShaderFunctions/NormalCreate.asset | 29 + .../ShaderFunctions/NormalCreate.asset.meta | 8 + .../EditorResources/ShaderFunctions/Or.asset | 39 + .../ShaderFunctions/Or.asset.meta | 8 + .../ShaderFunctions/PerturbNormal.asset | 29 + .../ShaderFunctions/PerturbNormal.asset.meta | 8 + .../ShaderFunctions/PerturbNormalHQ.asset | 44 + .../PerturbNormalHQ.asset.meta | 8 + .../ShaderFunctions/Polar Coordinates.asset | 43 + .../Polar Coordinates.asset.meta | 8 + .../ShaderFunctions/Polygon.asset | 45 + .../ShaderFunctions/Polygon.asset.meta | 8 + .../PreparePerturbNormalHQ.asset | 39 + .../PreparePerturbNormalHQ.asset.meta | 8 + .../ShaderFunctions/Procedural Sample.asset | 200 + .../Procedural Sample.asset.meta | 8 + .../ShaderFunctions/Projection.asset | 39 + .../ShaderFunctions/Projection.asset.meta | 8 + .../ShaderFunctions/Radial Shear.asset | 42 + .../ShaderFunctions/Radial Shear.asset.meta | 8 + .../ShaderFunctions/RadialUVDistortion.asset | 37 + .../RadialUVDistortion.asset.meta | 8 + .../ShaderFunctions/Random Range.asset | 41 + .../ShaderFunctions/Random Range.asset.meta | 8 + ...econstruct World Position From Depth.asset | 52 + ...truct World Position From Depth.asset.meta | 8 + .../ShaderFunctions/Rectangle.asset | 38 + .../ShaderFunctions/Rectangle.asset.meta | 8 + .../ShaderFunctions/Rejection.asset | 41 + .../ShaderFunctions/Rejection.asset.meta | 8 + .../ShaderFunctions/Replace Color.asset | 46 + .../ShaderFunctions/Replace Color.asset.meta | 8 + .../ShaderFunctions/Rounded Rectangle.asset | 46 + .../Rounded Rectangle.asset.meta | 8 + .../SRP Additional Light.asset | 117 + .../SRP Additional Light.asset.meta | 8 + .../ShaderFunctions/Sawtooth Wave.asset | 39 + .../ShaderFunctions/Sawtooth Wave.asset.meta | 8 + .../ShaderFunctions/Simple HUE.asset | 18 + .../ShaderFunctions/Simple HUE.asset.meta | 8 + .../ShaderFunctions/Smooth Wave.asset | 40 + .../ShaderFunctions/Smooth Wave.asset.meta | 8 + .../ShaderFunctions/SphereMask.asset | 39 + .../ShaderFunctions/SphereMask.asset.meta | 8 + .../ShaderFunctions/Spherize.asset | 42 + .../ShaderFunctions/Spherize.asset.meta | 8 + .../ShaderFunctions/Spiral.asset | 41 + .../ShaderFunctions/Spiral.asset.meta | 8 + .../ShaderFunctions/Square Wave.asset | 39 + .../ShaderFunctions/Square Wave.asset.meta | 8 + .../ShaderFunctions/Step Antialiasing.asset | 40 + .../Step Antialiasing.asset.meta | 8 + .../ShaderFunctions/Stereo Screen Pos.asset | 42 + .../Stereo Screen Pos.asset.meta | 8 + .../ShaderFunctions/Stripes.asset | 38 + .../ShaderFunctions/Stripes.asset.meta | 8 + .../SubstanceBlendMetallic.asset | 55 + .../SubstanceBlendMetallic.asset.meta | 8 + .../Terrain Wind Animate Vertex.asset | 44 + .../Terrain Wind Animate Vertex.asset.meta | 8 + .../ShaderFunctions/Terrain Wind Value.asset | 41 + .../Terrain Wind Value.asset.meta | 8 + .../ShaderFunctions/Triangle Wave.asset | 40 + .../ShaderFunctions/Triangle Wave.asset.meta | 8 + .../ShaderFunctions/Truchet.asset | 40 + .../ShaderFunctions/Truchet.asset.meta | 8 + .../ShaderFunctions/Twirl.asset | 41 + .../ShaderFunctions/Twirl.asset.meta | 8 + .../UI-Sprite Effect Layer.asset | 71 + .../UI-Sprite Effect Layer.asset.meta | 8 + .../ShaderFunctions/Whirl.asset | 42 + .../ShaderFunctions/Whirl.asset.meta | 8 + .../ShaderFunctions/Zig Zag.asset | 43 + .../ShaderFunctions/Zig Zag.asset.meta | 8 + .../EditorResources/ShaderLibrary.meta | 9 + .../ShaderLibrary/ShaderLibrary.txt | 1 + .../ShaderLibrary/ShaderLibrary.txt.meta | 8 + .../Plugins/EditorResources/Shaders.meta | 9 + .../Shaders/ASESShaderSelectorUnlit.shader | 39 + .../ASESShaderSelectorUnlit.shader.meta | 9 + .../Shaders/Unlit-ColoredAlpha.shader | 165 + .../Shaders/Unlit-ColoredAlpha.shader.meta | 13 + .../Plugins/EditorResources/Templates.meta | 9 + .../CustomRTTemplates.unitypackage.meta | 8 + .../HDSRPTemplates.unitypackage.meta | 8 + .../LWSRPTemplates.unitypackage.meta | 8 + .../EditorResources/Templates/Legacy.meta | 9 + .../Templates/Legacy/DefaultUnlit.shader | 86 + .../Templates/Legacy/DefaultUnlit.shader.meta | 9 + .../Templates/Legacy/Lit.shader | 2302 ++++ .../Templates/Legacy/Lit.shader.meta | 9 + .../Templates/Legacy/MultiPassUnlit.shader | 297 + .../Legacy/MultiPassUnlit.shader.meta | 9 + .../Legacy/Particle Alpha Blend.shader | 123 + .../Legacy/Particle Alpha Blend.shader.meta | 9 + .../Templates/Legacy/PostProcess.shader | 94 + .../Templates/Legacy/PostProcess.shader.meta | 9 + .../Templates/Legacy/Sprites-Default.shader | 114 + .../Legacy/Sprites-Default.shader.meta | 9 + .../Templates/Legacy/UIDefault.shader | 133 + .../Templates/Legacy/UIDefault.shader.meta | 9 + .../Templates/Legacy/Unlit.shader | 103 + .../Templates/Legacy/Unlit.shader.meta | 9 + .../Templates/Legacy/UnlitLightmap.shader | 127 + .../Legacy/UnlitLightmap.shader.meta | 9 + .../PPStackTemplates.unitypackage.meta | 8 + .../Templates/SRP (Legacy).meta | 9 + ...RPTemplates 3xx (Legacy).unitypackage.meta | 8 + ...RPTemplates 4xx (Legacy).unitypackage.meta | 8 + ...RPTemplates 572 (Legacy).unitypackage.meta | 8 + ...RPTemplates 5xx (Legacy).unitypackage.meta | 7 + ...RPTemplates 6xx (Legacy).unitypackage.meta | 8 + ...lates 718 - 743 (Legacy).unitypackage.meta | 8 + ...lates 7xx - 9xx (Legacy).unitypackage.meta | 8 + ...RPTemplates 3xx (Legacy).unitypackage.meta | 8 + ...RPTemplates 4xx (Legacy).unitypackage.meta | 8 + .../Templates/SRP (Legacy)/README.txt | 36 + .../Templates/SRP (Legacy)/README.txt.meta | 8 + ...lates 7xx - 9xx (Legacy).unitypackage.meta | 8 + .../Templates/USRPTemplates.unitypackage.meta | 8 + .../Plugins/EditorResources/Textures.meta | 9 + .../EditorResources/Textures/About.png | Bin 0 -> 57164 bytes .../EditorResources/Textures/About.png.meta | 76 + .../EditorResources/Textures/Icon64.png | Bin 0 -> 46810 bytes .../EditorResources/Textures/Icon64.png.meta | 82 + .../EditorResources/Textures/black.png | Bin 0 -> 150 bytes .../EditorResources/Textures/black.png.meta | 59 + .../Plugins/EditorResources/Textures/blue.png | Bin 0 -> 158 bytes .../EditorResources/Textures/blue.png.meta | 59 + .../Plugins/EditorResources/Textures/flat.png | Bin 0 -> 158 bytes .../EditorResources/Textures/flat.png.meta | 59 + .../EditorResources/Textures/green.png | Bin 0 -> 156 bytes .../EditorResources/Textures/green.png.meta | 59 + .../Plugins/EditorResources/Textures/grey.png | Bin 0 -> 158 bytes .../EditorResources/Textures/grey.png.meta | 59 + .../Plugins/EditorResources/Textures/red.png | Bin 0 -> 154 bytes .../EditorResources/Textures/red.png.meta | 59 + .../EditorResources/Textures/white.png | Bin 0 -> 158 bytes .../EditorResources/Textures/white.png.meta | 59 + .../Plugins/EditorResources/UI.meta | 9 + .../Plugins/EditorResources/UI/Buttons.meta | 9 + .../EditorResources/UI/Buttons/AddToList.png | Bin 0 -> 18832 bytes .../UI/Buttons/AddToList.png.meta | 76 + .../EditorResources/UI/Buttons/Checkmark.png | Bin 0 -> 461 bytes .../UI/Buttons/Checkmark.png.meta | 76 + .../UI/Buttons/CircularToggle_OFF_Dark.png | Bin 0 -> 157 bytes .../Buttons/CircularToggle_OFF_Dark.png.meta | 76 + .../UI/Buttons/CircularToggle_ON_Dark.png | Bin 0 -> 189 bytes .../Buttons/CircularToggle_ON_Dark.png.meta | 76 + .../EditorResources/UI/Buttons/CleanupOFF.png | Bin 0 -> 24764 bytes .../UI/Buttons/CleanupOFF.png.meta | 76 + .../UI/Buttons/CleanupOFFNew.png | Bin 0 -> 19719 bytes .../UI/Buttons/CleanupOFFNew.png.meta | 76 + .../EditorResources/UI/Buttons/CleanupON.png | Bin 0 -> 24813 bytes .../UI/Buttons/CleanupON.png.meta | 76 + .../UI/Buttons/CleanupONNew.png | Bin 0 -> 19776 bytes .../UI/Buttons/CleanupONNew.png.meta | 76 + .../UI/Buttons/CustomExpAddIconActive.png | Bin 0 -> 373 bytes .../Buttons/CustomExpAddIconActive.png.meta | 76 + .../UI/Buttons/CustomExpAddIconNormal.png | Bin 0 -> 363 bytes .../Buttons/CustomExpAddIconNormal.png.meta | 76 + .../UI/Buttons/CustomExpRemoveIconActive.png | Bin 0 -> 366 bytes .../CustomExpRemoveIconActive.png.meta | 76 + .../UI/Buttons/CustomExpRemoveIconNormal.png | Bin 0 -> 329 bytes .../CustomExpRemoveIconNormal.png.meta | 76 + .../EditorResources/UI/Buttons/FitView.png | Bin 0 -> 19122 bytes .../UI/Buttons/FitView.png.meta | 76 + .../EditorResources/UI/Buttons/FocusNode.png | Bin 0 -> 18938 bytes .../UI/Buttons/FocusNode.png.meta | 76 + .../EditorResources/UI/Buttons/Help.png | Bin 0 -> 23168 bytes .../EditorResources/UI/Buttons/Help.png.meta | 76 + .../EditorResources/UI/Buttons/Help2.png | Bin 0 -> 21750 bytes .../EditorResources/UI/Buttons/Help2.png.meta | 76 + .../UI/Buttons/ItemCleanupOFF.png | Bin 0 -> 22515 bytes .../UI/Buttons/ItemCleanupOFF.png.meta | 76 + .../UI/Buttons/ItemCleanupON.png | Bin 0 -> 22640 bytes .../UI/Buttons/ItemCleanupON.png.meta | 76 + .../EditorResources/UI/Buttons/Library.png | Bin 0 -> 21851 bytes .../UI/Buttons/Library.png.meta | 76 + .../EditorResources/UI/Buttons/LiveOFF.png | Bin 0 -> 22523 bytes .../UI/Buttons/LiveOFF.png.meta | 76 + .../EditorResources/UI/Buttons/LiveON.png | Bin 0 -> 22677 bytes .../UI/Buttons/LiveON.png.meta | 76 + .../UI/Buttons/LivePending.png | Bin 0 -> 22735 bytes .../UI/Buttons/LivePending.png.meta | 76 + .../UI/Buttons/MaximizeWindow.png | Bin 0 -> 202 bytes .../UI/Buttons/MaximizeWindow.png.meta | 76 + .../UI/Buttons/MiniBotLeftOff.png | Bin 0 -> 267 bytes .../UI/Buttons/MiniBotLeftOff.png.meta | 63 + .../UI/Buttons/MiniBotLeftOffHover.png | Bin 0 -> 268 bytes .../UI/Buttons/MiniBotLeftOffHover.png.meta | 63 + .../UI/Buttons/MiniBotLeftOn.png | Bin 0 -> 267 bytes .../UI/Buttons/MiniBotLeftOn.png.meta | 63 + .../UI/Buttons/MiniBotLeftOnHover.png | Bin 0 -> 259 bytes .../UI/Buttons/MiniBotLeftOnHover.png.meta | 63 + .../UI/Buttons/MiniBotMidOff.png | Bin 0 -> 230 bytes .../UI/Buttons/MiniBotMidOff.png.meta | 63 + .../UI/Buttons/MiniBotMidOffHover.png | Bin 0 -> 236 bytes .../UI/Buttons/MiniBotMidOffHover.png.meta | 63 + .../UI/Buttons/MiniBotMidOn.png | Bin 0 -> 227 bytes .../UI/Buttons/MiniBotMidOn.png.meta | 63 + .../UI/Buttons/MiniBotMidOnHover.png | Bin 0 -> 222 bytes .../UI/Buttons/MiniBotMidOnHover.png.meta | 63 + .../UI/Buttons/MiniBotRightOff.png | Bin 0 -> 269 bytes .../UI/Buttons/MiniBotRightOff.png.meta | 63 + .../UI/Buttons/MiniBotRightOffHover.png | Bin 0 -> 283 bytes .../UI/Buttons/MiniBotRightOffHover.png.meta | 63 + .../UI/Buttons/MiniBotRightOn.png | Bin 0 -> 260 bytes .../UI/Buttons/MiniBotRightOn.png.meta | 63 + .../UI/Buttons/MiniBotRightOnHover.png | Bin 0 -> 260 bytes .../UI/Buttons/MiniBotRightOnHover.png.meta | 63 + .../UI/Buttons/MinimizeWindow.png | Bin 0 -> 204 bytes .../UI/Buttons/MinimizeWindow.png.meta | 76 + .../EditorResources/UI/Buttons/New.png | Bin 0 -> 21763 bytes .../EditorResources/UI/Buttons/New.png.meta | 76 + .../EditorResources/UI/Buttons/Open.png | Bin 0 -> 22139 bytes .../EditorResources/UI/Buttons/Open.png.meta | 76 + .../UI/Buttons/OpenListedShader.png | Bin 0 -> 18999 bytes .../UI/Buttons/OpenListedShader.png.meta | 76 + .../UI/Buttons/OpenSourceCodeOFF.PNG | Bin 0 -> 29269 bytes .../UI/Buttons/OpenSourceCodeOFF.PNG.meta | 76 + .../UI/Buttons/OpenSourceCodeON.PNG | Bin 0 -> 29267 bytes .../UI/Buttons/OpenSourceCodeON.PNG.meta | 76 + .../EditorResources/UI/Buttons/Options.png | Bin 0 -> 22418 bytes .../UI/Buttons/Options.png.meta | 76 + .../UI/Buttons/RemoveFromList.png | Bin 0 -> 18698 bytes .../UI/Buttons/RemoveFromList.png.meta | 76 + .../UI/Buttons/ResetInspectorIcon.png | Bin 0 -> 267 bytes .../UI/Buttons/ResetInspectorIcon.png.meta | 76 + .../EditorResources/UI/Buttons/SaveOFF.png | Bin 0 -> 21808 bytes .../UI/Buttons/SaveOFF.png.meta | 76 + .../EditorResources/UI/Buttons/SaveON.png | Bin 0 -> 21907 bytes .../UI/Buttons/SaveON.png.meta | 76 + .../UI/Buttons/SelectionAsTemplate.png | Bin 0 -> 19030 bytes .../UI/Buttons/SelectionAsTemplate.png.meta | 76 + .../UI/Buttons/ShaderSelectOFF.png | Bin 0 -> 25602 bytes .../UI/Buttons/ShaderSelectOFF.png.meta | 76 + .../UI/Buttons/ShaderSelectON.png | Bin 0 -> 25380 bytes .../UI/Buttons/ShaderSelectON.png.meta | 76 + .../EditorResources/UI/Buttons/ShareOFF.png | Bin 0 -> 17818 bytes .../UI/Buttons/ShareOFF.png.meta | 76 + .../UI/Buttons/SliderHoriz.png | Bin 0 -> 232 bytes .../UI/Buttons/SliderHoriz.png.meta | 76 + .../UI/Buttons/TakeScreenshotOFF.png | Bin 0 -> 18141 bytes .../UI/Buttons/TakeScreenshotOFF.png.meta | 76 + .../UI/Buttons/TransparentPixel.png | Bin 0 -> 68 bytes .../UI/Buttons/TransparentPixel.png.meta | 58 + .../EditorResources/UI/Buttons/UpdateOFF.png | Bin 0 -> 23051 bytes .../UI/Buttons/UpdateOFF.png.meta | 76 + .../UI/Buttons/UpdateOutdated.png | Bin 0 -> 23131 bytes .../UI/Buttons/UpdateOutdated.png.meta | 76 + .../UI/Buttons/UpdateUpToDated.png | Bin 0 -> 23084 bytes .../UI/Buttons/UpdateUpToDated.png.meta | 76 + .../Plugins/EditorResources/UI/Canvas.meta | 9 + .../UI/Canvas/CircleBackground.png | Bin 0 -> 15526 bytes .../UI/Canvas/CircleBackground.png.meta | 76 + .../EditorResources/UI/Canvas/Grid128.png | Bin 0 -> 26802 bytes .../UI/Canvas/Grid128.png.meta | 76 + .../EditorResources/UI/Canvas/LineTex 2.png | Bin 0 -> 198 bytes .../UI/Canvas/LineTex 2.png.meta | 84 + .../EditorResources/UI/Canvas/LineTex 3.png | Bin 0 -> 199 bytes .../UI/Canvas/LineTex 3.png.meta | 84 + .../EditorResources/UI/Canvas/LineTex 4.png | Bin 0 -> 214 bytes .../UI/Canvas/LineTex 4.png.meta | 84 + .../EditorResources/UI/Canvas/LineTex.png | Bin 0 -> 470 bytes .../UI/Canvas/LineTex.png.meta | 84 + .../UI/Canvas/MainCanvasTitleBg.png | Bin 0 -> 201 bytes .../UI/Canvas/MainCanvasTitleBg.png.meta | 96 + .../EditorResources/UI/Canvas/Material.png | Bin 0 -> 197 bytes .../UI/Canvas/Material.png.meta | 96 + .../UI/Canvas/MaterialModeIcon.PNG | Bin 0 -> 23223 bytes .../UI/Canvas/MaterialModeIcon.PNG.meta | 76 + .../UI/Canvas/MaterialModeIconOFF.png | Bin 0 -> 23047 bytes .../UI/Canvas/MaterialModeIconOFF.png.meta | 76 + .../UI/Canvas/SelectionBox.png | Bin 0 -> 15302 bytes .../UI/Canvas/SelectionBox.png.meta | 96 + .../EditorResources/UI/Canvas/Shader.png | Bin 0 -> 197 bytes .../EditorResources/UI/Canvas/Shader.png.meta | 96 + .../UI/Canvas/ShaderFunction.png | Bin 0 -> 194 bytes .../UI/Canvas/ShaderFunction.png.meta | 96 + .../UI/Canvas/ShaderFunctionIcon.png | Bin 0 -> 4615 bytes .../UI/Canvas/ShaderFunctionIcon.png.meta | 96 + .../UI/Canvas/ShaderFunctionModeIcon.png | Bin 0 -> 4051 bytes .../UI/Canvas/ShaderFunctionModeIcon.png.meta | 96 + .../UI/Canvas/ShaderFunctionModeIconOFF.png | Bin 0 -> 3614 bytes .../Canvas/ShaderFunctionModeIconOFF.png.meta | 76 + .../UI/Canvas/ShaderModeIcon.PNG | Bin 0 -> 25967 bytes .../UI/Canvas/ShaderModeIcon.PNG.meta | 76 + .../UI/Canvas/ShaderModeIconOFF.png | Bin 0 -> 25875 bytes .../UI/Canvas/ShaderModeIconOFF.png.meta | 76 + .../UI/Canvas/ShaderModeMatIcon.png | Bin 0 -> 927 bytes .../UI/Canvas/ShaderModeMatIcon.png.meta | 76 + .../UI/Canvas/TransparentOverlay.png | Bin 0 -> 180454 bytes .../UI/Canvas/TransparentOverlay.png.meta | 96 + .../Plugins/EditorResources/UI/Nodes.meta | 9 + .../UI/Nodes/BlueNormalBase.png | Bin 0 -> 438 bytes .../UI/Nodes/BlueNormalBase.png.meta | 76 + .../UI/Nodes/BlueNormalBaseLeft.png | Bin 0 -> 283 bytes .../UI/Nodes/BlueNormalBaseLeft.png.meta | 76 + .../UI/Nodes/BlueNormalBaseSquare.png | Bin 0 -> 350 bytes .../UI/Nodes/BlueNormalBaseSquare.png.meta | 76 + .../UI/Nodes/BlueNormalHeader.png | Bin 0 -> 5052 bytes .../UI/Nodes/BlueNormalHeader.png.meta | 76 + .../UI/Nodes/ButtonBackground.png | Bin 0 -> 338 bytes .../UI/Nodes/ButtonBackground.png.meta | 76 + .../UI/Nodes/CommentNodeBase.png | Bin 0 -> 870 bytes .../UI/Nodes/CommentNodeBase.png.meta | 96 + .../UI/Nodes/CommentaryResizeIcon.png | Bin 0 -> 18758 bytes .../UI/Nodes/CommentaryResizeIcon.png.meta | 76 + .../UI/Nodes/CommentaryResizeIconInv.png | Bin 0 -> 15089 bytes .../UI/Nodes/CommentaryResizeIconInv.png.meta | 76 + .../UI/Nodes/FlatBackground.png | Bin 0 -> 158 bytes .../UI/Nodes/FlatBackground.png.meta | 76 + .../EditorResources/UI/Nodes/GraphButton.png | Bin 0 -> 383 bytes .../UI/Nodes/GraphButton.png.meta | 76 + .../UI/Nodes/GraphButtonActive.png | Bin 0 -> 381 bytes .../UI/Nodes/GraphButtonActive.png.meta | 76 + .../EditorResources/UI/Nodes/GraphPopup.png | Bin 0 -> 375 bytes .../UI/Nodes/GraphPopup.png.meta | 76 + .../UI/Nodes/GrayNormalHeader.png | Bin 0 -> 5427 bytes .../UI/Nodes/GrayNormalHeader.png.meta | 76 + .../UI/Nodes/GrayNormalHeaderSquare.png | Bin 0 -> 5263 bytes .../UI/Nodes/GrayNormalHeaderSquare.png.meta | 76 + .../EditorResources/UI/Nodes/NoPreview.png | Bin 0 -> 386 bytes .../UI/Nodes/NoPreview.png.meta | 76 + .../EditorResources/UI/Nodes/NodeSelected.png | Bin 0 -> 549 bytes .../UI/Nodes/NodeSelected.png.meta | 76 + .../UI/Nodes/NodeSelectedSquare.png | Bin 0 -> 428 bytes .../UI/Nodes/NodeSelectedSquare.png.meta | 76 + .../Nodes/ObjectPickerBackgroundOutline.png | Bin 0 -> 206 bytes .../ObjectPickerBackgroundOutline.png.meta | 76 + .../EditorResources/UI/Nodes/PopupPicker.png | Bin 0 -> 231 bytes .../UI/Nodes/PopupPicker.png.meta | 76 + .../EditorResources/UI/Nodes/PreviewOff.png | Bin 0 -> 243 bytes .../UI/Nodes/PreviewOff.png.meta | 76 + .../EditorResources/UI/Nodes/PreviewOn.png | Bin 0 -> 229 bytes .../UI/Nodes/PreviewOn.png.meta | 76 + .../UI/Nodes/PropertyPicker.png | Bin 0 -> 180 bytes .../UI/Nodes/PropertyPicker.png.meta | 76 + .../EditorResources/UI/Nodes/SliderButton.png | Bin 0 -> 406 bytes .../UI/Nodes/SliderButton.png.meta | 58 + .../UI/Nodes/WhitePortOutline.png | Bin 0 -> 19719 bytes .../UI/Nodes/WhitePortOutline.png.meta | 84 + .../UI/Nodes/WhitePortSolid.png | Bin 0 -> 19671 bytes .../UI/Nodes/WhitePortSolid.png.meta | 84 + .../UI/Nodes/WireNodeSelection.png | Bin 0 -> 933 bytes .../UI/Nodes/WireNodeSelection.png.meta | 58 + Assets/AmplifyShaderEditor/Readme.txt | 90 + Assets/AmplifyShaderEditor/Readme.txt.meta | 8 + Assets/Plugins.meta | 8 + Assets/Plugins/Demigiant.meta | 8 + Assets/Plugins/Demigiant/DOTween.meta | 21 + Assets/Plugins/Demigiant/DOTween/DOTween.XML | 2963 +++++ .../Demigiant/DOTween/DOTween.XML.meta | 4 + Assets/Plugins/Demigiant/DOTween/DOTween.dll | Bin 0 -> 172032 bytes .../Plugins/Demigiant/DOTween/DOTween.dll.mdb | Bin 0 -> 66532 bytes .../Demigiant/DOTween/DOTween.dll.mdb.meta | 4 + .../Demigiant/DOTween/DOTween.dll.meta | 22 + Assets/Plugins/Demigiant/DOTween/Editor.meta | 5 + .../DOTween/Editor/DOTweenEditor.XML | 110 + .../DOTween/Editor/DOTweenEditor.XML.meta | 4 + .../DOTween/Editor/DOTweenEditor.dll | Bin 0 -> 66048 bytes .../DOTween/Editor/DOTweenEditor.dll.mdb | Bin 0 -> 11774 bytes .../DOTween/Editor/DOTweenEditor.dll.mdb.meta | 4 + .../DOTween/Editor/DOTweenEditor.dll.meta | 22 + .../Demigiant/DOTween/Editor/Imgs.meta | 5 + .../DOTween/Editor/Imgs/DOTweenIcon.png | Bin 0 -> 1565 bytes .../DOTween/Editor/Imgs/DOTweenIcon.png.meta | 47 + .../DOTween/Editor/Imgs/DOTweenMiniIcon.png | Bin 0 -> 319 bytes .../Editor/Imgs/DOTweenMiniIcon.png.meta | 68 + .../Demigiant/DOTween/Editor/Imgs/Footer.png | Bin 0 -> 4409 bytes .../DOTween/Editor/Imgs/Footer.png.meta | 47 + .../DOTween/Editor/Imgs/Footer_dark.png | Bin 0 -> 4429 bytes .../DOTween/Editor/Imgs/Footer_dark.png.meta | 47 + .../Demigiant/DOTween/Editor/Imgs/Header.jpg | Bin 0 -> 22787 bytes .../DOTween/Editor/Imgs/Header.jpg.meta | 47 + Assets/Plugins/Demigiant/DOTween/Modules.meta | 5 + .../DOTween/Modules/DOTweenModuleAudio.cs | 202 + .../Modules/DOTweenModuleAudio.cs.meta | 8 + .../Modules/DOTweenModuleEPOOutline.cs | 142 + .../Modules/DOTweenModuleEPOOutline.cs.meta | 12 + .../DOTween/Modules/DOTweenModulePhysics.cs | 216 + .../Modules/DOTweenModulePhysics.cs.meta | 8 + .../DOTween/Modules/DOTweenModulePhysics2D.cs | 193 + .../Modules/DOTweenModulePhysics2D.cs.meta | 8 + .../DOTween/Modules/DOTweenModuleSprite.cs | 93 + .../Modules/DOTweenModuleSprite.cs.meta | 8 + .../DOTween/Modules/DOTweenModuleUI.cs | 660 + .../DOTween/Modules/DOTweenModuleUI.cs.meta | 8 + .../Modules/DOTweenModuleUnityVersion.cs | 403 + .../Modules/DOTweenModuleUnityVersion.cs.meta | 8 + .../DOTween/Modules/DOTweenModuleUtils.cs | 167 + .../Modules/DOTweenModuleUtils.cs.meta | 8 + Assets/Plugins/Demigiant/DOTween/readme.txt | 29 + .../Plugins/Demigiant/DOTween/readme.txt.meta | 4 + .../Demigiant/DOTweenPro Examples.meta | 23 + .../DOTweenAnimation_Advanced.unity | 5311 ++++++++ .../DOTweenAnimation_Advanced.unity.meta | 4 + ...DOTweenAnimation_AdvancedSettings.lighting | 64 + ...enAnimation_AdvancedSettings.lighting.meta | 8 + .../DOTweenAnimation_Basics.unity | 1801 +++ .../DOTweenAnimation_Basics.unity.meta | 4 + .../DOTweenAnimation_BasicsSettings.lighting | 64 + ...weenAnimation_BasicsSettings.lighting.meta | 8 + .../DOTweenPro Examples/DOTweenPath.unity | 1594 +++ .../DOTweenPath.unity.meta | 4 + .../DOTweenPathSettings.lighting | 64 + .../DOTweenPathSettings.lighting.meta | 8 + .../DOTweenPro Examples/Examples Assets.meta | 5 + .../Examples Assets/dotweenpro_logo.png | Bin 0 -> 17098 bytes .../Examples Assets/dotweenpro_logo.png.meta | 98 + Assets/Plugins/Demigiant/DOTweenPro.meta | 23 + .../Demigiant/DOTweenPro/DOTweenAnimation.cs | 884 ++ .../DOTweenPro/DOTweenAnimation.cs.meta | 8 + .../Demigiant/DOTweenPro/DOTweenDeAudio.cs | 9 + .../DOTweenPro/DOTweenDeAudio.cs.meta | 12 + .../DOTweenPro/DOTweenDeUnityExtended.cs | 9 + .../DOTweenPro/DOTweenDeUnityExtended.cs.meta | 12 + .../Demigiant/DOTweenPro/DOTweenPro.XML | 67 + .../Demigiant/DOTweenPro/DOTweenPro.XML.meta | 4 + .../Demigiant/DOTweenPro/DOTweenPro.dll | Bin 0 -> 15872 bytes .../Demigiant/DOTweenPro/DOTweenPro.dll.mdb | Bin 0 -> 2910 bytes .../DOTweenPro/DOTweenPro.dll.mdb.meta | 4 + .../Demigiant/DOTweenPro/DOTweenPro.dll.meta | 22 + .../DOTweenPro/DOTweenProShortcuts.cs | 90 + .../DOTweenPro/DOTweenProShortcuts.cs.meta | 8 + .../DOTweenPro/DOTweenTextMeshPro.cs | 1037 ++ .../DOTweenPro/DOTweenTextMeshPro.cs.meta | 8 + .../Demigiant/DOTweenPro/DOTweenTk2d.cs | 247 + .../Demigiant/DOTweenPro/DOTweenTk2d.cs.meta | 8 + .../Plugins/Demigiant/DOTweenPro/Editor.meta | 5 + .../Editor/DOTweenAnimationInspector.cs | 750 ++ .../Editor/DOTweenAnimationInspector.cs.meta | 8 + .../Editor/DOTweenPreviewManager.cs | 263 + .../Editor/DOTweenPreviewManager.cs.meta | 8 + .../DOTweenPro/Editor/DOTweenProEditor.XML | 18 + .../Editor/DOTweenProEditor.XML.meta | 4 + .../DOTweenPro/Editor/DOTweenProEditor.dll | Bin 0 -> 35840 bytes .../Editor/DOTweenProEditor.dll.mdb | Bin 0 -> 5678 bytes .../Editor/DOTweenProEditor.dll.mdb.meta | 4 + .../Editor/DOTweenProEditor.dll.meta | 22 + .../Plugins/Demigiant/DOTweenPro/readme.txt | 35 + .../Demigiant/DOTweenPro/readme.txt.meta | 4 + Assets/Plugins/Demigiant/DemiLib.meta | 21 + Assets/Plugins/Demigiant/DemiLib/Core.meta | 5 + .../Demigiant/DemiLib/Core/DemiLib.dll | Bin 0 -> 13312 bytes .../Demigiant/DemiLib/Core/DemiLib.dll.mdb | Bin 0 -> 3576 bytes .../DemiLib/Core/DemiLib.dll.mdb.meta | 4 + .../Demigiant/DemiLib/Core/DemiLib.dll.meta | 22 + .../Demigiant/DemiLib/Core/DemiLib.xml | 205 + .../Demigiant/DemiLib/Core/DemiLib.xml.meta | 4 + .../Demigiant/DemiLib/Core/Editor.meta | 5 + .../DemiLib/Core/Editor/DemiEditor.dll | Bin 0 -> 187392 bytes .../DemiLib/Core/Editor/DemiEditor.dll.mdb | Bin 0 -> 63264 bytes .../Core/Editor/DemiEditor.dll.mdb.meta | 4 + .../DemiLib/Core/Editor/DemiEditor.dll.meta | 22 + .../DemiLib/Core/Editor/DemiEditor.xml | 2290 ++++ .../DemiLib/Core/Editor/DemiEditor.xml.meta | 4 + .../Demigiant/DemiLib/Core/Editor/Imgs.meta | 5 + .../DemiLib/Core/Editor/Imgs/blackSquare.png | Bin 0 -> 109 bytes .../Core/Editor/Imgs/blackSquare.png.meta | 47 + .../Core/Editor/Imgs/blackSquareAlpha10.png | Bin 0 -> 109 bytes .../Editor/Imgs/blackSquareAlpha10.png.meta | 47 + .../Core/Editor/Imgs/blackSquareAlpha15.png | Bin 0 -> 109 bytes .../Editor/Imgs/blackSquareAlpha15.png.meta | 47 + .../Core/Editor/Imgs/blackSquareAlpha25.png | Bin 0 -> 109 bytes .../Editor/Imgs/blackSquareAlpha25.png.meta | 47 + .../Core/Editor/Imgs/blackSquareAlpha50.png | Bin 0 -> 109 bytes .../Editor/Imgs/blackSquareAlpha50.png.meta | 47 + .../Core/Editor/Imgs/blackSquareAlpha80.png | Bin 0 -> 109 bytes .../Editor/Imgs/blackSquareAlpha80.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/blueSquare.png | Bin 0 -> 106 bytes .../Core/Editor/Imgs/blueSquare.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/circle.png | Bin 0 -> 455 bytes .../DemiLib/Core/Editor/Imgs/circle.png.meta | 47 + .../Editor/Imgs/circle_dashedBorderEmpty.png | Bin 0 -> 673 bytes .../Imgs/circle_dashedBorderEmpty.png.meta | 68 + .../DemiLib/Core/Editor/Imgs/greenSquare.png | Bin 0 -> 106 bytes .../Core/Editor/Imgs/greenSquare.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/grid_bright.png | Bin 0 -> 222 bytes .../Core/Editor/Imgs/grid_bright.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/grid_dark.png | Bin 0 -> 216 bytes .../Core/Editor/Imgs/grid_dark.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alert.png | Bin 0 -> 540 bytes .../Core/Editor/Imgs/ico_alert.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignB.png | Bin 0 -> 131 bytes .../Core/Editor/Imgs/ico_alignB.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignBC.png | Bin 0 -> 158 bytes .../Core/Editor/Imgs/ico_alignBC.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignBL.png | Bin 0 -> 152 bytes .../Core/Editor/Imgs/ico_alignBL.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignBR.png | Bin 0 -> 150 bytes .../Core/Editor/Imgs/ico_alignBR.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignCC.png | Bin 0 -> 152 bytes .../Core/Editor/Imgs/ico_alignCC.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignCL.png | Bin 0 -> 158 bytes .../Core/Editor/Imgs/ico_alignCL.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignCR.png | Bin 0 -> 153 bytes .../Core/Editor/Imgs/ico_alignCR.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignHC.png | Bin 0 -> 147 bytes .../Core/Editor/Imgs/ico_alignHC.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignL.png | Bin 0 -> 136 bytes .../Core/Editor/Imgs/ico_alignL.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignR.png | Bin 0 -> 145 bytes .../Core/Editor/Imgs/ico_alignR.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignT.png | Bin 0 -> 129 bytes .../Core/Editor/Imgs/ico_alignT.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignTC.png | Bin 0 -> 164 bytes .../Core/Editor/Imgs/ico_alignTC.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignTL.png | Bin 0 -> 153 bytes .../Core/Editor/Imgs/ico_alignTL.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignTR.png | Bin 0 -> 155 bytes .../Core/Editor/Imgs/ico_alignTR.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_alignVC.png | Bin 0 -> 135 bytes .../Core/Editor/Imgs/ico_alignVC.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_camera.png | Bin 0 -> 206 bytes .../Core/Editor/Imgs/ico_camera.png.meta | 47 + .../Core/Editor/Imgs/ico_camera_border.png | Bin 0 -> 347 bytes .../Editor/Imgs/ico_camera_border.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_cog.png | Bin 0 -> 197 bytes .../DemiLib/Core/Editor/Imgs/ico_cog.png.meta | 47 + .../Core/Editor/Imgs/ico_cog_border.png | Bin 0 -> 376 bytes .../Core/Editor/Imgs/ico_cog_border.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_comment.png | Bin 0 -> 176 bytes .../Core/Editor/Imgs/ico_comment.png.meta | 47 + .../Core/Editor/Imgs/ico_comment_border.png | Bin 0 -> 426 bytes .../Editor/Imgs/ico_comment_border.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_delete.png | Bin 0 -> 145 bytes .../Core/Editor/Imgs/ico_delete.png.meta | 47 + .../Core/Editor/Imgs/ico_demigiant.png | Bin 0 -> 605 bytes .../Core/Editor/Imgs/ico_demigiant.png.meta | 47 + .../Editor/Imgs/ico_distributeHAlignT.png | Bin 0 -> 174 bytes .../Imgs/ico_distributeHAlignT.png.meta | 47 + .../Editor/Imgs/ico_distributeVAlignL.png | Bin 0 -> 197 bytes .../Imgs/ico_distributeVAlignL.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_end.png | Bin 0 -> 475 bytes .../DemiLib/Core/Editor/Imgs/ico_end.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_flipV.png | Bin 0 -> 167 bytes .../Core/Editor/Imgs/ico_flipV.png.meta | 47 + .../Core/Editor/Imgs/ico_foldout_closed.png | Bin 0 -> 158 bytes .../Editor/Imgs/ico_foldout_closed.png.meta | 47 + .../Core/Editor/Imgs/ico_foldout_open.png | Bin 0 -> 170 bytes .../Editor/Imgs/ico_foldout_open.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_heart.png | Bin 0 -> 210 bytes .../Core/Editor/Imgs/ico_heart.png.meta | 47 + .../Core/Editor/Imgs/ico_heart_border.png | Bin 0 -> 307 bytes .../Editor/Imgs/ico_heart_border.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_light.png | Bin 0 -> 190 bytes .../Core/Editor/Imgs/ico_light.png.meta | 47 + .../Core/Editor/Imgs/ico_light_border.png | Bin 0 -> 292 bytes .../Editor/Imgs/ico_light_border.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_lock.png | Bin 0 -> 300 bytes .../Core/Editor/Imgs/ico_lock.png.meta | 47 + .../Core/Editor/Imgs/ico_lock_open.png | Bin 0 -> 293 bytes .../Core/Editor/Imgs/ico_lock_open.png.meta | 47 + .../Core/Editor/Imgs/ico_nodeArrow.png | Bin 0 -> 168 bytes .../Core/Editor/Imgs/ico_nodeArrow.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_ok.png | Bin 0 -> 715 bytes .../DemiLib/Core/Editor/Imgs/ico_ok.png.meta | 47 + .../Core/Editor/Imgs/ico_optionsDropdown.png | Bin 0 -> 135 bytes .../Editor/Imgs/ico_optionsDropdown.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_play.png | Bin 0 -> 256 bytes .../Core/Editor/Imgs/ico_play.png.meta | 47 + .../Core/Editor/Imgs/ico_play_border.png | Bin 0 -> 386 bytes .../Core/Editor/Imgs/ico_play_border.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_skull.png | Bin 0 -> 227 bytes .../Core/Editor/Imgs/ico_skull.png.meta | 47 + .../Core/Editor/Imgs/ico_skull_border.png | Bin 0 -> 332 bytes .../Editor/Imgs/ico_skull_border.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_star.png | Bin 0 -> 203 bytes .../Core/Editor/Imgs/ico_star.png.meta | 47 + .../Core/Editor/Imgs/ico_star_border.png | Bin 0 -> 323 bytes .../Core/Editor/Imgs/ico_star_border.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/ico_ui.png | Bin 0 -> 223 bytes .../DemiLib/Core/Editor/Imgs/ico_ui.png.meta | 47 + .../Core/Editor/Imgs/ico_ui_border.png | Bin 0 -> 259 bytes .../Core/Editor/Imgs/ico_ui_border.png.meta | 47 + .../Core/Editor/Imgs/ico_visibility.png | Bin 0 -> 298 bytes .../Core/Editor/Imgs/ico_visibility.png.meta | 47 + .../Core/Editor/Imgs/ico_visibility_off.png | Bin 0 -> 367 bytes .../Editor/Imgs/ico_visibility_off.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/orangeSquare.png | Bin 0 -> 104 bytes .../Core/Editor/Imgs/orangeSquare.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/project.meta | 5 + .../Core/Editor/Imgs/project/ico_atlas.png | Bin 0 -> 218 bytes .../Editor/Imgs/project/ico_atlas.png.meta | 47 + .../Core/Editor/Imgs/project/ico_audio.png | Bin 0 -> 338 bytes .../Editor/Imgs/project/ico_audio.png.meta | 47 + .../Core/Editor/Imgs/project/ico_bundle.png | Bin 0 -> 522 bytes .../Editor/Imgs/project/ico_bundle.png.meta | 47 + .../Core/Editor/Imgs/project/ico_cog.png | Bin 0 -> 406 bytes .../Core/Editor/Imgs/project/ico_cog.png.meta | 47 + .../Core/Editor/Imgs/project/ico_cross.png | Bin 0 -> 210 bytes .../Editor/Imgs/project/ico_cross.png.meta | 47 + .../Editor/Imgs/project/ico_demigiant.png | Bin 0 -> 388 bytes .../Imgs/project/ico_demigiant.png.meta | 47 + .../Core/Editor/Imgs/project/ico_folder.png | Bin 0 -> 150 bytes .../Editor/Imgs/project/ico_folder.png.meta | 47 + .../Core/Editor/Imgs/project/ico_fonts.png | Bin 0 -> 465 bytes .../Editor/Imgs/project/ico_fonts.png.meta | 47 + .../Core/Editor/Imgs/project/ico_heart.png | Bin 0 -> 334 bytes .../Editor/Imgs/project/ico_heart.png.meta | 47 + .../Editor/Imgs/project/ico_materials.png | Bin 0 -> 355 bytes .../Imgs/project/ico_materials.png.meta | 47 + .../Core/Editor/Imgs/project/ico_models.png | Bin 0 -> 380 bytes .../Editor/Imgs/project/ico_models.png.meta | 47 + .../Editor/Imgs/project/ico_particles.png | Bin 0 -> 493 bytes .../Imgs/project/ico_particles.png.meta | 47 + .../Core/Editor/Imgs/project/ico_play.png | Bin 0 -> 217 bytes .../Editor/Imgs/project/ico_play.png.meta | 47 + .../Core/Editor/Imgs/project/ico_prefab.png | Bin 0 -> 343 bytes .../Editor/Imgs/project/ico_prefab.png.meta | 47 + .../Core/Editor/Imgs/project/ico_scripts.png | Bin 0 -> 208 bytes .../Editor/Imgs/project/ico_scripts.png.meta | 47 + .../Core/Editor/Imgs/project/ico_shaders.png | Bin 0 -> 379 bytes .../Editor/Imgs/project/ico_shaders.png.meta | 47 + .../Core/Editor/Imgs/project/ico_skull.png | Bin 0 -> 368 bytes .../Editor/Imgs/project/ico_skull.png.meta | 47 + .../Core/Editor/Imgs/project/ico_star.png | Bin 0 -> 289 bytes .../Editor/Imgs/project/ico_star.png.meta | 47 + .../Core/Editor/Imgs/project/ico_terrains.png | Bin 0 -> 309 bytes .../Editor/Imgs/project/ico_terrains.png.meta | 47 + .../Core/Editor/Imgs/project/ico_textures.png | Bin 0 -> 278 bytes .../Editor/Imgs/project/ico_textures.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/purpleSquare.png | Bin 0 -> 106 bytes .../Core/Editor/Imgs/purpleSquare.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/redSquare.png | Bin 0 -> 106 bytes .../Core/Editor/Imgs/redSquare.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/squareBorder.png | Bin 0 -> 122 bytes .../Core/Editor/Imgs/squareBorder.png.meta | 47 + .../Core/Editor/Imgs/squareBorderAlpha15.png | Bin 0 -> 116 bytes .../Editor/Imgs/squareBorderAlpha15.png.meta | 47 + .../Core/Editor/Imgs/squareBorderCurved.png | Bin 0 -> 196 bytes .../Editor/Imgs/squareBorderCurved.png.meta | 47 + .../Core/Editor/Imgs/squareBorderCurved02.png | Bin 0 -> 281 bytes .../Editor/Imgs/squareBorderCurved02.png.meta | 47 + .../Imgs/squareBorderCurved02_darkBorders.png | Bin 0 -> 336 bytes .../squareBorderCurved02_darkBorders.png.meta | 47 + .../Editor/Imgs/squareBorderCurvedAlpha.png | Bin 0 -> 197 bytes .../Imgs/squareBorderCurvedAlpha.png.meta | 47 + .../Editor/Imgs/squareBorderCurvedEmpty.png | Bin 0 -> 180 bytes .../Imgs/squareBorderCurvedEmpty.png.meta | 47 + .../Editor/Imgs/squareBorderCurvedEmpty02.png | Bin 0 -> 217 bytes .../Imgs/squareBorderCurvedEmpty02.png.meta | 47 + .../Imgs/squareBorderCurvedEmptyThick.png | Bin 0 -> 233 bytes .../squareBorderCurvedEmptyThick.png.meta | 47 + .../Imgs/squareBorderCurved_darkBorders.png | Bin 0 -> 216 bytes .../squareBorderCurved_darkBorders.png.meta | 47 + .../squareBorderCurved_darkBordersAlpha.png | Bin 0 -> 200 bytes ...uareBorderCurved_darkBordersAlpha.png.meta | 47 + .../Core/Editor/Imgs/squareBorderEmpty.png | Bin 0 -> 114 bytes .../Editor/Imgs/squareBorderEmpty.png.meta | 47 + .../Core/Editor/Imgs/squareBorderEmpty01.png | Bin 0 -> 114 bytes .../Editor/Imgs/squareBorderEmpty01.png.meta | 47 + .../Core/Editor/Imgs/squareBorderEmpty02.png | Bin 0 -> 121 bytes .../Editor/Imgs/squareBorderEmpty02.png.meta | 47 + .../Core/Editor/Imgs/squareBorderEmpty03.png | Bin 0 -> 122 bytes .../Editor/Imgs/squareBorderEmpty03.png.meta | 47 + .../Editor/Imgs/squareBorderThickEmpty.png | Bin 0 -> 121 bytes .../Imgs/squareBorderThickEmpty.png.meta | 47 + .../Editor/Imgs/squareBorderThickerEmpty.png | Bin 0 -> 122 bytes .../Imgs/squareBorderThickerEmpty.png.meta | 47 + .../Core/Editor/Imgs/squareCorners03.png | Bin 0 -> 133 bytes .../Core/Editor/Imgs/squareCorners03.png.meta | 47 + .../Core/Editor/Imgs/squareCornersEmpty02.png | Bin 0 -> 131 bytes .../Editor/Imgs/squareCornersEmpty02.png.meta | 47 + .../Core/Editor/Imgs/tileBars_empty.png | Bin 0 -> 236 bytes .../Core/Editor/Imgs/tileBars_empty.png.meta | 47 + .../Core/Editor/Imgs/tileBars_slanted.png | Bin 0 -> 285 bytes .../Editor/Imgs/tileBars_slanted.png.meta | 47 + .../Editor/Imgs/tileBars_slanted_alpha.png | Bin 0 -> 266 bytes .../Imgs/tileBars_slanted_alpha.png.meta | 47 + .../Core/Editor/Imgs/transparentSquare.png | Bin 0 -> 97 bytes .../Editor/Imgs/transparentSquare.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/whiteDot.png | Bin 0 -> 148 bytes .../Core/Editor/Imgs/whiteDot.png.meta | 47 + .../Core/Editor/Imgs/whiteDot_darkBorder.png | Bin 0 -> 219 bytes .../Editor/Imgs/whiteDot_darkBorder.png.meta | 47 + .../Editor/Imgs/whiteDot_whiteBorderAlpha.png | Bin 0 -> 176 bytes .../Imgs/whiteDot_whiteBorderAlpha.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/whiteSquare.png | Bin 0 -> 103 bytes .../Core/Editor/Imgs/whiteSquare.png.meta | 47 + .../Core/Editor/Imgs/whiteSquareAlpha10.png | Bin 0 -> 107 bytes .../Editor/Imgs/whiteSquareAlpha10.png.meta | 47 + .../Core/Editor/Imgs/whiteSquareAlpha15.png | Bin 0 -> 109 bytes .../Editor/Imgs/whiteSquareAlpha15.png.meta | 47 + .../Core/Editor/Imgs/whiteSquareAlpha25.png | Bin 0 -> 107 bytes .../Editor/Imgs/whiteSquareAlpha25.png.meta | 47 + .../Core/Editor/Imgs/whiteSquareAlpha50.png | Bin 0 -> 107 bytes .../Editor/Imgs/whiteSquareAlpha50.png.meta | 47 + .../Core/Editor/Imgs/whiteSquareAlpha80.png | Bin 0 -> 110 bytes .../Editor/Imgs/whiteSquareAlpha80.png.meta | 47 + .../Core/Editor/Imgs/whiteSquareCurved.png | Bin 0 -> 144 bytes .../Editor/Imgs/whiteSquareCurved.png.meta | 68 + .../Core/Editor/Imgs/whiteSquareCurved02.png | Bin 0 -> 190 bytes .../Editor/Imgs/whiteSquareCurved02.png.meta | 68 + .../Editor/Imgs/whiteSquare_fadeOut_bt.png | Bin 0 -> 131 bytes .../Imgs/whiteSquare_fadeOut_bt.png.meta | 47 + .../DemiLib/Core/Editor/Imgs/yellowSquare.png | Bin 0 -> 106 bytes .../Core/Editor/Imgs/yellowSquare.png.meta | 47 + .../Plugins/Demigiant/readme_DOTweenPro.txt | 35 + .../Demigiant/readme_DOTweenPro.txt.meta | 19 + Assets/Plugins/Sirenix.meta | 8 + Assets/Plugins/Sirenix/Assemblies.meta | 8 + .../Plugins/Sirenix/Assemblies/NoEditor.meta | 8 + .../NoEditor/Sirenix.Serialization.dll | Bin 0 -> 324608 bytes .../NoEditor/Sirenix.Serialization.dll.mdb | Bin 0 -> 122915 bytes .../Sirenix.Serialization.dll.mdb.meta | 8 + .../NoEditor/Sirenix.Serialization.dll.meta | 80 + .../Assemblies/NoEditor/Sirenix.Utilities.dll | Bin 0 -> 144896 bytes .../NoEditor/Sirenix.Utilities.dll.mdb | Bin 0 -> 46903 bytes .../NoEditor/Sirenix.Utilities.dll.mdb.meta | 8 + .../NoEditor/Sirenix.Utilities.dll.meta | 80 + .../Sirenix/Assemblies/NoEmitAndNoEditor.meta | 8 + .../Sirenix.Serialization.dll | Bin 0 -> 314880 bytes .../Sirenix.Serialization.dll.mdb | Bin 0 -> 119893 bytes .../Sirenix.Serialization.dll.mdb.meta | 8 + .../Sirenix.Serialization.dll.meta | 77 + .../NoEmitAndNoEditor/Sirenix.Utilities.dll | Bin 0 -> 142336 bytes .../Sirenix.Utilities.dll.mdb | Bin 0 -> 45996 bytes .../Sirenix.Utilities.dll.mdb.meta | 8 + .../Sirenix.Utilities.dll.meta | 77 + .../Sirenix.OdinInspector.Attributes.dll | Bin 0 -> 38400 bytes .../Sirenix.OdinInspector.Attributes.dll.mdb | Bin 0 -> 22404 bytes ...enix.OdinInspector.Attributes.dll.mdb.meta | 8 + .../Sirenix.OdinInspector.Attributes.dll.meta | 47 + .../Sirenix.OdinInspector.Attributes.xml | 5731 ++++++++ .../Sirenix.OdinInspector.Attributes.xml.meta | 8 + .../Sirenix.OdinInspector.Editor.dll | Bin 0 -> 1506816 bytes .../Sirenix.OdinInspector.Editor.dll.mdb | Bin 0 -> 363782 bytes .../Sirenix.OdinInspector.Editor.dll.mdb.meta | 8 + .../Sirenix.OdinInspector.Editor.dll.meta | 47 + .../Sirenix.OdinInspector.Editor.xml | 10940 ++++++++++++++++ .../Sirenix.OdinInspector.Editor.xml.meta | 8 + .../Sirenix.Serialization.Config.dll | Bin 0 -> 17408 bytes .../Sirenix.Serialization.Config.dll.mdb | Bin 0 -> 1341 bytes .../Sirenix.Serialization.Config.dll.mdb.meta | 8 + .../Sirenix.Serialization.Config.dll.meta | 47 + .../Sirenix.Serialization.Config.xml | 202 + .../Sirenix.Serialization.Config.xml.meta | 8 + .../Assemblies/Sirenix.Serialization.dll | Bin 0 -> 369152 bytes .../Assemblies/Sirenix.Serialization.dll.mdb | Bin 0 -> 133720 bytes .../Sirenix.Serialization.dll.mdb.meta | 8 + .../Assemblies/Sirenix.Serialization.dll.meta | 47 + .../Assemblies/Sirenix.Serialization.xml | 9565 ++++++++++++++ .../Assemblies/Sirenix.Serialization.xml.meta | 8 + .../Assemblies/Sirenix.Utilities.Editor.dll | Bin 0 -> 542720 bytes .../Sirenix.Utilities.Editor.dll.mdb | Bin 0 -> 116027 bytes .../Sirenix.Utilities.Editor.dll.mdb.meta | 8 + .../Sirenix.Utilities.Editor.dll.meta | 47 + .../Assemblies/Sirenix.Utilities.Editor.xml | 7788 +++++++++++ .../Sirenix.Utilities.Editor.xml.meta | 8 + .../Sirenix/Assemblies/Sirenix.Utilities.dll | Bin 0 -> 154112 bytes .../Assemblies/Sirenix.Utilities.dll.mdb | Bin 0 -> 48100 bytes .../Assemblies/Sirenix.Utilities.dll.mdb.meta | 8 + .../Assemblies/Sirenix.Utilities.dll.meta | 47 + .../Sirenix/Assemblies/Sirenix.Utilities.xml | 3658 ++++++ .../Assemblies/Sirenix.Utilities.xml.meta | 8 + Assets/Plugins/Sirenix/Assemblies/link.xml | 6 + .../Plugins/Sirenix/Assemblies/link.xml.meta | 7 + Assets/Plugins/Sirenix/Demos.meta | 8 + ...tom Attribute Processors.unitypackage.meta | 8 + .../Demos/Custom Drawers.unitypackage.meta | 8 + .../Demos/Editor Windows.unitypackage.meta | 8 + .../Sample - RPG Editor.unitypackage.meta | 8 + Assets/Plugins/Sirenix/Odin Inspector.meta | 8 + .../Sirenix/Odin Inspector/Assets.meta | 8 + .../Sirenix/Odin Inspector/Assets/Editor.meta | 8 + .../Assets/Editor/ConfigData.bytes | Bin 0 -> 1616 bytes .../Assets/Editor/ConfigData.bytes.meta | 8 + .../Assets/Editor/Odin Inspector Logo.png | Bin 0 -> 23267 bytes .../Editor/Odin Inspector Logo.png.meta | 57 + .../Assets/Editor/OdinPathLookup.asset | 13 + .../Assets/Editor/OdinPathLookup.asset.meta | 8 + .../Sirenix/Odin Inspector/Config.meta | 8 + .../Sirenix/Odin Inspector/Config/Editor.meta | 8 + .../Config/Editor/GeneralDrawerConfig.asset | 14 + .../Editor/GeneralDrawerConfig.asset.meta | 8 + .../Config/Editor/InspectorConfig.asset | 19 + .../Config/Editor/InspectorConfig.asset.meta | 8 + .../Config/Editor/OdinModuleConfig.asset | 19 + .../Config/Editor/OdinModuleConfig.asset.meta | 8 + .../Sirenix/Odin Inspector/Modules.meta | 8 + .../Modules/Unity.Entities.data | Bin 0 -> 41801 bytes .../Modules/Unity.Entities.data.meta | 8 + .../Modules/Unity.Mathematics.data | Bin 0 -> 46862 bytes .../Modules/Unity.Mathematics.data.meta | 8 + .../Modules/Unity.Mathematics.meta | 8 + .../Unity.Mathematics/MathematicsDrawers.cs | 883 ++ .../MathematicsDrawers.cs.meta | 11 + ...nInspector.Modules.UnityMathematics.asmdef | 11 + ...ector.Modules.UnityMathematics.asmdef.meta | 7 + .../Modules/Unity.Mathematics/manifest.txt | 8 + .../Unity.Mathematics/manifest.txt.meta | 7 + .../Sirenix/Odin Inspector/Scripts.meta | 8 + .../Odin Inspector/Scripts/Editor.meta | 8 + .../AssemblyImportSettingsAutomation.cs | 134 + .../AssemblyImportSettingsAutomation.cs.meta | 12 + .../Scripts/Editor/BuildAOTAutomation.cs | 79 + .../Scripts/Editor/BuildAOTAutomation.cs.meta | 12 + .../Editor/EnsureOdinInspectorDefine.cs | 121 + .../Editor/EnsureOdinInspectorDefine.cs.meta | 12 + .../FixBrokenUnityObjectWrapperDrawer.cs | 208 + .../FixBrokenUnityObjectWrapperDrawer.cs.meta | 12 + ...Inspector.CompatibilityLayer.Editor.asmdef | 15 + ...ctor.CompatibilityLayer.Editor.asmdef.meta | 7 + .../Scripts/Editor/SyncListDrawer.cs | 88 + .../Scripts/Editor/SyncListDrawer.cs.meta | 12 + .../Scripts/Editor/SyncVarAttributeDrawer.cs | 42 + .../Editor/SyncVarAttributeDrawer.cs.meta | 12 + .../Editor/Vector2IntMinMaxAttributeDrawer.cs | 73 + .../Vector2IntMinMaxAttributeDrawer.cs.meta | 12 + .../Scripts/Editor/VectorIntDrawers.cs | 141 + .../Scripts/Editor/VectorIntDrawers.cs.meta | 12 + .../Editor/VectorIntPropertyResolvers.cs | 54 + .../Editor/VectorIntPropertyResolvers.cs.meta | 12 + .../Scripts/SerializedNetworkBehaviour.cs | 67 + .../SerializedNetworkBehaviour.cs.meta | 12 + ...ix.OdinInspector.CompatibilityLayer.asmdef | 11 + ...inInspector.CompatibilityLayer.asmdef.meta | 7 + .../Scripts/VectorIntFormatters.cs | 80 + .../Scripts/VectorIntFormatters.cs.meta | 12 + Assets/Plugins/Sirenix/Readme.txt | 35 + Assets/Plugins/Sirenix/Readme.txt.meta | 8 + Assets/Resources.meta | 8 + Assets/Resources/DOTweenSettings.asset | 53 + Assets/Resources/DOTweenSettings.asset.meta | 8 + ...niversalRenderPipelineGlobalSettings.asset | 0 ...salRenderPipelineGlobalSettings.asset.meta | 0 Assets/勍.meta | 8 + Assets/勍/场景.meta | 8 + .../场景/骨骼测试场景.unity} | 127 + .../场景/骨骼测试场景.unity.meta} | 0 Assets/勍/美术资源.meta | 8 + Assets/勍/美术资源/马啊PSD.psb | Bin 0 -> 686353 bytes Assets/勍/美术资源/马啊PSD.psb.meta | 6960 ++++++++++ Assets/勍/预制体.meta | 8 + Assets/勍/预制体/马骨骼.prefab | 2245 ++++ Assets/勍/预制体/马骨骼.prefab.meta | 7 + Packages/manifest.json | 2 + Packages/packages-lock.json | 16 + ProjectSettings/EditorBuildSettings.asset | 2 +- ProjectSettings/ProjectSettings.asset | 5 +- ProjectSettings/SceneTemplateSettings.json | 167 + UserSettings/EditorUserSettings.asset | 12 + UserSettings/Layouts/default-2021.dwlt | 1032 +- 2295 files changed, 249335 insertions(+), 425 deletions(-) rename Assets/{Scenes.meta => AmplifyShaderEditor.meta} (77%) create mode 100644 Assets/AmplifyShaderEditor/AmplifyShaderEditor.asmdef create mode 100644 Assets/AmplifyShaderEditor/AmplifyShaderEditor.asmdef.meta create mode 100644 Assets/AmplifyShaderEditor/ChangeLog.txt create mode 100644 Assets/AmplifyShaderEditor/ChangeLog.txt.meta create mode 100644 Assets/AmplifyShaderEditor/CreatingTerrainsWithASE.txt create mode 100644 Assets/AmplifyShaderEditor/CreatingTerrainsWithASE.txt.meta create mode 100644 Assets/AmplifyShaderEditor/Examples.meta create mode 100644 Assets/AmplifyShaderEditor/Examples/Built-In Samples.unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Examples/Credits.txt create mode 100644 Assets/AmplifyShaderEditor/Examples/Credits.txt.meta create mode 100644 Assets/AmplifyShaderEditor/Examples/DownloadSamplesInstructions.txt create mode 100644 Assets/AmplifyShaderEditor/Examples/DownloadSamplesInstructions.txt.meta create mode 100644 Assets/AmplifyShaderEditor/Examples/HDRP Samples (Legacy).unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Examples/HDRP Samples.unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Examples/LWRP Samples (Legacy).unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Examples/LWRP Samples.unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Examples/README Samples.txt create mode 100644 Assets/AmplifyShaderEditor/Examples/README Samples.txt.meta create mode 100644 Assets/AmplifyShaderEditor/Examples/Sample Resources.unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Examples/URP Samples.unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Actions.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionData.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionData.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionLog.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionLog.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionSequence.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionSequence.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Constants.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Constants.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEBeginDecorator.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEBeginDecorator.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEEndDecorator.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEEndDecorator.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/EditableIf.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/EditableIf.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/NoKeywordToggle.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/NoKeywordToggle.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSliders.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSliders.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSlidersFull.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSlidersFull.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/SingleLineTexture.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/SingleLineTexture.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateFunction.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateFunction.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateShader.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateShader.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/EditorOptions.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/EditorOptions.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Graphs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/NodeGrid.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/NodeGrid.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/ParentGraph.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/ParentGraph.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderEditorWindow.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderEditorWindow.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunction.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunction.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunctionEditor.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunctionEditor.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AutoPanData.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AutoPanData.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Clipboard.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Clipboard.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConfirmationWindow.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConfirmationWindow.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConsoleLogWindow.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConsoleLogWindow.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ContextMenuItem.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ContextMenuItem.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/CustomStylesContainer.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/CustomStylesContainer.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DebugConsoleWindow.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DebugConsoleWindow.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DragAndDropTool.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DragAndDropTool.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DuplicatePreventionBuffer.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DuplicatePreventionBuffer.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/GraphContextMenu.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/GraphContextMenu.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/MenuParent.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/MenuParent.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeParametersWindow.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeParametersWindow.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeWireReferencesUtils.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeWireReferencesUtils.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/ContextPalette.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/ContextPalette.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteParent.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteParent.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PalettePopUp.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PalettePopUp.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteWindow.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteWindow.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/PortLegendInfo.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/PortLegendInfo.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/SceneSaveCallback.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/SceneSaveCallback.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderEditorModeWindow.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderEditorModeWindow.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderLibrary.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderLibrary.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButton.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButton.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonParent.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonParent.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonSep.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonSep.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsWindow.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsWindow.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackColor.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackColor.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackFloat.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackFloat.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackInt.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackInt.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackMatrix4x4.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackMatrix4x4.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackString.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackString.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackTexture.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackTexture.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVariable.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVariable.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector2.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector2.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector3.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector3.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector4.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector4.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/IFallbackVars.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Native/IFallbackVars.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CommentaryNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CommentaryNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ColorNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ColorNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GlobalArrayNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GlobalArrayNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GradientNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GradientNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/IntNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/IntNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix3X3Node.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix3X3Node.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix4X4Node.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix4X4Node.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/MatrixParentNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/MatrixParentNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PiNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PiNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PropertyNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PropertyNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/RangedFloatNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/RangedFloatNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraProjectionNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraProjectionNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraWorldClipPlanes.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraWorldClipPlanes.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/OrthoParams.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/OrthoParams.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ProjectionParams.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ProjectionParams.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ScreenParams.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ScreenParams.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/WorldSpaceCameraPos.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/WorldSpaceCameraPos.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ZBufferParams.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ZBufferParams.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstVecShaderVariable.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstVecShaderVariable.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstantShaderVariable.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstantShaderVariable.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogAndAmbientColorsNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogAndAmbientColorsNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogParamsNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogParamsNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/CustomStandardSurface.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/CustomStandardSurface.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectDiffuseLighting.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectDiffuseLighting.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectSpecularLight.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectSpecularLight.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightAttenuation.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightAttenuation.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightColorNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightColorNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/WorldSpaceLightPos.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/WorldSpaceLightPos.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ShaderVariablesNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ShaderVariablesNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/CosTime.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/CosTime.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/DeltaTime.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/DeltaTime.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SimpleTimeNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SimpleTimeNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SinTimeNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SinTimeNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/TimeNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/TimeNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/CameraToWorldMatrix.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/CameraToWorldMatrix.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseProjectionMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseProjectionMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseTranspMVMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseTranspMVMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewProjectionMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewProjectionMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVPMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVPMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ObjectToWorldMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ObjectToWorldMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ProjectionMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ProjectionMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture0MatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture0MatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture1MatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture1MatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture2MatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture2MatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture3MatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture3MatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformDirectionNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformDirectionNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformPositionNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformPositionNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformVariables.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformVariables.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransposeMVMatrix.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransposeMVMatrix.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorClipMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorClipMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityScaleMatrix.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityScaleMatrix.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewProjectionMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewProjectionMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToCameraMatrix.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToCameraMatrix.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToObjectMatrix.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToObjectMatrix.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToTangentMatrix.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToTangentMatrix.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/ColorSpaceDouble.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/ColorSpaceDouble.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/FaceVariableNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/FaceVariableNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/InstanceIdNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/InstanceIdNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/LODFadeNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/LODFadeNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/PrimitiveIdVariableNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/PrimitiveIdVariableNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/SwitchByFaceNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/SwitchByFaceNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/VertexIdVariableNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/VertexIdVariableNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/WorldTransformParams.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/WorldTransformParams.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/StaticSwitch.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/StaticSwitch.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TauNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TauNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TextureArrayNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TextureArrayNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector2Node.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector2Node.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector3Node.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector3Node.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector4Node.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector4Node.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomAddNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomAddNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DrawInfo.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DrawInfo.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DynamicTypeNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DynamicTypeNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/CameraDepthFade.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/CameraDepthFade.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeGrabScreenPosHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeGrabScreenPosHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeScreenPosHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeScreenPosHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeDepthNormalNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeDepthNormalNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGBAHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGBAHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeLightmapHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeLightmapHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeViewNormalStereoHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeViewNormalStereoHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DepthFade.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DepthFade.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DiffuseAndSpecularFromMetallicNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DiffuseAndSpecularFromMetallicNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DitheringNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DitheringNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeDepthNormalNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeDepthNormalNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGBAHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGBAHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeViewNormalStereoHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeViewNormalStereoHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/GammaToLinearNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/GammaToLinearNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/HelperParentNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/HelperParentNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LinearToGammaNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LinearToGammaNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LuminanceHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LuminanceHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceLightDirHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceLightDirHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceViewDirHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceViewDirHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxMappingNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxMappingNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOcclusionMappingNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOcclusionMappingNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOffsetHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOffsetHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ShadeVertexLightsHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ShadeVertexLightsHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/SurfaceDepthNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/SurfaceDepthNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/TriplanarNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/TriplanarNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToClipPosHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToClipPosHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToViewPosHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToViewPosHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceLightDirHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceLightDirHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceViewDirHlpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceViewDirHlpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ISignalGenerator.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ISignalGenerator.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/BlendOpsNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/BlendOpsNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/DesaturateOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/DesaturateOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/HSVToRGBNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/HSVToRGBNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/LuminanceNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/LuminanceNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/NoiseGeneratorNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/NoiseGeneratorNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/PosterizeNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/PosterizeNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/RGBToHSVNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/RGBToHSVNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimpleContrastOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimpleContrastOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimplexNoiseNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimplexNoiseNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/TFHCGrayscale.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/TFHCGrayscale.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/VoronoiNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/VoronoiNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/Compare.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/Compare.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/ConditionalIfNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/ConditionalIfNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/KeywordSwitchNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/KeywordSwitchNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareEqual.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareEqual.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreater.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreater.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreaterEqual.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreaterEqual.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLower.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLower.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLowerEqual.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLowerEqual.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareNotEqual.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareNotEqual.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareWithRange.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareWithRange.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCIf.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCIf.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCStub.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCStub.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalDefinesHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalDefinesHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalIncludesHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalIncludesHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalPragmasHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalPragmasHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalSurfaceOptionsHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalSurfaceOptionsHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BlendOpsHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BlendOpsHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CodeGenerationData.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CodeGenerationData.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ColorMaskHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ColorMaskHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CustomTagsHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CustomTagsHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/DependenciesHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/DependenciesHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FallbackPickerHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FallbackPickerHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionInput.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionInput.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionOutput.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionOutput.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSubtitle.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSubtitle.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitch.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitch.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitchByPipeline.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitchByPipeline.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/LogNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/LogNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNodeDataCollector.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNodeDataCollector.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutlineOpHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutlineOpHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutputNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutputNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingOptionsOpHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingOptionsOpHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingPlatformsOpHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingPlatformsOpHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StandardSurface.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StandardSurface.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StencilBufferOpHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StencilBufferOpHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TerrainDrawInstancedHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TerrainDrawInstancedHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TessellationOpHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TessellationOpHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/UsePassHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/UsePassHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ZBufferOpHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ZBufferOpHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/AppendNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/AppendNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/BreakToComponentsNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/BreakToComponentsNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/CustomExpressionNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/CustomExpressionNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/DynamicAppendNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/DynamicAppendNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/FresnelNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/FresnelNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/GetLocalVarNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/GetLocalVarNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LayeredBlendNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LayeredBlendNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LinearDepthNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LinearDepthNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/MatrixFromVectors.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/MatrixFromVectors.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/PosFromTransformMatrix.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/PosFromTransformMatrix.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RegisterLocalVarNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RegisterLocalVarNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RelayNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RelayNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RotateAboutAxisNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RotateAboutAxisNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SummedBlendNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SummedBlendNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwitchNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwitchNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwizzleNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwizzleNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/ToggleSwitchNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/ToggleSwitchNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ObjectToWorldTransfNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ObjectToWorldTransfNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ParentTransfNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ParentTransfNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/WorldToObjectTransfNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/WorldToObjectTransfNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/VectorFromMatrixNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/VectorFromMatrixNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedAvgNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedAvgNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedBlendNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedBlendNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WireNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WireNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeAttributes.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeAttributes.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeRestrictions.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeRestrictions.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUsageRegister.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUsageRegister.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUtils.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUtils.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ACosOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ACosOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ASinOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ASinOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATan2OpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATan2OpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATanOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATanOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/AbsOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/AbsOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CeilOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CeilOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClampOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClampOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClipNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClipNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ComponentMaskNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ComponentMaskNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CosOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CosOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CoshOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CoshOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CrossProductOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CrossProductOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdxOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdxOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdyOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdyOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DegreesOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DegreesOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DeterminantOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DeterminantOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DistanceOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DistanceOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DotProductOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DotProductOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Exp2OpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Exp2OpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ExpOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ExpOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FWidthOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FWidthOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FloorOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FloorOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FmodOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FmodOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FractNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FractNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/GradientSampleNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/GradientSampleNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/InverseOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/InverseOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LengthOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LengthOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LerpOp.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LerpOp.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log10OpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log10OpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log2OpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log2OpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LogOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LogOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/MultipleInputOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/MultipleInputOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NegateNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NegateNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NormalizeNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NormalizeNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/OneMinusNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/OneMinusNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/PowerNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/PowerNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RSqrtOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RSqrtOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RadiansOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RadiansOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ReflectOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ReflectOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RefractOpVec.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RefractOpVec.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RoundOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RoundOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SaturateNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SaturateNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleAndOffsetNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleAndOffsetNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SignOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SignOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SimplifiedFModOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SimplifiedFModOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SingleInputOp.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SingleInputOp.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinhOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinhOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SmoothstepOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SmoothstepOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SqrtOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SqrtOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/StepOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/StepOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TFHCRemapNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TFHCRemapNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanhOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanhOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransformVectorOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransformVectorOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransposeOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransposeOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TruncOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TruncOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/VariablePortTypeOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/VariablePortTypeOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ReordenatorNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ReordenatorNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/BakedGINode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/BakedGINode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/HD.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/HD/HDEmissionNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/HD/HDEmissionNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/MaterialQualityNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/MaterialQualityNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/URP.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/URP/ReflectionProbeNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/URP/ReflectionProbeNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SignalGeneratorNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SignalGeneratorNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleAddOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleAddOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleDivideOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleDivideOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMaxOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMaxOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMinOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMinOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMultiplyOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMultiplyOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleRemainderNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleRemainderNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleSubtractOpNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleSubtractOpNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/StickyNoteNode .cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/StickyNoteNode .cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ColorInputsNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ColorInputsNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/GrabScreenPosition.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/GrabScreenPosition.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/LocalVertexPosNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/LocalVertexPosNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenColorNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenColorNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenDepthNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenDepthNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenPosInputsNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenPosInputsNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/SurfaceShaderINParentNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/SurfaceShaderINParentNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/TexelSizeNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/TexelSizeNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/UVCoordsParentNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/UVCoordsParentNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ViewDirInputsCoordNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ViewDirInputsCoordNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalInputsNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalInputsNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalVector.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalVector.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldPosInputsNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldPosInputsNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflInputsNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflInputsNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflectionVector.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflectionVector.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/BlendNormalsNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/BlendNormalsNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/HeightMapBlendNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/HeightMapBlendNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/PannerNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/PannerNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/RotatorNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/RotatorNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerStateNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerStateNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SubstanceSamplerNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SubstanceSamplerNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCFlipBookUVAnimation.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCFlipBookUVAnimation.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCPixelate.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCPixelate.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureCoordinatesNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureCoordinatesNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TexturePropertyNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TexturePropertyNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureTransformNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureTransformNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/UnpackScaleNormalNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/UnpackScaleNormalNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/VirtualTextureObject.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/VirtualTextureObject.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/UndoParentNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/UndoParentNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BillboardNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BillboardNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BitangentVertexDataNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BitangentVertexDataNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendIndicesNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendIndicesNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendWeightsNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendWeightsNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ColorVertexDataNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ColorVertexDataNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/NormalVertexDataNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/NormalVertexDataNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ObjectScaleNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ObjectScaleNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/OutlineNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/OutlineNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/PosVertexDataNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/PosVertexDataNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentSignVertexDataNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentSignVertexDataNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentVertexDataNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentVertexDataNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/DistanceBasedTessNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/DistanceBasedTessNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthCullTessNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthCullTessNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthTessNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthTessNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/TessellationParentNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/TessellationParentNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoord1VertexDataNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoord1VertexDataNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoordVertexDataNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoordVertexDataNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexBinormalNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexBinormalNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexColorNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexColorNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexDataNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexDataNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexTangentNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexTangentNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexToFragmentNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexToFragmentNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/PreMadeShaders.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/PreMadeShaders.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAlphaToMaskModule.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAlphaToMaskModule.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDBItem.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDBItem.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateRenderPlatformHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateRenderPlatformHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPPSHelperTool.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPPSHelperTool.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPackageManagerHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPackageManagerHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEStartScreen.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEStartScreen.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASETextureArrayCreator.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASETextureArrayCreator.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomMaterialInspector.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomMaterialInspector.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomShaderInspector.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomShaderInspector.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomTexture2DArrayInspector.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomTexture2DArrayInspector.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/EditorVariablesManager.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/EditorVariablesManager.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GeneratorUtils.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GeneratorUtils.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GenericMessage.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GenericMessage.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/IOUtils.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/IOUtils.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InlineProperty.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InlineProperty.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InvalidDataChecker.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InvalidDataChecker.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/NodeExporterUtils.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/NodeExporterUtils.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/Preferences.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/Preferences.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/RectExtension.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/RectExtension.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/SamplerStateAutoGenerator.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/SamplerStateAutoGenerator.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ShortcutsManager.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ShortcutsManager.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TextureArrayCreatorAsset.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TextureArrayCreatorAsset.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TipsWindow.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TipsWindow.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UIUtils.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UIUtils.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UndoUtils.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UndoUtils.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UpperLeftWidgetHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UpperLeftWidgetHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowHelper.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowHelper.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowsUtil.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowsUtil.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Version.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Version/About.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Version/About.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Version/VersionInfo.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Version/VersionInfo.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires/GLDraw.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires/GLDraw.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires/InputPort.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires/InputPort.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires/OutputPort.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires/OutputPort.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireBezierReference.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireBezierReference.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WirePort.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WirePort.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireReference.cs create mode 100644 Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireReference.cs.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/GUISkins.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/GUISkins/MainSkin.guiskin create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/GUISkins/MainSkin.guiskin.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/Bezier1X2AA.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/Bezier1X2AA.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconON.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconON.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/LinkIcon.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/LinkIcon.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/MasterNodeIconOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/MasterNodeIconOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/MasterNodeIconON.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/MasterNodeIconON.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/TextureReferenceBg.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/TextureReferenceBg.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/IndirectSpecularPreview.exr create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/IndirectSpecularPreview.exr.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/LinearPreviews.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/LinearPreviews.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ACosOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ACosOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ASinOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ASinOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATan2OpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATan2OpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATanOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATanOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AbsOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AbsOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AppendNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AppendNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendNormalsNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendNormalsNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendOpsNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendOpsNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BreakToComponentsNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BreakToComponentsNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CeilOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CeilOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClampOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClampOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Clip.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Clip.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClipPlanes.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClipPlanes.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorSpaceDouble.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorSpaceDouble.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Compare.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Compare.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComponentMaskNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComponentMaskNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComputeScreenPos.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComputeScreenPos.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ConditionalIfNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ConditionalIfNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosTime.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosTime.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CoshOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CoshOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CrossProductOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CrossProductOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdxOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdxOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdyOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdyOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeDepthNormalNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeDepthNormalNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGBAHlpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGBAHlpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGHlpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGHlpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeLightmapHlpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeLightmapHlpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeViewNormalStereoHlpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeViewNormalStereoHlpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DegreesOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DegreesOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DeltaTime.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DeltaTime.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DesaturateNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DesaturateNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DiffuseAndSpecularFromMetallic.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DiffuseAndSpecularFromMetallic.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DistanceOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DistanceOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DotProductOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DotProductOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DynamicAppendNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DynamicAppendNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGBAHlpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGBAHlpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGHlpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGHlpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeViewNormalStereoHlpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeViewNormalStereoHlpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Exp2OpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Exp2OpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ExpOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ExpOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FWidthOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FWidthOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FaceVariableNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FaceVariableNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FloorOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FloorOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FmodOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FmodOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogAndAmbientColors.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogAndAmbientColors.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogParams.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogParams.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FractNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FractNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FresnelNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FresnelNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionInputNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionInputNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionOutputNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionOutputNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GammaToLinearNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GammaToLinearNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GetLocalVarNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GetLocalVarNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GradientSample.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GradientSample.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GrayscaleNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GrayscaleNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HSVToRGBNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HSVToRGBNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HeightMapTextureBlend.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HeightMapTextureBlend.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectDiffuseLight.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectDiffuseLight.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectSpecularLight.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectSpecularLight.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_InstanceIDNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_InstanceIDNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IntNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IntNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LODFadeNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LODFadeNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LayeredBlendNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LayeredBlendNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LengthOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LengthOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LerpOp.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LerpOp.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightAttenuation.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightAttenuation.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightColorNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightColorNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearDepthNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearDepthNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearToGammaNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearToGammaNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log10OpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log10OpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log2OpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log2OpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LogOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LogOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LuminanceNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LuminanceNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NegateNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NegateNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NodeMasking.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NodeMasking.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NoiseGeneratorNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NoiseGeneratorNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalVertexDataNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalVertexDataNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalizeNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalizeNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceLightDirHlpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceLightDirHlpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceViewDirHlpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceViewDirHlpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectScaleNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectScaleNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToClipPos.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToClipPos.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToViewPos.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToViewPos.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToWorldTransfNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToWorldTransfNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OneMinusNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OneMinusNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OrthoParams.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OrthoParams.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PannerNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PannerNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxMappingNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxMappingNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxOffset.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxOffset.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PiNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PiNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosVertexDataNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosVertexDataNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosterizeNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosterizeNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PowerNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PowerNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PrimitiveIDVariableNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PrimitiveIDVariableNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ProjectionParams.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ProjectionParams.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RGBToHSVNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RGBToHSVNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RadiansOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RadiansOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RangedFloatNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RangedFloatNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ReflectOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ReflectOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RefractOpVec.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RefractOpVec.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RegisterLocalVarNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RegisterLocalVarNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RelayNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RelayNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RotatorNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RotatorNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RoundOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RoundOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RsqrtOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RsqrtOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SamplerNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SamplerNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SaturateNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SaturateNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleAndOffsetNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleAndOffsetNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenParams.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenParams.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenPosInputsNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenPosInputsNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ShadeVertexLights.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ShadeVertexLights.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SignOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SignOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleAddOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleAddOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleContrastNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleContrastNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleDivideOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleDivideOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMaxOp.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMaxOp.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMinNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMinNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMultiplyOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMultiplyOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleRemainderNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleRemainderNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleSubtractOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleSubtractOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleTimeNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleTimeNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimplifiedFModOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimplifiedFModOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinTimeNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinTimeNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinhOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinhOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SmoothstepOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SmoothstepOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SqrtOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SqrtOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StaticSwitchNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StaticSwitchNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StepOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StepOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SubstanceSamplerNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SubstanceSamplerNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SummedBlendNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SummedBlendNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchByFaceNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchByFaceNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwizzleNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwizzleNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareEqual.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareEqual.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreater.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreater.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreaterEqual.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreaterEqual.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLessNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLessNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLowerEqual.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLowerEqual.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareNotEqual.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareNotEqual.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareWithRange.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareWithRange.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCFlipBookUVAnimation.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCFlipBookUVAnimation.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCIf.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCIf.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCPixelateUV.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCPixelateUV.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCRemap.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCRemap.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentSignVertexDataNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentSignVertexDataNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentVertexDataNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentVertexDataNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanhOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanhOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TauNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TauNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TemplateShaderProperty.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TemplateShaderProperty.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexCoordVertexDataNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexCoordVertexDataNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexelSize.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexelSize.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Texture2D.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Texture2D.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureArrayNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureArrayNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureCoordinatesNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureCoordinatesNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexturePropertyNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexturePropertyNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureTransform.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureTransform.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TimeNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TimeNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ToggleSwitchNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ToggleSwitchNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TriplanarNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TriplanarNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TruncOpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TruncOpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_UnpackScaleNormalNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_UnpackScaleNormalNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector2Node.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector2Node.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector3Node.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector3Node.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector4Node.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector4Node.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexBinormalNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexBinormalNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexColorNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexColorNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexIdVariableNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexIdVariableNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexTangentNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexTangentNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ViewDirInputsCoordNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ViewDirInputsCoordNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VoronoiNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VoronoiNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WeightedBlendNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WeightedBlendNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WireNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WireNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldNormalVector.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldNormalVector.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldPosInputsNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldPosInputsNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldReflectionVector.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldReflectionVector.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceCameraPos.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceCameraPos.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightDirHlpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightDirHlpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightPosNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightPosNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceViewDirHlpNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceViewDirHlpNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldToObjectTransfNode.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldToObjectTransfNode.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldTransformParams.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldTransformParams.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ZBufferParams.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ZBufferParams.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/TextureArrayInspector.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/TextureArrayInspector.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/And.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/And.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bacteria.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bacteria.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Precompute.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Precompute.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Sample.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Sample.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bidirectional Parallax Mapping.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bidirectional Parallax Mapping.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Half Vector.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Half Vector.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Light.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Light.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BlinnPhongLightWrap.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BlinnPhongLightWrap.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BoxMask.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BoxMask.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bricks Pattern.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bricks Pattern.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Checkerboard.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Checkerboard.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Color Mask.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Color Mask.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ComputeFilterWidth.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ComputeFilterWidth.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ConstantBiasScale.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ConstantBiasScale.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/CotangentFrame.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/CotangentFrame.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Create Orthogonal Vector.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Create Orthogonal Vector.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Decode Directional Lighmap.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Decode Directional Lighmap.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/DepthMaskedRefraction.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/DepthMaskedRefraction.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Derive Tangent Basis.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Derive Tangent Basis.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Detail Albedo.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Detail Albedo.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Dots Pattern.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Dots Pattern.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Ellipse.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Ellipse.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchHDColorPyramid.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchHDColorPyramid.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchLightmapValue.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchLightmapValue.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flipbook.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flipbook.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flow.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flow.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Four Splats First Pass Terrain.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Four Splats First Pass Terrain.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Grid.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Grid.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Half Lambert Term.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Half Lambert Term.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Height-based Blending.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Height-based Blending.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Herringbone.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Herringbone.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Hex Lattice.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Hex Lattice.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Houndstooth.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Houndstooth.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Inverse Lerp.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Inverse Lerp.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Lerp White To.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Lerp White To.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Midtones Control.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Midtones Control.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Noise Sine Wave.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Noise Sine Wave.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Non Stereo Screen Pos.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Non Stereo Screen Pos.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Height.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Height.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Texture.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Texture.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/NormalCreate.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/NormalCreate.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Or.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Or.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormal.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormal.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormalHQ.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormalHQ.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polar Coordinates.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polar Coordinates.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polygon.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polygon.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PreparePerturbNormalHQ.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PreparePerturbNormalHQ.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Procedural Sample.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Procedural Sample.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Projection.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Projection.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Radial Shear.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Radial Shear.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/RadialUVDistortion.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/RadialUVDistortion.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Random Range.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Random Range.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Reconstruct World Position From Depth.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Reconstruct World Position From Depth.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rectangle.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rectangle.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rejection.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rejection.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Replace Color.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Replace Color.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rounded Rectangle.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rounded Rectangle.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SRP Additional Light.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SRP Additional Light.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Sawtooth Wave.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Sawtooth Wave.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Simple HUE.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Simple HUE.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Smooth Wave.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Smooth Wave.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SphereMask.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SphereMask.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spherize.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spherize.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spiral.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spiral.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Square Wave.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Square Wave.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Step Antialiasing.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Step Antialiasing.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stereo Screen Pos.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stereo Screen Pos.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stripes.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stripes.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SubstanceBlendMetallic.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SubstanceBlendMetallic.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Animate Vertex.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Animate Vertex.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Value.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Value.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Triangle Wave.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Triangle Wave.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Truchet.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Truchet.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Twirl.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Twirl.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/UI-Sprite Effect Layer.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/UI-Sprite Effect Layer.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Whirl.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Whirl.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Zig Zag.asset create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Zig Zag.asset.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderLibrary.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderLibrary/ShaderLibrary.txt create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderLibrary/ShaderLibrary.txt.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/ASESShaderSelectorUnlit.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/ASESShaderSelectorUnlit.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/Unlit-ColoredAlpha.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/Unlit-ColoredAlpha.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/CustomRTTemplates.unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/HDSRPTemplates.unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/LWSRPTemplates.unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/DefaultUnlit.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/DefaultUnlit.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Lit.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Lit.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/MultiPassUnlit.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/MultiPassUnlit.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Particle Alpha Blend.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Particle Alpha Blend.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/PostProcess.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/PostProcess.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Sprites-Default.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Sprites-Default.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UIDefault.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UIDefault.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Unlit.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Unlit.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UnlitLightmap.shader create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UnlitLightmap.shader.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/PPStackTemplates.unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy).meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 3xx (Legacy).unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 4xx (Legacy).unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 572 (Legacy).unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 5xx (Legacy).unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 6xx (Legacy).unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 718 - 743 (Legacy).unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 7xx - 9xx (Legacy).unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/LWSRPTemplates 3xx (Legacy).unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/LWSRPTemplates 4xx (Legacy).unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/README.txt create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/README.txt.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/USRPTemplates 7xx - 9xx (Legacy).unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/USRPTemplates.unitypackage.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/About.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/About.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/Icon64.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/Icon64.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/black.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/black.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/blue.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/blue.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/flat.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/flat.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/green.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/green.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/grey.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/grey.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/red.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/red.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/white.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/white.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/AddToList.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/AddToList.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Checkmark.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Checkmark.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_OFF_Dark.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_OFF_Dark.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_ON_Dark.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_ON_Dark.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFFNew.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFFNew.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupON.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupON.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupONNew.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupONNew.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpAddIconActive.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpAddIconActive.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpAddIconNormal.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpAddIconNormal.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpRemoveIconActive.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpRemoveIconActive.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpRemoveIconNormal.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpRemoveIconNormal.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FitView.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FitView.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FocusNode.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FocusNode.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help2.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help2.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ItemCleanupOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ItemCleanupOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ItemCleanupON.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ItemCleanupON.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Library.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Library.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveON.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveON.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LivePending.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LivePending.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MaximizeWindow.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MaximizeWindow.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOff.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOff.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOffHover.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOffHover.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOn.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOn.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOnHover.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOnHover.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOff.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOff.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOffHover.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOffHover.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOn.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOn.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOnHover.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOnHover.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOff.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOff.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOffHover.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOffHover.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOn.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOn.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOnHover.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOnHover.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MinimizeWindow.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MinimizeWindow.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/New.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/New.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Open.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Open.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenListedShader.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenListedShader.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenSourceCodeOFF.PNG create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenSourceCodeOFF.PNG.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenSourceCodeON.PNG create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenSourceCodeON.PNG.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Options.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Options.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/RemoveFromList.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/RemoveFromList.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ResetInspectorIcon.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ResetInspectorIcon.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SaveOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SaveOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SaveON.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SaveON.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SelectionAsTemplate.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SelectionAsTemplate.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ShaderSelectOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ShaderSelectOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ShaderSelectON.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ShaderSelectON.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ShareOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ShareOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SliderHoriz.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SliderHoriz.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/TakeScreenshotOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/TakeScreenshotOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/TransparentPixel.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/TransparentPixel.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateOutdated.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateOutdated.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateUpToDated.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateUpToDated.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/CircleBackground.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/CircleBackground.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Grid128.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Grid128.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 2.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 2.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 3.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 3.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 4.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 4.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MainCanvasTitleBg.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MainCanvasTitleBg.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Material.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Material.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MaterialModeIcon.PNG create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MaterialModeIcon.PNG.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MaterialModeIconOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MaterialModeIconOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/SelectionBox.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/SelectionBox.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Shader.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Shader.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunction.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunction.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionIcon.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionIcon.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIcon.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIcon.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIconOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIconOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeIcon.PNG create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeIcon.PNG.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeIconOFF.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeIconOFF.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeMatIcon.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeMatIcon.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/TransparentOverlay.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/TransparentOverlay.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBase.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBase.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBaseLeft.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBaseLeft.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBaseSquare.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBaseSquare.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalHeader.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalHeader.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/ButtonBackground.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/ButtonBackground.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/CommentNodeBase.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/CommentNodeBase.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/CommentaryResizeIcon.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/CommentaryResizeIcon.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/CommentaryResizeIconInv.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/CommentaryResizeIconInv.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/FlatBackground.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/FlatBackground.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphButton.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphButton.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphButtonActive.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphButtonActive.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphPopup.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphPopup.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GrayNormalHeader.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GrayNormalHeader.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GrayNormalHeaderSquare.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GrayNormalHeaderSquare.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/NoPreview.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/NoPreview.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/NodeSelected.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/NodeSelected.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/NodeSelectedSquare.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/NodeSelectedSquare.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/ObjectPickerBackgroundOutline.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/ObjectPickerBackgroundOutline.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PopupPicker.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PopupPicker.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOff.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOff.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOn.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOn.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PropertyPicker.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PropertyPicker.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/SliderButton.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/SliderButton.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortOutline.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortOutline.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortSolid.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortSolid.png.meta create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WireNodeSelection.png create mode 100644 Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WireNodeSelection.png.meta create mode 100644 Assets/AmplifyShaderEditor/Readme.txt create mode 100644 Assets/AmplifyShaderEditor/Readme.txt.meta create mode 100644 Assets/Plugins.meta create mode 100644 Assets/Plugins/Demigiant.meta create mode 100644 Assets/Plugins/Demigiant/DOTween.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/DOTween.XML create mode 100644 Assets/Plugins/Demigiant/DOTween/DOTween.XML.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/DOTween.dll create mode 100644 Assets/Plugins/Demigiant/DOTween/DOTween.dll.mdb create mode 100644 Assets/Plugins/Demigiant/DOTween/DOTween.dll.mdb.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/DOTween.dll.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.XML create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.XML.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.dll create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.dll.mdb create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.dll.mdb.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.dll.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/Imgs.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/Imgs/DOTweenIcon.png create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/Imgs/DOTweenIcon.png.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/Imgs/DOTweenMiniIcon.png create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/Imgs/DOTweenMiniIcon.png.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer.png create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer.png.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer_dark.png create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer_dark.png.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Header.jpg create mode 100644 Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Header.jpg.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleAudio.cs create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleAudio.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleEPOOutline.cs create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleEPOOutline.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics.cs create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics2D.cs create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics2D.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleSprite.cs create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleSprite.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUI.cs create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUI.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUnityVersion.cs create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUnityVersion.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUtils.cs create mode 100644 Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUtils.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTween/readme.txt create mode 100644 Assets/Plugins/Demigiant/DOTween/readme.txt.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Advanced.unity create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Advanced.unity.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_AdvancedSettings.lighting create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_AdvancedSettings.lighting.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Basics.unity create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Basics.unity.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_BasicsSettings.lighting create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_BasicsSettings.lighting.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPath.unity create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPath.unity.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPathSettings.lighting create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPathSettings.lighting.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/Examples Assets.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/Examples Assets/dotweenpro_logo.png create mode 100644 Assets/Plugins/Demigiant/DOTweenPro Examples/Examples Assets/dotweenpro_logo.png.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenAnimation.cs create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenAnimation.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeAudio.cs create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeAudio.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeUnityExtended.cs create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeUnityExtended.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.XML create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.XML.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.dll create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.dll.mdb create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.dll.mdb.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.dll.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenProShortcuts.cs create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenProShortcuts.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenTextMeshPro.cs create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenTextMeshPro.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenTk2d.cs create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/DOTweenTk2d.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/Editor.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenAnimationInspector.cs create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenAnimationInspector.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenPreviewManager.cs create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenPreviewManager.cs.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.XML create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.XML.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll.mdb create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll.mdb.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll.meta create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/readme.txt create mode 100644 Assets/Plugins/Demigiant/DOTweenPro/readme.txt.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.dll create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.dll.mdb create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.dll.mdb.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.dll.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.xml create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.xml.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll.mdb create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll.mdb.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.xml create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.xml.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquare.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquare.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha10.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha10.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha15.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha15.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha25.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha25.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha50.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha50.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha80.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha80.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blueSquare.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blueSquare.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle_dashedBorderEmpty.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle_dashedBorderEmpty.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/greenSquare.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/greenSquare.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/grid_bright.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/grid_bright.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/grid_dark.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/grid_dark.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alert.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alert.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignB.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignB.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignBC.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignBC.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignBL.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignBL.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignBR.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignBR.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCC.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCC.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCL.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCL.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCR.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCR.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignHC.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignHC.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignL.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignL.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignR.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignR.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignT.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignT.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTC.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTC.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTL.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTL.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTR.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTR.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignVC.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignVC.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_camera.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_camera.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_camera_border.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_camera_border.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_cog.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_cog.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_cog_border.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_cog_border.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_comment.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_comment.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_comment_border.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_comment_border.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_delete.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_delete.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_demigiant.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_demigiant.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_distributeHAlignT.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_distributeHAlignT.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_distributeVAlignL.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_distributeVAlignL.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_end.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_end.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_flipV.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_flipV.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_foldout_closed.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_foldout_closed.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_foldout_open.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_foldout_open.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_heart.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_heart.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_heart_border.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_heart_border.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_light.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_light.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_light_border.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_light_border.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_lock.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_lock.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_lock_open.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_lock_open.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_nodeArrow.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_nodeArrow.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ok.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ok.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_optionsDropdown.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_optionsDropdown.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_play.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_play.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_play_border.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_play_border.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_skull.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_skull.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_skull_border.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_skull_border.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_star.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_star.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_star_border.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_star_border.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ui.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ui.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ui_border.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ui_border.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_visibility.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_visibility.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_visibility_off.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_visibility_off.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/orangeSquare.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/orangeSquare.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_atlas.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_atlas.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_audio.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_audio.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_bundle.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_bundle.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_cog.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_cog.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_cross.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_cross.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_demigiant.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_demigiant.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_folder.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_folder.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_fonts.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_fonts.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_heart.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_heart.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_materials.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_materials.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_models.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_models.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_particles.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_particles.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_play.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_play.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_prefab.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_prefab.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_scripts.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_scripts.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_shaders.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_shaders.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_skull.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_skull.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_star.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_star.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_terrains.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_terrains.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_textures.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_textures.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/purpleSquare.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/purpleSquare.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/redSquare.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/redSquare.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorder.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorder.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderAlpha15.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderAlpha15.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved02.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved02.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved02_darkBorders.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved02_darkBorders.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurvedAlpha.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurvedAlpha.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurvedEmpty.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurvedEmpty.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurvedEmpty02.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurvedEmpty02.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurvedEmptyThick.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurvedEmptyThick.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved_darkBorders.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved_darkBorders.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved_darkBordersAlpha.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved_darkBordersAlpha.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty01.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty01.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty02.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty02.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty03.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty03.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickEmpty.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickEmpty.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickerEmpty.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickerEmpty.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareCorners03.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareCorners03.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareCornersEmpty02.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareCornersEmpty02.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_empty.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_empty.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_slanted.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_slanted.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_slanted_alpha.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_slanted_alpha.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/transparentSquare.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/transparentSquare.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_darkBorder.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_darkBorder.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_whiteBorderAlpha.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_whiteBorderAlpha.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquare.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquare.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha10.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha10.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha15.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha15.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha25.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha25.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha50.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha50.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha80.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha80.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareCurved.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareCurved.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareCurved02.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareCurved02.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquare_fadeOut_bt.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquare_fadeOut_bt.png.meta create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/yellowSquare.png create mode 100644 Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/yellowSquare.png.meta create mode 100644 Assets/Plugins/Demigiant/readme_DOTweenPro.txt create mode 100644 Assets/Plugins/Demigiant/readme_DOTweenPro.txt.meta create mode 100644 Assets/Plugins/Sirenix.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEditor.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll.mdb create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll.mdb.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll.mdb create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll.mdb.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll.mdb create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll.mdb.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Utilities.dll create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Utilities.dll.mdb create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Utilities.dll.mdb.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Utilities.dll.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.dll create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.dll.mdb create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.dll.mdb.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.dll.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.xml create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.xml.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.dll create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.dll.mdb create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.dll.mdb.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.dll.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.xml create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.xml.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll.mdb create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll.mdb.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.xml create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.xml.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.dll create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.dll.mdb create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.dll.mdb.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.dll.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.xml create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.xml.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.dll create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.dll.mdb create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.dll.mdb.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.dll.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.xml create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.xml.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll.mdb create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll.mdb.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.xml create mode 100644 Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.xml.meta create mode 100644 Assets/Plugins/Sirenix/Assemblies/link.xml create mode 100644 Assets/Plugins/Sirenix/Assemblies/link.xml.meta create mode 100644 Assets/Plugins/Sirenix/Demos.meta create mode 100644 Assets/Plugins/Sirenix/Demos/Custom Attribute Processors.unitypackage.meta create mode 100644 Assets/Plugins/Sirenix/Demos/Custom Drawers.unitypackage.meta create mode 100644 Assets/Plugins/Sirenix/Demos/Editor Windows.unitypackage.meta create mode 100644 Assets/Plugins/Sirenix/Demos/Sample - RPG Editor.unitypackage.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Assets.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/ConfigData.bytes create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/ConfigData.bytes.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/Odin Inspector Logo.png create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/Odin Inspector Logo.png.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/OdinPathLookup.asset create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/OdinPathLookup.asset.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Config.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Config/Editor.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/GeneralDrawerConfig.asset create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/GeneralDrawerConfig.asset.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/InspectorConfig.asset create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/InspectorConfig.asset.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/OdinModuleConfig.asset create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/OdinModuleConfig.asset.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Modules.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Entities.data create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Entities.data.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.data create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.data.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/MathematicsDrawers.cs create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/MathematicsDrawers.cs.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/Sirenix.OdinInspector.Modules.UnityMathematics.asmdef create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/Sirenix.OdinInspector.Modules.UnityMathematics.asmdef.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/manifest.txt create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/manifest.txt.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/AssemblyImportSettingsAutomation.cs create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/AssemblyImportSettingsAutomation.cs.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/BuildAOTAutomation.cs create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/BuildAOTAutomation.cs.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/EnsureOdinInspectorDefine.cs create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/EnsureOdinInspectorDefine.cs.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Sirenix.OdinInspector.CompatibilityLayer.Editor.asmdef create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Sirenix.OdinInspector.CompatibilityLayer.Editor.asmdef.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncListDrawer.cs create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncListDrawer.cs.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncVarAttributeDrawer.cs create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncVarAttributeDrawer.cs.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Vector2IntMinMaxAttributeDrawer.cs create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Vector2IntMinMaxAttributeDrawer.cs.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntDrawers.cs create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntDrawers.cs.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntPropertyResolvers.cs create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntPropertyResolvers.cs.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/SerializedNetworkBehaviour.cs create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/SerializedNetworkBehaviour.cs.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Sirenix.OdinInspector.CompatibilityLayer.asmdef create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Sirenix.OdinInspector.CompatibilityLayer.asmdef.meta create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/VectorIntFormatters.cs create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/VectorIntFormatters.cs.meta create mode 100644 Assets/Plugins/Sirenix/Readme.txt create mode 100644 Assets/Plugins/Sirenix/Readme.txt.meta create mode 100644 Assets/Resources.meta create mode 100644 Assets/Resources/DOTweenSettings.asset create mode 100644 Assets/Resources/DOTweenSettings.asset.meta rename Assets/{ => Settings}/UniversalRenderPipelineGlobalSettings.asset (100%) rename Assets/{ => Settings}/UniversalRenderPipelineGlobalSettings.asset.meta (100%) create mode 100644 Assets/勍.meta create mode 100644 Assets/勍/场景.meta rename Assets/{Scenes/SampleScene.unity => 勍/场景/骨骼测试场景.unity} (66%) rename Assets/{Scenes/SampleScene.unity.meta => 勍/场景/骨骼测试场景.unity.meta} (100%) create mode 100644 Assets/勍/美术资源.meta create mode 100644 Assets/勍/美术资源/马啊PSD.psb create mode 100644 Assets/勍/美术资源/马啊PSD.psb.meta create mode 100644 Assets/勍/预制体.meta create mode 100644 Assets/勍/预制体/马骨骼.prefab create mode 100644 Assets/勍/预制体/马骨骼.prefab.meta create mode 100644 ProjectSettings/SceneTemplateSettings.json diff --git a/Assets/Scenes.meta b/Assets/AmplifyShaderEditor.meta similarity index 77% rename from Assets/Scenes.meta rename to Assets/AmplifyShaderEditor.meta index ee46714..826f52c 100644 --- a/Assets/Scenes.meta +++ b/Assets/AmplifyShaderEditor.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 109e9bdd0fcc649c5bc59085c35bdc83 +guid: d6c88676b731edb44a84c7646056a8da folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/AmplifyShaderEditor/AmplifyShaderEditor.asmdef b/Assets/AmplifyShaderEditor/AmplifyShaderEditor.asmdef new file mode 100644 index 0000000..9cb8cff --- /dev/null +++ b/Assets/AmplifyShaderEditor/AmplifyShaderEditor.asmdef @@ -0,0 +1,15 @@ +{ + "name": "AmplifyShaderEditor", + "references": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/AmplifyShaderEditor/AmplifyShaderEditor.asmdef.meta b/Assets/AmplifyShaderEditor/AmplifyShaderEditor.asmdef.meta new file mode 100644 index 0000000..594d160 --- /dev/null +++ b/Assets/AmplifyShaderEditor/AmplifyShaderEditor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f540dafdfbc0586439d98823585550d4 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/ChangeLog.txt b/Assets/AmplifyShaderEditor/ChangeLog.txt new file mode 100644 index 0000000..74f7e0a --- /dev/null +++ b/Assets/AmplifyShaderEditor/ChangeLog.txt @@ -0,0 +1,4744 @@ +Release Notes: +* Warning: + * Some rendering platform tags changed across sub-SRP versions and we decided to update our templates to the latest ones. + On SRP 10 and above there's no issue as all versions are updated but on version 7, only the latest 7.6 version recognizes the new tags. + All other older SRP 7 versions as well as all SRP 8 versions don't recognize the new tags. + Over this new ASE version we added the Rendering Platforms menu over the Master Node properties window on SRP templates so if on your current SRP version p.e this warning appear + * Unrecognized renderer for #pragma only_renderers: xboxseries + You only need to go to the Rendering Platforms menu and deselect that specific tag. + +v1.8.9 rev 12: +* Fixes: + * Fixed issue on incorrectly writing render platform info on shader meta even if none is present over its template + +* Improvements: + * Moved Render Platform declaration on URP templates to SubShader level so it can be properly used by latest Render Platform feature on templates + +v1.8.9 rev 11: +* Fixes: + * Fixed missing link id over fragment Normal port on URP 10 + +* Improvements: + * Added new NaN prevention checkbox over 'HeighMap Texture Blend' node + * Added support to Rendering Platform selection on templates API + * Not all templates have it implemented + * Added both switch and nomrt tags into Rendering Platforms list + +v1.8.9 rev 10: +* New Nodes: + * Bone Blend Weights + * Only compatible with Unity 2019.1 or above and template type shaders + * Bone Blend Indices + * Only compatible with Unity 2019.1 or above and template type shaders + +* Fixes: + * Fixed issue on some port results not being correctly written on GBuffer pass over URP v.11 + * Fixed yet another issue with ransomned property names + * Fixed redefinition error on 'Triplanar Sample'node + * Fixed undeclared standard surface Tessellation properties for both Edge Length and Edge Length with Cull + * Fixed warning on duplicates directives being set over options template type shaders + * Fixed truncation warning on Legacy Refraction over URP/PBR + * Fixed error on 'Global Array' node where index clamping was being done always with local value even on Reference setup + * Fixed multiple redefinition warnings on MultiPassUnlit template + * Fixed issue with obsolete Decal custom inspector on HDRP 10 being used on HDRP 11 + * Fixed issue on incorrect naming when creating shaders/shader functions on local packages + * Had to revert node previews render texture format to its original one + * Time based previews weren't working correctly due to lack of precision over new format + +* Improvements: + * Face type nodes now also using SRP core macros when on URP + * These macros use either VFACE or SV_IsFrontFace according to graphics API + * For Builtin pipeline custom Face macros were created similar to SRP ones + +v1.8.9 rev 09: +* Fixes: + * Limiting new XBox and Playstation Render Platform tags to Unity 2019.4 and above + * They throw an unrecognized renderer warning on older versions + * Created new HDRP package for versions 7 prior to 7.5.1 to apply correct legacy render platform tags over those + +v1.8.9 rev 08: +* New Community Sample: + * URP Reflection Probe by Dawie + * http://deenvironment.com/ + +* Fixes: + * Fixed dummy render texture used when previews are off being lost on hot-code reload + +v1.8.9 rev 07: +* Fixes: + * Fixed compilation errors shown when building with HDRP 10 Lit shaders + * Fixed incorrect normal usage order when dealing with Decals on HD Lit + * Fixed detected leak on nodes previews + * Fixed minor typo on matrix label over 'Global Array' node + +* Improvements: + * Updated Playstation and XBox HDRP template's render platforms + * Updated Render Platforms on Standard Surface with new Playstation and XBox + * Decreased memory usage by previews + * Added new 'Disable Node Previews' option on Preferences panel + * Completely disables all node previews to gain extra performance on large graphs + +v1.8.9 rev 06: +* Fixes: + * Fixed issue with property nodes set in Fetch mode not properly releasing their property names + * Sampler state generation now takes node variable mode into account to prevent compilation errors + * Variable declaration disabled in Fetch mode + * Fetch Lightmap Value SF 'Texture Object' node using unity_Lightmap now on Fetch mode + * Texture object and sampler state were being incorrectly declared over Unity Built In + +v1.8.9 rev 05: +* Fixes: + * Fixed compilation error on 'Voronoi' node + +v1.8.9 rev 04: +* Fixes: + * Removed duplicate Dependencies on URP Terrain sample + * Fixed issue on 'Camera Depth Fade', 'Depth Fade' and 'Surface Depth' nodes when used on vertex body alone and alongside fragment function + * Fixed incorrect code generation when using 'Depth Fade' on Surface's vertex function + +* Improvements: + * Added Diffuse Tint capabilities into Four Splats First Pass Terrain SF for URP + * User also needs to change the shader's Custom Inspector to UnityEditor.Rendering.Universal.TerrainLitShaderGUI + * A Unity restart is required after saving the shader for the Terrain inspector to correctly show the values + * This info is available inside the shader function over a sticky note + +v1.8.9 rev 03: +* New Node: + * Reflection Probe + * Only available for URP + +* Improvements: + * Added Legacy Behavior for 'LOD Fade' node over 2019 and above + * Values given by internal variable unity_LODFade.x now can be either positive (fade-out) or negative (fade-in) + * Toggling Legacy option makes that value given is similar to old one ( always positive and sum of fade in/out is 1 ) + * Added new Apply To Id over 'Voronoi' node to apply smoothess to IDs + * Behavior similar to Blender Voronoi Smooth Ids + * Added Shadow Mask option for 'SRP Additional Light' shader function + * Only available for URP 10 and above + +* Fixes: + * Fixed issue with 'Billboard' node over URP + +v1.8.9 rev 02: +* Fixes: + * Fixed conditional error thrown by Custom Lighting over Unity 2020.3 + * Correct template is now imported on SRP 7.6.0 + * Fixed issue on using undeclared clipPos variable on all URP Unlit versions + * Fixed issue on usage of undeclared struct over Decal HDRP 10 + +* Improvements: + * Internal AddRGBToHSVFunction is now static (API) + * 'HD Emission' node is now imported with main package + * Adding failsafe and error message to when used outside an HDRP shader + * Adding File mode into 'Custom Expression' node + * User can drag and drop a .cginc/.hsls file into the new Source field and will automatically include it on shader as an #include + * Function call uses value set on Name + * Can also automatically add precision suffix into call via the Precision Suffix toggle + * Behavior similar to Shader Graph + +v1.8.9 rev 01: +* Fixes: + * Fixed issue when using Tessellation on Standard Surface type shaders over iOS + +v1.8.9 rev 00: +* Improvements: + * Added Safe Normalize option into 'Normalize' node to prevent division by zero warnings + * Added Safe option when Normalize is toggled on 'Transform Direction' node to prevent division by zero warnings + +* Fixes: + * Fixed issues with HDRP Decal template on v10.3.2 + * Fixed issue on 'Get Local Var' node syncing with its 'Register Local Var' node counterparts type change too late leading to port type issues over nested shader functions + +v1.8.8 rev 14: +* Improvements: + * Added new Receive SSR Transparent into HDRP Lit v10.x.x + +* Fixes: + * Removed unnecessary DX11 debug symbols from all URP PBR templates + * They were causing compilation errors over users on Windows 7 + +v1.8.8 rev 13: +* New Shader Function: + * Stereo Screen Pos + * Transforms a Screen Position value from non Stereo to VR Stereo + +* Fixes: + * Fixed View to World transform over 'Transform Position' node + * Fixed issue on concurrent late opening over materials, shaders and shader functions + +* Improvements: + * ASE shaders can now be opened while in Play Mode over Unity 2018.4 if no SRP template is required to be imported + * Renamed legacy HDRP and URP 7xx packages to explicitly show version range + * 'HDSRPTemplates 7xx (Legacy)' to 'HDSRPTemplates 7xx - 9xx (Legacy)' + * 'USRPTemplates 7xx (Legacy)' to 'USRPTemplates 7xx - 9xx (Legacy)' + * To avoid GUID conflicts renamed files have new GUID + * Due to how Unity importer works old files are maintained in project + * These can be safely deleted from project + +v1.8.8 rev 12: +* Improvements: + * Added directive ASE_USING_SAMPLING_MACROS when Use Sampling Macros is active + * To be used inside 'Custom Expressions' for multiple sampling behaviors + * Added Sampler State port into Bidirectional Parallax Mapping SF + * Only visible when new Unity 2018 or Higher toggle is active + * Added option "Update on Scene save" into ASE Preferences to lock SceneSaveCallback usage (Ctrl+S) + +* Fixes: + * Fixed incorrect sampler declaration on 'Custom expression' node over Standard surface when Use Sampling Macros is active + * Fixed Bidirectional Parallax Mapping SF issues when Use Sampling Macros is active + * Fixed issue with incorrect loading of Depth Vffset values on Standard Surface node + * Fixed potential issue with trying to set custom data types into 'Texture Sample node's Tex port + +v1.8.8 rev 11: +* Fixes: + * Fixed issue with Reconstruct World Position From Depth SF on both URP and HDRP v7.5.3 + +* Improvements: + * Ported Omni Decal sample to URP + +v1.8.8 rev 10: +* Fixes: + * Fixed incorrect templates package import over new SRP v7.5.3 + * Fixed visual issue with both Remap Sliders and Remap Sliders Full custom material drawers + +v1.8.8 rev 09: +* Improvements: + * Added new Write Depth option over URP PBR templates + * If Early Z option is selected SV_DepthLessEqual semantic is used instead of SV_Depth + * Added new Sample interpolator attribute on 'Vertex To Fragment' node + * Interpolates at sample location rather than at the pixel center + +v1.8.8 rev 08: +* Fixes: + * Fixed retro-compatibility issue on 'Texture Sample' node input port data + * Fixed code redefinition issue on 'Triplanar Sampler' node + +v1.8.0 rev 07: +* Improvements: + * Internaly deprecating custom NoKeywordToggle attribute in favor of Unity's native ToggleUI when on Unity 2018.1 or higher + * 'Toggle Switch' node now has option to deactivate keyword creation by its drawer + +* Fixes: + * Fixed missing end pass tag over Double Pass Unlit template used on Multipass Distortion sample + +v1.8.8 rev 06: +* Fixes: + * Fixed issue on custom values set on template modules (Blend,Cull,Depth,etc) being overwritten when reloading shader + * Fixed issue on duplicating local variables when registered with different precisions across multiple nodes + +v1.8.8 rev 05: +* Fixes: + * Fixed compilation error on 'Linear Depth' node both on URP and HDRP + * Fixed issue with canvas screenshot while window is maximized over Unity 2020.2 + * Fixed issue with sampling macros usage on 'Outline' node leading to compilation errors + +* Improvements: + * Added info message for Unity 2019.4 or higher when async shader compilation is active + * Can be turned off via Preferences > Amplify Shader Editor > Show Shader Async. Compilation Message + * 'Diffusion Profile' node now makes use of new Material Property Drawer introduced on HDRP 10 + * Only on Unity 2020.2 or higher + +v1.8.8 rev 04: +* Fixes: + * Fixed Decals not showing correctly on HDRP 10 Lit template + +v1.8.8 rev 03: +* Fixes: + * Fixed issue with Distortion feature over HD Unlit templates + * After compiling, the user may need to switch Surface Type from Transparent to Opaque and then back to Transparent over the Material Inspector + * This is due to some internal properties which need to be set by Unity's internal HD Unlit material inspector + * Fixed compilation issue with Tessellation when creating a URP/HDRP shader with multiple shader lods + * Fixed issue when updating shaders with multiple lods using deprecated templates + +v1.8.8 rev 02: +* Fixes: + * Fixed Update button message not refreshing correctly + * Fixed multiple editor visual issues when using ASE under the iOS platform + * Fixed Fetch Lightmap Value SF setting incorrect instructions for its Decode function over URP on Gamma color space + * Fixed issue with new Shadowmask feature over URP PBR 10 + +* Improvements: + * Added better fallback to shaders created with deprecated (and already inexistent) templates + * Refactored shown message by Update button tooltip + * Added new Exposure option and LOD port for 'Grab Screen Color' node (Only active on HDRP) + +v1.8.8 rev 01: +* Fixes: + * Fixed issue on 'Billboard' node with Ignore Rotation toggled over HDRP + * 'Custom Expression' node non void return test now takes internal expression mode into account + * Fixed issue with Final Color x Alpha option deactivation on Universal PBR + +* Improvements: + * Refactored how custom ASEBegin and ASEEnd decorators are placed over shader properties + * Responsible for adding the Open In Shader Editor button over Unity native inspectors and refreshing material property values over ASE canvas respectively + +v1.8.8 rev 00: +* Fixes: + * Fixed SSAO issue over Universal 10 PBR template + * Fixed issue with GPU instancing and Stereo VR on multiple Builtin Legacy templates + +v1.8.7 rev 18: +* Fixes: + * Fixed missing ASE Pragma tag over HDRP 10 Decal template + +* Improvements: + * Added new DepthNormals and GBuffer passes over Universal 10 PBR template + +v1.8.7 rev 17: +* Fixes: + * Fixed issue with debug display across multiple HDRP 10 templates + * Fixed 'Compile and show code' button not working over ASE custom shader inspector on Unity 2020.2 + +* Improvements: + * Added new strip #line directives over ASE custom shader inspector on Unity 2020.2 + +v1.8.7 rev 16: +* Fixes: + * Fixed multiple _BlendMode issues across all HDRP templates + * Fixed issue with using custom meshes on standard surface custom material inspector over 2020.1 and above + +v1.8.7 rev 15: +* Fixes: + * Automatically converting obsolete custom inspectors from HDRP v.7/8/9 when reading shaders into HDRP 10 + * Bumped internal HDRP version control to force new HDRP 10 templates to be unpacked + +v1.8.7 rev 14: +* New Node: + * Sticky Note + * Allows user to add notes directly on the ASE canvas + +* Improvements: + * Updated HDRP templates to be compatible with SRP 10 + +* Fixes: + * Fixed issue with inverted depth dir on Reconstruct World Position From Depth SF over HDRP 8 and above + * Fixed minor issue over Tags foldout on templates node properties + * Added missing SRP versions into ASE Package Manager + * SRP v.8.3.1 + * SRP v.7.5.1 + * SRP v.7.5.2 + * SRP v.9.0.0 Preview 71 + +v1.8.7 rev 13: +* Fixes: + * Fixed issue with capturing canvas screen shot while maximized + * Removed multiple incorrect port restrictions over 'Triplanar Sample' node + * Fixed issue on incorrect template behavior if on a template inline option its internal property is selected via the the inline dropdown + * Fixed issue on template options type set to inline but with no inline property selected + * Fixed issue on losing inline properties between canvas + +* Improvements: + * 'Dither' node now has new SS input port to be able to use custom sampler states + +v1.8.7 rev 12: +* Fixes: + * Fixed issue with removing Header attributes + +v1.8.7 rev 11: +* New Sample: + * Transparent Cutout for both URP and HDRP + +v1.8.7 rev 10: +* Fixes: + * Fixed issue on user not being able to use the dot/period character on Header attributes + * Fixed issue on Header attributes not being correctly shown on 'Color' node + +v1.8.7 rev 09: +* Improvements: + * User can now specify multiple headers for each property + +v1.8.7 rev 08: +* Improvements: + * Added new No Interpolation option into 'Vertex To Fragment' node + * Added new Header attribute for property type nodes + * Added new No Keyword Toggle attribute for 'Float' node + * Added new Remap Slider custom drawer for 'Vector4' node + * User must specify min limit and max limit on Z and W coordinate respectively + +v1.8.7 rev 07: +* Fixes: + * Fixed issue on 'Texture Sampler' node incorrectly generating sampler states when its R,G,B,A ports were being used + +v1.8.7 rev 06: +* Fixes: + * Fixed compilation error on Built-in RP with 'Grab Screen Color' node when Auto-Register is turned on over Unity 5.6 and above + +v1.8.7 rev 05: +* Fixes: + * Fixed issue on 'Indirect Diffuse Light' node not showing correct results over Builtin templates on Unity 2019 + * Fixed issue on SubShader body not being correctly filled if main master node's pass is disabled + * Fixed issue on incorrect clip over holes usage on URP Terrain sample + +v1.8.7 rev 04: +* New Shader Function: + * Normal From Texture + +Fixes: + * Fixed issues on Normal From Height shader function + * Fixed issue on ASE window attempting to import templates when entering in Play mode + * Fixed issue on 'Function Switch' node not updating correctly when on Reference mode + +* Improvements: + * Empty textfield value on 'Function Subtitle' node now removes the sub-title over its shader function node + * Added new Clear Log on Update option into ASE preferences (on by default) + * Clears an ASE log window each time the user hits the Update button + +v1.8.7 rev 03: +* Shader Functions: + * Removed High Quality option from Normal From Height shader function + * This will be later added on a separate shader function + +* Fixes: + * Inline code from set by 'Custom Expression' node now placed under their own scope { (...) } to prevent duplication errors + * Fixed issue on Procedural Texture type not having a texture to wire correspondence over 'Texture Sampler' node + +v1.8.7 rev 02: +* IMPORTANT - Node renamed: + * 'Break To Components' node renamed to 'Split' to decrease its canvas size + +* New Shader Functions: + * Bicubic Precompute + * Bicubic Sample + +* Fixes: + * Fixed issue on 'Break To Components' node disabling connections on loading it from disk + * Fixed issue on duplicate error thrown when multiple Normal From Height shader functions are used + +v1.8.7 rev 01: +* Shader Function Removed: + * Procedural Sample 2D Array was removed + * Procedural Sample 2D now renamed to Procedural Sample and has internal options that allow usage with 2D Array and more + +* Improvements: + * Added Fast and High Quality options to Normal From Height shader function + * Improved error messages thrown by 'Custom Expression' node + * Renamed Procedural Sample 2D to Procedural Sample and added Sample Mode option + * Planar 2D + * Planar 2D Array + * Triplanar 2D + * Triplanar 2D Array + +* Fixes: + * Fixed issue on only converting CRLF to LF and not CR to LF when reading templates or using pasted code on 'Custom Expression' nodes + * This lead to inconsistent line ending warnings being thrown + * Fixed issue on some warnings from 'Custom Expression' node no being clickable on log to select which node they were thrown from + +v1.8.7 rev 00: +* New Shader Function: + * Procedural Sample 2D Array + +* Improvements: + * Improved Procedural Sample 2D shader function + +v1.8.6 rev 02: +* Fixes: + * Fixed division by zero warning on 'Gradient Sample' node + * Fixed issue on 'Static Switch ' node incorrectly adding suffixes into fetched custom keywords + * Fixed issue with attempting to register duplicate property names when reading 'Static Switch' node meta from old ASE versions + +v1.8.6 rev 01: +* New Shader Function: + * Procedural Sample 2D + +* Fixes: + * Fixed issue with duplicate generated code over 'World Reflection' node + +v1.8.6 rev 00: +* Improvements: + * Improved Plane Clip sample + +v1.8.5 rev 06: +* Fixes: +    * Locking 'Decode Depth Normals' usage to Builtin pipeline and informing of that when used on SRP +        * Was currently generating compilation errors over SRP +    * Fixed issue on Auto-Register flag over property nodes not being correctly registered in certain cases +    * Fixed issue where graph sampling macro flag was incorrectly being set by non main master nodes + +* Improvements: +    * Auto-register check on texture property type node also register sampler if 'Use Sampling Macros' flag is enabled on master node +    * Adding support for mask maps over 'Four Splats First Pass Terrain' shader function +        * Only available on SRP and output node must have 'Use Sampling Macros' flag turned on + +v1.8.5 rev 05: +* Fixes: + * Fixed issue with incorrect values returned from nodes using internal 'Texture Object' instances + * Fixed duplicate uv declarations issue when being requested different sizes by 'Texture Sampler' nodes + * Fixed duplicate directives issue caused by adding directives on both 'Outline' node generated surface and main one + +v1.8.5 rev 04: +* Fixes: + * Fixed issue on texture node types auto-sampler generator + +v1.8.5 rev 03: +* New Sample: + * Plane Clip + +* Fixes: + * Fixed issue on 'Blend Normals' node preview not taking SRP options into account + * Fixed visual issue on node properties menu over nodes: + * Template Parameter + * Template Local Var + * Template Vertex Data + * Template Fragment Data + +* Improvements: + * Simplified 'Template Parameter' usage + * User no longer need to choose scope to parameters to be available + * New Advanced View toggle added to switch to old view + * Added widget on 'Texture Coordinates' node to change output size directly from the node + +v1.8.5 rev 02: +* New Community Shader Function + * Depth Masked Refraction by @saismirk + +Fixes: + * Fixed incorrect uv variable name being used when set is greater that 3 + * Fixed incorrect swizzling when using texture sets on vertex data over surface shaders + * Fixed issue over texture array tool on not being able to use compressed formats + +v1.8.5 rev 01: +* Fixes: + * Fixed issue regarding uv coordinates usage with tessellation on URP PBR template + +* Improvements: + * Replaced fmod instruction usage on 'Remainder' node by faster true remainder calculation + +v1.8.5 rev 00: +* Fixes: + * Fixed desync issue between graph and master node sampling macro flag + * Fixed unknown INSTANCEID_SEMANTICS enum value being thrown on legacy HDRP + +v1.8.4 rev 04: +* Fixes: + * Fixed issue on 'Substance Sampler' node + * Fixed incorrectly drawn preview on Unity 2018 and above + * Prevented incorrect ports types being set when texture order is internally changed on Substance + * Fixed variable redefinition on 'Gradient' node when used on shader functions + * Fixed duplicate issue when declaring cbuffers on both outline and main surface shaders + * Fixed URP Terrain sample layer composition + +* Improvements: + * 'FWidth' node now throws an ASE console error when connected to non-fragment ports + * Also generates dummy value to prevent compilation error + * Added terrain holes support on Four Splats First Pass Terrain shader function + * Activate Holes option + * Added new Final Color x Alpha option on URP PBR template + * Required to correctly blend terrain layers + +v1.8.4 rev 03: +* Fixes: + * Fixed Color Mask MRT Id not being written on inline properties + * Caused HDRP Lit shaders to become invisible when compiled in some versions + +v1.8.4 rev 02: +* New Template: + * Legacy/Lit + * Mimics behavior of standard surface but without some of its limitations + * Can override Baked GI + * Removes limitation of using nodes like 'Indirect Specular Light' only on Custom Lighting + +* Fixes: + * Added missing support for per-pixel normals in terrain shaders for URP (still requires adding the keyword separately) + * Fixed issue with alpha clip threshold not working properly in all cases when using the HDRP Lit template + * Fixed issue with template loading that was not catching global variable in certain situations (API) + * Fixed rare issue where changing shader templates could cause the options to fail to load properly due to not finding the new master node + * Fixed issue on Depth Texture macro declaration being incorrectly duplicated when already present on template + * Now depth related nodes can be correctly used on Particle Alpha Blended template + * Fixed issue on uncaught exception when attempting to load an in-existent Assembly-CSharp-Editor assembly + * Could happen when attempting to load invalid nodes + * Fixed issue on not being able to connect 'Texture Object' nodes to 'Register Local Var' node + * Fixed issue on vertex instructions generated by outline fragment ports to be correctly written on its vertex code + * Fixes 'Camera Depth Fade' usage on 'Outline' node + +* Improvements: + * Updated the Four Splats First Pass Terrain shader function to include a new option for SRP terrain to allow per pixel normals + * 'Static Switch' node + * Now allows editing of certain parameters while in Fetch mode + * Now allow the explicit naming of the keyword created besides the automatic one with a lock button + * Forcing vertex position w component to 1 when setting a new offset or position over Standard Surface type shaders + * Prevent real-time shadow issues on vertex manipulation + +v1.8.4 rev 01: +* Improvements: + * Added "Open in Shader Editor" button into SRP materials (needs shader save) + * Now SRP materials update ASE editor property values while the editor is open (needs shader save) + * Remove dependencies for custom shader inspector (now, allows deleting the file) + +* Fixes: + * Fixed Dots instancing option in URP unlit + * Fixed UV generation in Mesh Decals template + * Fixed Normals and Emission Bias in Mesh Decals template + +v1.8.4 rev 00: +* New HDRP Samples: + * Added new 'Decal Muddy Ground' and 'Decal Scifi Panel' HDRP samples using various types of decals + +* Improvements: + * Added automatic 'Open and Save All' button in shader function files that tries to compiled all dependency shaders and shader functions + * Texture Array tool now allows to create an asset file representing all options in order to save work for later + * Texture Array no longer locks width and height at power of two for more recent versions of unity + * Added clip shadow threshold and alpha to coverage options to URP PBR and URP Unlit shaders + +* Fixes: + * Fixed leak in the automatic template importer + * Template importer now properly skips non-shaders files when checking for changes + * Fixed issue with properties in fetch mode not loading correctly and making some property names hostage + * Fixed issue with UVs generation in specific situations where it would create variables with the same name + +v1.8.3 rev 03: +* Improvements: + * Global macros sampling option has been removed in favor of another that is set by the shader (older shader load with this option OFF while new ones start with it ON) + * Made property panel option labels flexible to the width of the panel + * Some help text added to 'Sampler State' node + +* Fixes: + * Fixed issue with assembly definition files where nodes outside of the assembly would fail to load + * Fixed issue of emission channel not working in HDRP decal template + +v1.8.3 rev 02: +* New 'Sampler State' Node: + * Allows using the default sampler state of a texture or the creation of a new one with specific options (versions prior to Unity 2018.1 have limited support) + +* Improvements: + * You can now use custom sampler states when sampling, however, in order for this to work you need to activate the option at Preferences > Amplify Shader Editor > Sampling Macros + * Activating this may cause some issues in specific situations, namely, custom expressions that do sampling must be converted to use macros as well so for now this option is OFF by default + * There are two new connection types, one for texture arrays and another for sampler states which are supported in function nodes and custom expression nodes + * Texture Array node as been deprecated in favor of the regular 'Sampler' node which now supports texture arrays and works inside shader functions + * 'Parallax Occlusion Mapping' node and 'Triplanar Sample' node now automatically detect if the input is a texture array and no longer use a toggle to turn ON the support + +* Fixes: + * Fixed issue with URP 2D templates accessing the wrong uv set + * Fixed Bitangent calculation in SRP which wasn't taking tangent sign into account + * Fixed issue with 'show and compile' button in shader inspector in unity 2020.1 + +v1.8.3 rev 01: +* Fixes: + * Fixed issues over 'Substance Sample' node + * Fixed compilation error on Unity 2018 and above + * Fixed normal texture port detection on Unity 2018 and above + +v1.8.3 rev 00: +* New HDRP Sample: + * Added new 'TV' HDRP sample using Vector Displacement Maps (VDMs) + +* New Shader Option: + * URP PBR template now has a 'Fragment Normal Space' option that allows selecting between Object, World and Tangent space outputs for the master node + +* Improvements: + * Added normal space output option for 'Triplanar' node + * Added help text for the PPS helper tool + +* Fixes: + * Fixed issue with world view dir calculation in URP PBR template + * Fixed issue with normal unpacking and scaling in SRP + * Removed HDRP dependency in ASE asmdef file + * Fixed the mosaic PPS sample that was conflicting with assembly definition files + * Fixed issues with focusing the editor window would sometimes select text fields or prevent nodes from being interactive + * Fixed 'Diffusion Profile' for HDRP 6.X.X + +v1.8.2 rev 01: +* Fixes: + * Fixed Fixed issue with auto generated UVs sometimes generate the UVs twice and failing to compile + +v1.8.2 rev 00: +* Fixes: + * Fixed 'Rejection' node to support multiple length input types just like 'Projection' node does + +v1.8.1 rev 04: +* New HDRP Template + * Decal + +* Improvements: + * Added new port to 'Voronoi' node that outputs the UVs of the current voronoi cells + * Added support for MRT for ColorMask, Blend and BlendOp in templates and template Options + * AlphaToMask is now it's own separate module that can be activated independently and supports inline properties + * Changed UV creation to support pre-calculated UVs in templates (ie: decals) + +* Fixes: + * Fixed Texture Array Creator tool in order to properly allow signed and higher bit texture formats + * Voronoi now properly creates UVs in all situations and preview was updated accordingly + * Fixed issue with instancing macro not being detected properly and being included in the wrong place occasionally generating errors in URP + +v1.8.1 rev 03: +* Improvements: + * Improved URP and HDRP templates in order to minimize their CBUFFER contents + * Updated libraries for SRP 7.3.1 and 7.4.1 + +* Fixes: + * Fixed issue with instance ID node not working correctly in URP due to templates not properly detecting the existing ones + * Fixed issue with unused tessellation properties showing up in the shader inspector + * Fixed issue with 'Reconstruct World Position From Depth' node that was preventing from compiling when used with 'Depth Fade' node + * Fixed issue with 'Reconstruct World Position From Depth' node that wasn't working correctly in SRP 7.4.X and up + +v1.8.1 rev 02: +* New Shader Functions: + * And + * Or + * Projection + * Rejection + +* Improvements: + * Added more description text to custom expression node + * Live update doesn't kick in when editing a field + * Shader Functions options label size resize according to the panel width + +* Fixes: + * Fixed 'Texture Sample' node and 'Texel Size' node previews so that they update when it's referenced texture changes + * Fixed issue with certain namespaces not being available when Assembly Definitions files are present + * Fixed samples by adding new Assembly Definition files for samples that contain their own scripts + * Fixed issue with sampler states option not working if reference node was not compiled + +v1.8.1 rev 01: +* Improvements: + * Added AssemblyDefinition file and made it so nodes can be found in the main editor assembly besides ASE assembly + * If you which to extend ASE with your own node and you already use your own assembly file you need to add ASE as a dependency + +* Fixes: + * Fixed issue with function nodes not saving their GUID correctly to the metadata + * Fixed issue with function switch nodes not saving correctly when inputs were left unconnected + * Fixed issue with reading options due to system cultural differences + * Fixed issue where clipboard copy/pasting was not respecting system cultural differences + +v1.8.1 rev 00: +* New Shader Options: + * Added new option called 'DOTS Instancing' that provides initial support for hybrid renderer for URP and HDRP + * Works for both latest V1 and V2 (check unity docs) + * URP requires shader model 4.5 in order for it to work + * Some properties nodes now have a new 'Hybrid Instanced' option when set to property mode + +* Improvements: + * CBuffer properties are now ordered by datatype for performance reasons + +* Fixes: + * Fixed issue with tessellation in HDRP where tessellation was not measuring the position correctly when relative camera was ON + * Fixed issue with the new 'Field' option type that wasn't reading float values correctly in all situations due to system cultural differences + * Fixed typo with the 'Trigonometry Operators' category + +v1.8.0 rev 03: +* New Shader Options: + * Added Translucency and Transmission options for URP + * Options are based on Built-in renderer ports respectively + * New fields are generated for both but can be manipulated as 'Inline Properties' in property panel + +* New 'Compare' node: + * Replaces all the now deprecated 'Compare XXX' nodes, this node should be easier to work with since it does ternary operations and allows for any kind of vector comparison + +* Improvements: + * 'Voronoi' node ID port now returns a vector 2 ID instead of a single float value + +* Fixes: + * Fixed issue with instanced properties marked as auto register not working inside shader functions + * Fixed issue with 'Function Switch' node that was causing some nodes to run even if unconnected + * Fixed issue with 'Decode Lightmap' node that was not compiling correctly in all situations + * Other small changes and fixes to last revision + +v1.8.0 rev 02: +* New Shader Options: + * Added Tessellation options for URP and HDRP + * Options are based on Built-in renderer options supporting Fixed, Distance-Based, Edge Length and Edge Length With Cull mode, with or without Phong displacement + * By default Float fields are generated at the bottom of the materials inspector but can be replaced by 'Inline Properties' allowing for further field customization + +* Improvements: + * Templates API now supports new 'Field' options that create Int or Float fields that can act when values change + * Templates API now support 'SetMaterialProperty' action that allows a 'Field' to interact with the value in the material inspector + * Added Q as an alternative panning modifier key (for trackpad users) while Q+Alt zooms (order is important due to Alt being used for other actions) + +* Fixes: + * Fixed issue with Start Screen icon on MacOS editors + * Fixed issue with templates not properly detecting floating values + * Fixed issue with log window and palette window producing layout errors + * Fixed issue with live editing mode not working properly with shader functions and producing errors + * Fixed 'Texel Size' node issue where variable declaration was not respecting the SRP batcher and breaking it in the process + * Fixed issue with auto spacing of shader function titles + * Fixed/Changed refraction for both URP and Built-in due to issues with webGL version + +v1.8.0 rev 01: +* Improvements: + * Now 'Texel Size' and 'Texture Transfom' nodes also contain the 'None' option for consistency + +* Fixes: + * Fixed issue with start screen window in Unity 5.6 + * Fixed issue with 'Texture Coordinates' node generating multiple texture references in some occasions + * Fixed 'Texture Coordinates' losing it's selected reference option on port connection + +v1.8.0 rev 00: +* New Shader Functions: + * Bacteria + * Bricks Pattern + * Dots Pattern + * Grid + * Herringbone + * Hex Lattice + * Houndstooth + * Smooth Wave + * Spiral + * Stripes + * Truchet + * Whirl + * Zig Zag + +* Improvements: + * Updated some shader functions to expose their internal data + +* Fixes: + * Fixed default value for start screen option + * Fixed context menu showing shader templates not yet imported on first install + * Fixed drawing issues with slider in 'Float' node in the new Unity UI + +v1.7.9 rev 02: +* Improvements: + * Added Refraction option with respective ports to URP that works like the built-in Refraction port + * Added versioning to templates so that they can track changes and import new versions if necessary + +* Fixes: + * Fixed issue with start screen showing the wrong change log + * Fixed issue with start screen not always respecting the selected option + * Fixed issue with 'Fresnel' node when loading a shader from an older version of ASE + * Fixed loop detection check for 'Get' node in certain situations + * Fixed menu listing for templates with duplicated names + * Fixed 'VertexID' node for HDRP causing errors due to motion vectors + * Fixed inline properties being broken on certain template internal pass ordering + +v1.7.9 rev 01: +* Improvements: + * Start screen option is now a dropdown to allow for more control of how it behaves + * Added more options to the preference window + * Option to prevent automatic import of SRP templates + * Option to force the use of Unity's macros for sampling + * Option to allow or prevent the use of ASE define symbol + +* Fixes: + * Included missing files for 'Diffusion Profile' node from last release which prevented the use of the new default inspector option + * Fixed issue with 'Gradient Sample' node that was not generating the component channel correctly + +v1.7.9 rev 00: +* New Start Screen: + * New window that will popup when on a new session starts and/or if a new version is released (can be dismissed) + * Provides easy start up links for the wiki and contact channels + * Streamlines the process of importing ASE samples for each rendering pipeline + * Automatically tracks the release of new versions + +* New Preferences Entry: + * Currently only controls the start screen settings but in the future it will contain many more options that are currently hidden + +* New Shader Function: + * Random Range + * Returns random value between a minimum and maximum range values + +* Improvements: + * Removed alpha to coverage alpha test check for consistency between pipeline and setups + * Added check to custom shader inspector and updated missing features like keywords popups and other small changes that came with unity 2019.3 + * Added new option to 'Diffusion Profile' node to be able to create the unity default profile inspector for users that need to share their shaders + * Changed the color of Int ports to white for proper differentiation between Float and Int + +* Fixes: + * Depth texture is now uses proper macros even when using global texture samplers to prevent duplication errors + * Added infinite loop detection to 'Get Local Var' nodes to prevent the case where you can change the 'Get Local Var' node reference to itself + * Fixed Issue with diffusion profile drawer not being able to change profiles if ASE window wasn't open + * Fixed issue with outline in surface shaders not respecting the selected precision type + +v1.7.8 rev 02: +* New Property Attributes: + * Remap Sliders attribute for Vector2 node that creates a min-max slider in the 0-1 range + * Single Line Texture attribute for texture properties nodes that minimizes texture object field into single line fields + +* Fixes: + * Fixed fog color and ambient color node values in HDRP + * Fixed issue with Fabric and Hair HDRP templates not correctly writing to depth offset in all shader passes + * Fixed custom expression precision types that didn't respect the selected choice in all cases and added a new Inherit option + * Fixed possible issue with saving files when path is null + +* Improvements: + * Improved loading of shaders by preventing unnecessary loads of other types of assets + * Added warning with fix button to diffusion profile property drawer for when profile isn't present in the profile list + * Shader functions names now have automatic spacing when searched in the palette + * Added a direct dependency check for shader function files that allows to search which shaders and shader function are currently directly using it + * Templates context entry generation is now done by name to prevent random sorting + +v1.7.8 rev 01: +* New HDRP Templates: + * Hair + * Fabric + +* New Shader Function: + * Inverse Lerp + * Inverse operation of the 'Lerp' node + +* Improvements: + * Update HD templates to v.7.1.8 and above + +* Fixes: + * Fixed issue with 'Component Mask' node preview not correctly showing alpha channel in all situations + +v1.7.8 rev 00: +* Fixes: + * Fixed issues with 'Function Switch' node incorrectly displaying reference nodes and not properly ordering when in Reference mode + +v1.7.7 rev 06: +* Fixes: + * Fixed 'Parallax Occlusion Mapping' node texture array sampling in LW/URP + * Fixed issue with 'Light Attenuation' node not taking into account vertex offset in URP templates + +* Improvements: + * Added extra pre pass option for Lightweight and Universal RP that allows for custom outline passes + * World position dependent nodes will now take vertex offset into account over LW templates + +v1.7.7 rev 05: +* Fixes: + * Fixed issues when reading shader over updated template + * Fixed 'Light Attenuation' issue on URP 7.2.X which was causing rendering errors + +* Improvements: + * World position dependent nodes will now take vertex offset into account over default Unlit and URP templates + * Improved Diffusion Profile support in HDRP 7.2.X + +v1.7.7 rev 04: +* Fixes: + * Fixed compatibility issues with HDRP v7.2.0 and above + * Fixed issue with 'Indirect Diffuse Light' node on Normal port not properly working over Lightweight RP + +v1.7.7 rev 03: +* Fixes: + * Fixed issue on Unity ignoring Emission channel values set over Debug Port + * Fixed issue with multiple uses of 'Voronoi' node over a graph + * Fixed helper window colors in personal skin + * Fixed emission contribution on baked lighting + * Fixed GUID conflicts between Lightweight and Universal samples + +v1.7.7 rev 02: +* Fixes: + * Fixed incorrect values given by time related nodes + * Fixed shadow compilation issue on HD Lit template + * Added null checks on updating shader over master node to prevent saving issues + +* Improvements: + * Decode Directional Lightmap shader function now compatible with all pipelines + * Added events that can be registered externally which indicate shader type change and shader save (API) + * IOUtils.OnShaderSavedEvent called when shader is saved + * IOUtils.OnShaderTypeChangedEvent called when shader + * Registered functions must receive three arguments + * Shader shader: Current shader being modified + * bool isTemplate: Current shader type is template based + * string type: GUID of template in use or string.empty if Standard Surface + +v1.7.7 rev 01: +* Improvements: + * Some adjustments were made to the Decode Lightmap's Instructions port + * Port is set be only visible when on SRP + * ASE automatically sets Unity's default instruction values if no value is connected to it + +v1.7.7 rev 00: +* Fixes: + * Fixed multiple connections on Wire node when Alt + dragging nodes from it + * Fixed issue with normal map usage over URP PBR + +* Improvements: + * Added new previews: + * Heightmap Texture Blend + * Parallax Offset + * Clip Planes + * Fog and Ambient Colors + * Fog Params + * Instance ID + * Object To Clip + * Object To View + * Shade Vertex Lights + +v1.7.6 rev 02: +* Fixes: + * Assured latest fix for time related nodes over SRP is only applied on latest versions + * Fixed issue on declaring variables inside CBuffer that are already on native template + +v1.7.6 rev 01: +* Fixes: + * Fixed usage of legacy variables over SRP on time related nodes + * Time + * Time Parameters + * Sin Time + * Cos Time + * Fixed issue on HD Unlit Vertex Offset input code not being set on all passes + +v1.7.6 rev 00: +* New Shader Function: + * SRP Additional Light + * Returns SRP's additional lights information calculated with a selected lighting mode + +* Improvements: + * 'Light Attenuation' node on Lightweight/Universal now outputs only the attenuation of the main light + * Before it outputted the sum of all light attenuations which didn't have a practical use + +v1.7.5 rev 03: +* New Templates: + * Universal Experimental 2D Lit + * Universal Experimental 2D Unlit + +* Fixes: + * Fixed issue on incorrectly setting a wrong instanced block name on non-main passes when using GPU Instancing over templates + * Added Safe Power option into both 'Power' and 'Fresnel' nodes + * Ensures base for power operation is always greater than zero to prevent NaN over the result + * Fixed 'Indirect Diffuse Light' and 'Indirect Specular Light' nodes preview when Normal Space option is set to World + * Fixed 'Fresnel' node preview as it wasn't showing the correct result when scale was different than 1 + * Fixed Alpha Clip issue across multiple Unlit Lightweight and Universal template versions + +* Improvements: + * Improved mouse focus behavior when ASE is not focused + * Migrated Lightweight samples into Universal RP + +v1.7.5 rev 02: +* Fixes: + * Fixed issue with incorrect _ST variable declaration on templates over 'Texture Array' node + * Fixed issue on 'Grab Screen Color' node creating a default Grab Pass when using the default grab name with Custom Grab Pass activated + * Fixed issue on 'Texture Transform' node giving incorrect values on certain connections + * Fixed node preview update for missing shader functions + * Fixed issue on 'Static Switch' node using in-existent keyword indices + * Fixed 'Static Switch' reordering issues when in Reference mode + +* Improvements: + * Added missing previews to nodes + * Ortho Param + * Projection Param + * Screen Param + * ZBuffer Param + * Clip + * Compute Screen Pos + * Texel Size + * Texture Transform + * Tweaked 'Texture Object' and 'Texture Sampler' node previews to avoid recent for AMD crashes + +v1.7.5 rev 01: +* Fixes: + * Fixed 'Color Space Double' node issue in SRP + * Fixed 'Texture Array' node ordering issue in the material inspector when on Reference mode + * Fixed issue with references lost over 'Texture Sample' on shader functions + * Small fixes and optimizations to the URP unlit template + * Fixed texture fields not being modifiable on 'Texture Sample' nodes when ASE window was not focused + +* Improvements: + * Updated 'Flow' shader function to make Strength a Vector2 input + * Improved registered local variables usage on templates + * Removed hard-code directives declaration on LWRP and added them as Port options on templates + +v1.7.5 rev 00: +* New Nodes: + * Inverse Projection Matrix + * Inverse View Projection Matrix + +* New Shader Functions: + * Noise Sine Wave + * Creates a sine wave from a given input with an added pseudo-random value + * Sawtooth Wave + * Creates a saw-tooth wave from a given input + * Square Wave + * Creates a square wave from a given input + * Triangle Wave + * Creates a triangle wave from a given input + * Checkerboard + * Created a checkerboard pattern with given colors where Frequency controls its tiling + * Ellipse + * Creates an ellipse based on given uv and dimensions + * Polygon + * Creates a polygon shape with a specified amount of sides + * Rectangle + * Creates a rectangle shape with a specified size + * Rounded Rectangle + * Creates a round rectangle shape from a given size and radius + +* Improvements: + * Added new Smooth toggle option to 'Voronoi' node + * Only available under the Cells Method + * Improved selection box inside the editor graph to match Unity's and not be version dependent + * Ported terrain sample to Universal Rendering Pipeline + * Packed inside Examples > Universal SRP Samples.unitypackage + +* Fixes: + * Fixed multiple issues regarding using instanced properties over 'Outline' node + * Fixed hard-crash when modifying pass amount over template (API) + * Fixed Native Directives display over Templates in Unity 2019.3 + * Fixed GPU instancing on Particles Alpha Blended template + * Removed Clip from From option over 'Transform Position' and 'Transform Direction' nodes + * Transform matrix was incorrect and there's no viable replacement over those nodes context + +v1.7.4 rev 02: +* New Shader Functions: + * Flow + * Creates a flow effect which can be given from a flow map. + * Twirl + * Sets a twirl effect to a given input UV. Created by The C.reator @cayou66 + * Normal From Height + * Extrapolate a normal vector from an height value + +* New Sample: + * Scale Independent Tile + +* Improvements: + * Added new Rotation Independent Scale option into 'Object Scale' node + * Tweaked 'Remainder' node to always use the % operator on Unity 2018.1 and above + +* Fixes: + * Fixed issue on loading multipass multi visible master nodes losing their names + * Fixed issue with point lights not working with instanced terrain shaders + * Fixed issue on terrain getting black when drawn instanced + * Fixed alpha test issues over deprecated HDRP Lit + * Fixed issue where not setting pass name on port options lead to incorrect option behavior (API) + * Fixed previews not updating correctly in shader functions + +v1.7.4 rev 01: +* New Template: + * Unlit for HD SRPv6.x.x + +* New Node: + * Luminance + +* Fixes: + * Fixed alpha-clip issues with legacy HD templates + * Fixed issue on incorrectly initializing custom type variables on 'Custom Expression' node + * Fixed nodes preview getting lost on loading scenes + * Fixed preview issue on 'Noise Generator' node + * Fixed preview issue on 'Panner' node + * Fixed preview issue on 'Rotator' node + * Fixed issue on ignored Passes over SubShader options appearing on both shader reload hot code reload + * Fixed issue with 'Parallax Occlusion Mapping' node when used on shader functions + * Fixed issue with setting directly the property name over its textfield wouldn't trigger the duplicates prevention system + +* Improvements: + * Updated 6.9.2 Lightweight templates to includes the same options as URP templates + +v1.7.4 rev 00: +* Fixes: + * Fixed critical error where users could not create a surface shader if no ASE window was opened + +v1.7.3 rev 00: +* Fixes: + * Fixed preview issues on multiple nodes + * Fixed incorrect template reload when multiple shaders using the same template are opened + * Fixed Ignore Rotation issues on 'Billboard' node over Lightweight RP + * Fixed issue on not importing latest SRP templates when an unregistered version is detected + * HDRP templates no longer throw console errors on Unity 2019.3 + * Fixed Alpha Clip issue on deprecated HDRPLit template + * Fixed issue on incorrectly resetting port internal data on load with matrices types + +* Improvement: + * Minor renaming on 'Baked GI' node name to 'SRP Baked GI' + * Updated URP templates to include a Baked GI port similarly to HDRP + +v1.7.2 rev 03: +* Fixes: + * Fixed issue on templates not capturing properties with certain attributes + * Fixed issue on templates inline properties not being properly set on modules if main master node wasn't the first pass + +* Improvements: + * Added Builtin Fog toggle option into Lightweight PBR template + +v1.7.2 rev 02: +* Fixes: + * Fixed issue on 'Toggle Switch' node + * Fixed abnormal behavior when reading template with more interpolators than the ones allowed by its Shader Model (API) + +* Improvements: + * Template can now read Shader Model from area outside SubShader (API) + +v1.7.2 rev 01: +* Fixes: + * Fixed issues on generating incorrect precision inputs on both 'Screen Position' and 'World Position' node + * Fixed issue on multi-pass master nodes not setting correct given shader name when created from file + * Fixed issue on WaterSample shader + * Fixed issue on 'Custom Expression' node not generating correct function code without a return statement + +* Improvements: + * Users can, like on Shader Functions, immediately name shader when creating it + * Adding Instanced option into 'Texture Transform' node + * Determines if the _ST texture transform variable is created as an instanced property + +v1.7.2 rev 00: +* Improvements: + * 'Toggle Switch' node now uses a ternary operator to prevent incorrect results on NaN inputs + +v1.7.1 rev 13: +* Fixes: + * Fixed issue duplicating certain nodes + +v1.7.1 rev 12: +* Fixes: + * Fixed issue when using more than one Octave on 'Voronoi' node + * Fixed issue on Motion Vectors pass over HD templates + * Fixed issue on generating incorrect keyword value on 'Static Switch' node using Reference Mode + +v1.7.1 rev 11: +* Fixes: + * Fixed issue on registering/unregistering internal template generated nodes over the reorder node event + * Fixed multiple issues on 'Custom Expression' node + * Fixed issue on using 'Voronoi' node over shader functions + +v1.7.1 rev 09/10: +* New Node: + * HD Emission + +* Fixes: + * Fixed issue when reading shader with missing shader function + * Fixed issue when duplicating property nodes on Fetch mode would reset property name + * Fixed issue on 'Parallax Occlusion Mapping' node incorrectly generating instanced _ST vars outside the CBuffer + * Fixed alpha cutoff issues on HD Lit templates v5.7.2 and v5.16.1 + * Fixed issue on not declaring both BakedGI and BakedBackGI on Lit template + * Fixed issue on not setting some ports with graph data over templates + +* Improvements: + * Listing on nodes is now alphabetically ordered + * Get Local Var + * Grab Screen Color + * Static Switch + * Texture Array + * Texture Sample + * Node search bar text now takes property name and inspector name into account + +v1.7.1 rev 08: +* Fixes: + * Fixed issue on 'Register Local Var' not allowing to reset name to loaded one + * Fixed Console Log issues with Personal Skin + * Fixed issue on overwriting Render Type custom values over a template(API) + * Fixed issue on local variables generation over the 'Unpack Scale Normal' node + * Fixed issue with setting special tags over template options (API) + +* Improvements: + * Added more flexibility to 'Static Switch' node + * Can have empty property names when Material Toggle is toggled off + * It no longer modifies keywords ( setting to upper, adding _ON, etc ) if Material Toggle is toggled off + * Tweaked visible options when on Fetch mode + * Added hot-fix to 2019.2 Lit template in order to generate shaders without errors when used on HDRP v7.x.x + +v1.7.1 rev 07: +* New Shader Functions: + * Derive Tangent Basis + * Height-based Blending + +* Improvements: + * Clicking on node specific messages over ASE log now jumps to which node generated it + * Changing ports types to matrix now sets the identity matrix into its internal data + * Relevant on nodes like 'Custom Expression' + +* Fixes: + * Fixed issue on incorrectly adding 0 to W channel when creating position vectors + * Fixed issue on not auto-importing templates correctly over Unity 2019 + * Fixed multiple issues regarding shader function previews + * Fixed compilation issue when using unreferenced 'Get Local Var' nodes + * Fixed issue on changing 'Static Switch' name not being reflected on referenced list + * Fixed issues with 'Texture Coordinates' and 'Texture Sampler' nodes with 'Relay' or 'Wire' nodes on Tex port + +v1.7.1 rev 06: +* Fixes: + * Fixed new and old shader templates for HDRP 6.9.X so the diffusion profile value is passed around correctly + * Fixed issue on 'Texture Coordinates' node not correctly swizzling data on template vertex functions + * Prevented Additional Directives reference lost when saving certain shader functions + +v1.7.1 rev 05: +* Fixes: + * Fixed issue on getting incorrect inline properties on templates + +v1.7.1 rev 04: +* Fixes: + * Fixed 'Diffusion Profile' node issues on SRP v6.9.X + * Fixed multiple issues regarding shader functions Additional Directives usage + +v1.7.1 rev 02/03: +* Fixes: + * Fixed issue both on creating duplicate texture ST constants and being declared out of the cbuffer + * Fixed possible issues on 'Texture Transform' node over SRP + * Fixed baked lighmap issues over Lightweight/Universal PBR templates + * Fixed SimpleTerrain sample water shader which was broken due to recent 'Screen Depth' node changes + * Fixed compilation errors on 'Voronoi' node + * Fixed issue on registering duplicate instanced variables which are already on template as non-instanced + +v1.7.1 rev 01: +* Fixes: + * Removed unused variable warning + * Broadened up Shader Function versions to apply serialized fix on Origin field + +v1.7.1 rev 00: +* Fixes: + * Fixed issue with Face related nodes not working in HDRP v6.9.0 due to bad version handling + * Fixed retro-compatibility issue with incorrectly reading Shader Function Custom Directives as Native + +* Improvements: + * Tweaked 'Get Local Var' node message thrown when no Reference is selected + * Natives UI listing is now locked on Unity 2019.3 to prevent incorrect behaviors on new UI system + +v1.7.0 rev 09: +* Improvements: + * Changing Variable Mode from Fetch to Create no longer rewrites property name on Property Nodes + * Improved property renaming when duplicating Property nodes + * Added property name to items on Material Properties list + * Can be clicked to focus on specified node + +v1.7.0 rev 08: +* Fixes: + * Fixed issue on HD Lit Diffusion Profile port being incorrectly set as type Int + * Multi Pass Master Nodes no longer reads/writes input port meta data as this must always be given by template + +v1.7.0 rev 07: +* Fixes: + * Fixed issue with the 'Diffusion Profile' node not updating from and to the material inspector + +* Improvements: + * Added new internal console inside shader canvas to more easily check ASE related messages + +v1.7.0 rev 06: +* New Shader Function: + * Non Stereo Screen Pos + * Converts a VR screen position into a non-VR one + +* Fixes: + * Fixed issue with both 'Gradient' and 'Gradient Sample' nodes on Lightweight/Universal + * Fixed 'Voronoi' node issue over templates + * 'Reconstruct World Position From Depth' now correctly works on VR + +* Improvements + * Tweaked Lightweight and Universal templates + * Pragma tag now after native includes + * Removed unused _MainTex_ST variable from Meta pass + * Shader Properties can now be fully rewritten through template options(API) + * Added Vulkan to Standard Surface Rendering Platforms + +v1.7.0 rev 05: +* New Templates: + * Added templates for Universal Rendering Pipeline + * Packed inside AmplifyShaderEditor\Plugins\EditorResources\Templates\USRPTemplates.unitypackage + +* Fixes: + * Fixed multiple issues with Lit HDRP template + * Fixed issue on not taking the 'Int' node as SRP compatible + * Fixed both 'Transform Direction' and 'Transform Position' nodes issues regarding Tangent space + * Fixed multiple issues regarding template options + * Fixed issue on incorrect reading over Depth Offset values from shader + * Minor fix on templates post-processor to prevent null pointer exceptions + +* Improvements: + * Unity global variables used as inline properties on templates are now registered so they can be correctly maintained over the final shaders + * Added LOD Cross Fade into Lightweight RP templates + * Added Inherit type into precision popup and made sure most nodes can now compile with the proper precision type + * Some nodes have a specific precision on purpose + * Improved 'Diffusion Profile' node behavior + * Added material property attribute + * Updated source code able to create profile properties in HDRP 7.X + +v1.7.0 rev 04: +* Improvements: + * When switching between shader type the connections with the same port name are kept intact + * Custom inspector for SRP 7.X is now detected automatically and upgraded from previous versions + * Templates master nodes now display the shader name in their title for better consistency +* Fixes: + * Fixed issue in SRP 7.X where certain auto defines were overriding the selected options + * Fixed issue in templates system where in certain situations defines would be set forever + * Fixed stencil options in HDRP 7.X + * Thickness port in HDRP 7.X is now always visible + * Some properties in HDRP 7.X are now override-able + +v1.7.0 rev 03: +* Improvements: + * Added support for pragma options to the template system +* Fixes: + * Fixed issue where dependent template options would be visible when it's dependency was off in some situations + * Fixed issue with wrong connection types on creation of new nodes when dragging from ports + * Fixed issue with detecting LOD parameter in templates + +v1.7.0 rev 02: +* Fixes: + * Fixed issue when selecting a shader that contains errors in 2019.3 would generate inspector errors + +v1.7.0 rev 01: +* Fixes: + * Fixed issue on incorrect initial node setup from previously saved options + +v1.7.0 rev 00: +* New Node: + * Voronoi + +* Fixes: + * Fixed issue on all templates not being available to choose over the Creates > Amplify Shader menu + * Fixed issue on Unlit absolute mode + * Fixed issue on both Lightweight templates absolute mode + * Fixed issue on 'World Space View Dir' node preview + * Fixed blinking window when 'Add'or 'Mul' nodes are dynamically changing their input ports + * Fixed issue with detection loop function that was causing massive slow downs on node connection on big graphs + * Fixed multiple issues with new Lit template + * 'Face' and 'Switch By Face' now correctly work on the latest HDRP version + * Fixed multiple issue on latest HD Lit template + * Fixed issue when selecting shaders on Unity 2019.3 + * Fixed incorrect local variable generation on multiple nodes over Standard Surface's Vertex ports + +* Improvements: + * Improved editor performance by only refreshing when needed and only updating previews that are necessary to update + * Texture array auto sorting on texture drop over Texture Array tool + * Directives can now be written both before or after (via mouse drag ) to native directives detected on template + * Added dropdown for custom editor in templates that contain the HD material inspector + * 'Depth Fade' and 'Screen Depth' can now be used on vertex shader + * Improved and optimized node search on context menu + * Node developers can now associate tags to their nodes + * Small improvement to shader function properties order when multiple shader functions are inside each other + * Improved 'Noise Generator' node + * Added new Gradient type + * Added new option to auto set noise generator values to a 0-1 range + * Added new scale input port to scale its Size input + * Extended Port options versatility when declared on SubShader (API) + * Shader Properties default values can now be set through the SetShaderProperty action (API) + * Refactored templates paths + +* Deprecated: + * Disabled ASE custom texture array inspector on Unity 2019 and above + * Marked old templates as deprecated + * These will be eliminated from the package on a future build + +v1.6.9 rev 02: +* New Template: + * Re-designed a new HD Lit template for SRP v6 and above + * Compatible with Unity's default HD material inspector + +* Fixes: + * Fixed division by zero issues on 'Blend Operations' node + * Fixed VR stereo issue in Standard Surface custom shadow caster + * Fixed issue with reorderable properties in shader function being stuck when two or more of the same SF was used inside another one + * Fixed incorrect variable naming on certain operations over both 'Transform Position' and 'Transform Direction' nodes + * Fixed issue on Input Port internal wrapper creating float3x3 with float4x4 contents + * Minor tab fixing on Unlit template + * Fixed issue on HD templates Auto-Importer + * Fixed issue on not always capturing the template custom inspector correctly + * Fixed compatibility issue with 'Diffusion Profile' node on Unity 2019.3 + +* Improvements: + * Added tag system to node search and improved how nodes are searched + * Now words don't have to be in the same order of the name to match + * Reactivated SRP Batcher compatibility + * Each UnityPerMaterial Cbuffer set in pass now contains all declared property variables + +v1.6.9 rev 01: +* Improvements: + * Added support for HDRP v6xx over Unity 2019.2 + * HDRP v5xx now set as legacy and moved into the SRP (Legacy) folder + * LWRP templates remain the same between v5 and v6 + * 'Swizzle' node is now non-destructive when connecting data with less info than selected options + +v1.6.9 rev 00: +* Fixes: + * Fixed 'Component Mask' node preview + +v1.6.8 rev 07: +* New Nodes: + * Gradient + * Gradient Sample + +* Fixes: + * Fixed nodes incorrectly moving when interacting with popup fields in recent Unity versions + * Fixed issue on incorrect size for vertex normal data on LWRP Unlit template + +* Improvements: + * Added Built-in Fog option to LWRP Unlit template + +v1.6.8 rev 06: +* Fixes: + * Fixed issue on incorrectly selecting Shader Name textfield when opening an ASE shader + * Fixed issues on incorrect uv coordinates size over 'Grab Screen Color' node + * Fixed GPU instancing and vertex offset issues on all HDRP templates + * Fixed parse issues when capturing structs inside templates (API) + * Temporarily disabled SRP Batcher as it was not properly working + +v1.6.8 rev 05: +* Fixes: + * 'Grab Screen Color' now prevents Unity macro inconsistent behavior between Unity versions + +v1.6.8 rev 04: +* Fixes: + * Fixed issues regarding Diffusion Profile usage on HDRP + +v1.6.8 rev 03: +* Fixes: + * 'Grab Screen Color' now prevents Unity macro inconsistent declaration ending between VR and non-VR compilation + * Preventing compilation errors related to GPU Instancing on SRP + +v1.6.8 rev 02: +* Fixes: + * Added missing stereo config on LW Unlit template + * Fixed Blend Mode config on HD Lit template when choosing Opaque mode + +v1.6.8 rev 01: +* Fixes: + * Fixed compilation issue with 'Grab Screen Color' node on VR + * Fixed issue on Shadow Caster pass over HD Lit template v5.16.1 + * 'Grab Screen Color' node now takes VR into account on LWRP + +* Improvements: + * Share links now have permanent lifetime + * Added new Depth Offset option into HD Lit template v5.16.1 + +v1.6.8 rev 00: +* New features: + * Added Share button that uploads select data to the cloud for easy sharing + * Added Screenshot button that takes a screenshot of the whole graph and saves it to disk + * For now this is a Windows only feature + +* Fixes: + * Fixed issue on 'Toggle Switch' node registering a toggle drawer twice causing inspector warnings + * Fixed issue on not always capturing the Fallback library on templates + * Fixed both 'HSV to RBG' and 'RGB to HSV' node previews + * Fixed issue on sometimes losing directives info on Shader Functions after being moved into a different path + * Fixed issue on Shader Function being incorrectly loaded into a separate tab after being moved into a different path + * Fixed issue on certain Pass Options only being applied to main pass Master Node + +* Improvements: + * ASE now auto-imports SRP templates if they are installed via Package Manager + * It will also import correct templates in case of user switches between versions + * User still need to open the shaders and hit the Update button so they are compiled on the correct version + * Improved canvas buttons to better represent their purpose + * Improved PPS Template under Single Pass VR + * Mosaic Effect PPS sample now fully works across VR + * Set Port Name action can now be registered on Port options block(API) + +v1.6.7 rev 06: +* Fixes: + * Fixed multiple issues on 'Custom Expression' node + * Fixed layout issue when writing input names + * Fixed issue on updating InOut/Out ports when reordering inputs + * Fixed custom loading issue on void Output or Call mode when no inputs are declared + * Fixed issue where user could set main output type as OBJECT type + * Fixed incorrect text replacement on Call mode code + * Fixed Custom Types not being correctly declared + * Fixed compilation issues both on HD Lit and PBR when WRITE_MSAA_DEPTH directive is used + * Possible fix on VR issue with Lightweight RP + * Possible fix on issue with Unlit template when using Single Pass Stereo VR + * Possible fix on issue with 'Grab Screen Color' node when using Single Pass Stereo VR + +* Improvements: + * Added Variable Mode to 'Grab Screen Color' node + * Added new Alpha port on 'Blend Operations' node to enable a more layered like behavior + * Added support to SRP 5.16.1 + +v1.6.7 rev 05: +* Fixes: + * Fixed issue with alpha cutoff on both HD Lit 5.7.2 and 5.13 templates + +* Improvements: + * Added new template option functionality to copy properties from sub shader module (API) + +v1.6.7 rev 04: +* Fixes: + * Fixed issue on not taking variables declared on template into account when registering instanced variables + +v1.6.7 rev 03: +* Fixes: + * Fixed issue on 'Static Switch' node when setting default value on Enum type + * Fixed issue on 'Triplanar Sampler' node incorrectly activating mid and bottom index ports + * Fixed normal map unpacking issues with Lightweight RP over mobile + +* Improvements: + * Adding INTERNALTESSPOS into template semantics to prevent user issues + +v1.6.7 rev 02: +* Fixes: + * Fixed exposure issue on both diffuse and specular components over HDRP templates + +* New Templates: + * Adding specific templates for legacy HDRP v5.7.2 + +v1.6.7 rev 01: +* Fixes: + * Changed how depth fetch is done to prevent issues on single pass vr + * Tweaked 'World Position' node preview shader to prevent issues over PS4 + * Fixed issue on 'World to Object' node when used on templates + * Fixed 'Custom Expression' node issue with Auto-Register on shader functions + +* Improvements: + * Post-Processing Tool now works under a InvariantCulture to be region independent + * 'Static Switch' node now supports both shader_feature_local and multi_compile_local + * Only available on Unity 2019.1 and above + * Activate the Is Local toggle over the node properties + +v1.6.7 rev 00: +* New Sample: + * Volumetric Pixelize by Raphael Ernaelsten + +* New Nodes: + * Diffusion Profile + * Packed inside HDSRPTemplates.unitypackage + * To be used on Unity 2019 with HDRP 5.13 + * Baked GI + +* Improvements: + * 'Grab Screen Color' node now works on both HDRP 4.x.x and 5.x.x + * Added new Is Variable toggle on 'Custom Expression' node + +* Fixes: + * Fixed possible null pointer access when losing focus on a ASE window + * 'Texture Sample' and 'Texture Coordinates' nodes no longer breaks GPU Instancing/SRP Batcher + +v1.6.6 rev 00: +* Improvements: + * Added support for both Lightweight and HD SRP v5.13.0 on Unity 2019 + * Templates for SRP v4.x.x on Unity 2018.3 are still accessible through packages + * HDSRPTemplates 4xx (Legacy) + * LWSRPTemplates 4xx (Legacy) + * Updated 'Triplanar Sample' node to include a new position port + * Also updated TriplanarProjection sample to include this node usage + +* Fixes: + * Fixed issue with using vertex tangent data over SRP templates + +v1.6.5 rev 00: +* Fixes: + * Fixed issue on interpolator usage on template based shaders when current shader model max amount is reached + +v1.6.4 rev 03: +* Improvements: + * Improved Post-Processing Tool behavior + * Removed dependencies on Unity's Post-Processing Stack libs to prevent compilation issues + * Added new 'Allow In Scene View' option + +v1.6.4 rev 02: +* Fixes: + * Added missing ase_pragma tag over PPS template + +v1.6.4 rev 01: +* Fixes: + * Fixed issue with using 'Indirect Diffuse Light' node with Lightweight PBR template + +v1.6.4 rev 00: +* Fixes: + * 'Indirect Diffuse Light' node now works on the HD SRP templates + * Fixed memory leak on closing ASE windows + * Fixed port define issue with linked ports over template options (API) + * Fixed loading issue on 'Reconstruct World Position From Depth' shader function + +v1.6.3 rev 09: +* Fixes: + * Added missing ase_frag_input tag on Lightweight Unlit SRP template + * Fixed compiler issues when using 'Face' and 'Switch by Face' nodes on Vertex Ports + +* Improvements: + * Minor tweak on Simple GPU Instancing sample for GPU Instancing behavior to be more evident + +v1.6.3 rev 08: +* Improvements: + * Standard Surface custom ASE shadow caster can now be turned off + * Toggle on new 'Use Default Shadowcaster' option over Rendering Options group + +* Fixes: + * Nodes 'Face' and 'Switch by Face' now properly work over the HD Unlit template + * Fixed issue on missing ase_frag_input tags over HD Unlit + * Template Port Options can now be properly registered over SubShader (API) + +v1.6.3 rev 07: +* Fixes: + * Removed unnecessary code being used when on Custom Lighting + * Fixed 'Light Color' node not being correctly reset when on subtractive lightmaps + * Removed gi.light.color usage from Blinn Phong Light shader function as it was a temporary fix for the above + +v1.6.3 rev 06: +* Fixes: + * Fixed issues on 'Light Attenuation' node over Lightweight SRP + * Removed incorrect N.L contribution + * Fixed issue on duplicate variables when using multiple nodes + +v1.6.3 rev 05: +* New Sample: + * SRP HD Omni Decal + +* Fixes: + * 'Indirect Diffuse Light', 'Indirect Specular Light' and 'Light Attenuation' now works on Lightweight SRP + * Fixed issue on 'Screen Position' node previewer when on Screen Mode + * Fixed 'Screen Depth' node issue over Particle Alpha Blended template + +* Improvements: + * 'Static Switch' nodes now have a Reference mode + * Can use other nodes as reference, similar to 'Texture Sample' node + * Minor cleanup on 'Reconstruct World Position From Depth' shader function + * Can set shader functions as hidden so it wont show on context menu + * Activate Hidden toggle over shader function General options + +v1.6.3 rev 04: +* Fixes: + * Minor fix on Screen Space Detail sample + * Fixed issue on instanced surface terrains not being able to be picked/selected + * Fixed issue with lightmaps and instanced standard surface terrains + * Fixed issue with 'Four Splats First Pass Terrain' shader function on default templates + * Fixed issue with duplicate local variables on 'Texture Coordinates' + * Fixed issue on duplicate ST variable when using Particle Texture Parameter over Particles template + +* Improvements: + * 'Switch By Pipeline' node now takes default template and surface into account + * UsePasses can be directly registered by nodes on data collector(API) + * ASE Custom Shader Inspector now also shows SRP Batcher compatibility status + +v1.6.3 rev 03: +* Fixes: + * Fixed issues with Custom Lighting on Subtractive Lighting Mode + * Fixed issue on Diffusion Profile Id not being correctly written when Transmission is activated on HD Lit template + +v1.6.3 rev 02: +* Fixes: + * Fixed issue with Mosaic Effect PPS sample not opening correctly on Unity 2018.1 and 2018.2 + * Fixed issue on Multi Pass Distortion sample not taking skybox into account + +* Improvements: + * User can now specify sub-shader tags + * Moved RenderType tag to sub-shader level + +v1.6.3 rev 01: +* Fixes: + * Fixed issue on screen position calculation across all templates + * Fixed issue with 'Parallax Occlusion Mapping' node + +* Improvements: + * Minor tweak on Post-Processing Stack template + +v1.6.3 rev 00: +* Fixes: + * Fixed multiple issues with 'Triplanar Sample' node over SRP + +v1.6.2 rev 11: +* Fixes: + * Fixed issue on ST registry at 'Parallax Occlusion Mapping' node not taking SRP name convention into account + * 'Reconstruct World Position From Depth' shader function now compatible with HDRP + * Fixed crash caused by the 'Outline' node when attempting to be used on nested shader functions + * Fixed issues with 'Screen Position', 'Depth Fade' and 'Screen Depth' nodes on PPS template + +v1.6.2 rev 10: +* New Template: + * PostProcessStack + * Post-Processing shader based on Unity provided example + +* New Sample: + * Mosaic Effect PPS + +* New Tool: + * Post-Processing Stack Tool + * Generates a cs script with a PPS Renderer and Settings from a given shader + +* New Shader Function: + * Decoding Directional Lightmap + +* Improvements: + * Added inline property for Alpha to Coverage option on Standard Surface Shader Type + +* Fixes: + * Fixed 'Triplanar Sample' and 'Parallax Occlusion Mapping' nodes issues with texture arrays on SRP + * Fixed crash caused by the 'Outline' node when attempting to be used on templates + * This node is specific to Standard Surface Shader Type + * Fixed issue with using Lightweight PBR legacy template + +v1.6.2 rev 08/09: +* Fixes: + * Fixed issue with depth texture fetching on Lightweight SRP + +v1.6.2 rev 07: +* Fixes: + * Fixed issue on template asset post processor + +v1.6.2 rev 06: +* Improvements: + * Updated Decals code and removed warnings from HD Lit template + * Improved behavior when loading outdated meta from shaders using modified templates + * Added No Scale and Offset attribute to 'Texture Array' node + +* Fixes: + * Fixed instancing issues over HD Lit template + +v1.6.2 rev 05: +* New Shader Function: + * Blinn Phong Light Wrap + +* Fixes: + * Fixed issue with null pointer exception when hacking selection on dynamic ports + * Input ports which appear on p.e. 'Add' and 'Multiply' nodes when dragging wires + * Fixed shadow issues on HD PBR samples + * Fixed 'Billboard' node issues on HD SRP + * Fixed D3D11 internal compiler error on Android + VR over multiple templates + * Fixed issue with Depth Texture declaration on particles template over Android + VR + * Fixed issue with local var declaration of custom types on 'Custom Expression' node + * Fixed issue with 'Object To World','World To Object' and 'Transform Position' nodes + +* Improvements: + * Added the action of (de)activating ZWrite when Surface type is selected on HD Lit template + * Added the action of selecting correct Blend RGB when Surface Type is selected on HD Lit template + * Improved failsafe to when template creators changes order on passes, removes or add new ones + * Depth Texture now being declared with Unity's own macro on Unity 5.6 and above to prevent issues + * Updated HD templates and samples to v.4.9.0 + * Users can still use v4.8.0 although template shaders will present an error + * Final compiled shader will have error removed + * Added Refraction's Chromatic Aberration as an Inline Property on Standard Surface + * Located on Blend Mode menu, bellow Refraction Layer option + * Only shows when Refraction port is connected + * 'DecodeLightmap' now working on latest SRP templates + * 'Fetch Lightmap Value' shader function now takes SRP into account + +v1.6.2 rev 04: +* Fixes: + * Fixed World To Object and Object To World operations on Lightweight SRP + +* Improvements: + * Added support for Terrain instancing over Unity 2018.3 + * Correctly handling when user wants to disable main output node + * Minor tweaks over SRP templates global tags to be able to properly inject code dependent on vertex data + +v1.6.2 rev 03: +* Fixes: + * Fixed issue on HD Lit Motion Vector's pass + * Fixed issue with Default UI template when used on Sprite Renderers + +* Improvements: + * SRP templates no longer have CBuffer block pre-written + * Instanced Properties now correctly declare CBlocks + * Added new Receive Shadows option into Lightweight templates to correctly handle shadows + +v1.6.2 rev 02: +* New Node: + * Instance Id + +* Fixes: + * Fixed issue on not being able to have multiple property nodes fetching the same variable + * Fixed version issue on both HD and LW samples + +* Improvements: + * Removed hard cap on interpolator usage on templates + * Message is thrown to the user if maximum allowed by shader model is reached + +v1.6.2 rev 01: +* New Template: + * HD Lit + +* New Sample: + * SRP HD Lit Refraction + +* Improvements: + * Can add options on template which lets users change its behavior when using it on ASE + * Added Vertex Position option into Unlit and SRP templates + * Specified value on Vertex input port can now be either a relative value or an absolute one + * Passes can now be excluded from final shader through Available Passes menu over SubShader Properties + +* Fixes: + * Fixed issues with Lightweight PBR Shadow Caster on WebGL and Android + +v1.6.2 rev 00 / v1.6.1 rev 05: +* New Template: + * Unlit Lightmap + +* New Sample: + * Unlit With Lightmap + +* Fixes: + * Fixed issue on 'Depth Fade' node with custom Vertex Positions + * Fixed issue with using the X,Y,Z,W output ports on 'Object To World' node + +v1.6.1 rev 04: +* New Node: + * Linear Depth + * Converts values given on logarithmic space to linear + +* Improvements: + * Minor improvement on nodes loading time when initializing ASE + +* Fixes: + * Fixed local variable duplicate issue when using 'Depth Fade' and 'Screen Position' nodes + * Fixed serialization issue with Additional Use Passes and Fallback data when going into play mode + * Fixed HDRP issues on Motion Vectors pass + * Fixed issue with uniform keyword usage inside cbuffers (SRP templates) over PS4 + * Fixed issue with 'Common Transform Matrices' node over SRP templates + * Fixed object to world/world to object space transform on transform nodes over HD templates + * 'Transform Position', 'Object To World' and 'World To Object' nodes + * They now take SHADEROPTIONS_CAMERA_RELATIVE_RENDERING keyword into account + * Fixed issue with 'Pixelate UV' node when used over vertex functions + * Fixed foldout issue between Additional Surface Options and Custom SubShader Tags on Surface node properties + +v1.6.1 rev 03: +* New Shader Functions: + * Terrain Wind Value + * Terrain Wind Animate Vertex + * Updated Simple Terrain sample to use this shader function + +* Improvements: + * Updated HDRP PBR template to v4.6.0 + * Added Alpha To Coverage/Alpha To Mask option into templates + * Set under the Blend Mode area + +* Fixes: + * Fixed issue on Emission color being added over Forward Add pass when using 'Standard Surface Light' node + +v1.6.1 rev 02: +* Fixes: + * Fixed issue with reordering material properties for Translucency and Refraction port's properties + * Fixed issue with 'Texture Sample' node when referencing an unconnected node + +v1.6.1 rev 01: +* Improvements: + * Updated HDRP templates to v4.3.0 + * 'Vertex Tangent' node now has Size option + * Added access to all 8 UV sets on Surface shaders + * Re-added 'Clip' node + * First Input Port acts as a relay + * Clip uses difference between Alpha and Threshold ( Alpha - Threshold ) + +* Fixes: + * Fixed issue with late directives being injected on globals tag when functions area is available + * Affected usage of 'World Space Light' nodes on HDRP templates + * Fixed division by 0 issue on 'Triplanar Sample' node + * Fixed incorrect directional light vector usage on HDRP templates + +v1.6.1 rev 00: +* Fixes: + * Excluding Primitive ID source code from MacOS + +v1.6.0 rev 00: +* Improvements: + * Updated SRP templates to v4.2.0 + +* Fixes: + * Fixed issue on GBuffer pass over HD PBR template + * Fixed alpha clip issues on Legacy HD PBR template + +v1.5.9 rev 02: +* New Nodes: + * Vertex Id + * Primitive ID + +* New Shader Functions: + * Perturb Normal HQ + * Prepare Perturb Normal HQ + +* Improvements: + * Matrix type nodes can now be GPU instanced + +* Fixes: + * Fixed issue with 'Fresnel' node with Tangent Normal vectors on Surface shaders + * Fixed issues on Motion Vector pass on both 3.x.x. and 4.x.x templates + * Fixed issue with world pos generation on HD 4.x.x + +v1.5.9 rev 01: +* Improvements: + * Added Auto Gamma to Linear option into 'Color' nodes when set to Constant + * Added access to all 8 uv channels on 'Texture Coordinates' and 'Vertex TexCoord' nodes + * Only for 2018.2 and above + +* Fixes: + * Fixed 'Gamma To Linear' and 'Linear To Gamma' compiler errors on SRP v.4.x.x + +v1.5.9 rev 00: +* Fixes: + * 'Grab Screen Color' node now also working on Lightweight SRP v3.x.x + * Fixed possible issue with Shader Function creation callback not being inside AmplifyShaderEditor namespace + +v1.5.8 rev 03: +* Fixes: + * Fixed multiple issues in both PBR and Unlit templates for HD SRP v4.x.x + * Fixed issue over clip space transforms on HD SRP + * Fixed issue on sampling depth buffer on HD SRP + +v1.5.8 rev 02: +* Improvements: + * Multiple improvements over 'Global Array' node + * Added support for jagged arrays + * Added Auto-Register toggle + * Can reference other nodes through new Mode dropdown ( similar to 'Grab Screen Color' node ) + +* Fixes: + * Fixed memory leak over 'Template Local Var' node + * Fixed HD templates issues over new HD 4.1.0 + +v1.5.8 rev 01: +* Fixes: + * Fixed issue on Live Mode writing on non ase shaders when loaded into canvas + * Fixed issue on MacOS with scroll bar over Texture Array Creator tool + * Fixed issue on MacOS with 'Function Input' node generated default Sampler 2D value + +* New Shader Function: + * Substance Blend Metallic + +* Improvements: + * 'Grab Screen Color' node is now supported on LW SRP + * Uses the new _CameraOpaqueTexture which must be requested on the pipeline asset + * Must toggle on the Opaque Texture option over its General foldout + * Added Clip and Tangent spaces into 'Transform Direction' node + * Added Tangent space into 'Transform Position' node + +v1.5.8 rev 00: +* New Sample: + * Substance 2018 + +* Fixes: + * Fixed canvas crash when loading shaders with missing templates + * Fixed issue on UV Coords creation over 'Substance Sample' Node + * Fixed issue with loosing Substance reference on 'Substance Sample' node when applying new changes on it + * Only happened on Unity 2018 with Substance in Unity plugin + * Fixed issue on nested instanced properties over shader functions not being taken into account + +* Improvements: + * Upgraded Lightweight and HD templates to v5.0.0 + * Maintained templates for v.3.x.x under the packages HDSRPTemplates (Legacy) and LWSRPTemplates (Legacy) + +v1.5.7 rev 02: +* Fixes: + * Fixed issues on 'Static Switch' node + * Property Name wasn't available in all options + * Keys on Keyword Enum over Fetch Mode were being automatically upper cased + * Fixed issue on 'Get Local Var' node not propagating node data correctly after being loaded + +v1.5.7 rev 01: +* New Templates: + * Custom RT Init + * Packed inside AmplifyShaderEditor > Plugins > EditorResources > Templates > CustomRTTemplates + * Custom RT Update + * Packed inside AmplifyShaderEditor > Plugins > EditorResources > Templates > CustomRTTemplates + +* New Sample: + * Custom Render Texture Rain + * Packed inside AmplifyShaderEditor > Examples > Custom RT Samples + * Needs both Custom RT Init and Custom RT Update templates to be imported into project + +* Fixes: + * Fixed issue on Queue Offset incorrect writing over templates + * Fixed issue on templates not recognizing uint + * Fixed minor issue over Directives UI + * Fixed Shadow Coord macro registry differences between Unity 5.5 and above + +* Improvements: + * Added Substance Plugin integration over ASE for Unity 2018 and above + * Added Mirror option into 'Depth Fade' node + * Enabled by default, which was older behavior + * If toggled on, sets an abs operation over the final value + * Custom Render Textures can now be used/dragged over ASE + * Can Pan and Zoom ASE canvas camera through keyboard directional keys + * Up/Down/Left/Right Arrow keys pan camera + * Alt+Up/Alt+Down/Alt+Left/Alt+Right Arrow keys zoom camera + +v1.5.7 rev 00: +* Fixes: + * Fixed issue with using FACE type nodes over both Lightweight and HD Unlit templates + * Fixed issue regarding 'Lerp' node's Alpha input port always loading as a Float type + * Fixed minor issue on 'Function Subtitle' node tooltip + * Fixed minor issue on 'Posterize' node + * Power variable should not be shown on property window if its input port is connected + * Fixed minor issue with auto-spacing over shader function names + +v1.5.6 rev 08: +* Fixes: + * Fixed Queue Offset not being correctly set when loading certain template based shaders + * Fixed HSV nodes previews + * Fixed multiple issues with Directives over shaders functions + * Fixed issue on nodes not being correctly set up over template's invisible passes with linked ports + +* Improvements: + * Directives in Include mode now fully support cgincs and hlsl files to be dragged into them + * Similar behavior of inline properties, click on button right next to Include textfield to activate object drop UI + * Adding GPU Instancing support to Unlit template + * Adding new Vertex Position port into 'Depth Fade' node + * Adding new Saturate option into 'Depth Fade' node + * Can now set precision to each 'Custom Expression' node items individually + +v1.5.6 rev 07: +* Fixes: + * Fixed duplicated events registry when loading graphs + * Fixed incorrect instanced variables reset over shader functions + +v1.5.6 rev 06: +* Fixes: + * Out variables on 'Custom Expression' node no longer appears as inputs + * Fixed issue on not updating output port names correctly over 'Custom Expression' node + * Fixed issue on properties with Header(...) not being written on shader + * Fixed incorrect read/write on MRT Blend Mode and Op over template based shaders + * Fixed possible infinite loops caused by 'Register/Get Local Var' nodes + * Fixed Shader Type dropdown items not updating names correctly according to changes on template + * Fixed issue on adding multiple ASE tabs on Unity 2018.3 + * Fixed WebGL error over 2018.3b + * Fixed 'Parallax Offset' node issues when used on Lightweight and HD SRP templates + * Fixed dynamically created outputs over shader function not being correctly set after hot code reload + +* Improvements: + * Property Name and Values get its label clamped when too big + * Full original name and value is shown over its node tooltip + * Hidden tag on template shader names no longer created a category called Hidden + * Adding new ase_funcs tag functionality to determine where function code should be injected + * If not specified, functions are grouped with global variables as before + * Improved template reloading after being manually edited + +v1.5.6 rev 05: +* Fixes: + * Fixed 'Smoothstep' node code generation issue + * Fixed ASE item grouping issue on Create menu over Unity 2017 and above + +v1.5.6 rev 04: +* Fixes: + * Fixed shortcut manager to take 2018.3 new event behavior into account + +v1.5.6 rev 03: +* Fixes: + * Fixed several shader functions issues + * Fixed Undo issue when using directives textfields + * Fixed issue of null references being set on directives list when loaded + * Fixed directives not being correctly written on shader + * Fixed incorrect Refraction port activation issue on Standard Surface Custom Lighting + * Fixed issue on Property nodes with Auto-Register toggled on not being registered + * Fixed cascaded shadows issue on HD PBR template + +* Improvements: + * Minor update on 'Smoothstep' node ports behavior + * Added preview to 'Swizzle' node + +v1.5.6 rev 02 +* Fixes: + * Fixed issue on multi-pass templates not getting correct interpolator count from subshader info + * Fixed issue on Depth Offset template option auto enabling after hot code reload + +* Improvements: + * Using current world position and world view direction when getting indirect specular light values on templates + +v1.5.6 rev 01 +* Fixes: + * Fixed issue with global variables on Property type nodes being ignored by Auto-Register toggle + * Fixed Native Directives capture issue over templates + * Fixed issues on adding duplicate directives if they are already natively on the template + * Fixed compilation errors from Gamma/Linear nodes on SRP templates + * Fixed ArgumentOutOfRangeException over file path on new shader creation + * Fixed issues over Motion Vector pass on HD PBR template + * Fixed issue on 'Light Color' node with HD templates + * Fixed issue on 'World Space Light Dir' node with HD templates + * Fixed issue on 'Object Space Light Dir' node with HD templates + +* Improvements: + * Added support for Variable Mode over Texture Objects type nodes + * Adding UI Widget helper for setting Render Type and Queue for templates + * On SubShader Tags group, Value UI changes as soon as user writes RenderType or Queue on the Name textfield + +v1.5.6 rev 00 +* New Samples: + * SRP Lightweight Terrain + * Multi Pass Distortion + +* New Node: + * Switch by Pipeline + * Shader function specific node to choose different paths according to current pipeline + +* New Shader Function: + * Fetch HD Color Pyramid + +* Fixes: + * Fixed world position issues over HD PBR Template + * Fixed transparent issues over HD PBR template + * Prevented WorldNormalVector macro to confuse lerp operations + * Fixed issue on created shaders being placed in incorrect folders when on two column node + * Fixed issue on property registering over multi-pass shaders + +* Improvements: + * Custom Options can now be added directly over templates + * Adding Final Color x Alpha custom option into LW PBR + * If toggled on multiples fragment final color by its alpha + * Apply Fog on LW PBR takes Add Pass directive into account + * Adding SRP support to Four Splats First Pass Terrain shader function + * Material Global lIllumination flags for emission can now be modified over Surface Rendering Options + * Activated Variable mode into 'Texture Sample' nodes + +v1.5.5 rev 01 +* Fixes: + * Fixed issue over incorrect name registration over 'Register Local Var' on pasting into another shader + * Fixed issue on reading shaders using old shader functions with deprecated nodes + * Fixed 'World Pos' node issue on HD SRP template + * Fixed issue on 'World Normal' node when used in 'Lerp' node + +* Improvements: + * 'Register/Get Local Var' nodes maintain connections even if copied to another shader + +v1.5.5 rev 00 +* New Node: + * Diffuse And Specular From Metallic + +* Fixes: + * Fixed issues on graph not being updated with material changes on inspector if tab is opened but not selected + * Preventing Culture difference issues on material copy-paste + * Fixed issue on all modules template tag conflict with existing shader model definition + * Fixed HD issue on 'World Position' node + * Fixed issue on losing name when copy-pasting property nodes between shaders + * Fixed issue on resetting custom inspector to ASE default when loading or hot code reloading shader with its textfield empty + * Fixed issue on not setting importer correctly on 'Texture Sample' node when setting a normal map type texture from inspector + +* Improvements: + * Properties on invisible passes can now be synced with main pass over templates + +v1.5.4 dev 10: +* New Sample: + * SRP HD Material Types + * Please notice that for SSS to work properly, a Diffusion profile must be attached to the HD pipeline asset + * We already supply one over the sample folder ( Diffusion Profile Settings ) + +* Fixes: + * Fixed UX issue with Auto-Register/Set Unique flags on 'Custom Expression' node + * Fixed issue with cascade shadows over Lightweight template + +* Improvements: + * Added Material Types selector into HD template + * Subsurface Scattering + * Standard (Metallic) + * Specular + * Anisotropy + * Iridescence + * Translucent + +v1.5.4 dev 09: +* Fixes: + * Fixed Grab Pass issue with 'Outline' node + * Fixed PreviewRenderUtility leak over shader and material inspector on 2018.2 + * Fixed issue with 'PI' node over HD SRP + +* Improvements: + * Minor improvement over shader save time + +v1.5.4 dev 08: +* Fixes: + * Fixed issue on 'Component Mask' node generating compilation errors inside shader functions with auto-cast inputs + * Fixed issue on loop unroll error over 'Parallax Occlusion Mapping' node + * Fixed issue on crashing ASE when loading a shader or shader function with a missing shader function reference + * Adding error message when loading a shader or shader function with missing shader functions + +* Improvements: + * Added support to Vertex Normal modification on both Unlit and PBR HD templates + * Adding 'Global Array' variable name info directly on node + +v1.5.4 dev 07: +* New Templates: + * HD PBR + * HD Unlit + +* Fixes: + * Fixed issue on incorrectly capturing module tags + * Fixed issues with 'Flipbook UV Animation' node + * Fixed multiple issues with Directives usage under shader functions with templates + * Fixed issue on 'Custom Expression' node loading on Call mode + * Fixed issue on unpacking normals with scale on templates over multiple nodes + * Changing tessellation on Procedural Wall sample shader from edge to distanced based to prevent metal issues on Mac + +v1.5.4 dev 06: +* Fixes: + * Fixed issue on 'Toggle Switch' node not taking Custom Attributes into account + * Fixed out of bounds exception over 'Static Switch' node + * Fixed issue on templates port linking behavior + * Fixed issues on 'Texture Array', 'Triplanar Sample' and 'Unpack Scale Normal' nodes on Lightweight SRP + * Fixed issue on shader function directives not being written on template based shaders + * Fixed serialization issue on saving/loading shader function directives + * Fixed issue with using 'Texture Array' node inside shader functions + * Fixed shader compilation errors on'Parallax Occlusion Mapping' + * Now it does not generate code if no 'Texture Object' node is connected to it + * Fixed issue on 'Grab Screen Color' node not updating reference list correctly when copy/pasted + * Fixed issue with Undo'ing a 'Grab Screen Color' node on reference mode + +* Improvements: + * Min and Max Samples options on 'Parallax Occlusion Mapping' node are now inline options + +v1.5.4 dev 05: +* Fixes: + * Fixed issue with Vector and Matrix UI spacing on 'Custom Expression' node + * Fixed issue on functions being generated twice over a 'Custom Expression' node when auto register and connection are both on + * Fixed Blend Op issues with OFF state + +* Improvements: + * Can now use a custom screen position into 'Dither' node + * Added Normalize option into 'Compute Screen Pos' node + +v1.5.4 dev 04: +* Fixes: + * Fixed issue on resetting material's Render Queue setting when compiling the shader in Material mode + * Fixed issue on Blend Op menu not showing when loading a template based shader + +* Improvements: + * Re-adding DX11 specific Blend Ops into its respective dropdowns + * 'Custom Expression' node items are now reorderable + * 'Custom Expression' node can now register dependencies to other ones + * Can now better control function register order on final shader + +v1.5.4 dev 02/dev 03: +* New Shader Function: + * Color Mask + +* Fixes: + * Fixed issue on template Unlit SRP generating an error when creating a Color or MainTex named property + * Fixed issue on both 'Surface Depth' and 'Camera Depth Fade' nodes when inputting a custom vertex position + * Stencil module on Pass now uses SubShader Cull mode if it's not specified on it + * Important since Cull determines if separate stencil ops are show for each face + * Fixed issue with Fallback shader selector not updating if its textfield is focused + * Fixed issue on Grab Pass only being registered on first pass when on multi-pass templates + +* Improvements: + * Added auto register option into 'Grab Screen Color' node + * Adding UsePass support + * New Additional Use Passes section on both Surface and Template output nodes + * Can add UsePass before or after Surface code via a Location dropdown + * On Templates the Below location is still under development and its not available + +v1.5.4 dev 01: +* New Shader Function: + * Fetch Lightmap Value + +* Improvements: + * Simple Terrain sample now support more than four splats + +* Fixes: + * Fixed issue on Node Palette reading incorrect maximized value when opening ASE window + +v1.5.3 dev 12: +* Fixes: + * Fixed null pointer exception with texture arrays over shader functions + * Fixed memory leak on shader functions destruction + +* Improvements: + * Improved templates loading behavior after hot code reload + * Replaced individual lists for pragmas, defines and includes by a single reorderable list + * Now user select what each line represents via a dropdown + * Additional surface options can now be added via the Additional Surface Options tab on the Output node + * Added custom type for 'Custom Expression' node data type specification + +v1.5.3 dev 11: +* Fixes: + * Fixed issue on not correctly cleaning Undo stack when changing master node + * Fixed multiple issues with safe normalize operation over world light dir and view dir + * Fixed world light dir issues over Lightweight SRP + * Fixed GPU instancing compile issues on Lightweight SRP + * Fixed issue on Includes/Pragmas/Defines UI not showing when no other modules over a template + +* Improvements: + * Optimizing property block allocation for instanced variables to have less internal padding involved + * Added custom attributes to 'Toggle Switch' node + * Added toggle to 'Matrix from Vector' node use each input as column + +v1.5.3 dev 10: +* Fixes: + * Fixed issue with being able to duplicate output nodes on templates + * Fixed issue on foldout flag values being shared between multiple ASE tabs + +* Improvements: + * 'Get Local Var' port is locked until a valid reference is set to prevent incorrect connections + * Updated About image and added Manual link on Amplify Shader Editor menu group + * Adding unique id duplicate prevention over shader load + * Added support for stencil operations on Lightweight templates + +v1.5.3 dev 09: +* New Shader Functions: + * Lerp White To + * Detail Albedo + +* Fixes: + * Fixed API library excluding tool for custom nodes + +* Improvements: + * Template creators can now register all modules + * Simply add the /*ase_all_modules*/ either on the Pass or SubShader body + * Templates now support Fallback definition on shader + * Templates now support Dependencies definition on shader + +v1.5.3 dev 08: +* Fixes: + * Fixed Instance ID issue over Lightweight SRP template + +* Improvements: + * Added API option to remove includes on data collector + * Stencil can now be toggled off on templates which have it + +v1.5.3 dev 07: +* New Sample: + * Projectors + * Exemplify Unity Projectors usage under ASE + +* Improvements: + * Improved Texture Array Tool + * Now also creates Texture3D by hitting the Texture 3D toggle + * Can drag and drop multiple textures into tool + * Can drag and drop a folder and it will include all its nested textures + * Added Clear button to remove all textures from Texture List ( UI still work in progress ) + * 'Parallax Occlusion Mapping' node now also supports Texture 3D + * Replaced the Texture Array toggle by a Texture Type dropdown + * User must explicitly set the current 3D texture slice via the Tex3D Slice input port + * Removed Fixed precision type since it's no longer available on Unity 2018 + * Updated Lightweight PBR template to v1.1.8 + * Re-factored Templates location and names + * New and more flexible templates will be gradually added to replace legacy ones + * A cleaner Unlit template shader was already added on this build + +* Fixes: + * Fixed issue on using depth operations on particle template + * Fixed sometimes light attenuation not showing up correctly + * Fixed allowing to open unity built-in shaders on ASE + * Fixed issue on using incorrect port value on 'Refract' node + * Fixed issue on Texture Object type nodes loosing texture type after load + +v1.5.3 dev 06: +* New Sample: + * XRay + * Object has different drawing behavior in front and behind a wall + * Wall pattern is procedurally generated + +* Improvements: + * Template internal properties can be used as inline properties on modules + * Modules can now read inline properties from the template original source + * Unreadable data message is no longer shown on node properties + * Added more options to 'Fresnel' node + * Now supports custom view vector + * Preventing cast warning with object to clip internal function usage when building shader code for Lightweight SRP + * Added new icons for inline properties to the Unity personal skin to make them easier to spot + * Updated Lightweight SRP templates + * Cull Mode now shared across base, shadow and depth pass + * Added new Normal input port + +* Fixes: + * Fixed issue over templates on not assuming inline properties when loading/saving Cull Mode module + * Fixed incorrect cast and type assignment on connections between 'Texture Object' and 'Texture Sample' nodes + * Fixed issue on deleting outputs on shader functions and later opening the shaders that use it + * Fixed issues on Vertex Offset port on Lightweight PBR template + * Fixed issue on not correctly loading 'Rotate About Axis' node from old shaders + * Fixed issue on header not showing with texture properties with the NoScaleOffset attribute + +v1.5.3 dev 05: +* Fixes: + * Fixed world normal issues over 'Outline' node + * Fixed issues on reading/writing cull mode on templates meta + * Fixed issue on capturing includes over templates + * Fixed issue on Specular workflow over Lightweight PBR template + +* Improvements: + * Cull Mode can now be modified over outline node + +v1.5.3 dev 04: +* New nodes: + * Transform Position + * Transform Direction + +* Improvements: + * Added inline property support over templates modules + * Also added inline property support over Depth Offset values in both template and standard surface + * Minor tweak over 'Clamp' node + * Internal max value defaulted to 1 + * Adding additional modules into Lightweight templates + * Enabling ZTest over Particles Alpha Blended template + +* Fixes: + * Fixed issue on Lightweight PBR template over tangents on objects with non-uniform scales + * Fixed issue on Lightweight PBR not receiving real time shadows + * Fixed issue on Lightweight Unlit template available interpolators + * Fixed issue on Lightweight Unlit template not showing correctly on dropdown menu + * Fixed issue on tab titles not being correctly written on shader mode over templates + * Fixed issue on property names incorrectly appearing over inline properties + * Fixed issue with copy/pasting 'Append' nodes + * Fixed issue on 'Global Array' node loading from older shaders + +v1.5.3 dev 03: +* New Template: + * Lightweight Unlit + * Renamed already existing SRP Template to Lightweight PBR + +* New Sample: + * SRP Lightweight 2D Fractal + +* Fixes: + * Fixed issue with 'Parallax Occlusion Mapping' node over Lightweight templates + * Fixed Safe Normalize issues with 'View Dir' node on templates + +* Improvements: + * Added Auto-Register option into 'Static Switch' node + * Minor improvement over 'Parallax Occlusion Mapping' node generated code to avoid duplicate calculations + +v1.5.3 dev 02: +* Fixes: + * Fixed infinite loop via context menu issue + +* Improvements: + * Added support for Specular workflow into Lightweight SRP template + * Use either the new Specular port or the already existing Metallic port to choose which workflow to use + * Added extra ASE null pointer exception prevention test on attempting loading shader with missing shader functions + +v1.5.3 dev 01: +* Improvements: + * Conditional 'If' node also support Int as compare values + * Added Triplanar scale port for normal scaling when using normals in 'Triplanar Sample' node + * Improved code generation for 'Texture Coordinates' node + * Changed way float values were being generated when their value was an integer + * Removes warnings and makes sure some operations are done in the correct space, like divisions + * Improved operations order on 'Panner' node + * Added Force Disable Instancing option into Surface output node Rendering Options + * Updated Lightweight SRP template to be compatible with Unity latest LW SRP version 1.1.5 + +* Fixes: + * Fixed issue on 'Global Array' node not being correctly detected by ASE + * Fixed texture array sampling error caused by 'Parallax Occlusion Mapping' node on Unity 2018 + * Fixed issue on local variable excluded reset method + * Fixed issue on 'Triplanar Sample' node Material Mode not being correctly set + +v1.5.2 dev 05: +* New Samples: + * Single Channel Masking by Sarah Akers and David Marshall + * Dithering Fade Blue Noise + +* New Node: + * Inverse View Matrix + +* Fixes: + * Fixed issue on not copying defaults to material values when changing Type from Global to Property over property type nodes + * Fixed Stencil Comparison not being correctly written on shader when set as an inline property + * Fixed issue on Reference mode not being taken into account when registering 'Texture Sample' properties + * Fixed infinite loop on 'Texture Sample' nodes with Reference mode + * Fixed custom outline alpha mask mode + * Fixed issues on compare type nodes accessing their Wiki page + * Fixed dropdown left title padding for nodes that have it but don't have a preview arrow + +* Improvements: + * Improved 'Unpack Scale Normal' node usage on Burn Effect sample + * Now compatible across all Unity versions + * Re-factored Global variables behavior over property type nodes + * Material values can no longer be edited + * Auto-fetching global variables values every 2 seconds + * Parameter type can be changed in node over texture type nodes + * Removing automatic header creation by properties under shader functions + * User now can manually set headers on property type nodes via its attributes + * Turned the main Mask Clip Value an inline property so users can set it to be a specific node + * Updated 'Screen Position' node preview + +* New Previews: + * Compare ( A > B ) + * Compare ( A >= B ) + * Compare ( A < B ) + * Compare ( A <= B ) + * Compare ( A == B ) + * Compare ( A != B ) + * Compare With Range + * If [Community] + * Decode Float RG + * Encode Float RG + * Decode Float RGBA + * Encode Float RGBA + * Decode View Normal Stereo + * Encode View Normal Stereo + * Decode Lightmap + * ColorSpaceDouble + * Face + * Switch By Face + * LOD Fade + * Layered Blend + * Weighted Blend + * Summed Blend + +v1.5.2 dev 04: +* Fixes: + * Fixed issue on Post-Process sample scenes crashing on lower Unity versions + * Fixed issue on fallback behavior when required template on loaded shader is not found + * Fixes issue on texture type nodes moving when a texture is selected over it's picker + * ASE window now aware when ObjectSelectorClosed command is fired to ignore incorrect mouse delta values + +* Improvements: + * View Dir vector on templates is now calculated on fragment by default + * World Reflection vector on templates is now calculated on fragment by default + * Native View Dir vector calculation on Lightweight SRP template is now done on fragment + * Shader function 'Reconstruct World Position From Depth' now also works with screen shaders + * Updated Skybox - Cubemap Extended by Cristian Pop sample + +v1.5.2 dev 03: +* Fixes: + * Fixed issue with 'Grab Screen Color' node on Lightweight SRP template + * Fixed multiple issues with Shader Model selection over templates + * Fixed issue on not correctly syncing module data from modified template + +* Improvements: + * Re-factored local variable creation over ports to make it more robust + * Vertex ports are now analyzed before fragment ones + * Vertex position dependent operations now take applied offsets into account + * Pragmas, Includes and Defines are copied from linked nodes if Pass is set as invisible + * Added preview to 'Vertex To Frag' node + * Small optimization on drawing connections + * Minor tweak over Particles Alpha Blended template + * Assigned dynamic interpolators now take both sub shader and pass info into account + * Modified Lightweight SRP template to share dynamic interpolators amount over hidden passes + +v1.5.2 dev 02: +* Improvements: + * Added Safe Normalize option to 'World Space Light Dir' node + * Assures vector is not zero even if there's no lights in scene + * Added Safe Normalize option to 'View Dir' node + * Assures vector is not zero even if there's no cameras on scene + * Property names can neither be or start with numerical values nor Unity reserved names + * Variables from 'Register Local Var' nodes cannot start or be numerical + +* Fixes: + * Fixed shader function subtitles not being shown after being set with the 'Function Subtitle' node + * Fixed Custom Lighting using opacity and opacity mask duplicating code + +v1.5.2 dev 01: +* Fixes: + * Changed alpha generation for Custom Lighting to work correctly with alpha mask + * Fixed issue on shader function reloading not being taken as a load operation + * Fixed instanced properties not being correctly taken into account inside shader functions + +* Improvements: + * Improved shader function asset loading on Shader Function node + +v1.5.1 dev 06: +* Improvements: + * Added preview to 'Noise Generator' node + * Improved node internal data viewer performance + * Improved the shader changed/dirty flag behavior + * Improved graph canvas position adjust on loading from a previously different window configuration + * Renamed 'Melting' sample shader to be in accordance with other community samples + +* Fixes: + * Fixed property node auto-register issue on 'Skybox - Cubemap Extended' sample + * Fixed issues with 'World Normal' and 'World Reflection' nodes on PS4 + * Fixed multiple cast issues across multiple nodes + * Fixed incorrect port behavior on 'Refract' node + * Fixed issue on undoing instanced properties assignment + * Fixed 'Break To Components' node duplicating code and generating errors + +v1.5.1 dev 05: +* Improvements: + * Added previews to nodes + * Desaturate + * Grayscale + * Posterize + * Simple Contrast + * Normal type input ports now show the correct default tangent vector on nodes internal value previewer + * Indirect Diffuse Light + * Indirect Specular Light + * Fresnel + * World Normal + +* Fixes: + * Fixed possible issue with 'Desaturate' node on PS4 + * Fixed issues with Undo/Redo operations over Wire nodes + * Fixed light color and light dir info on 'Light Color' + * Now takes into account Unity different behaviors between versions + * Fixed issue on loading canvas on ASE tabs pointing to inexistent resources + +v1.5.1 dev 04: +* New Node: + * Function Subtitle + * Allows creation for custom subtitles on Shader Functions + +* New Shader Functions: + * Perturb Normal + * Cotangent Frame + +* Improvements: + * Can now assign property to both blend modes and operations + * Removing carriage return when saving 'Custom Expression' node code on meta + * Improved restrictions on Shader Functions outputting Matrix type data + * Name is carried over Pasted/Duplicated 'Custom Expression' nodes + * Custom Editor/Inspector option is now available over templates + * Updated both Lightweight template and samples to new beta version + * Template now support vertex offset and alpha test + * Nodes internal data can be viewed directly on canvas + * Can be turned on/off through the 'I' key + * Added Editable If Custom Drawer by BinaryCats + * Dynamic interpolator cap now respecting pass choice on graph + * Updating current templates to be dynamically cap'ed + * 'Light Color' and 'World Space Light Dir' nodes now behave properly when used with lightmaps + +* Fixes: + * Fixed issue with incorrectly trying to write fragment instructions on template without specified frag code area + * Fixed issue where reference 'Function Switch' nodes were not displaying their option in all cases + * Fixed wire node Undo issues + +v1.5.1 dev 03: +* New Samples: + * Simple Potion Liquid + * Melting by Gil Damoiseaux + +* Improvements: + * Extended functionalities on 'Custom Expression' node + * Added Auto-Register toggle to create custom functions even if not connected to output node + * Added void to Output Type + * Call Mode toggle is now a Mode dropdown + * Mode Call now only allows external function calls or inline instructions + * If a return instruction is detected on code, Mode is set to Create and return type set to void + +* Fixes: + * Fixed Undo issue with property type nodes auto-register option + * Fixed issue on calculation view direction on tangent space over templates + +v1.5.1 dev 02: +* Fixes: + * Fixed issue with 'Standard Surface Light' not taking Normal Space option into account + * Fixed minor issue over 'Outline' node + * Fixed issue on Undo not resetting correctly ports internal values + * Fixed issue on incorrectly assigning main output node status into copy-pasted 'Function Output' nodes + +* Improvements: + * Added custom attributes to 'Static Switch' node + * Custom Material Inspector now properly copies texture scale and offset values + +v1.5.1 dev 01: +* Fixes: + * Fixed 'Static Switch' node not properly generating Enum code in the correct order + * Fixed normal generation issue on 'Standard Surface Light' node + * Fixed issue when attempting to load shader using inexistent template on project folder + * Now fall-backing to Standard Surface when template is not found + * Fixed issue capturing properties with attributes on templates + * Fixed incorrect tool-tip on 'Template Multi-Pass Switch' node + * Fixed issue on normal generation over 'Fresnel' node + * Fixed initialization issue on Default UI template + * Fixed issue with accessing uninitialized textures on 'Triplanar Sample' node + * Fixed preview issue on 'Template Parameter' node + * Fixed issue locking picker on texture type nodes to current type when auto-cast is on + +* Improvements: + * Improved 'Break To Components' generated code + * Preventing duplicates/re-definition of Pragmas, Defines and Includes over templates + +v1.5.0 dev 02: +Fixes: + * Fixed issue on template capturing commented properties + * Fixed multiple issues over templates with multiple sub-shaders + * Fixed issue on master nodes attempting to access uninitialized UI texture + * Fixed issue with sometimes not extracting the correct pass name from template + * Fixed issue on incorrectly catching shader name on fetching modules info + * Fixed issue with correctly setting the shader name + +v1.5.0 dev 01: +* New Samples: + * SRP Lightweight GlintSparkle + * SRP Lightweight Coverage + +* Fixes: + * Fixed issue on loading shader with missing shader functions + * Fixed issue on duplicate pragmas over generated shader + * Fixed issue with template post processor not correctly registering new templates + * Fixed issue on template output nodes modules incorrectly sharing foldout value + * Fixed Undo issue when undoing deleted property type nodes after saving shader + * Fixed 'Static Switch' node registering duplicates in the material properties group + +* Improvements: + * Reorganized samples shader paths + * Reorganized template menu items + * Canvas and output node title now shows shader name without relative paths + * 'Register Local Var' node now generates a new name when duplicated + * 'Indirect Diffuse Light', 'Indirect Specular Light' and 'Light Attenuation' nodes now work on templates + +v1.4.5 dev 04: +* New features: + * Added support for multi-pass templates + * Added support for Lightweight Scriptable Rendering Pipeline + +* New Shader Function: + * Create Normal : Generates a normal map from a height map + +* New Template: + * LightweightSRP + +* Fixes: + * Fixed texture coordinates generation in templates + * Changed initialization in 'Triplanar Sample' node to prevent null pointer errors + +v1.4.5 dev 03: +* Improvements: + * Exposed Specular Color property into the Output node material list when Blinn Phong Light Model is selected + +v1.4.5 dev 02: +* Fixes: + * Fixed Auto-Register option not being saved for property type nodes + * Fixed issues with generated normalized screen position values over templates + +* Improvements: + * Cull, Stencil, Color Mask and Depth options can now reference properties instead of standard options + * Redone visuals of property type nodes Attributes list to be easier to use + * Added new Enum and Custom attributes to property type nodes + * Enum on Create Enum mode creates an Enum attribute using the specified Name/Value pairs + * Enum on Use Engine Enum Class mode creates an Enum attribute from the specified class + * Custom attribute allows to specify completely custom attributes + * Outline now forces shader to be Forward only to prevent visual inconsistencies + +v1.4.5 dev 01: +* New Shader Function: + * Constant Bias Scale + +* Fixes: + * Fixed null pointer issue with removing connections with Alt key + * Fixed issue on 'Template Local Var' node only working on fragment function + +v1.4.4 dev 06: +* Fixes: + * Fixed issue on 'Texture Sample' nodes not automatically setting the texture type on AUTO + * Fixed connection type mismatch after CTRL + swap shortcut + * Fixed issue on 'Dither' node + +v1.4.4 dev 05: +* Fixes: + * Fixed multiple Undo issues on shader functions + * Fixed serialization issue with both nodes and graph when hitting Unity play button + +v1.4.4 dev 04: +* Fixes: + * Fixed issue on Specular Highlights and Reflection toggle not being read/written into shader meta + * Fixed issue on not correctly taking templates global variables into account when building shader + * Fixed issue where 'Triplanar Sample' node wasn't being initialized properly + * Fixed Undo issues on create/delete nodes + * Fixed Undo issues on preview node resizing + +* Improvements: + * Added new Enum Property Attributes for both 'Float' and 'Int' nodes + * Added new Keyword Enums option to 'Static Switch' node Type option + * Improved its interface to better accommodate new options + * Added new keywords to 'Static Switch' Keyword dropdown + * Increase max port count for 'Function Switch' node to 9 + * Added/Changed shortcuts for various nodes + * R - Create 'Register Local Var' node + * G - Create 'Get Local Var' node + * Z - Create 'Swizzle' node + * X - Create 'Cross' product node + * Period(.) - Create 'Dot' product node + * B - Create 'Break to Components' node + * K - Create 'Component Mask' node + * V - Create 'Append' node + +v1.4.4 dev 03: +* New Sample: + * Skybox - Cubemap Extended by Cristian Pop + +* New Shader Functions: + * Step Antialiasing + * Create Orthogonal Vector + +* Improvements: + * Node graph is now a ScriptableObject to better deal with automatic serialization + * Templates can now register and use local variables + * Use /*ase_local_var*/ before the variable declaration over the template + * Access the local variable through the new 'Template Local Var Data' node over the graph + * Added new Normal Space option into 'Standard Surface Light' node + * Optimized nodes port internal data usage + * Node tooltip no longer shown online link for shader function nodes + * Small optimizations to node previews + +* Fixes: + * Fixed function registry on 'Custom Expression' node to correctly deal with dependencies + * Fixed issue on linear textures over the texture creator tool + * Fixed issue where the editor was being called on play mode but no window was present + * Fixed issue on texture coordinates of different sizes being created with the same name + +v1.4.4 dev 02: +* Fixes: + * Fixed issue on templates where vertex normal was being declared as a float4 on vertex data + * Fixed PS4 issue on billboards generated code + * Updated Orientation Based Sprite sample to include fix + +* Improvements: + * Changed texture array creator to support compressed formats + * Added custom inspector for texture arrays to allows previewing their contents on the inspector window + * Added new Set Unique option into 'Custom Expression' node + * If toggled off, generated internal function doesn't use unique id on its name + +v1.4.4 dev 01: +* Improvements: + * Custom Pragmas, Includes and Defines are now also included on the Outline pass + * Automatically removing crlf from copy-pasted code over the 'Custom Expression' node + * Custom Render Type can now be specified on the Render Type dropdown over the Output node properties + +* Fixes: + * Fixed issues on 'Remainder' node + +v1.4.3 dev 05: +* Fixes: + * Fixed issue on excluding Add Pass independently of Debug port connection + +v1.4.3 dev 04: +* New Shader Function: + * Radial UV Distortion + * Sample with the same name was also added to demonstrate its usage + +* Fixes: + * Fixed multiple issues related to Debug port usage on Output node + * It now works as a custom lighting port instead of emission + * Fixed issue on incorrectly opening standard materials into ASE + * Fixed issue on duplicate local variable creation when using 'Parallax Mapping' node on shader functions + +v1.4.3 dev 03: +* Fixes: + * Fixed issue on 'Vertex Tangent' node internally outputting float4 data in templates instead of float3 + * Fixed shader function category typos + * Fixed issue on ports accessing already destroyed nodes for previews + * Fixed issue on precision type used in shader functions + +* Improvements: + * Added ZWrite and ZTest options to 'Outline' node + +v1.4.3 dev 02: +* Improvements: + * Shader tags can now be modified on templates based shaders + * Added new Particle Additive option on Blend RGB and Blend Alpha dropdown + * Sets Source to 'Source Alpha' and Destination to 'One' + * Added new options to 'Shade Vertex Lights' node + * Can now select amount of lights to take into account and if as spot or point light + +* Fixes: + * Fixed issue on incorrectly indented code generated by some nodes on template shaders + +v1.4.3 dev 01: +* New Samples: + * Orientation Based Sprite + * UI Sprite FX + +* New Shader Function: + * Box Mask + * UI-Sprite Effect Layer + +* Fixes: + * Fixed issue on attempting to deactivate destroyed nodes + +* Improvements: + * Updated Sprite and UI templates to better support normal maps + * Changed way logic is updated in some nodes to be more consistent and work inside shader functions + +v1.4.2 dev 06: +* Fixes: + * Fixed incorrect wire highlighting caused by 'Register Local Var' node + * Fixed issue with 'Texture Sample' node not generating proper UVs in specific cases when using templates + * Minor UI and refresh fixes to 'Function Switch' node + * Fixed issue on incorrectly loading SimpleTerrain sample + * Fixed issue on unnecessary loading when opening a changed shader or function + +* Improvements: + * Added compatibility with Unity 2018 + * For now 'Substance Sample' node is unavailable on this version + * Substance example is now inside a unity package to prevent sbsar importing error + * Removed Substance and API update warnings on Unity 2017 + * Added new Vertex Position input port into 'Surface Depth' and 'Camera Depth Fade' nodes + * Can now take custom vertex positions into account + * Added some minor improvements into 'Register Local Var'/'Get Local Var' node usage + * 'Register Local Var' node is now highlighted if one of its 'Get Local Var' nodes are selected + * 'Register Local Var' node now lists and can focus each 'Get Local Var' which uses it + * Added reference capabilities to 'Function Switch' + * One node can now control different paths of a shader function graph + +v1.4.2 dev 05: +* Fixes: + * Fixed Undo issues with connections created/deleted by drag + Alt + * Fixed issue on templates vertex local variables when using 'Vertex To Fragment' node + * Fixed bug where 'Function Switch' node options were being incorrectly saved which caused a crash on load + * Fixed shader 'Function Switch' node options not being correctly ordered all the time + * Fixed connection signal detection to make 'Function Switch' nodes know when to turn on + +v1.4.2 dev 04: +* New Node: + * Function Switch + * Node specific to shader functions which allows switching options at compile time on them + +* New Shader Function: + * Flipbook + +* Improvements: + * Changed switch type nodes port order to match 'Function Switch' and maintain consistency + +* Fixes: + * Fixed issue on duplicated functions when both outline and shadow caster passes are active + * Fixed issue with calculating label size for nodes + * Fixed UI issue when not being able to read depth info from template + +v1.4.2 dev 03: +* Improvements: + * Added Depth module into templates + * Minor improvement on Four Splats First Pass Terrain shader function + * Minor improvement on TerrainSnowCoverage and SimpleTerrain samples + * Added preview and access to internal data into 'HSV To RGB' and 'RGB To HSV' nodes + * Added preview to 'If' node + * Added new Normalize option into 'World Normal' and 'World Reflection' nodes + * 'Outline' node now supports transparency and mask operations through the new Alpha Mode option + * An additional depth pass can be added via the new Extra Depth Pass option on the Output Node properties + * Property nodes can now register its properties/global variables without being connected to Output node + * Done via the new Auto-Register option + +* Fixes: + * Fixed minor issue on 'Rotate About Axis' node UI + * Fixed issue with 'World Reflection' node on templates + +v1.4.2 dev 02: +* Improvements: + * 'Toggle Switch' node can now share properties + * Added lock button to property name on property type nodes + * Allows to customize the internal variable name used + * Added support for 'View Dir' node on templates + * Added preview position selection to shader functions to further customize function nodes + +* Fixes: + * Fixed issue where custom shadows were ignoring vertex colors + * Fixed issue on 'Fresnel' node using a non-normalized normal vector + * Small fix on 'Static Switch' node getting and setting values from the material + +v1.4.2 dev 01: +* Improvements: + * Lowered Shader Model target of Custom Lighting Toon example to be compatible with MacOs + * Improved generated code for 'Grab Screen Color' and 'Grab Screen Position' nodes + * Changed automatic generation of 'Grab Screen Color' node to make sure normalization is happening only once + * Added a toggle on 'Grab Screen Color' node which chooses if it normalizes/projects the input or not (default OFF) + +* Fixes: + * Fixed issue on generating default values for shader functions + * Fixed issue on normal generation with the following nodes: + * 'Fresnel' + * 'Indirect Specular Light' + * 'World Reflection' + +v1.4.1 dev 02: +* New Nodes: + * Decode Depth Normal + * Encode Depth Normal + +* Improvements: + * Added internal data into shader functions + * If inputs are unconnected is now possible to change the default value from its node property panel + * Property type nodes can now keep material value when not connected to an Output node + * Tweaked 'Static Switch' node properties + * Initial opened tab on property nodes depends on material mode + +* Fixes: + * Fixed issue on 'Custom Expression' node when using out variables in Call mode + * Preventing 'Commentary' node from generating infinite loops when copy-pasted + * Fixed issue with incorrect refresh call order on pasted nodes + * Fixed issue on nodes are not being correctly nested into their parent 'Commentary' node when copy-pasted + * Fixed issue on 'Toggle Switch' node not updating port names correctly after loading + * Fixed focus issue on pickers with Mac + +v1.4.1 dev 01: +* Fixes: + * Fixed issue on 'Texture Sampler' node getting incorrectly configured on load + * When default texture type different from material texture type + +v1.4.0 dev 06: +* New Samples: + * Simple Terrain + * Terrain Snow Coverage + * Custom Outline Toon + +* New Nodes: + * Rotate About Axis + * Outline + +* New Shader Functions: + * Four Splats First Pass Terrain + +* Improvements: + * Tweaked 'Scale And Offset' node behavior + * Added Defines tab into Output node properties + * Preventing possible compilation errors on Experimental .NET 4.6 + +* Fixes: + * Fixed issue on 'Texture Sampler' node not previewing a connected 'Texture Object' node + * Fixed issue on texture picker not working correctly on texture nodes + * Fixed incorrect version reading Convert To Linear parameter at 'Screen Depth' and 'Depth Fade' node + * Fixed issue on duplicate UV Set on 'Texture Sampler' node when connected to a 'Texture Object' + * Fixed issue shader function inputs and outputs getting lost when re-focusing on them by double clicking the shader function node + * Fixed issue on 'Custom Expression' node name editing on node body + +v1.4.0 dev 05: +* Fixes: + * Fixed issue on shadow caster for legacy samples: + * Matcap + * Parallax Mapping Iterations + * Reflect Refract Soap Bubble + * Screen Space Curvature + * Fixed typo in 'Toggle Switch' node + * Fixed issue on incorrectly accessing port through array id instead of unique id + * Fixed issue on deprecated internal data not being correctly read into new 'Append' node + +* Improvements: + * Up and Down arrow keys can now change the focus of the node element in the context palette search similar to the Tab key + +v1.4.0 dev 04: +* New Samples: + * Animated UV Distortion + +* Fixes: + * Fixed issue on a shader function node crashing when its corresponding asset is not found + * Fixed issue on applying Undo on Material Inspector not being caught by ASE canvas + * Fixed issue on 'Float' node slider not being registered on Undo stack + * Fixed issue on generating duplicate function names at 'Noise Generator' node + * Fixed issue on returning to from a shader function to a main graph using with that shader function selected + +* Improvements: + * Added new Variable Mode property into property nodes when their type are not Constant + * Create Mode, this is the current option on which an uniform variable is always created when the node is analyzed + * Fetch Mode, assumes that this variable is already declared elsewhere, p.e. an external lib and doesn't declare it + * When Property Type is selected, the property declaration is still created + * Added explicit call to both Thread and CultureInfo system classes to avoid conflicts with user classes without proper namespace + * Shader function's input and output ports maintain correct connections after being internally re-ordered + * Automatically adding spaces into camelcase'd shader function node titles + +v1.4.0 dev 03: +* Improvements: + * Added validity check on Output and Input data types + * Improved color code request for ports + +v1.4.0 dev 02: +* New Shader Functions: + * Compute Filter Width + +* Improvements: + * Explicitly calling System.Globalization on TextInfo usage to avoid compilation errors + * Added custom pragmas for shader functions + * Updated Vertex Normal Reconstruction sample + * Added Reflection and Specular Highlight toggles into the Rendering Options group that mimic Unity's Standard + * Added ToggleOff option to 'Static Switch' node which should now allow the creation of OFF toggles + +* Fixes: + * Fixed issue of properties not being properly ordered if their material property group wasn't open + * Blend modes now update properly even if group is collapsed + +v1.4.0 dev 01: +* Fixes: + * Fixed issue with 'World Space Light Pos', 'World Space Light Dir' and 'Object Space Light Dir' nodes + * Fixed issue on 'Texture Coordinates' node forcing a sampler to be picked even when none was selected + * Fixed issue on 'Indirect Diffuse Light'node ignoring the tangent space normal completely + * Small fix to shader functions so they can refresh their custom include list properly on change + +* Improvements: + * Added node previews for 'Light Attenuation' and both Indirect Light nodes + * Added explicit call to Unity Editor ShaderUtil on Material Inspector to prevent class issues + * Added Dependencies List on the Output Node properties + +v1.3.9 dev 03: +* New Nodes: + * 'Projector Matrix' + * 'Projector Clip Matrix' + * 'Texture Transform' + +* Improvements: + * Properties can be re-ordered on Template shaders + * Cull, Blend Mode, Blend Ops, Color Mask and Stencil Buffer data can be read and modified on Template shaders + * Added new custom Time port into 'Flipbook UV Animation' node + * Templates no longer need /*ase_pass*/ tag to be declared + * Adding UnityEngine.Object redundancy on its usage to prevent issues with other plugins + * Outline can now take fog into account + +* Fixes: + * Fixed issue on shader function headers being placed last on shader property list + +v1.3.9 dev 02: +* Fixes: + * Additional fix on custom colored categories + +v1.3.9 dev 01: +* Fixes: + * Fixed issue with 'Texture Coordinates' node not generating proper code for sizes bigger than float2 + * Fixed issue on reading old shaders data into new ASE versions + * Fixed issue on custom colored categories + +* Improvements: + * Updated various samples that were still compiled on older ASE versions + * ASE window now loses text focus when losing its focus to prevent UI issues + * Added proper Texcoord support in custom shadow caster + * Added new toggle on 'Screen Depth' and 'Depth Fade' nodes to disable conversion from log to linear space + * Important for Orthographic camera projections where Depth Buffer values are already stored in linear space + +v1.3.8 dev 02/03: +* Improvements: + * Added new custom lighting port and migrated the emission connection to this port + * Now custom lighting display both albedo and emission to be used in baking + * 'Function Input' and 'Function Output' names can be edited through node body + +* Fixes: + * Fixed indentation issue on some templates generated code + * Fixed issue in texture property that would forget it's auto cast type on load + * Fixed issue on 'Triplanar Sample' node being initialized with incorrect internal tiling value + * Fixed issue on screen position for 'Dither' node + * Now it changes the screen position interpolator globally to make it work on the shadow caster + +v1.3.8 dev 01 ( the same as v1.3.7 dev 07 but bumped version for Asset Store release ): +* Improvements: + * Added Shader Function previews + * Improved node list update on current focused window when renaming a shader function + +* Fixes: + * Fixed issue on tabs node list not being updated with shader function renaming + * Fixed issue with opacity mask not working correctly in custom lighting mode + +v1.3.7 dev 05/06: +* New Shader Functions: + * Half Lambert Term + * Blinn-Phong Light + +* Fixes: + * Fixed issue with setting the proper canvas mode when load the shader or the editor window on hotcode reload + * Fixed issue with shader function titles not supporting hyphen characters + * Fixed issue on not refreshing shader function include files on load + * Fixed issue on shader function tab name not being renamed when its file is renamed from the editor + * Fixed 'Texture Sampler' node preview when in reference mode + * Fixed stack overflow crash with pasting 'Commentary' nodes + +* Improvements: + * Premultiplied options now multiply RGB values with Alpha when in custom lighting mode + * Shader Functions are now loaded by guid and fallback to name search method if load fails + * Added custom categories for shader functions + * Recompiled existing shader functions to account for new categories + * Improved 'Triplanar Sample' node texture array support + * Now allows different index for each texture when doing triplanar in cylindrical mode + * Area from picking inputs from connections now only take the port icon into account and only include the label when dropping the connection + * Added preview for 'Static Switch' node + +v1.3.7 dev 04: +* Fixes: + * Fixes issue on Shader Function includes + +v1.3.7 dev 03: +* Fixes: + * Fixed issue on custom lighting nodes not compiling correctly when inside a shader function + * Fixed dithermask being declared when not in use + * Fixed texture array support with 'Triplanar Sample' node generating index code inside the function instead of outside of it + * Fixed issue with 'Append' node preview + +* Improvements: + * Replacing '\' with '/' instead of removing it when writing Additional Include path names + * Added Additional Include list into shader functions + +v1.3.7 dev 02: +* Fixes: + * Fixed issue with 'Texture Coordinates' node not generating local variables correctly + * Fixed issue with Refraction port not correctly working with Tessellation + * Fixed issue on applying vertex offset in certain Templates + * Fixed cast and per channel operation issues on remaining blends on 'Blend Ops' node + * Fixed issue on Soft Light Blend Op on 'Blend Ops' node + * Fixed issue of Shader Function nodes not propagating data when generating code + * Fixed focus issues when adding new items on Additional Includes, Pragmas, Sub-Shaders Tags and 'Custom Expression' node tools + +v1.3.7 dev 01: +* Fixes: + * Fixed 'Fmod' node issue with Int type connections + * Small fix to the path button in the new Texture Array Creator tool + +* Improvements: + * Adding fallback when searching template by guid fails + +v1.3.6 dev 01: +* Fixes: + * Fixed error when setting previews for texture related nodes + +* Improvements: + * Improved cubemap support into texture related nodes + * Removing Texture 0-3 and Scale Matrix options from 'Common Transform Matrices' node + * Major rewrite for 'Triplanar Sample' node to make it easy to extend on the future + * Small performance increase to 'Triplanar Sample' node + +* Deprecated nodes: + * 'Texture 0 Matrix' + * 'Texture 1 Matrix' + * 'Texture 2 Matrix' + * 'Texture 3 Matrix' + * 'Scale Matrix' + +v1.3.5 dev 02: +* New Tool: + * Added Texture Array Creator tool + * Available at Window > Amplify Shader Editor > Texture Array Creator + +* Fixes: + * Fixed Undo not being able to recover some nodes + +* Improvements: + * Changed Custom Material Inspector to be able to set and show custom meshes in it's Preview + * Template Data nodes now expand individual channels if data selected is from vector/color type + * Expanded individual channels ports on: + * 'Object Space Light Dir' + *'World Space Light Dir' + * 'World Space Camera Pos' + * 'Position From Transform' + * 'Vector From Matrix' + +v1.3.5 dev 01: +* New Shader Functions: + * Blinn-Phong Half Vector + +* Fixes: + * Fixed issue on 'Toggle Switch' node not being correctly registered when created + +v1.3.4 dev 02: +* Fixes: + * Fixed issue on text fields in nodes picking up values from other text fields in the editor + * Fixed cast issue on 'Flipbook UV Animation' node + * Fixed issue on creating sampler wire nodes + * Small fix for resize buttons of 'Comment' nodes + * Small fix to focus and select search text in the context menu not happening in specific situations + * Fixed issue with 'Object To View Pos' local variable + * Fixed 'Triplanar Sample' node normal mode signs in certain situations + * Fixed issue on adding the same grab pass declaration multiple times + * Fixed issue on incorrectly getting separate channels from transform nodes after local variables are created + * Fixed issue on duplicate uniforms with some templates + * Fixed issue where shader function properties were resetting after every save + +* Improvements: + * Locking blend type nodes from sampler and matrix type connections + * Expanded 'Object To View Pos' vector output vector into individual ports + * Changed 'Triplanar Sample' node base UV direction to match unity terrain + * Expanded vector ports for 'Object Space View Dir' and 'World Space View Dir' + * 'Lerp' node now converts int types in the alpha input port to float types to prevent errors + +v1.3.4 dev 01 +* Fixes: + * Fixed issue with Opacity Mask port incorrect type + * Fixed issue with incorrectly saving/loading multilines state in editor prefs + * Fixed issue on not being able to create relays on texture type connections + +v1.3.3 dev 01: +* Fixes: + * Fixed multiple issues with 'Append' node behavior + * Fixed null pointer exception when Shift + Tabbing helper window + * Fixed duplication error on UV generation code + +* Improvements: + * Added Alpha To Coverage option ( tied to Opacity port being active ) + * Opacity Mask now only generates code if connected + * Blend ops defaults are now OFF instead of ADD + * Blend ops now pick the respective refined options when a specific blend mode is selected to make it easy to switch between them and the custom option ( opaque doesn't change anything ) + +v1.3.2 dev 04/05: +* Fixes: + * Fixed Asset Post Processor issue with Templates renaming + * Fixed middle clicking on reference preview focusing on referenced node + * Fixed graphic glitch on 'Static Switch' node button + * Fixed issue with copy/pasting nodes taking incorrect property names + * Fixed issue on 'Toggle Switch' incorrectly being read from older ASE versions + * Minor fix on 'Object To Clip Pos' node + * Fixed Undo issue with pasted property nodes + * Fixed issue with duplicate local variables on templates when having multiple ports from the same category + +* Improvements: + * Minor visual tweak on 'Standard Surface Light' node + * Removed dependencies on custom shader inspector over the main ASE window so it can be removed by users + * Setting first vector port automatically invisible ( if unconnected ) on nodes representing Unity built-in parameters ( since they are never used as vectors ) + * Improved custom template reader behavior + * Minor improvement on Undo node paste behavior + * Added Stencil Buffer Back and Front face options ( only visible when Culling is Off ) + * Changed input ports number of connections and data type visualization to represent the data being transferred in each cast + * Improved crooked lines when nodes are too close to each other + * Added custom single line texture properties for when the texture is marked to not have scale and offset properties + +v1.3.2 dev 03: +* Fixes: + * Fixed issue with 'Texture Sampler' node not taking procedural textures correctly into account + * Matrices can no longer be connected into 'Vertex To Fragment' nodes input port + * Fixed reordering issues with shader functions when these were updated + * Fixed rare compile issue where shader function headers were created but no property was present + * Fixed issue where view direction vector shader code was being generated with different precision types + * Fixed issue with Matrix nodes being able to choose its type as Property and add Attributes + * Fixed issue with Matrix nodes initial value not corresponding to internal draw data + * Fixed issue with Matrix3x3 not working correctly when its type was set as Global + * Fixed issue on function nodes generating local variables for Sampler data type variables + +* Improvements: + * Activating internal data for tessellation nodes + * Minor tweak on vertex position data across all templates + * Preventing 'DDX' and 'DDY' nodes to generate code when in vertex function + * Removed Sampler data types as valid 'Custom Expression' output valid type + +v1.3.2 dev 02: +* New Shader Functions: + * 'Bidirectional Parallax Mapping' + * Mimics iterative Parallax Mapping with reference plane + * 'Reconstruct World Position From Depth' + +* New Samples: + * Added new Vertex Normal Reconstruction sample + +* Fixes: + * Fixed issue with shader function nodes generating the same code multiple times + * Fixed issue with function input generating duplicated code + * Fixed issue with 'Texture Coordinates' node generating code in the vertex function when used inside a shader function + * Fixed issue on 'Texture Coordinates' node in templates not respecting the size of the Coord Size option + * Fixed issue on matrix multiplication via the 'Multiply' node not taking correct output type into account + * Minor fix on Search Bar positioning + * Recompiled Triplanar sample to be PS4 compatible + * Recompiled Translucency sample to be PS4 compatible + * Recompiled Hologram sample to be PS4 compatible + * Fixed compilation issue with Billboard generated code in PS4 + * Fixed hot code reload issue with 'Template Parameter', 'Template Vertex Data' and 'Template Fragment Data' + * Fixed issue on 'Fresnel' node not read/writing new normal space option + * Fixed issue on 'Screen Position' node when used on Templates + +* Improvements: + * Functions inputs now allow the use of node default graph trees supporting complex default operations + * Particle Alpha Blend template now uses a float4 on its TEXCOORD0 semantic both for vertex and interpolator data + * Added pragma tag into Default Sprites template + * Added port failsafe config into 'Texture Sample' node after reading all its internal data + * Making vector port invisible in Unity Parameters type nodes if not being used + * 'Component Mask' node only creates local variables if needed + * Multi-wire colored connections now active by default + * 'Fresnel' node now have Normal Space option set to Tangent by default + * Shader functions now display their description on its Inspector window + * Fixed 'Grab Screen Position' and 'Grab Screen Color' nodes for VR and updated the respective samples accordingly + +v1.3.2 dev 01: +* New nodes: + * 'Camera To World Matrix' + * 'World To Camera Matrix' + +* Fixes: + * Fixed issues with 'Toggle Switch' node + * It now properly creates a toggle property and lets user change material in the editor + * Fixed issue on vertex local variables not being registered correctly on custom lighting + * Precision selection on 'Grab Screen Color' node is no longer locked when Custom Grab pass is disabled + * Fixed issue with 'Depth Fade' node on OpenGL platforms + * Normalized screen position code now works properly in all platforms + * Fixed issue with 'Texture Array' node preview + * Fixed issue with 'Vertex To Fragment' node generating duplicated code + +* Improvements: + * Added toggle button into 'Static Switch' node + * Improved wire auto-connection to node when its created from the context palette when dragging a wire + * Auto screen UVs from 'Grab Screen Color' node now also take Unity Single Pass Stereo into account + * Improved code generation on screen position related nodes + * Activating internal port data into 'Toggle Switch' node + * Updated Simple Blur and Simple noise examples to be fully android compatible + * Tweaked 'Desaturate' node to prevent issues with PS4 + * Tweaked 'Parallax Occlusion Mapping' node to prevent issues with PS4 + +v1.3.1 dev 11: +* Fixes: + * Fixed incorrect UV variable name on Post-Process template + * Fixed Perforce integration again + * Fixed preview on 'Fresnel' node for the new tangent mode + * Fixed issue with 'Screen Position' subtitle + * Fixed issue with 'Vertex to Fragment' node on templates + +* Improvements: + * Added two additional nodes to templates,'Template Vertex Data' and 'Template Fragment Data' + * These nodes allow direct access to vertex and interpolated fragment data from the template + * Adding vertex code entry tag into Post-Process template + * Improved fail-safe behavior on attempt to write vertex code on template with no vertex tag declared + * Minor tweaks on some nodes port names and order + * 'Dither' node now has a input port that allows the use of a custom dither pattern + * 'Vertex to Fragment' node no longer generates unnecessary code and now acts as a relay if connected to a vertex path + +v1.3.1 dev 10: +* Fixes: + * Fixed cast issues on 'Smoothstep' node + +v1.3.1 dev 09: +* Fixes: + * Multiple fixes on custom shadow caster + * Fixed issue on Templates Manager being incorrectly destroyed in some situations + * Fixed issue on Template data not being correctly synced when user changes its source code and returns to ASE + * Fixed issue where referenced 'Texture Sampler' nodes was not respecting the original property order + * Fixed issue on 'Grab Screen Color' node not using Unity default grab pass when selected to use it + * Fixed small issues on multiple examples + +* Improvements: + * Added tangent space normals to 'Fresnel' node and removed the internal normal value from its properties + +v1.3.1 dev 08: +* Fixes: + * Fixed issue on 'Simple Contrast' node + * Fixed boundaries issues on 'Dither' node + +* Improvements: + * Minor tweak on 'Smoothstep' ports order + * Added new Color and Intensity ports into 'Light Color' node + * Minor overall optimizations on node previews + * Added preview for 'Substance Sample' node + * Added preview for 'Blend Operations' + * Added input port for automatic texture dithering into 'Dither' node + +v1.3.1 dev 07: +* Fixes: + * Fixed issue on 'Simple Contrast' node ignoring Value internal data + * Fixed issue on nodes preview data not being written when its internal data is read from shader + * Fixed 'Texture Sampler' node to output a Color instead of Vector type + * Fixed 'Swizzle' node not detecting changes on its input ports + * Fixed issue on allowing invalid characters when typing a custom keyword on the 'Static Switch' node + +* Improvements: + * Improved code generated by 'If' node and hides unused internal data + * Improved 'Rotator' node behavior + * Improved 'Panner' node behavior + * Added checkout for version control systems that need it to edit files like perforce. + * Changed labels and port order for various nodes in the Image Effects category to improve consistency + +v1.3.1 dev 06: +* Fixes: + * Fixed issue on template output node attempting to access template data before its initialization is complete + * Fixed issue with validate/execute commands like duplicate on Mac + * Fixed issue on not updating correctly mouse position when doing multiple pastes/duplicates + * Fixed disappearing titles when selecting 'Register Local Var' nodes being used by 'Get Local Var' nodes located outside the visible graph area + * 'Toggle Switch' node now properly casts its main port type for both input ports + +v1.3.1 dev 05: +* Fixes: + * 'Indirect Specular Light' and 'Indirect Diffuse Light' now compile properly in vertex functions but provide dynamic baking results only + * Changed mask clip variable name to be compatible with internal unity functions + * Fixed issue with texture arrays derivatives not being declared in 'Parallax Occlusion Mapping' nodes + * Fixed 'Texture Sample' node not changing cast mode automatically when in reference mode + * 'Lerp' node now works as the hlsl/cg specification and allows for component based interpolation + * Fixed issue on template native properties getting lost when hot code reloading + +* Improvements: + * 'Get Local Var' nodes now get highlighted in green when their referenced 'Register Local Var' node are selected + * It should be now easier to spot how many and which nodes use a determined Register node, we intend to expand this idea to other similar cases + * 'Static Switch' now allows to use define symbols and material toggle is now optional + * 'Keyword Switch' is now deprecated (opening the shader in newer versions should replace it by 'Static Switch') + * 'Static Switch' and 'Grab Screen Color' nodes now show their node name in title but still allows to edit their variable by double clicking + * Reorganized toolbar buttons for consistency + * Showing internal value name at the node properties window when selecting a property on the 'Template Parameter' node + +v1.3.1 dev 04: + +* Fixes: + * Fixed issue with 'Static Switch' node duplicatnig code + * 'Static Switch' node now properly allows the use of the same keyword + * Fixed issue with Int ports generating black previews + * Fixed issue where 'Custom Standard Lighting' node was generating garbage code when connected multiple times + * Fixed dynamic baked lightmapping for 'Indirect Diffuse Light' node + * Default fallback is now only added if shader doesn't use it's own + +* Improvements: + * Changed 'Template Parameter' node to mimic the same look from the equivalent property nodes + * Changed some labels and warning texts to be more clear on what's going on for texture objects + * Int port color now uses the same color as float nodes + * Added ASE custom inspector to the default templates + * Added support for Texture Arrays with 'Parallax Occlusion Mapping' node + +v1.3.1 dev 03: +* New Features: + * Added custom pragmas support to the main property panel + +* Fixes: + * Fixed issue with texture arrays when in reference mode creating multiple properties + * Fixed issue of 'Vertex To Frag' node not generating code in certain situations + * Fixed issue with 'World Reflection' node not generating code correctly in vertex functions + * Fixed issue of custom shadow caster not using the correct shader model + * Fixed issue with dynamic port nodes not updating correctly in some occasions + * Fixed issue of some nodes not properly using the selected precision type + * Matrix 3x3 port types now display properly in the node property panel and compile correctly + +* Improvements: + * 'World Position' node now forces float precision + * Some more changes for the nodes subtitles for consistency + * Minor performance and GC improvements + +v1.3.1 dev 02: +* Fixes: + * Fixed issue with 'World Normal' node not generating it's components values properly in some occasions + * Fixed issue with some parameters foldouts not displaying correctly and added a new context message for empty foldouts + +* Improvements: + * Changed some subtitles prefixes to be more consistent about what they represent + * Changed dropdown icon to a less confusing and more intuitive one + * More editor performance improvements and reduction of GC in various places + +v1.3.1 dev 01: +* Fixes: + * Fixed issue on copy-pasting custom lighting nodes + * Fixed issue on null pointer reference on preview material when hitting play mode + +* Improvements: + * Added upper left widgets into several nodes to change important properties directly on node body + * Added secondary title into several nodes to show its current state directly from node body + +v1.3.0 dev 03: +* Improvements: + * Completely refactored and changed the graph and node rendering to use a semi-MVC model + * Improves the overall performance in several orders of magnitude + * Various small visual fixes and improvements + * Various changes to prevent most memory allocations heavily reducing GC + * Changed zoom and auto-pan to a smooth version and fixed its auto-boundaries + * This should make the editor feel more snappy and responsive + * New object pickers for 'Substance Sampler' and 'Triplanar Sampler' + * New outline for selected Wire nodes + * Now is easier to see in all situations + * Various previews were added,improved or fixed + * 'Texture Sampler' nodes now properly display default values + * Tweaked Input Type labels on 'Custom Expression' nodes to match shader variable type names + * Custom Lighting nodes now show internal data and have additional Normal options + +* Fixes: + * Fixed 'Texture Array' node issue when referencing an un-connected node + * Fixed UI issue on 'Custom Expression' qualifiers + * Fixed issue on shader name being overwritten when changing template + * Fixed issue on copy/cut/paste not being correctly caught by nodes search bar + +v1.3.0 dev 02: +* Fixes: + * Fixed issue with Output Node Opacity Mask port not working with Custom Lighting + * Fixed errors with some nodes inside shader function + +* Improvements: + * Improved internal file reader to be more robust in case of trying to load in-existent files + * Templates Manager can now also be initialized by its post processor in case of an ASE window is not open + * 'Blend Operations' node show current selected Blend Op on node body + * Locked Custom Light nodes from being used on Templates + +v1.3.0 dev 01: +* New Features: + * Templates + * Create new shaders from already existing ones which serves as base/templates + +* Fixes: + * Fixed issue on ports internal data not showing on 'Append' node + * Fixed infinite loop on 'Texture Coordinates' and 'Texel Size' nodes + +v1.2.1 dev 02: +* Fixes: + * Fixed issues with previews on 'Multiply' node + * Fixed incorrect tooltip on 'Face' node + * Fixed issue on 'Standard Surface Light' node where GI wasn't correctly picking normals + * Fixed 'Texture Sampler' node not correctly generating code when connected to relays or shader functions + * Fixed issue on 'Texel Size' and 'Texture Coordinate' nodes when referencing nodes not connected to Master Node + +* Improvements: + * 'Grab Screen Color' node now uses Unity default grab texture and allows overriding it like it's previous behavior + +v1.2.1 dev 01: +* Improvements: + * Major refactor on all nodes categories and colors to improve consistency + * Added subtitle to 'Swizzle' and 'Component Mask' nodes to reflect their options + * Added configurable background color for 'Commentary' nodes + +* Fixes: + * Fixed issue with lightmaps when using the 'Standard Surface Light' node on Custom Lighting Light Model + * Fixed issue on overwriting default texture values on 'Texture Sample' node when loading values from material + +v1.2.0 dev 02: +* Improvements: + * Adding Call Mode into 'Custom Expression' node + * On this mode all code written into the Code area will be directly injected into the shader code without being assigned to a local variable + * The result written on the output port will be what is directly connected to the first input port ( named In ) which is not taken into account by the code expression. The In/Out pair will act as a simple relay. + +v1.2.0 dev 01: +* Fixes: + * Fixed issue on generating UI exception when sometimes iterating between Search Node Bar results + * Fixed issue on Output node size increasing infinitely with shader name + * Fixed issue on incorrect serialization on 'Texture Sampler' node + +* Improvements: + * Texture Object type nodes no longer auto-set the 'Texture Sampler' Normal Map option + * Normal Map option was renamed to Unpack Normal Map + * A warning is shown if a Texture Object marked as normal map is connected to a 'Texture Sampler' node with the Unpack Normal Map options turned off + +v1.1.0 dev 13: +* Fixes: + * Fixed issue with reading incorrect legacy port info into 'Lerp' node + * Fixed issue on cycling through deleted nodes when using the Nodes Search Bar + * Fixed issue with incorrectly moving nodes nested into multiple 'Commentary' nodes + * Fixed issue on Undo not registering internal node movement on 'Commentary' nodes + * Fixed issue when using 'Virtual Texture Object' node on Vertex ports + * Fixed issue with incorrectly moving selected nodes while resizing side menus + +* Improvements: + * 'Simple Contrast' node now always store its result on a local variable + * Greatly improved 'Commentary' node: + * You now can use box selection inside the node body + * You now can create Wire nodes by double clicking on a wire inside the node body + * You now select and drag the node via its header or by pressing anywhere on the node body having the Alt key down + * You now need to double click the node header to be able to modify its comment directly from there + +v1.1.0 dev 12: +* Fixes: + * Fixed issue with creating legacy code for LOD Cross Fade on Unity v.2017 and above + * Fixed issue on 'Lerp' node not adjusting correctly when disconnecting input ports + * Fixing issue with node drag with snap + * Now done by having both Ctrl+Shift pressed + +* Improvements: + * 'Blend Operations' node now automatically adapts to input ports + * Improving Search Bar focus behavior + +v1.1.0 dev 11: +* Fixes: + * Fixed incorrect behavior on creating connections through Alt + Shift + * Fixed out of bounds exception caused by removing ports on shader functions + * Fixed issue with 'Triplanar Sampler' node not deleting correctly in some occasions + * Fixed ordering issues with Stencil Buffer example + +* Improvements: + * Overall improvements on nodes descriptions + +v1.1.0 dev 10: +* Fixes: + * Fixed new Billboard Ignore Rotation option incorrectly ignoring game object translation + +v1.1.0 dev 09: +* Fixes: + * Fixed issue with deprecated nodes warning message throwing an exception on recent Unity versions + * Fixed 'Texel Size' node issues on Shader Functions + +v1.1.0 dev 08: +* New Features: + * New 'Keyword Switch' node + +* Improvements: + * Improved 'Lerp' and 'Clamp' nodes behavior + * Added new improved dynamic 'Append' node which adapts to inputs and deprecated the old one + * Billboards can now ignore object original rotation via its new Ignore Rotation toggle + * New Soft Light option was added to 'Blend Operations' node + +v1.1.0 dev 07: +* New Features: + * Added support for Custom Subshader Tags on Output Node properties + +* Fixes: + * Fixed issue with having 'Custom Expression' nodes with similar port names + +* Improvements + * Small improvements on canvas zoom behavior + +v1.1.0 dev 06: +* New Features: + * Added new nodes: + * 'World Transform Params' + * 'Vertex Bitangent' + * 'Vertex Tangent Sign' + +* Improvements: + * Able to specify an HDR color on 'Color' node if the HDR attribute is set + * Added previews to nodes: + * Time + * Object Scale + * Improved how vertex data is being generated to prevent future issues + +* Fixes: + * Fixed incorrect order of instruction write on 'Texture Coordinates' node + +v1.1.0 dev 05: +* New Features: + * New 'Standard Surface Light' node ( exclusive to Custom Lighting Light Model ) + +* New Samples: + * Double Layer Custom Surface + +* Fixes: + * Fixed issue with pasting nodes not refreshing external references from original ones + * Fixed issue with generating helper local variable ids on several nodes which may lead to issues on shader functions + * Fixed issue on 'Depth Fade' node + * Fixed issue with not registering sampler dummies correctly when using 'Texture Coordinates' node with Tessellation + * Fixed issue on multi-tabs with breaking all tabs except the focused one when dragging wires + +* Improvements: + * Added previews to nodes: + *'World Space Camera Pos' + *'Object Space Light Dir' + *'World Space Light Dir' + *'Light Color' + *'Object To World' + *'World To Object' + +v1.1.0 dev 04: +* Fixes: + * Fixed issue on 'Texture Coordinates' node generating wrong dummies on UV Sets different than 1 + * Fixed issue on 'Register Local Var' node usage with shader functions + +* Improvements: + * Setting Enable Instancing option default value to false + * Adding Exact Conversion option into 'Gamma To Linear' and 'Linear To Gamma' nodes for more accurate results + +v1.1.0 dev 03: +* Fixes: + * Fixed issue on 'Pi' node + * Fixed issue on 'Texture Coordinates' node not generating unique names when used on vertex body + * Fixed issue with incorrectly counting amount of 'Virtual Texture Object' nodes on graphs + * Fixed issue on 'Texture Array' drawers + * Fixed issue on 'Remap' node preview preventing division by zero + +* Improvements: + * 'Texture Array' node: + * Now work with shader functions + * Added derivative option to 'Texture Array' node + * Minor tweak on tooltip text + +* New Features: + * New Community Node 'GlobalArray' submitted by Vincent van Brummen and created by Johann van Berkel + * Added new Enable Instancing toggle into Rendering Options to be able to activate instancing without having to use Property nodes + +v1.1.0 dev 02: +* Improvements: + * 'Vertex TexCoord' and 'Swizzle' node types can be selected from node body + +* Fixes: + * Fixed issue with 'Grab Screen Color', 'Get Local Var' and 'Texture Sample' nodes loosing references inside Shader Functions + * Fixed issue on not correctly registering all Grab Passes from multiple 'Grab Screen Color' nodes + * Fixed small issue on 'Commentary' node not being able to focus on comment text field when created + +v1.1.0 dev 01: +* Fixes: + * Fixed issue with being able to open recently created shader multiple times + +* Improvements: + * Added preview for 'Screen Position' node + * 'Append' output type can be selected from node body + * Small overall optimizations + +v1.0.0 dev 12: +* Fixes: + * Fixed wrong casting issues on dynamic type nodes + * Fixed lost reference when deleting 'Grab Screen Color' node + +v1.0.0 dev 11: +* New Features: + * Additional includes (.cginc) can now be used into an ASE shader via the Additional Includes sections on the Output node + * Their contents can be accessed via the 'Custom Expression' node + * Added Node Search bar to quickly find nodes on the canvas + * Ctrl + F: Shows Search Bar + * Enter/Return/F3: Goes to next occurrence + * Shift + (Enter/Return/F3): Goes to previous occurrence + * Escape: Hides Search Bar + +* New samples: + * UV Light Reveal + +* Fixes: + * Fixed issue on creating unnecessary casts from floats + * Fixed minor issue on GPU Instancing sample + * Fixed minor UI issues on 'Reflect' and 'Refract' nodes + * Fixing shader paths for Community Shaders + * Fixed issue on incorrect cast when using Floats and Ints in certain nodes + * Fixed issue on resetting in certain situations vertex local variables generated during Output Node fragment code generation + * Fixed issue on property name update in 'Grab Screen Color' node + +* Improvements: + * Improved nodes local variables reset behavior to prevent future issues + * Added previews to 'Gamma To Linear' and 'Linear To Gamma' nodes + * Forcing 'Dot' and 'Normalize' nodes to store results in local value and prevent with power operations + +v1.0.0 dev 10: +* Fixes: + * Fixed issue with temporary variable assignment Id on 'Texture Coordinates' node + +v1.0.0 dev 09: +* New Features: + * New 'Static Switch' node which allows creation of shader variants + +* Fixes: + * Fixed minor issue on reading inputs from dynamic 'Add' and 'Multiply' nodes on older shader versions + * Fixed issue on Parent Graph attempting to delete in-existent connections + * Fixed issue with always disabling Light Maps when using Tessellation + * Fixed issue with Texture Nodes reference drop down selector showing incorrect labels both on 'Texture Sampler' and 'Texture Coordinates' nodes + * Fixed issues on incorrect loosing references with 'Texture Sampler' node on Reference mode + +* Improvements: + * Improved 'Append' node connection management + * Added Local Var selector directly on 'Get Local Var' node body + +v1.0.0 dev 08: +* New Features: + * New Output node Rendering Options + * Disable Batching + * Ignore Projector + * Force No Shadow Casting + +* Fixes: + * Fixed issue with new dynamic 'Add' and 'Multiply' nodes not registering port creation/destruction into Undo system + * Fixed issue on 'Grab Screen Color' node duplicating code + * Fixed issue with Opacity Mask port being incorrectly Enabled/Disabled on certain situations + * Fixed issue on 'Get Local Var' nodes getting wrong ids on certain situations when a 'Register Local Var' node is deleted + * Small fix to force property name update when changing type on property nodes + * Fixed issue where 'View Dir' node was generating code in the wrong space when in vertex function for both world space and tangent space + +v1.0.0 dev 07: +* Fixes: + * Fixed name conflict on 'Custom Expression' node + * Fixed issue for both normal input in indirect lighting nodes that were asking from normal in world space instead of tangent space + +v1.0.0 dev 06: +* New Features: + * Added LOD Cross Fade support for LOD groups ( located in the Output node Rendering Options tab ) + +* Improvements: + * 'Add' and 'Multiply' nodes can have more than 2 input ports ( max 10 ) + * Minor improvements on several nodes + * Refraction port use Unity's grabpass by default so it can pick other refraction materials + * Avoiding possible compiler misunderstandings with System.Type calls + * Ensuring variables/functions created by custom expressions have unique names + * Auto enabling instance mode on material ( if on Unity 5.6 or above ) when detecting instance mode on ASE shader + * Improved zoom behavior + +* Fixes: + * Fixed issue when remapping ports from very old shaders + * Fixed swizzle issue on 'Vertex Position' node + * Fixed matrix 'Invert' node + * Fixed SimpleGPUInstancing sample not fully batching on Unity 5.6 + * Fixed opening a SF in more than one tab after creation + * Fixed header click to edit name when zoomed out + * Fixed both Commentary node side menus resize not following the mouse movement correctly + +* New Shader Functions: ( AmplifyShaderEditor/Examples/Assets/ShaderFunctions ) + * Simple HUE + * SphereMask + +v1.0.0 dev 05: +* Fixes: + * Fixed issue with conditional 'If' node + * Fixed issue with 'Vertex Position' node swizzle in Local Vertex Ports + +* Improvements: + * Caching instanced property nodes into local variables to prevent multiple UNITY_ACCESS_INSTANCED_PROP() on them + * Added support for samplers types into 'Custom Expression' node + +v1.0.0 dev 04: +* Fixes: + * Fixed node drag and drop issue from palette + * Fixed issue with online reference button having a "too-large" click box + * Palette Menus now display the correct cursor on mouse hover + * Fixed clicking Enter on palette without selecting a node + * Changing lighting models should now show the error messages correctly + * Fixed issue of Custom Light nodes not loading properly + +* Improvements: + * Added Per Renderer Data tag to Properties available Attributes + * Adding help box into 'Virtual Texture Object' with additional info + +v1.0.0 dev 03: +* New Features: + * Custom Lighting + * New Nodes: ( can only be used on this light model ) + * Indirect Diffuse Light + * Indirect Specular Light + * Light Attenuation + +* New Samples: + * Custom Lighting Toon + +* Fixes: + * Fixed issue when zooming with Alt + Right Mouse button + * Fixed issue with window not detecting graph type on Unity load + * Fixed issue on 'Debug Switch' node not loading properly + * Fixed issue on assigning invalid cultures when an error/exception occurred inside ASE + +* Improvements: + * Context Palettes now allow Tab / Shift Tab to select between nodes instead of mouse selection (confirms with Return/Enter key) + * Added previews for 'Debug Switch' and 'Toggle Switch' nodes + * Added link to node documentation on its tooltip + * Small optimization on all nodes overall + * Preventing ASE to crash if some faulty class/dll is present on the project + +v1.0.0 dev 02: +* Fixes: + * Preventing shadow caster error on using 'Vertex TexCoord' with 'Vertex Normal' + +v1.0.0 dev 01: +* Fixes: + * Fixed issue on not recognizing Tessellation port correctly when at Lambert or BlinnPhong light models + * Fixed issue on dragging nodes via Alt mode not respecting ports unique ids when creating connections + * Fixed minor typo on 'Switch by Face' node + * Fixed minor issue when loading LoadPolyWater example + +v0.7.2 dev 08: +* Fixes: + * Fixed issue generating input ports instructions on 'Custom Expression' node + +v0.7.2 dev 07: +* New Features: + * Added support for multiple ASE windows opened simultaneously + +* New Samples: + * Animated Fire with Shader Functions + +* Improvements: + * Forcing InvariantCulture on ASE execution cycle to prevent issues with number parsing + * 'Texture Sampler' node no longer shows it's sampler properties when a 'Texture Object' node is connected to it + * Improved redundancy awareness on 'Virtual Texture Object' and 'Texture Sampler' nodes + * Improved 'Virtual Texture Object' tooltip + * Removed Return button from Shader Functions since it is now useless with new multi-tab behavior + +* Fixes: + * Fixed issue on changing Normal map option in 'Texture Sampler' node not changing its output type + * Changed 'Virtual Texture Object' node channel name to 'Layer' and fixed its default value not showing up correctly + * Virtual textures now generate properties with their correct name (requires user changes to the virtual texture itself) + * Fixed issue that break compiling when a missing shader function was present + * Forcing internal data update for shader function Output nodes to prevent errors when they are disconnected + * Fixed small issue with shader function nodes being stuck on selection when double clicking on them + +v0.7.2 dev 06: +* New Features: + * Added 'HSV To RGB' and 'RGB To HSV' nodes + +* Improvements: + * 'Custom Expression' node with a return instruction on its Code text area generates a function with the code contents thus enabling multiple instructions lines on its body + * Added small info text on node properties to explain its behavior + * Added new name field ( can also be edited directly on node by double clicking on it ) which is used to name the generated function/ local variable + * Small refactoring on some classes for consistency and warning removal from Visual Studio + +* Fixes: + * Fixed issue on some changes not being correctly caught on setting Blend Render Type + * Fixed issue with Unlit Light model doubling the value set on the Emission output port + * Small fix on title updates when using Shader Functions + * Removed warning from unused legacy source code on 'Register Local Var' and 'Get Local Var' nodes + * Fixed issues on incorrect casts on 'Texture Sampler' node + * Fixed issues on incorrectly snapping wires into hidden ports + +v0.7.2 dev 05: +* Improvements: + * Changed tool tip display to trigger when mouse is on top of the node ( now displays below the node) + * Shader Functions + * Added default values for input node in SF (these are used when there's no connection) + * Added port restrictions to dynamic node types + * Changed way input node work with restrictions when changing type to prevent invalid connections + +* Fixes: + * Fixed minor typo on 'Rotator' node + +v0.7.2 dev 04: +* Fixes: + * Fixed multiple issues on save behavior when changing modes + * Fixed issue with shader functions not assigning the main node correctly + * Fixed issue on Project Window Change callback + * Fixed graph count increasing on shader switch + * Fixed version numbering in function nodes + * Fixed nested SF issue with inputs + +v0.7.2 dev 03: +* Fixes: + * Fixed issue with 'Vertex TexCoord' not writing properties correctly into shader meta + +v0.7.2 dev 02: +* Fixes: + * Fixed cast and port activation issues on Blend Nodes + * Fixed various issues with SF: + * Saving no longer deselects + * Reordering is now working properly + * Autocast now has port restrictions into account and deletes with warning when possible + * Sampler types no longer duplicate + +* Improvements: + * Texture Objects node family can now be set as Globals + +v0.7.2 dev 01: +* New Features: + * Added Shader Functions + * Added new 'Object Scale' node + +* Fixes: + * Fixed multiple issues with Copy/Paste + * Fixed issues with nodes on Vertex Function + * 'Fresnel' + * 'Posterize' + * 'Heightmap Texture Blend' + * 'Unpack Scale Normal' + * Fixed issue with incorrect data read from 'Texture Coordinates' nodes on versions below 0.5.0 dev 003 + * Fixed issue on inverted Receive Shadows toggle + +* Improvements: + * Can Copy/Paste between different Shaders and Shader Functions + * Shader properties created by Refraction, Translucency, Mask Value and Tessellation now appear on the Output node Material Properties list and can be reordered + * Preventing UndoParentNode to generate DefaultValue conflicts caused by other plugins + * Removed warnings generated on some situations by the 'Screen Position' node + +* New Samples: + * LowPolyWater by The Four Headed Cat + * ForceShield by The Four Headed Cat + +v0.7.1 dev 02: +* Improvements: + * Improved 'Texture Coordinates' node and added new Tex input port into it + * Improved local variable usage on several node generated code to improve overall shader instruction count + * 'Vertex Position' node now has new Size property + +* Fixes: + * Fixed issues on 'Vertex to Fragment' node + * Fixed issue on loading an ASE shader with its window already opened but tabbed and not visible during play mode + * Fixed multiple issues with 'Grab Screen Position' node usage on Vertex function + * Fixed issue with Forward Shadows not being correctly written when Custom Shadow Caster was active + * Fixed issues with Blend nodes usage on Vertex function + * Fixed issues with 'Dithering' node usage on vertex function and when Tessellation is active + * Fixed issues with 'Screen Depth' node usage on vertex function and when Tessellation is active + * Dithering sample now works while Tessellation is active + +v0.7.1 dev 01: +* New Features: + * Alt + Node Drag to Auto-(dis)connect node on existing wire connection + +* Improvements: + * Added new Tex Input Port into 'Texel Size' node + * Optimized nodes list usage on palettes (API) + * Improved retro-compatibility handling with adding new ports on already existing nodes (API) + +* Fixes: + * Fixed issue on horizontal scroll bar not appearing on Helper Window + +v0.7.0 dev 03: +* New Features: + * Added 'Face' node + * Added 'Switch by Face' node + +* Fixes: + * Fixed issue on not setting shader version on graph when creating a new empty one which lead to copy/paste issues + * Fixed wrong port type assignment and incorrect conditional operator usage on community 'Compare ...' nodes + * Fixed issue with creating a material from a shader already with properties in Unity 5.6 + * Fixed multiple UI issues on Retina MacBook + +* New Samples: + * Highlight Animated by The Four Headed Cat + * 2 Sided by The Four Headed Cat + * Two Sided with Face + +v0.7.0 dev 02: +* Improvements: + * Improved Float to Vector auto-cast + * Double-clicking on a 'Get Local Var' node focus on its referenced 'Register Local Var' node + +* Fixes: + * Fixed issue with keyboard shortcuts on Mac + * Fixed renaming issues with 'Triplanar Sampler' node + * Fixed issue on property nodes UI not refreshing on Undo + * Fixed issues on 'Fresnel' and 'Vertex Normal' related with normal generation + * Fixed typos on POM + * Fixed issue with Wire node deletion + * Fixed auto-change port types issues on all Compare nodes + +v0.7.0 dev 01: +* Improvements: + * Greatly improved Undo + * Colored Port Mode behaves as a normal toggle and doesn't require double tap on W key + +* New Samples: + * Hologram by The Four Headed Cat + +* Fixes: + * Fixed issue on deleting nodes with Wire nodes on their connections + +v0.6.1 dev 05: +* Fixes: + * Fixed issue with custom Shadow Caster on Vulkan + +v0.6.1 dev 04: +* Improvement: + * Renaming 'Texture Sampler' Type property Instance to Reference and prevent confusion with GPU Instanced properties + +* Fixes: + * Fixed issue on unnecessary saves on Live mode + * Also increased Inactivity time from 0.5s to 1s + * Fixed issues on some node interactions not being detected by live mode ( and thus not being flagged to save ) + * Fixed issue on 'Rotator' node not correctly generating local values according to vertex/frag + * Fixed issue on 'Texture Coordinates' node when defining its Inputs with Tessellation active + * Fixed issue with custom Shadow Caster on Metal IOs + * Fixed small typo on Tessellation Shader Model warning message + +v0.6.1 dev 03: +* New Features: + * Adding Fallback shader picker on Master Node + * Adding Shader LOD value modifier on Master Node + +* Improvements: + * Node property title changes according to selected node + * Added Multi-Line mode to wires ( Ctrl + W ) + * Added ability to change 'Triplanar Sampler' node name + * Improved wire connections rendering while zoomed + * Tweaked live mode to save only when user is inactive for 0.5s + +* Fixes: + * Small node resizing issues fixed + * Fixed issues on Live mode not catching node connections and creation correctly + +v0.6.1 dev 02: +* New Features: + * Added 'Triplanar Sampler' node + * Added Vertex Output ( can now change from Relative/Local Vertex Offset to Absolute/Local Vertex Position ) + * Added Smear Sample + * Added Unlit Light Model + * Added simpler 'Time' node + * Added 'Depth Fade' node + * Added 'Camera Depth' Fade node + +* Improvements: + * Adding node info into Helper Window + * Adding drag and drag valid unity assets list to helper window + * 'Screen Position' and 'Grab Screen Position' now have a Output dropdown on its properties instead of a Toggle + * Improved GPU instancing example by adding a C# illustrating how to set instanced properties + +* Fixes: + * Fixed issue on preview materials not being initialized after returning from play mode + * Fixed issue on local variables reset + * Fixed issue with tangent and bitangent previews + * Fixed billboard issue with non-uniform scaling + * Fixed issue on Tex ports counting as having valid internal data on Node Properties UI + * Fixed issue on using 'Texture Sampler' or 'Screen Color instances on Master Node Debug port + +v0.6.1 dev 01: +* Improvements: + * Activating internal data into 'Object To World' and 'World To Object' nodes and setting it to (0,0,0,1) by default + * 'Texture Array' nodes can be created by dragging a Texture 2D Array object into ASE canvas +* Fixes: + * Fixed issue on 'Texture Array' node when connecting it to Vertex Ports + * Fixed issue on 'Vertex TexCoord' not generating correct source according to their properties + * Fixed issues on MourEnvironment, SandPOM and WaterSample shaders + +v0.6.0 dev 01: +* Improvements: + * Added Texture Coordinate Coord Size parameter for 'Vertex TexCoord' node +* Fixes: + * Fixed issue when doing custom shadow caster with translucency on deferred mode + * Fix for texture coordinates zeroing out Z and W + * Fixed issue with input port internal name not being set correctly + * Fixed issue with custom shader inspector on unity 5.6 + * Fixed shadows issue on Matcap example + * Fixed 'Virtual Texture Object' sampling the correct UVs when not connected + +v0.5.1 dev 012: +* Fixed issue with LightColor node not generating the proper values +* Fixed issue when doing custom shadow caster with translucency on deferred mode +* Made the code generation compiler friendly because of unity 5.5 and up changes + +v0.5.1 dev 011: +* Adding new Billboard option into Master Node +* Control key can be also used to append nodes to selection +* Fixed issue with not updating material inspector in real time ( because out of focus ) when changing properties on canvas +* Fixed cast issues on object picker with 'Texture Sample' and 'Texture Object' nodes +* Added Mask buttons on Previews +* Improved overall editor performance + +v0.5.1 dev 010: +* Added 'Desaturate' node +* Fixed small visual issue with Color Mask UI +* Improved overall UI performance + +v0.5.1 dev 009: +* Linking both Up/Down keys and right mouse dragging to scroll behavior into menus +* Canvas zoom can be changed by right mouse dragging while pressing Alt key +* Fixing multiple issues with 'Swizzle' node +* Heavily optimized drawing the node lines +* Fixed issue with loading default shaders to ports + +v0.5.1 dev 008: +* Fixed issues when using line feed on 'Custom Expression' node code area +* Fixed wires and previews displaying on top of the title bar +* Fixed order issues on 'Commentary' node +* Fixed issue with BurnEffect sample +* Majorly improved Previews update speed +* Added LOD levels to previews ( sampler and texture arrays ) +* Added many more node previews +* Updated TriplanarProjection and ParallaxMappingIterations samples +* Optimization on drawing wires +* 'World Normal', 'World Reflection' and 'Fresnel' input ports now modify their previews +* Improved Nodes Graph internal ordering to correctly create connections on shader load + +v0.5.1 dev 007: +* Fixed issues with 'Texture Coordinates' node usage with Tessellation +* Fixed swizzling issues on 'View Dir' node + +v0.5.1 dev 006: +* Added new Helper Window accessible via the right most button on the graph window +* (De)Activating Tessellation and Outlines forces shader to save +* Expanded the amount of nodes with available preview +* Added fail safe to continue loading shader if in-existing community nodes are detected +* Added Normal Map unpacking to 'Texture Array' node and updated its sample +* Fixed issues on Debug Port usage +* Fixed issues on 'Flipbook UV Animation' when property nodes are connected to rows and column input ports +* Fixed issues on Not configuring 'Texture Array' node ports after read +* Fixed issues on Major fix on register/get local var mechanics +* Fixed issues on Adding a space on the node palette search when opening it via space bar +* Fixed issue on ignoring color masks setup on certain situations +* Forcing default values on input port internal data if an exception is caught + +v0.5.1 dev 005: +* Added new Curvature Parameter for 'Parallax Occlusion Mapping' Node +* Added 'World To Object' node +* Added 'Object To World' node +* Fixed issue on 'World Normal' node +* Fixed issue on 'World Tangent' node +* Fixed issue on 'World Bitangent' node +* Fixed issue on 'World Reflection' node +* Fixed issue on 'Register Local Var' node +* Fixed issue with Tessellation used with Custom Shadow Caster +* Fixed issue with Mip Level not being used with 'Texture Sampler' nodes on Vertex Ports +* Fixed issues with Master Node Debug port usage + +v0.5.0 dev 005: +* Applied overall UI changes from Master Node into all other nodes +* Added Node Previews +* Added new Frame Title parameter on 'Commentary' nodes + * Auto focus on new Frame Title textfield when node is created +* Added new Soap Bubble sample using both Reflection and Refraction +* Fixed issue with 'Custom Expression' node +* Fixed issues on 'Scale' node +* Fixed issues on 'Panner' node +* Fixed issues on 'View Dir' node +* Fixed issues on 'Substance Sample' node +* Fixed Repaint issues on ASE custom material editor +* Fixed issue with texture defaults not being correctly written on shader meta +* Fixed issue on reading alpha:fade option from older versions +* Tweaked 'Component Mask' node +* Tweaked 'Pi' node +* Improved 'Substance Sample' node previewer +* Refraction to now have Specularity into account +* Removed warnings on importing ASE to Unity v5.6.0 + +v0.5.0 dev 004: +* Added new Outline option on Master Node properties +* Tweaked Tessellation material update + +v0.5.0 dev 003: +* Fixed issue with Live Mode load/save state +* Fixed repaint issue with picking ports +* Tweaked 'Substance Sample' node preview +* Adding Toggle Attribute to 'Switch Toggle' node + +v0.5.0 dev 002: +* 'Texture Coordinate' now support float3 or float4 output types +* Changed Colored ports saving mechanism +* Tweaked how ports are saved/loaded via shader meta to easily modify existing nodes port amount without breaking older versions (API) +* Tweaked Simple Noise example +* Tweaked Read Atlas examples +* Tweaked Translucency example +* Minor tweak on 'Texture Sample' node +* Fixed issue with local variable declaration on Master Node Debug port +* Fixed issue with Screen Space Curvature example +* Fixed issue with reading fade parameter on master node +* Fixed issue with Transparency shader + +v0.5.0 dev 001: +* Fixed issues with 'Texture Array' node +* Fixed issues with 'Texture Coordinates' node +* Fixed issues with Tessellation example on MacOs +* Fixed issues on multiple examples with Unity beta version 6 and above +* Added new 'Substance Sample' Node +* Added example using the new 'Substance Sample' node located at Examples/Official/Substance +* Added Attributes to Property Nodes +* Added Conditional 'If' Node with Dynamic Branching option +* Tweaked 'Flipbook UV Animation' node + +v0.4.1 dev 002: +* Fixed issue 'Flipbook UV Animation' node not resetting properly and added a start frame parameter + +v0.4.1 dev 001: +* Fixed issue with Texture Array sample + +v0.4.0 dev 003: +* Default Alpha mode set to Transparent and not Alpha Pre-Multiply +* Minor tweak on node sorting on palette windows +* Minor tweak on Master Node Property UI +* Added new Rendering Options foldout on Master Node properties +* Added check to prevent division by zero warning with 'Grab Screen Position' and 'Screen Position' nodes + +v0.4.0 dev 002: +* Forcing LF on all shaders to prevent CRLF mixed with LF when upgrading them +* Fixed issues with custom shader inspector + +v0.4.0 dev 001: +* Minor fix on 'Grab Screen Position' node +* Added new Refraction port into Master Node. Only works correctly with Unity 5.5.1 p1 and above due to an internal unity issue +* Added new Refraction Example ( AmplifyShaderEditor/Official/ObjectNormalRefraction ) +* Added new Vertex Normal port into Master Node +* Small update to Material and Shader mode borders +* Parameter types can now be changed from node itself on property nodes via dropdown on its upper left corner +* Various fixes from the way the Blend Mode works to take new translucent option into account +* Fixed issue with connections from cache when changing Light Mode on Master Node not respecting port availability +* Changed Refracted Shadow demo blend mode +* Fixed Vertex Offset issue with custom shadow caster +* Small fix to auto change blend mode on rendertype and render queue changes +* Fixed some samples with wrong version or wrong connections +* Fixed UI problems in Unity Personal skin + +v0.3.2 dev 003: +* Fixed issue with 'Multiply' node +* Fixed issue with 'Divide' node +* Fixed issue with 'Texture Sample' node +* Fixed issue with 'Dot' node +* Tweaked 'Fresnel' node to use Unity's interpolators and made the default values match Schlick Fresnel +* Tweaked 'World Normal' node to prevent multiple normals generation +* Added 'Texture Array' node +* Added 'Linear to Gamma' and 'Gamma to Linear' nodes +* Majorly revamped the UI for the master nodes options +* Revamped Blend Modes and added additional options +* Added pos-load test on nodes invalid connections to prevent issues with older ASE versions + +v0.3.2 dev 001: +* Added custom shadow caster +* Small fix to both emission and alpha on Fade mode +* Fixed minor issues on reading shaders from older versions( < v0.2.0 dev 002 ) +* Fixed issues on 'Custom Expression' node +* Fixed issues with 'Grab Screen Position' node +* Property nodes with Parameter Type set to Global doesn't force _ on the parameter internal name + +v0.3.1 dev 009: +* Fixed 'Grab Screen Color' node issues +* Minor tweaks on Context menu +* Tweaked 'Screen Position' and 'Grab Screen Position' behavior +* Added switching of input ports connections by holding the CTRL key +* Added removing of input ports connections by double clicking with the left mouse button on them +* Forcing Shader Model to at least 4.6 if Tessellation is active + +v0.3.1 dev 008: +* Small fix to 'Virtual Texture Object' node +* Fixed issues on 'Texture Sample' node +* Fixed issue on not correctly unregistering nodes from 'Commentary' nodes when they were deleted +* Fixed issue when reading old shaders created with v0.2.4 dev 004 +* Fixed issue with 'Texture Coordinates' node when using Tessellation +* Fixed issues and tweaked overall normals generation +* Fixed issue on 'Vector From Matrix' node +* Fixed issue on ASE canvas camera incorrectly panning when hitting a tooltip with Middle/Right Mouse Button +* Fixed connection errors with 'Vector From Matrix' node +* Fixed issue with 'Vertex To Fragment' node +* Deprecated 'Local Position' node +* Added 'Grab Screen Position' node +* Tweaks on nodes and ports names to maintain overall consistency +* Added new Scale and Offset option on 'Screen Position' node +* 'Register Local Var' node now also has system to prevent duplicate names + +v0.3.1 dev 007: +* Added auto-order option into 'Register Local Var' node +* Added new 'Improved Read From Atlas Tiled' example +* Added 'Simplified Fmod' node + +v0.3.1 dev 006: +* Fixed control argument exception when deleting connection with Alt key on selected node +* Fixed issue with 'Switch Toggle' node + +v0.3.1 dev 005 +* Side menus are now resizable +* Tweaked 'Weighted Blend' node +* Added 'Summed Blend' node +* Added 'Toggle Switch' node +* Added new 'Scale and Offset' node +* Fixed issues on 'Vertex Binormal World' and '[VS]Vertex Tangent' nodes +* Fixed issues with 'Texture Sample' nodes created via dragging a texture to ASE +* Fixed issue with 'Scale' node +* Fixed issues on incorrectly reading 'Receive Shadows' parameter from ASE shader previous to v0.2.5 + +v0.3.1 dev 004 +* Fixed issues with accessing 'Texture Coordinates' node when tessellation is active + +v0.3.1 dev 003 +* Fixed yet another issue with accessing 'Texture Coordinates' node on vertex function +* Reverted shader update mechanism after save to previous old one until issue reported by Seith is fixed + +v0.3.1 dev 002 +* Fixed issues with accessing 'Texture Coordinates' node on vertex function + +v0.3.1 dev 001 +* Improved overall editor UI +* Improved Live Mode +* Nodes can generate shader comments ( API ) +* Each port can now have multiple restrictions ( API ) +* 'Texture Object' can now only be connected to 'Texture Sample' nodes +* Added 'Switch' toggle node + +v0.3.0 dev 005 +* Auto adding AMPLIFY_SHADER_EDITOR symbol on current target group when initializing ASE ( API - to be used on external community nodes ) +* Added keyboard shortcut [F5] to force available nodes refresh ( API ) + +v0.3.0 dev 004 +* Fixed yet another issue with local variables generation + +v0.3.0 dev 003 +* Fixed crash from infinite loop generated on port 'Tex' at 'Texture Sample' node +* Fixed cast issue when using internal port data on some nodes +* Fixed issues with local variables generation +* Tweaked Vertex Displacement port on Master Node +* Added ability to specify range of valid data types for input ports ( API ) +* Locked 'Tex' port from 'Texture Sample' node to only allow connections to 'Texture Object' nodes + +v0.3.0 dev 002 +* Updated POM to clip edges using a tilling parameter +* Updated the sand POM example and its height texture +* Updated Water sample +* 'Vertex NormalWorld', 'World Position' and 'View Dir' nodes now also output into vertex offset correctly +* All editor resources are loaded via their own guid +* Added Tessellation port into master node to be able to create custom Tessellation behaviors + * Tessellation parameters ( excluding Phong ) on Master Node Properties will be deactivated if its port is being used + * Created Nodes for each of the builtin Tessellation functions + * Distance-base Tessellation + * Edge Length Tessellation + * Edge Length Tessellation with Cull +* Fixed issues with not creating local variable correctly if graph is shared between vertex and frag ports +* Fixed issue with local variables created on automatic casting not taking port category into account +* Fixed node width issue regarding its header title size + +v0.3.0 dev 001 +* Fixed issue on where deprecated nodes needed to be available to be replaced by their replacement type +* Fixed issues on all conditional nodes +* Fixed issue on local variable creations on vertex shader +* Fixed issue on 'Commentary' node +* Amplify Texture dependency is dynamically set through asset guid +* Texture Sampler will quietly ignore virtual object if AT is not found in project and will not generate a broken shader +* Deprecated nodes are automatically excluded from the palette +* Updated version in all samples +* Optimized 'Multiply' and 'Divide' nodes +* Added Edge Length based tessellation +* Added Fixed Amount based tessellation + +v0.2.6 dev 001 +* Fixed issue on 'Virtual Texture Object' node +* Fixed issue on 'If' node +* Fixed issues in 'Parallax Occlusion Mapping' node +* Fixed issues on 'Texture Sampler' node +* Fixed issue for translucency on point lights +* Fixed issues on 'Texture Coordinates' node +* Fixed issue on not correctly syncing ASE when when hitting paste button on our custom inspector +* Avoiding null pointer exception when compiling a 'Texel Size' node without references +* Re-Organized ASE folder system and added initial pop-up window to clean old/deprecated data +* Tweaked Default/Material values UI on Property nodes +* Node Properties window can now be show by double clicking a node +* Renamed Uniform parameter type to Global +* Added Distance-Based tessellation. Can be activated/configured on Master Node properties + * Added Tessellation sample +* Added emission baking support. Queue must be set to "Geometry" to work properly +* Added Tiled Atlas sample +* Added scenes for each sample +* Added tool tips for Master Node properties + +v0.2.5 dev 004 +* Added Parallax Occlusion Mapping node (uses linear search with customizable samples in conjuntion with interval mapping for refinement of sidewalls) +* Added simple snapping behavior when moving nodes (left-control) +* Fixed background grid image sliding when zooming +* Fixed issue with 'Texcoord Vertex Data' on writing +* Fixed issues with default values of 'Virtual Texture Object' +* Fixed issues when drawing 'Matrix3x3' and 'Matrix4x4' nodes +* Fixed compilation error when creating builds + +v0.2.5 dev 003 +* Fixed issues on 'Texture Coordinate' node +* Fixed issues with 'Texture Sample' node not reading the correct values from older shaders versions +* Fixed issues with instanced texture samples +* Fixed issues with 'Texel Size' node +* Fixed issues with adding new categories on community created nodes + * Custom category colors can now also be set up via NodeAttributes(...) +* Created simpler method ( GeneratePortInstructions(...) ) to generate input instructions. Handy for community members which are creating new custom nodes +* Fixed issue with propagating incorrect port types on master node when loading shader from older versions +* Fixed issues with parallax example +* Alpha channel/Opacity port is forced to 1 if Keep Alpha is set to true and port is not connected to prevent UI issues +* Added index property in '[VS] Vertex TexCoord' node and marked '[VS] Vertex TexCoord1' node as deprecated +* Tweaked collision area on minimize/maximize buttons on lateral windows +* Small optimization on 'Custom Expression' node +* Added support for virtual texturing via Amplify Texture +* Community Node additions + * Jason Booth + * Added 'Vertex To Fragment' node + +v0.2.5 dev 002 +* Added 'Texture Object' node +* Tweaked 'Texture Sample' node behavior to use the new 'Texture Object' node +* Added Stencil Buffer support +* Added Depth foldout with access to ZWrite, ZTest and Offset configuration +* Added AMPLIFY_SHADER_EDITOR preprocessor directive +* Fixed issue on not resetting instance variables counter on reset/load +* Overall fixes on node UI and its adaptation when zooming out + + +v0.2.5 dev 001 +* Added Color Mask option on Master Node +* Added access to additional UV sets on "Texture Sample" and "Texture Coordinates" nodes +* Fixed issue when attempting to connect a wire to a locked port +* Fixed issue with incorrectly adding '#pragma multi_compile_instancing' on non instanced property shaders +* Minor tweak on palette foldout behavior + + +v0.2.4 dev 007 +* Fixed issue on wrong auto-snapping wires with invisible, locked ports +* Fixed issue with version control on Master Node +* Added Transmission input port on Master Node +* Added 'Mip Mode' in 'Texture Sample' node +* Property names can now be changed directly on node by double clicking on it +* Properties can be reordered through drag and drop operations on the Master Node properties via the Available Properties foldout area +* Min/Max values on 'Ranged Float' nodes can be modified directly on canvas + +v0.2.4 dev 006 ( for internal reasons we had to skip dev 005 ) +* Fixes issues on 'Panner' node +* Fixed issues with not correctly generating local variables according to port category +* Tweaked behavior and fixed issues on the 'Texture Coordinate' node +* Fixed issues on 'Texel Size' node +* Fixed issues on 'Local Vertex Pos' node +* Fixed issues with Burn Effect Sample +* Removed positive number restriction from Master Node 'Queue Index' property +* Custom Material Inspector can be selected/changed on Master Node + * Done through the Custom Editor property + * You can always reset to our own by hitting the Reset button next to hit +* Updated Rim Light Sample to use the new Space option on the 'View Dir' node +* Updated Parallax Sample to use the new Space option on the 'View Dir' node +* Added 'Translucency' input port into Master Node +* Added 'Dithering' node +* Added Matcap Sample +* Added Dithering Sample +* Added Rendering Platforms selector on Master node +* Added Water Sample on a small terrain in the Sample Scene + +v0.2.4 dev 004 +* Fixed issues with wire shader +* Fixed issues with 'Texture Coordinates' node +* Removed warnings occurring on Unity v5.5 +* Fixed issue with 'Append' Node +* Fixed issue with ASE Custom Material Inspector +* Tweaked 'Local Vertex Pos' node to output differently if generating code for vertex or fragment ports + +v0.2.4 dev 003 +* Added Texture Reference dropdown to 'Texture Coordinates' node +* Added Render Path dropdown in Master Node +* Tweaked 'View Dir' node so you're able to choose between getting the result in tangent or world space +* Tweaked 'World Space Light Dir' to no longer use internal input port data when nothing is connected, instead worldPos is automaticaly fed into it +* Added Unity version check for wires shader and fix compatibility issues +* Added Normalize toggle into 'Screen Position' node +* Community Node additions + * Tobias Pott + * Added 'Swizzle' node + +v0.2.4 dev 002 +* Added 'Layered Blend' node +* Added 'Weighted Blend' node +* Added 'Texel Size' node +* Merged '[VS] Vertex Color' and 'Vertex Color' nodes in order to avoid further confusions and marked the first one as deprecated + * Node internally changes its output if it's writing to a vertex or fragment port +* Added 'Surface Depth' node +* Added 'Screen Depth' node +* Fixed issue with property nodes uniform variables not taking selected precision into account + +v0.2.4 dev 001 +* Added 'Parallax Mapping' node +* Added 'Negate' node +* Added Fake Window user sample +* Added Parallax Mapping example with 4 iterations using the basic Parallax Mapping node + +v0.2.3 dev 002 +* Added 'Custom Expression' node +* Precision used is now the least between the one selected in the node and main one selected on the master node +* 'Register Local Var' and 'Get Local Var' nodes can now be used on Master Node Vertex ports +* Improved wires visuals +* Fixed issue with local variables generation +* Fixed issue with switching port internal data from float to int +* Fixed cast issue with 'Remap' node +* Added all the supported shader models into the Master Node dropdown + * When creating a shader the default selected is now 2.5 to match Unity default +* Community Node additions + * The Four Headed Cat + * Added 'Grayscale' node + +v0.2.3 dev 001 +* New control points can be added to wires to better manipulate its shape + * Double click a wire to create an additional control point + * Control points are selected, moved and deleted similar to regular nodes +* Fixed issue with box selection being active when dragging nodes with the 'Shift' key held down +* Fixed issues with wire resources not being correctly released when ASE is shut down +* Fixed issues with 'Pixel Normal World' and 'Vertex Normal World' nodes +* Fixed issue with 'Multiply' node on Matrix/Vector multiplications +* Fixed issue with 'Break To Components' node +* Fixed issue with 'Component Mask' node +* Fixed issue with wrong type propagation when replacing node connections +* Fixed issue with instance references being lost on 'Texture Sample' and 'Screen Color' nodes +* Tweaked 'Object to World' and 'World to Object' nodes to be more compile friendly +* Added 'Model' matrix node +* Added 'Relay' node +* Added 'TriplanarObjectSpace' sample to Samples folder +* Added precision selector for variables ( known issue: precision info is not being taken into account when auto local vars are created ) +* Community Node additions + * The Four Headed Cat + * Added 'Tau' node + * Rea + * Added 'Height Map Blend' node + +v0.2.2 dev 001 +* Fixed issue with 'Mask Clip Value' not being correctly synced between material and shader +* Added colored Debug Mode ... this is an experimental feature where each port and wire are colored according to its data type. Each color/type pair are not final + * Hold 'P' key to enable debug mode and release it to disable it + * Double hit 'P' key to toggle debug mode on. Double hit 'P' key again to disable it. +* Added 'Matrix From Vectors' node +* Fixed issue with 'Vertex Binormal World' node +* Added 'Shader Model' dropdown on Master Node properties +* Community Node additions + * The Four Headed Cat + * Fixed issues with 'Logical Operator' nodes + +v0.2.1 dev 001 +* Fixed multiple issues importing current version on top of v0.1.0 dev 001 + +v0.2.0 dev 003 +* Mask Clip Value when used is registered as a Material Property + +v0.2.0 dev 002 +* Improved duplicate code detection system +* Slight improvement on save/update times ( important for Live Mode ) +* Fixed issue with 'Texture Sample' node incorrectly outputting a float4 when no texture assigned and on Normal mode +* Fixed issue on not opening the correct shader from a material inspector if a new one is selected from its dropdown +* Fixed issue with 'Length' node incorrectly changing its output type +* Community Node additions + * The Four Headed Cat + * Flipbook UV Animation + +v0.2.0 dev 001 +* Fixed issues with 'Get Local Var' node + * Output port type is now correctly set to its reference type + * Changed how references are saved so it won't be affected by order index re-ordering +* Fixed issue with 'Power' node +* Fixed issue with 'ATan2' node +* Fixed issue with 'Cross' node +* Community Node additions + * The Four Headed Cat + * Logical If + * Pixelate +* Community Samples additions + * The Four Headed Cat + * DissolveBurn + * Mourelas Konstantinos + * EnvironmentGradient + +v0.1.5 dev 001 +* Community Node additions + * The Four Headed Cat ( moved to a separate 'Logical Operators' category ) + * Compare With Range + * Compare Not Equal + * Compare Lower Equal + * Compare Greater Equal + * Compare Lower + * Compare Greater + * Kebrus + * Vertex Tangent World + * Vertex Binormal World +* 'Register Local Var' node changes: + * Is now independent from Master Node execution order and generates activation signals + * Will always be executed even if not connected to Master Node + * Fixed issue updating name string array when loading from file + * Added order index to control their declaration order( lesser index declared first ) +* Fixed issue on port type change not propagating in certain nodes +* Hitting Escape key will disable context palette menu if active +* Fixed issue where right mouse clicking on certain port areas would delete their wire connection +* Minor improvement on nodes performance + +v0.1.4 dev 002 +* Dynamic type nodes now also reacting to input port disconnections +* Updated TFHCRemap node from benderete + +0.1.4 dev 001 +* Fixed issue with order index not being correctly read/written +* Redone Refraction Shader according to rea suggestion +* Register Local Var node now has a title style similar to Property Nodes with the local var name always visible +* Added Get Local Var Node. It allows the user to use already registered local vars anywhere in the graph +* Added Custom Node Remap ("TFHC - Remap") created by user benderete +* Fixed issue on Texture Sample UV port not correctly casting to float2 when needed +* Fixed issue with Texture Sample node not adapting layout when reference is in normal mode + +v0.1.3 dev 003 +* Added RegisterLocalVar node. This is a node to improve shader readability in certain situations, as it forces the shader to create a local var containing its input value and always use that as output +* Added Screen Color Texture Reference feature +* Created Simple Refraction example ( Samples/SimpleRefraction ) +* Fixed issues with sampler instance resizing +* Fixed issue with Fresnel node incident vector +* Fixed issue with attempting connection removal on inexistent nodes ( bug affecting Append node ) +* Fixed issue with overwriting render type and queue values with Blend Mode default values on read from file + +v0.1.3 dev 002 +* Fixed multiple issues with deleting a Texture Sample node being referenced by other nodes +* Tweaked Texture Sample reference UI + +v0.1.3 dev 001 +* Fixed issue when releasing mouse drag on menu areas not resetting auto*pan +* Tweaked Shader Instancing UI +* Fixed issue with material inspector crashing when updating a property with ASE window turned off +* Fixed issue with custom UI skins not being correctly initialized under some conditions +* Added Texture Reference feature +* Added 'Simple Blur' example to demonstrate how Texture referencing works +* Added small 'Made with Amplify Shader Editor' info as comment on generated shaders + +v0.1.2 dev 003 +* Fixed issues with opening materials via inspector with no ASE window initialized + +v0.1.2 dev 002 +* Added GPU Instancing ( see Samples/SimpleGPUInstancing example ) +* Added Screen Color node +* Fixed issue on version testing +* Tweaked Master Node icon +* Added additional icon into top-left master node node indicating if gpu instancing is being used or not + +v0.1.2 dev 001 +* Fixed typo on Texture Coordinate node +* Added explicit control on Render Type and Queue. They will be automatically set when a Blend Mode is selected. +* Added Fresnel node +* Fixed Trigonometry typo +* Improved local var generation on op nodes +* Added FWidth node +* Fixed issue with not immediately updating shader when hitting the Live Shader Mode button + +v0.1.1 dev 001 +* Community Contribution from kebrus: Added Rotator node, rotates UV Coordinates/ Vector2 nodes +* Fixed Vector2 Append Node bug +* Fixed Int to Float cast issues +* Added Shader title area on top canvas to forbidden node interaction area +* Adjusted Auto-Pan behavior +* Fixed issue with nodes infinite loop detection +* Tweaked mouse detection inside main canvas +* Fixed Queue Order typo when building shader +* Improved notifications when impossible cast is requested +* Added new VectorFromMatrix which gets a specific row or column from a 3x3 or 4x4 matrix +* Automatically hiding Order Index on Uniform Property Type nodes +* Simpler Searchable Node List also being called by hitting the space bar if focus is on main node canvas diff --git a/Assets/AmplifyShaderEditor/ChangeLog.txt.meta b/Assets/AmplifyShaderEditor/ChangeLog.txt.meta new file mode 100644 index 0000000..e6fba31 --- /dev/null +++ b/Assets/AmplifyShaderEditor/ChangeLog.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 580cccd3e608b7f4cac35ea46d62d429 +timeCreated: 1481127071 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/CreatingTerrainsWithASE.txt b/Assets/AmplifyShaderEditor/CreatingTerrainsWithASE.txt new file mode 100644 index 0000000..e0d0e96 --- /dev/null +++ b/Assets/AmplifyShaderEditor/CreatingTerrainsWithASE.txt @@ -0,0 +1,58 @@ +Creating terrains with Amplify Shader Editor is really quick and easy. We will give you a brief explanation on how you can start creating terrain shaders with ASE in no time. + +A standard unity terrain is a regular surface shader using properties with a specific naming. +Besides these properties, a small configuration is necessary. +[Create Shader] +As with any other ASE shaders, right-click on the Project view, select Create > Amplify Shader > Surface Shader and name it as you like. We advise you to have 'First-Pass' included on the shader name since it performs what is called a first pass over the terrain. + +[Queue Index] +Set the Queue Index to -100 on the Output Node Properties General tab. + +[Render Type] +By default a created shader already comes with the Opaque shader type selected, which is required by the terrain, but please go to the Blend Mode tab and check that Opaque is the selected option. + +[Specify Base Shader] +A Base shader must be specified. This shader will be responsible to render the terrain when over a certain distance specified at the Base Map Distance on the terrain settings. Beyond this distance, a lower resolution composite image will be used with this shader for efficiency reasons. + +We already have a base shader created and ready to be used, so you only need to: +- Go to your Dependencies Tab on the Output Node Properties +- Click on the Add Button to add a new entry +- Write BaseMapShader into the Name textfield +- Write ASESampleShaders/SimpleTerrainBase on the Value textfield + +Feel free to open the ASESampleShaders/SimpleTerrainBase shader located at AmplifyShaderEditor > Examples > Official > SimpleTerrain > SimpleTerrainBase.shader and check what is being done. Please note that property naming in the base shader is very strict and property names must be maintained. + +[Specify Splat Count] +ASE only supports up to four splats (single-pass) for now, this needs to be specified into the shader through a custom tag. +In order to do that: +- Go to Custom SubShader Tags tab on the Output Node Properties +- Click on the Add Button to add a new entry +- Write SplatCount into the Name textfield +- Write 4 into the Value textfield + +Future versions will introduce multi-pass support for more complex effects. + +[Create Properties] +This is the meat of how the terrain shader will behave. +We already have a shader function, Four Splats First Pass Terrain, which replicates Unity standard terrain and should be used as starting point on creating your own shader. + +[[Diffuse]] +Each splat can be accessed via their properties, having yet again strict naming to be maintained. +The splat diffuse colors are accessed through the sampler variables _Splat0 through _Splat3, so in your shader you must create four Texture Sampler nodes with the names Splat 0 through Splat 3 as the _ is automatically placed and the empty spaces are also automatically removed from the created variable name. + +[[Normal]] +The same goes to normal maps, they are accessed through the sampler variables _Normal0 through _Normal3 so, like with diffuse, in your shader you must create four Texture Sampler nodes with the names Normal 0 through Normal 3. One detail to take into account is that Unpack Normal Map should be turned off for each one of the nodes and an Unpack Scale Normal node should be applied after their values are combined. + +[[Smoothness + Metallic]] +Smoothness and Metallic values must also have specific variable names, _Smoothness0 through _Smoothness3 and _Metallic0 through _Metallic3 respectively. + +These variables however are Float properties, so to access them you need to create Float nodes, set them to Properties with the names Smoothness 0 through Smoothness 3 and Metallic 0 through Metallic 3 respectively. + +To maintain consistency with the Unity terrain shader, you should add the Gamma attribute to the Metallic property nodes. + +[[Combining Maps]] +The weight of each layer is given by yet another sampler variable. The _Control sampler variable contains, in each of its channels, the contribution each layer/splat have on the final result. +To get access to it, simply create a Texture Sampler node in your shader with its name being Control. +This Control texture is dynamically created when you paint your terrain with the Terrain tools and can be inspected by selecting the terrain asset on the Project view. + +Again, we invite you to check the Four Splats First Pass Terrain shader function located at AmplifyShaderEditor > Plugins > EditorResources > ShaderFunctions > Four Splats First Pass Terrain for a more in-depth view on how the Control texture is used. diff --git a/Assets/AmplifyShaderEditor/CreatingTerrainsWithASE.txt.meta b/Assets/AmplifyShaderEditor/CreatingTerrainsWithASE.txt.meta new file mode 100644 index 0000000..4a3259b --- /dev/null +++ b/Assets/AmplifyShaderEditor/CreatingTerrainsWithASE.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f11d5aaf59fc38544b8419242801ff97 +timeCreated: 1513615640 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Examples.meta b/Assets/AmplifyShaderEditor/Examples.meta new file mode 100644 index 0000000..607a472 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 425c3aed47dd05444960ca41af18e591 +folderAsset: yes +timeCreated: 1481126943 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Examples/Built-In Samples.unitypackage.meta b/Assets/AmplifyShaderEditor/Examples/Built-In Samples.unitypackage.meta new file mode 100644 index 0000000..ee1d5e4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/Built-In Samples.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e00e6f90ab8233e46a41c5e33917c642 +timeCreated: 1585839223 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Examples/Credits.txt b/Assets/AmplifyShaderEditor/Examples/Credits.txt new file mode 100644 index 0000000..3a22bde --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/Credits.txt @@ -0,0 +1,8 @@ +Fire texture - http://suicidecrew.deviantart.com/art/Fire-Seamless-tile-116721709 +Screen Space Curvature - http://madebyevan.com/shaders/curvature/ + +Grass Blades texture from: +http://www.fuzzimo.com/free-hi-res-ornamental-grass-blade-textures/ + +Keep them coming, contribute today! +http://amplify.pt/unity/amplify-shader-editor/contribute diff --git a/Assets/AmplifyShaderEditor/Examples/Credits.txt.meta b/Assets/AmplifyShaderEditor/Examples/Credits.txt.meta new file mode 100644 index 0000000..48f5980 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/Credits.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 451790f45b4e5434586d16e924540ee7 +timeCreated: 1481127071 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Examples/DownloadSamplesInstructions.txt b/Assets/AmplifyShaderEditor/Examples/DownloadSamplesInstructions.txt new file mode 100644 index 0000000..87035e7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/DownloadSamplesInstructions.txt @@ -0,0 +1,8 @@ +Use your Unity Asset Store invoice number in the Amplify Product download page to download the latest Amplify Shader Editor package and Shader Samples package. + +1 - Go to http://amplify.pt/download +2 - Enter your Unity Asset Store and click Unlock +3 - Scroll down to the Amplify Shader Editor entry +4 - Click the Sample button to download the sample package. + +NOTE: You can also use the product download page to download the latest Amplify Shader Editor package. Due to Asset Store review times and update cycles, the version hosted there is usually more recent. \ No newline at end of file diff --git a/Assets/AmplifyShaderEditor/Examples/DownloadSamplesInstructions.txt.meta b/Assets/AmplifyShaderEditor/Examples/DownloadSamplesInstructions.txt.meta new file mode 100644 index 0000000..a82e19c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/DownloadSamplesInstructions.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 03fe3bdcb7262a84ca060ff336c7d8d1 +timeCreated: 1481127071 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Examples/HDRP Samples (Legacy).unitypackage.meta b/Assets/AmplifyShaderEditor/Examples/HDRP Samples (Legacy).unitypackage.meta new file mode 100644 index 0000000..f31ed09 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/HDRP Samples (Legacy).unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dff05fea7446d7b4e9029bfab77455d2 +timeCreated: 1559836117 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Examples/HDRP Samples.unitypackage.meta b/Assets/AmplifyShaderEditor/Examples/HDRP Samples.unitypackage.meta new file mode 100644 index 0000000..59379f1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/HDRP Samples.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d1c0b77896049554fa4b635531caf741 +timeCreated: 1533059192 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Examples/LWRP Samples (Legacy).unitypackage.meta b/Assets/AmplifyShaderEditor/Examples/LWRP Samples (Legacy).unitypackage.meta new file mode 100644 index 0000000..9098be8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/LWRP Samples (Legacy).unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f7c4e22642de60d448f4e4809190f7b1 +timeCreated: 1559837332 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Examples/LWRP Samples.unitypackage.meta b/Assets/AmplifyShaderEditor/Examples/LWRP Samples.unitypackage.meta new file mode 100644 index 0000000..0aa21b5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/LWRP Samples.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6ecbfd0a046659943a69328c98ff0442 +timeCreated: 1520956522 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Examples/README Samples.txt b/Assets/AmplifyShaderEditor/Examples/README Samples.txt new file mode 100644 index 0000000..62fc082 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/README Samples.txt @@ -0,0 +1,12 @@ +Samples are provided by pipeline, if you want to import the samples please use the "Start Screen" to do so instead of unpacking manually, this will ensure that they are imported correctly. Go to Windows > Amplify Shader Editor > Start Screen and under "Shader Samples" select the ones you want to import. Do be aware that importing any SRP samples requires to first install the respective pipeline using the package manager. + +However if you still want to import them manually here is the breakdown of the included packages: + * "Sample Resources": constains the assets shared between all pipelines, like textures and meshes, this should always be imported first + * "Built-In Samples": contains the samples shaders with their scenes for the built-in rendering system + * "HDRP Samples": contains the samples shaders with their scenes for HDRP 7.X.X and up (Unity 2019.3 and up) + * "HDRP Samples (Legacy)": contains the samples shaders with their scenes for HDRP 6.X.X and down (from Unity 2018.2 to Unity 2019.2) + * "URP Samples": contains the samples shaders with their scenes for URP 7.X.X and up (Unity 2019.3 and up) + * "LWRP Samples": contains the samples shaders with their scenes for LWRP between 4.X.X and 6.X.X (from Unity 2018.3 to Unity 2019.2) + * "LWRP Samples (Legacy)": contains the samples shaders with their scenes for LWRP 3.X.X (Unity 2018.2) + +Please notice that in some cases the sample may have been created in a different version from the SRP that you are using which can produce "pink" shaders. If that happens it's usually the case that you only need to open the shader in ASE and save it to update it. diff --git a/Assets/AmplifyShaderEditor/Examples/README Samples.txt.meta b/Assets/AmplifyShaderEditor/Examples/README Samples.txt.meta new file mode 100644 index 0000000..a893d0a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/README Samples.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5c5208e121a880c4fbb9de7aaeaa8aa2 +timeCreated: 1541776170 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Examples/Sample Resources.unitypackage.meta b/Assets/AmplifyShaderEditor/Examples/Sample Resources.unitypackage.meta new file mode 100644 index 0000000..2de62af --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/Sample Resources.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c0a0a980c9ba86345bc15411db88d34f +timeCreated: 1585839223 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Examples/URP Samples.unitypackage.meta b/Assets/AmplifyShaderEditor/Examples/URP Samples.unitypackage.meta new file mode 100644 index 0000000..10f67fa --- /dev/null +++ b/Assets/AmplifyShaderEditor/Examples/URP Samples.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a9d68dd8913f05d4d9ce75e7b40c6044 +timeCreated: 1575902011 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins.meta b/Assets/AmplifyShaderEditor/Plugins.meta new file mode 100644 index 0000000..301d404 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3306ce0ede814a84c8d289893da72b7a +folderAsset: yes +timeCreated: 1481126943 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor.meta b/Assets/AmplifyShaderEditor/Plugins/Editor.meta new file mode 100644 index 0000000..e703561 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4a66239afbf6d2c4eb99238642c8d40f +folderAsset: yes +timeCreated: 1481126943 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Actions.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions.meta new file mode 100644 index 0000000..060fde1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a2ba8588f45692f4ea2fa5afa9faf434 +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionData.cs new file mode 100644 index 0000000..67572b4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionData.cs @@ -0,0 +1,336 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public class ActionData + { + public virtual void ExecuteForward() { } + public virtual void ExecuteReverse() { } + } + + // NODES + // Create node + public class CreateNodeActionData : ActionData + { + private int m_nodeId; + private System.Type m_nodeType; + private Vector2 m_nodePos; + + public CreateNodeActionData( ParentNode node ) + { + m_nodeId = node.UniqueId; + m_nodePos = node.Vec2Position; + m_nodeType = node.GetType(); + } + + + public CreateNodeActionData( int nodeId, System.Type nodeType, Vector2 nodePos ) + { + m_nodeId = nodeId; + m_nodePos = nodePos; + m_nodeType = nodeType; + } + + public override void ExecuteForward() + { + UIUtils.CreateNode( m_nodeType, false, m_nodePos, m_nodeId ); + } + + public override void ExecuteReverse() + { + UIUtils.DestroyNode( m_nodeId ); + } + + public override string ToString() + { + return "Create Node - Type: " + m_nodeType + " Node: " + m_nodeId + " Position: " + m_nodePos; + } + } + + // Destroy node + public class DestroyNodeActionData : ActionData + { + private int m_nodeId; + private System.Type m_nodeType; + private Vector2 m_nodePos; + + public DestroyNodeActionData( ParentNode node ) + { + m_nodeId = node.UniqueId; + m_nodePos = node.Vec2Position; + m_nodeType = node.GetType(); + } + + public DestroyNodeActionData( int nodeId, System.Type nodeType, Vector2 nodePos ) + { + m_nodeId = nodeId; + m_nodePos = nodePos; + m_nodeType = nodeType; + } + + public override void ExecuteForward() + { + UIUtils.DestroyNode( m_nodeId ); + } + + public override void ExecuteReverse() + { + UIUtils.CreateNode( m_nodeType, false, m_nodePos, m_nodeId ); + } + + public override string ToString() + { + return "Destroy Node - Type: " + m_nodeType + " Node: " + m_nodeId + " Position: " + m_nodePos; + } + } + + // Move node + public class MoveNodeActionData : ActionData + { + private int m_nodeId; + private Vector2 m_nodeInitalPos; + private Vector2 m_nodeFinalPos; + + public MoveNodeActionData( int nodeId, Vector2 nodeInitialPos, Vector2 nodeFinalPos ) + { + m_nodeId = nodeId; + m_nodeInitalPos = nodeInitialPos; + m_nodeFinalPos = nodeFinalPos; + } + + public override void ExecuteForward() + { + ParentNode node = UIUtils.GetNode( m_nodeId ); + if ( node != null ) + node.Vec2Position = m_nodeFinalPos; + } + + public override void ExecuteReverse() + { + ParentNode node = UIUtils.GetNode( m_nodeId ); + if ( node != null ) + node.Vec2Position = m_nodeInitalPos; + } + + public override string ToString() + { + return "Move Node - Node: " + m_nodeId + " Initial Position: " + m_nodeInitalPos + " Final Position: " + m_nodeFinalPos; + } + } + + // CONNECTIONS + // Create connection + public class CreateConnectionActionData : ActionData + { + private int m_inputNodeId; + private int m_inputPortId; + + private int m_outputNodeId; + private int m_outputPortId; + + public CreateConnectionActionData( int inputNodeId, int inputPortId, int outputNodeId, int outputPortId ) + { + m_inputNodeId = inputNodeId; + m_inputPortId = inputPortId; + m_outputNodeId = outputNodeId; + m_outputPortId = outputPortId; + } + + public override void ExecuteForward() + { + UIUtils.ConnectInputToOutput( m_inputNodeId, m_inputPortId, m_outputNodeId, m_outputPortId ); + } + + public override void ExecuteReverse() + { + UIUtils.DeleteConnection( true, m_inputNodeId, m_inputPortId, false, true ); + } + + public override string ToString() + { + return "Create Connection Node - Input Node: " + m_inputNodeId + " Input Port: " + m_inputPortId + " Output Node: " + m_outputNodeId + " Output Port: " + m_outputPortId; + } + } + + // Destroy connection + public class DestroyConnectionActionData : ActionData + { + private int m_inputNodeId; + private int m_inputPortId; + + private int m_outputNodeId; + private int m_outputPortId; + + public DestroyConnectionActionData( int inputNodeId, int inputPortId, int outputNodeId, int outputPortId ) + { + m_inputNodeId = inputNodeId; + m_inputPortId = inputPortId; + m_outputNodeId = outputNodeId; + m_outputPortId = outputPortId; + } + + public override void ExecuteForward() + { + UIUtils.DeleteConnection( true, m_inputNodeId, m_inputPortId, false, true ); + } + + public override void ExecuteReverse() + { + UIUtils.ConnectInputToOutput( m_inputNodeId, m_inputPortId, m_outputNodeId, m_outputPortId ); + } + + public override string ToString() + { + return "Destroy Connection Node - Input Node: " + m_inputNodeId + " Input Port: " + m_inputPortId + " Output Node: " + m_outputNodeId + " Output Port: " + m_outputPortId; + } + } + + // Move connection + public class MoveInputConnectionActionData : ActionData + { + private int m_oldInputNodeId; + private int m_oldInputNodePortId; + + private int m_newInputNodeId; + private int m_newInputNodePortId; + + private int m_outputNodeId; + private int m_outputPortId; + + public MoveInputConnectionActionData( int oldInputNodeId, int oldInputPortId, int newInputNodeId, int newInputPortId, int outputNodeId, int outputPortId ) + { + m_oldInputNodeId = oldInputNodeId; + m_oldInputNodePortId = oldInputPortId; + + m_newInputNodeId = newInputNodeId; + m_newInputNodePortId = newInputPortId; + + m_outputNodeId = outputNodeId; + m_outputPortId = outputPortId; + } + + public override void ExecuteForward() + { + UIUtils.DeleteConnection( true, m_oldInputNodeId, m_oldInputNodePortId, false, true ); + UIUtils.ConnectInputToOutput( m_newInputNodeId, m_newInputNodePortId, m_outputNodeId, m_outputPortId ); + } + + public override void ExecuteReverse() + { + base.ExecuteReverse(); + UIUtils.DeleteConnection( true, m_newInputNodeId, m_newInputNodePortId, false, true ); + UIUtils.ConnectInputToOutput( m_oldInputNodeId, m_oldInputNodePortId, m_outputNodeId, m_outputPortId ); + } + + public override string ToString() + { + return "Move Input Connection Node - Old Input Node: " + m_oldInputNodeId + " Old Input Port: " + m_oldInputNodePortId + " New Input Node: " + m_newInputNodeId + " New Input Port: " + m_newInputNodePortId + " Output Node: " + m_outputNodeId + " Output Port: " + m_outputPortId; + } + } + + public class MoveOutputConnectionActionData : ActionData + { + private int m_inputNodeId; + private int m_inputPortId; + + private int m_newOutputNodeId; + private int m_newOutputPortId; + + private int m_oldOutputNodeId; + private int m_oldOutputPortId; + + public MoveOutputConnectionActionData( int inputNodeId, int inputPortId, int newOutputNodeId, int newOutputPortId, int oldOutputNodeId, int oldOutputPortId ) + { + m_inputNodeId = inputNodeId; + m_inputPortId = inputPortId; + + m_newOutputNodeId = newOutputNodeId; + m_newOutputPortId = newOutputPortId; + + m_oldOutputNodeId = oldOutputNodeId; + m_oldOutputPortId = oldOutputPortId; + } + + public override void ExecuteForward() + { + UIUtils.DeleteConnection( false, m_oldOutputNodeId, m_oldOutputNodeId, false, true ); + UIUtils.ConnectInputToOutput( m_inputNodeId, m_inputPortId, m_newOutputNodeId, m_newOutputPortId ); + } + + public override void ExecuteReverse() + { + base.ExecuteReverse(); + UIUtils.DeleteConnection( false, m_newOutputNodeId, m_newOutputPortId, false, true ); + UIUtils.ConnectInputToOutput( m_inputNodeId, m_inputPortId, m_oldOutputNodeId, m_oldOutputPortId ); + } + + public override string ToString() + { + return "Move Input Connection Node - Input Node: " + m_inputNodeId + " Input Port: " + m_inputPortId + " Old Output Node: " + m_oldOutputNodeId + " Old Output Port: " + m_oldOutputPortId + " New Output Node: " + m_newOutputNodeId + " New Output Port: " + m_newOutputPortId; + } + } + + public class CreateNewGraphActionData : ActionData + { + private string m_name; + + public CreateNewGraphActionData( string name ) + { + m_name = name; + } + + public override void ExecuteForward() + { + UIUtils.CreateNewGraph( m_name ); + } + } + + public class ChangeNodePropertiesActionData : ActionData + { + private string m_originalProperties; + private string m_newProperties; + private int m_nodeId; + + public ChangeNodePropertiesActionData( ParentNode node, string originalProperties ) + { + m_nodeId = node.UniqueId; + m_originalProperties = originalProperties; + + m_newProperties = string.Empty; + string trash = string.Empty; + node.WriteToString( ref m_newProperties, ref trash ); + } + + public ChangeNodePropertiesActionData( int nodeId, string originalProperties ) + { + m_nodeId = nodeId; + m_originalProperties = originalProperties; + + m_newProperties = string.Empty; + string trash = string.Empty; + UIUtils.GetNode( nodeId ).WriteToString( ref m_newProperties, ref trash ); + } + + public override void ExecuteForward() + { + string[] properties = m_newProperties.Split( IOUtils.FIELD_SEPARATOR ); + UIUtils.GetNode( m_nodeId ).ReadFromString( ref properties ); + } + + public override void ExecuteReverse() + { + string[] properties = m_originalProperties.Split( IOUtils.FIELD_SEPARATOR ); + UIUtils.GetNode( m_nodeId ).ReadFromString( ref properties ); + } + + public override string ToString() + { + return "Change Node Propertie - Node: " + m_nodeId + "\nOriginal Properties:\n" + m_originalProperties + "\nNew Properties:\n" + m_newProperties; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionData.cs.meta new file mode 100644 index 0000000..0c1b5d4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 29204f353101f46439a93f1c503d3197 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionLog.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionLog.cs new file mode 100644 index 0000000..666c902 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionLog.cs @@ -0,0 +1,58 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public class ActionLog + { + private int m_maxCount; + private int m_index; + private List m_sequence; + + public ActionLog(int maxCount) + { + m_maxCount = maxCount; + m_index = 0; + m_sequence = new List(); + } + + public void AddToLog(ActionData actionData) + { + if (m_sequence.Count > m_maxCount) + { + m_sequence.RemoveAt(0); + } + + m_sequence.Add(actionData); + m_index = m_sequence.Count - 1; + } + + + public void UndoLastAction() + { + if ( m_index > -1 && m_index < m_sequence.Count ) + m_sequence[m_index--].ExecuteReverse(); + } + + public void RedoLastAction() + { + if (m_index < (m_sequence.Count - 1)) + m_sequence[++m_index].ExecuteForward(); + + } + + public void ClearLog() + { + m_sequence.Clear(); + m_index = 0; + } + + public void Destroy() + { + m_sequence.Clear(); + m_sequence = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionLog.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionLog.cs.meta new file mode 100644 index 0000000..4547013 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionLog.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bc089a69595d8994cb89946a919517c2 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionSequence.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionSequence.cs new file mode 100644 index 0000000..c60480e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionSequence.cs @@ -0,0 +1,39 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System.Collections.Generic; +namespace AmplifyShaderEditor +{ + public class ActionSequence + { + private string m_name; + private List m_sequence; + + public ActionSequence( string name ) + { + m_name = name; + m_sequence = new List(); + } + + public void AddToSequence( ActionData actionData ) + { + m_sequence.Add( actionData ); + } + + public void Execute() + { + for ( int i = 0; i < m_sequence.Count; i++ ) + { + m_sequence[ i ].ExecuteForward(); + } + } + + public void Destroy() + { + m_sequence.Clear(); + m_sequence = null; + } + + public string Name { get { return m_name; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionSequence.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionSequence.cs.meta new file mode 100644 index 0000000..58a732b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Actions/ActionSequence.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 43bd963fa46ee9c4680dacff1d8dc0b9 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Constants.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Constants.cs new file mode 100644 index 0000000..d43ebeb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Constants.cs @@ -0,0 +1,690 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + + public struct Constants + { + public readonly static string[] FaceMacros = + { + "#if defined(SHADER_API_GLCORE) || defined(SHADER_API_GLES) || defined(SHADER_API_GLES3) || defined(SHADER_API_D3D9)", + "#define FRONT_FACE_SEMANTIC VFACE", + "#define FRONT_FACE_TYPE float", + "#else", + "#define FRONT_FACE_SEMANTIC SV_IsFrontFace", + "#define FRONT_FACE_TYPE bool", + "#endif" + }; + + /*public readonly static string[] CustomASEStandardArgsMacros = + { + "#if defined(SHADER_API_D3D11) || defined(SHADER_API_XBOXONE) || defined(UNITY_COMPILER_HLSLCC)//ASE Args Macros", + "#define ASE_TEXTURE2D_ARGS(textureName) Texture2D textureName, SamplerState sampler##textureName", + "#define ASE_TEXTURE3D_ARGS(textureName) Texture3D textureName, SamplerState sampler##textureName", + "#define ASE_TEXTURECUBE_ARGS(textureName) TextureCube textureName, SamplerState sampler##textureName", + "#define ASE_TEXTURE2D_PARAMS(textureName) textureName, sampler##textureName", + "#define ASE_TEXTURE3D_PARAMS(textureName) textureName, sampler##textureName", + "#define ASE_TEXTURECUBE_PARAMS(textureName) textureName, sampler##textureName", + "#define ASE_TEXTURE2D_ARRAY_PARAMS(textureName) textureName, sampler##textureName", + "#else//ASE Args Macros", + "#define ASE_TEXTURE2D_ARGS(textureName) sampler2D textureName", + "#define ASE_TEXTURE3D_ARGS(textureName) sampler3D textureName", + "#define ASE_TEXTURECUBE_ARGS(textureName) samplerCUBE textureName", + "#define ASE_TEXTURE2D_PARAMS(textureName) textureName", + "#define ASE_TEXTURE3D_PARAMS(textureName) textureName", + "#define ASE_TEXTURECUBE_PARAMS(textureName) textureName", + "#define ASE_TEXTURE2D_ARRAY_PARAMS(textureName) textureName", + "#endif//ASE Args Macros\n" + }; + + public readonly static string[] CustomASEDeclararionMacros = + { + "#define ASE_TEXTURE2D(textureName) {0}2D(textureName)", + "#define ASE_TEXTURE2D_ARRAY(textureName) {0}2D_ARRAY(textureName)", + "#define ASE_TEXTURE3D(textureName) {0}3D(textureName)", + "#define ASE_TEXTURECUBE(textureName) {0}CUBE(textureName)\n" + }; + + public readonly static string[] CustomASEStandarSamplingMacrosHelper = + { + "#if defined(SHADER_API_D3D11) || defined(SHADER_API_XBOXONE) || defined(UNITY_COMPILER_HLSLCC)//ASE Sampling Macros", + "#else//ASE Sampling Macros", + "#endif//ASE Sampling Macros\n" + };*/ + + /*public readonly static string[] CustomASESamplingMacros = + { + "#define ASE_SAMPLE_TEXTURE2D(textureName,{0}coords) {1}2D{2}(textureName,{0}coords)", + "#define ASE_SAMPLE_TEXTURE2D_LOD(textureName, {0}coord2, lod) {1}2D{2}_LOD(textureName, {0}coord2, lod)", + "#define ASE_SAMPLE_TEXTURE2D_BIAS(textureName,{0}coord2, bias) {1}2D{2}_BIAS(textureName,{0}coord2, bias)", + "#define ASE_SAMPLE_TEXTURE2D_GRAD(textureName,{0}coord2, dpdx, dpdy) {1}2D{2}_GRAD(textureName,{0}coord2, dpdx, dpdy)", + + "#define ASE_SAMPLE_TEXTURE3D(textureName,{0}coord3) {1}3D{2}(textureName,{0}coord3)", + "#define ASE_SAMPLE_TEXTURE3D_LOD(textureName,{0}coord3, lod) {1}3D{2}_LOD(textureName,{0}coord3, lod)", + "#define ASE_SAMPLE_TEXTURE3D_BIAS(textureName,{0}coord3, bias) {1}3D{2}_BIAS(textureName,{0}coord3, bias)", + "#define ASE_SAMPLE_TEXTURE3D_GRAD(textureName,{0}coord3, dpdx, dpdy) {1}3D{2}_GRAD(textureName,{0}coord3, dpdx, dpdy)", + + "#define ASE_SAMPLE_TEXTURECUBE(textureName,{0}coord3) {1}CUBE{2}(textureName,{0}coord3)", + "#define ASE_SAMPLE_TEXTURECUBE_LOD(textureName,{0}coord3, lod) {1}CUBE{2}_LOD(textureName,{0}coord3, lod)", + "#define ASE_SAMPLE_TEXTURECUBE_BIAS(textureName,{0}coord3, bias) {1}CUBE{2}_BIAS(textureName,{0}coord3, bias)\n" + };*/ + + // SRP + /*public readonly static string[] CustomASESRPArgsMacros = + { + "#define ASE_TEXTURE2D_ARGS(textureName) TEXTURE2D(textureName), SAMPLER(textureName)", + "#define ASE_TEXTURE3D_ARGS(textureName) TEXTURE3D(textureName), SAMPLER(textureName)", + "#define ASE_TEXTURECUBE_ARGS(textureName) TEXTURECUBE(textureName), SAMPLER(textureName)", + "#define ASE_TEXTURE2D_PARAMS(textureName) textureName, sampler##textureName", + "#define ASE_TEXTURE3D_PARAMS(textureName) textureName, sampler##textureName", + "#define ASE_TEXTURECUBE_PARAMS(textureName) textureName, sampler##textureName", + "#define ASE_TEXTURE2D_ARRAY_PARAMS(textureName) textureName, sampler##textureName\n" + };*/ + + public readonly static RenderTextureFormat PreviewFormat = RenderTextureFormat.ARGBFloat; + public readonly static int PreviewSize = 128; + + public readonly static List UnityNativeInspectors = new List + { + "Rendering.HighDefinition.LightingShaderGraphGUI", + "Rendering.HighDefinition.HDUnlitGUI", + "UnityEditor.Rendering.HighDefinition.HDLitGUI", + "UnityEditor.ShaderGraph.PBRMasterGUI", + "UnityEditor.Rendering.HighDefinition.DecalGUI", + "UnityEditor.Rendering.HighDefinition.FabricGUI", + "UnityEditor.Experimental.Rendering.HDPipeline.HDLitGUI", + "Rendering.HighDefinition.DecalGUI", + "Rendering.HighDefinition.LitShaderGraphGUI", + "Rendering.HighDefinition.DecalShaderGraphGUI" + }; + + public readonly static Dictionary CustomInspectorHD7To10 = new Dictionary + { + { "UnityEditor.Rendering.HighDefinition.DecalGUI","Rendering.HighDefinition.DecalGUI"}, + { "UnityEditor.Rendering.HighDefinition.FabricGUI","Rendering.HighDefinition.LightingShaderGraphGUI"}, + { "UnityEditor.Rendering.HighDefinition.HDLitGUI","Rendering.HighDefinition.LitShaderGraphGUI"}, + { "UnityEditor.Experimental.Rendering.HDPipeline.HDLitGUI","Rendering.HighDefinition.LitShaderGraphGUI"}, + }; + + + public readonly static Dictionary CustomInspectorHDLegacyTo11 = new Dictionary + { + { "UnityEditor.Rendering.HighDefinition.DecalGUI","Rendering.HighDefinition.DecalShaderGraphGUI"}, + { "Rendering.HighDefinition.DecalGUI","Rendering.HighDefinition.DecalShaderGraphGUI"}, + { "UnityEditor.Rendering.HighDefinition.FabricGUI","Rendering.HighDefinition.LightingShaderGraphGUI"}, + { "UnityEditor.Rendering.HighDefinition.HDLitGUI","Rendering.HighDefinition.LitShaderGraphGUI"}, + { "UnityEditor.Experimental.Rendering.HDPipeline.HDLitGUI","Rendering.HighDefinition.LitShaderGraphGUI"}, + }; + + + public readonly static string CustomASEStandardSamplerParams = "#define ASE_TEXTURE_PARAMS(textureName) textureName\n"; + public readonly static string[] CustomASESRPTextureArrayMacros = + { + "#define ASE_TEXTURE2D_ARRAY_ARGS(textureName) TEXTURE2D_ARRAY_ARGS(textureName,sampler##textureName)\n" , + "#define ASE_TEXTURE2D_ARRAY_PARAM(textureName) TEXTURE2D_ARRAY_PARAM(textureName,sampler##textureName)\n" , + "#define ASE_SAMPLE_TEXTURE2D_ARRAY(textureName, coord3) textureName.Sample(sampler##textureName, coord3)", + "#define ASE_SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, coord3, lod) textureName.SampleLevel(sampler##textureName, coord3, lod)" + }; + public readonly static string CustomASESRPSamplerParams = "#define ASE_TEXTURE_PARAMS(textureName) textureName, sampler##textureName\n"; + + public readonly static string[] CustomSRPSamplingMacros = + { + "#if defined(SHADER_API_D3D11) || defined(SHADER_API_XBOXONE) || defined(UNITY_COMPILER_HLSLCC) || defined(SHADER_API_PSSL) || (defined(SHADER_TARGET_SURFACE_ANALYSIS) && !defined(SHADER_TARGET_SURFACE_ANALYSIS_MOJOSHADER))//3D SRP MACROS", + "#define SAMPLE_TEXTURE3D_GRAD(textureName, samplerName, coord3, dpdx, dpdy) textureName.SampleGrad(samplerName, coord3, dpdx, dpdy)", + "#define SAMPLE_TEXTURE3D_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias)", + "#else//3D SRP MACROS", + "#define SAMPLE_TEXTURE3D_GRAD(textureName, samplerName, coord3, dpdx, dpdy) SAMPLE_TEXTURE3D(textureName, samplerName, coord3)", + "#define SAMPLE_TEXTURE3D_BIAS(textureName, samplerName, coord3, bias) SAMPLE_TEXTURE3D(textureName, samplerName, coord3)", + "#endif//3D SRP MACROS\n" + }; + + public readonly static Dictionary TexDeclarationSRPMacros = new Dictionary + { + { TextureType.Texture2D,"TEXTURE2D({0}); SAMPLER(sampler{0});"}, + { TextureType.Texture3D,"TEXTURE3D({0}); SAMPLER(sampler{0});"}, + { TextureType.Cube,"TEXTURECUBE({0}); SAMPLER(sampler{0});"}, + { TextureType.Texture2DArray,"TEXTURE2D_ARRAY({0}); SAMPLER(sampler{0});"}, + }; + + public readonly static Dictionary SamplerDeclarationSRPMacros = new Dictionary + { + { TextureType.Texture2D,"SAMPLER(sampler{0});"}, + { TextureType.Texture3D,"SAMPLER(sampler{0});"}, + { TextureType.Cube,"SAMPLER(sampler{0});"}, + { TextureType.Texture2DArray,"SAMPLER(sampler{0});"}, + }; + + public readonly static Dictionary TexDeclarationNoSamplerSRPMacros = new Dictionary + { + { TextureType.Texture2D,"TEXTURE2D({0})"}, + { TextureType.Texture3D,"TEXTURE3D({0})"}, + { TextureType.Cube,"TEXTURECUBE({0})"}, + { TextureType.Texture2DArray,"TEXTURE2D_ARRAY({0})"}, + }; + + public readonly static Dictionary TexSampleSRPMacros = new Dictionary + { + { TextureType.Texture2D,"SAMPLE_TEXTURE2D{0}( {1}, {2}, {3} )"}, + { TextureType.Texture3D,"SAMPLE_TEXTURE3D{0}( {1}, {2}, {3} )"}, + { TextureType.Cube,"SAMPLE_TEXTURECUBE{0}( {1}, {2}, {3} )"}, + { TextureType.Texture2DArray,"SAMPLE_TEXTURE2D_ARRAY{0}( {1}, {2}, {3} )"}, + }; + + public readonly static Dictionary TexParams = new Dictionary + { + { TextureType.Texture2D,"ASE_TEXTURE2D_PARAMS({0})"}, + { TextureType.Texture3D,"ASE_TEXTURE3D_PARAMS({0})"}, + { TextureType.Cube,"ASE_TEXTURECUBE_PARAMS({0})"}, + { TextureType.Texture2DArray,"ASE_TEXTURE2D_ARRAY_PARAMS({0})"}, + }; + + public readonly static Dictionary WireToTexture = new Dictionary + { + { WirePortDataType.SAMPLER1D,TextureType.Texture1D}, + { WirePortDataType.SAMPLER2D,TextureType.Texture2D}, + { WirePortDataType.SAMPLER3D,TextureType.Texture3D}, + { WirePortDataType.SAMPLERCUBE,TextureType.Cube}, + { WirePortDataType.SAMPLER2DARRAY,TextureType.Texture2DArray}, + }; + + public readonly static Dictionary TextureToWire = new Dictionary + { + { TextureType.Texture1D,WirePortDataType.SAMPLER1D}, + { TextureType.Texture2D,WirePortDataType.SAMPLER2D}, + { TextureType.Texture3D, WirePortDataType.SAMPLER3D}, + { TextureType.Cube,WirePortDataType.SAMPLERCUBE}, + { TextureType.Texture2DArray,WirePortDataType.SAMPLER2DARRAY}, + { TextureType.ProceduralTexture,WirePortDataType.SAMPLER2D}, + }; + + public readonly static string SamplingMacrosDirective = "#define ASE_USING_SAMPLING_MACROS 1"; + + // STANDARD + public readonly static string[] CustomASEStandarSamplingMacrosHelper = + { +#if UNITY_2018_1_OR_NEWER + "#if defined(SHADER_API_D3D11) || defined(SHADER_API_XBOXONE) || defined(UNITY_COMPILER_HLSLCC) || defined(SHADER_API_PSSL) || (defined(SHADER_TARGET_SURFACE_ANALYSIS) && !defined(SHADER_TARGET_SURFACE_ANALYSIS_MOJOSHADER))//ASE Sampler Macros", +#else + "#if defined(SHADER_API_D3D11) || defined(SHADER_API_XBOXONE) || defined(UNITY_COMPILER_HLSLCC) || defined(SHADER_API_PSSL)//ASE Sampler Macros", +#endif + "#else//ASE Sampling Macros", + "#endif//ASE Sampling Macros\n" + }; + + public readonly static string[] CustomASEArraySamplingMacrosRecent = + { + "#define UNITY_SAMPLE_TEX2DARRAY(tex,coord) tex.Sample(sampler##tex,coord)", + "#define UNITY_SAMPLE_TEX2DARRAY_LOD(tex,coord,lod) tex.SampleLevel(sampler##tex,coord, lod)", + "#define UNITY_SAMPLE_TEX2DARRAY_BIAS(tex,coord,bias) tex.SampleBias(sampler##tex,coord,bias)", + "#define UNITY_SAMPLE_TEX2DARRAY_GRAD(tex,coord,ddx,ddy) tex.SampleGrad(sampler##tex,coord,ddx,ddy)", + }; + + public readonly static string[] CustomASEArraySamplingMacrosOlder = + { + "#define UNITY_SAMPLE_TEX2DARRAY(tex,coord) tex2DArray(tex,coord)", + "#define UNITY_SAMPLE_TEX2DARRAY_LOD(tex,coord,lod) tex2DArraylod(tex, float4(coord,lod))", + "#define UNITY_SAMPLE_TEX2DARRAY_BIAS(tex,coord,bias) tex2DArray(tex,coord)", + "#define UNITY_SAMPLE_TEX2DARRAY_GRAD(tex,coord,ddx,ddy) tex2DArray(tex,coord)", + }; + + public readonly static string[] CustomASEStandarSamplingMacrosRecent = + { + "#define SAMPLE_TEXTURE2D(tex,samplerTex,coord) tex.Sample(samplerTex,coord)", + "#define SAMPLE_TEXTURE2D_LOD(tex,samplerTex,coord,lod) tex.SampleLevel(samplerTex,coord, lod)", + "#define SAMPLE_TEXTURE2D_BIAS(tex,samplerTex,coord,bias) tex.SampleBias(samplerTex,coord,bias)", + "#define SAMPLE_TEXTURE2D_GRAD(tex,samplerTex,coord,ddx,ddy) tex.SampleGrad(samplerTex,coord,ddx,ddy)", + + "#define SAMPLE_TEXTURE3D(tex,samplerTex,coord) tex.Sample(samplerTex,coord)", + "#define SAMPLE_TEXTURE3D_LOD(tex,samplerTex,coord,lod) tex.SampleLevel(samplerTex,coord, lod)", + "#define SAMPLE_TEXTURE3D_BIAS(tex,samplerTex,coord,bias) tex.SampleBias(samplerTex,coord,bias)", + "#define SAMPLE_TEXTURE3D_GRAD(tex,samplerTex,coord,ddx,ddy) tex.SampleGrad(samplerTex,coord,ddx,ddy)", + + "#define SAMPLE_TEXTURECUBE(tex,samplerTex,coord) tex.Sample(samplerTex,coord)", + "#define SAMPLE_TEXTURECUBE_LOD(tex,samplerTex,coord,lod) tex.SampleLevel(samplerTex,coord, lod)", + "#define SAMPLE_TEXTURECUBE_BIAS(tex,samplerTex,coord,bias) tex.SampleBias(samplerTex,coord,bias)", + "#define SAMPLE_TEXTURECUBE_GRAD(tex,samplerTex,coord,ddx,ddy) tex.SampleGrad(samplerTex,coord,ddx,ddy)", + + "#define SAMPLE_TEXTURE2D_ARRAY(tex,samplerTex,coord) tex.Sample(samplerTex,coord)", + "#define SAMPLE_TEXTURE2D_ARRAY_LOD(tex,samplerTex,coord,lod) tex.SampleLevel(samplerTex,coord, lod)", + "#define SAMPLE_TEXTURE2D_ARRAY_BIAS(tex,samplerTex,coord,bias) tex.SampleBias(samplerTex,coord,bias)", + "#define SAMPLE_TEXTURE2D_ARRAY_GRAD(tex,samplerTex,coord,ddx,ddy) tex.SampleGrad(samplerTex,coord,ddx,ddy)", + }; + + public readonly static string[] CustomASEStandarSamplingMacrosOlder = + { + "#define SAMPLE_TEXTURE2D(tex,samplerTex,coord) tex2D(tex,coord)", + "#define SAMPLE_TEXTURE2D_LOD(tex,samplerTex,coord,lod) tex2Dlod(tex,float4(coord,0,lod))", + "#define SAMPLE_TEXTURE2D_BIAS(tex,samplerTex,coord,bias) tex2Dbias(tex,float4(coord,0,bias))", + "#define SAMPLE_TEXTURE2D_GRAD(tex,samplerTex,coord,ddx,ddy) tex2Dgrad(tex,coord,ddx,ddy)", + + "#define SAMPLE_TEXTURE3D(tex,samplerTex,coord) tex3D(tex,coord)", + "#define SAMPLE_TEXTURE3D_LOD(tex,samplerTex,coord,lod) tex3Dlod(tex,float4(coord,lod))", + "#define SAMPLE_TEXTURE3D_BIAS(tex,samplerTex,coord,bias) tex3D(tex,coord)", + "#define SAMPLE_TEXTURE3D_GRAD(tex,samplerTex,coord,ddx,ddy) tex3D(tex,coord)", + + "#define SAMPLE_TEXTURECUBE(tex,samplertex,coord) texCUBE(tex,coord)", + "#define SAMPLE_TEXTURECUBE_LOD(tex,samplertex,coord,lod) texCUBElod (tex,half4(coord,lod))", + "#define SAMPLE_TEXTURECUBE_BIAS(tex,samplertex,coord,bias) texCUBE(tex,coord)", + "#define SAMPLE_TEXTURECUBE_GRAD(tex,samplertex,coord,ddx,ddy) texCUBE(tex,coord)", + + "#define SAMPLE_TEXTURE2D_ARRAY(tex,samplertex,coord) tex2DArray(tex,coord)", + "#define SAMPLE_TEXTURE2D_ARRAY_LOD(tex,samplertex,coord,lod) tex2DArraylod(tex, float4(coord,lod))", + "#define SAMPLE_TEXTURE2D_ARRAY_BIAS(tex,samplerTex,coord,bias) tex2DArray(tex,coord)", + "#define SAMPLE_TEXTURE2D_ARRAY_GRAD(tex,samplerTex,coord,ddx,ddy) tex2DArray(tex,coord)", + }; + + public readonly static string[] CustomArraySamplingMacros = + { + "#if defined(UNITY_COMPILER_HLSL2GLSL) || defined(SHADER_TARGET_SURFACE_ANALYSIS)//ASE Array Sampler Macros", + "#define ASE_SAMPLE_TEX2DARRAY_GRAD(tex,coord,dx,dy) UNITY_SAMPLE_TEX2DARRAY (tex,coord)", + "#else//ASE Array Sampler Macros", + "#define ASE_SAMPLE_TEX2DARRAY_GRAD(tex,coord,dx,dy) tex.SampleGrad (sampler##tex,coord,dx,dy)", + "#endif//ASE Array Sampler Macros\n" + }; + + public readonly static Dictionary TexDeclarationStandardMacros = new Dictionary + { + { TextureType.Texture2D,"UNITY_DECLARE_TEX2D({0});"}, + { TextureType.Texture3D,"UNITY_DECLARE_TEX3D({0});"}, + { TextureType.Cube,"UNITY_DECLARE_TEXCUBE({0});"}, + { TextureType.Texture2DArray,"UNITY_DECLARE_TEX2DARRAY({0});"} + }; + + public readonly static Dictionary TexDeclarationNoSamplerStandardMacros = new Dictionary + { + { TextureType.Texture2D,"UNITY_DECLARE_TEX2D_NOSAMPLER({0})"}, + { TextureType.Texture3D,"UNITY_DECLARE_TEX3D_NOSAMPLER({0})"}, + { TextureType.Cube,"UNITY_DECLARE_TEXCUBE_NOSAMPLER({0})"}, + { TextureType.Texture2DArray,"UNITY_DECLARE_TEX2DARRAY_NOSAMPLER({0})"} + }; + + public readonly static Dictionary TexSampleStandardMacros = new Dictionary + { + { TextureType.Texture2D,"UNITY_SAMPLE_TEX2D{0}( {1}, {3} )"}, + { TextureType.Texture3D,"UNITY_SAMPLE_TEX3D{0}( {1}, {3} )"}, + { TextureType.Cube,"UNITY_SAMPLE_TEXCUBE{0}( {1}, {3} )"}, + { TextureType.Texture2DArray,"UNITY_SAMPLE_TEX2DARRAY{0}( {1}, {3} )"} + }; + + public readonly static Dictionary TexSampleSamplerStandardMacros = new Dictionary + { + { TextureType.Texture2D,"SAMPLE_TEXTURE2D{0}( {1}, {2}, {3} )"}, + { TextureType.Texture3D,"SAMPLE_TEXTURE3D{0}( {1}, {2}, {3} )"}, + { TextureType.Cube,"SAMPLE_TEXTURECUBE{0}( {1}, {2}, {3} )"}, + { TextureType.Texture2DArray,"SAMPLE_TEXTURE2D_ARRAY{0}( {1}, {2}, {3} )"} + }; + + public readonly static Dictionary TexSampleStandard = new Dictionary + { + { TextureType.Texture2D,"tex2D{0}( {1}, {2} )"}, + { TextureType.Texture3D,"tex3D{0}( {1}, {2} )"}, + { TextureType.Cube,"texCUBE{0}( {1}, {2} )"}, + { TextureType.Texture2DArray,"tex2DArray{0}( {1}, {2} )"} + }; + public readonly static char LineFeedSeparator = '$'; + public readonly static char SemiColonSeparator = '@'; + public readonly static string AppDataFullName = "appdata_full"; + public readonly static string CustomAppDataFullName = "appdata_full_custom"; + public readonly static string CustomAppDataFullBody = + "\n\t\tstruct appdata_full_custom\n" + + "\t\t{\n" + + "\t\t\tfloat4 vertex : POSITION;\n" + + "\t\t\tfloat4 tangent : TANGENT;\n" + + "\t\t\tfloat3 normal : NORMAL;\n" + + "\t\t\tfloat4 texcoord : TEXCOORD0;\n" + + "\t\t\tfloat4 texcoord1 : TEXCOORD1;\n" + + "\t\t\tfloat4 texcoord2 : TEXCOORD2;\n" + + "\t\t\tfloat4 texcoord3 : TEXCOORD3;\n" + + "\t\t\tfloat4 color : COLOR;\n" + + "\t\t\tUNITY_VERTEX_INPUT_INSTANCE_ID\n"; + + public readonly static string IncludeFormat = "#include \"{0}\""; + public readonly static string PragmaFormat = "#pragma {0}"; + public readonly static string DefineFormat = "#define {0}"; + + public readonly static string RenderTypeHelperStr = "RenderType"; + public readonly static string RenderQueueHelperStr = "Queue"; + public readonly static string DisableBatchingHelperStr = "DisableBatching"; + + public readonly static string DefaultShaderName = "New Amplify Shader"; + + public readonly static string UndoReplaceMasterNodeId = "Replacing Master Node"; + public readonly static string UnityLightingLib = "Lighting.cginc"; + public readonly static string UnityAutoLightLib = "AutoLight.cginc"; + public readonly static string UnityBRDFLib = "UnityStandardBRDF.cginc"; + public readonly static string LocalValueDecWithoutIdent = "{0} {1} = {2};"; + public readonly static string CustomTypeLocalValueDecWithoutIdent = "{0} {1} =({0}){2};"; + public readonly static string LocalValueDefWithoutIdent = "{0} {1} {2};"; + public readonly static string TilingOffsetFormat = "{0} * {1} + {2}"; + public static string InvalidPostProcessDatapath = "__DELETED_GUID_Trash"; + //TEMPLATES + + public static float PlusMinusButtonLayoutWidth = 15; + + public static float NodeButtonSizeX = 16; + public static float NodeButtonSizeY = 16; + public static float NodeButtonDeltaX = 5; + public static float NodeButtonDeltaY = 11; + + public readonly static string SafeNormalizeInfoStr = "With Safe Normalize division by 0 is prevented over the normalize operation at the expense of additional instructions on shader."; + public readonly static string ReservedPropertyNameStr = "Property name '{0}' is reserved and cannot be used"; + public readonly static string NumericPropertyNameStr = "Property name '{0}' is numeric thus cannot be used"; + public readonly static string DeprecatedMessageStr = "Node '{0}' is deprecated. Use node '{1}' instead."; + public readonly static string DeprecatedNoAlternativeMessageStr = "Node '{0}' is deprecated and should be removed."; + public readonly static string UndoChangePropertyTypeNodesId = "Changing Property Types"; + public readonly static string UndoChangeTypeNodesId = "Changing Nodes Types"; + public readonly static string UndoMoveNodesId = "Moving Nodes"; + public readonly static string UndoRegisterFullGrapId = "Register Graph"; + public readonly static string UndoAddNodeToCommentaryId = "Add node to Commentary"; + public readonly static string UndoRemoveNodeFromCommentaryId = "Remove node from Commentary"; + public readonly static string UndoCreateDynamicPortId = "Create Dynamic Port"; + public readonly static string UndoDeleteDynamicPortId = "Destroy Dynamic Port"; + public readonly static string UndoRegisterNodeId = "Register Object"; + public readonly static string UndoUnregisterNodeId = "Unregister Object"; + public readonly static string UndoCreateNodeId = "Create Object"; + public readonly static string UndoPasteNodeId = "Paste Object"; + public readonly static string UndoDeleteNodeId = "Destroy Object"; + public readonly static string UndoDeleteConnectionId = "Destroy Connection"; + public readonly static string UndoCreateConnectionId = "Create Connection"; + + public readonly static float MenuDragSpeed = -0.5f; + public readonly static string DefaultCustomInspector = "ASEMaterialInspector"; + public readonly static string ReferenceTypeStr = "Mode"; + public readonly static string AvailableReferenceStr = "Reference"; + public readonly static string InstancePostfixStr = " (Reference) "; + + public readonly static string ASEMenuName = "Amplify Shader"; + + public readonly static string LodCrossFadeOption2017 = "dithercrossfade"; + + public readonly static string UnityShaderVariables = "UnityShaderVariables.cginc"; + public readonly static string UnityCgLibFuncs = "UnityCG.cginc"; + public readonly static string UnityStandardUtilsLibFuncs = "UnityStandardUtils.cginc"; + public readonly static string UnityPBSLightingLib = "UnityPBSLighting.cginc"; + public readonly static string UnityDeferredLightLib = "UnityDeferredLibrary.cginc"; + public readonly static string ATSharedLibGUID = "ba242738c4be3324aa88d126f7cc19f9"; +#if UNITY_5_6_OR_NEWER + public readonly static string CameraDepthTextureValue = "UNITY_DECLARE_DEPTH_TEXTURE( _CameraDepthTexture );"; + +#else + public readonly static string CameraDepthTextureValue = "uniform sampler2D _CameraDepthTexture;"; +#endif + //public readonly static string CameraDepthTextureSRPVar = "TEXTURE2D(_CameraDepthTexture);"; + //public readonly static string CameraDepthTextureSRPSampler = "SAMPLER(sampler_CameraDepthTexture);"; + public readonly static string CameraDepthTextureLWEnabler = "REQUIRE_DEPTH_TEXTURE 1"; + + public readonly static string CameraDepthTextureTexelSize = "uniform float4 _CameraDepthTexture_TexelSize;"; + public readonly static string InstanceIdMacro = "UNITY_VERTEX_INPUT_INSTANCE_ID"; + public readonly static string InstanceIdVariable = "UNITY_GET_INSTANCE_ID({0})"; + + + public readonly static string HelpURL = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor"; + //public readonly static string NodeCommonUrl = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/Nodes#"; + //public readonly static string CommunityNodeCommonUrl = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/Community_Nodes#"; + public readonly static string NodeCommonUrl = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/"; + public readonly static string CommunityNodeCommonUrl = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/"; + public readonly static Color InfiniteLoopColor = Color.red; + + public readonly static Color DefaultCategoryColor = new Color( 0.26f, 0.35f, 0.44f, 1.0f ); + public readonly static Color NodeBodyColor = new Color( 1f, 1f, 1f, 1.0f ); + + public readonly static Color ModeTextColor = new Color( 1f, 1f, 1f, 0.25f ); + public readonly static Color ModeIconColor = new Color( 1f, 1f, 1f, 0.75f ); + + public readonly static Color PortTextColor = new Color( 1f, 1f, 1f, 0.5f ); + public readonly static Color PortLockedTextColor = new Color( 1f, 1f, 1f, 0.35f ); + public readonly static Color BoxSelectionColor = new Color( 0.5f, 0.75f, 1f, 0.33f ); + public readonly static Color SpecialRegisterLocalVarSelectionColor = new Color( 0.27f, 0.52f, 1.0f, 1f ); + public readonly static Color SpecialGetLocalVarSelectionColor = new Color( 0.2f, 0.8f, 0.4f, 1f ); + public readonly static Color NodeSelectedColor = new Color( 0.85f, 0.56f, 0f, 1f ); + public readonly static Color NodeDefaultColor = new Color( 1f, 1f, 1f, 1f ); + public readonly static Color NodeConnectedColor = new Color( 1.0f, 1f, 0.0f, 1f ); + public readonly static Color NodeErrorColor = new Color( 1f, 0.5f, 0.5f, 1f ); + public readonly static string NoSpecifiedCategoryStr = ""; + + public readonly static int MINIMIZE_WINDOW_LOCK_SIZE = 630; + + public readonly static int FoldoutMouseId = 0; // Left Mouse Button + + public readonly static float SNAP_SQR_DIST = 200f; + public readonly static int INVALID_NODE_ID = -1; + public readonly static float WIRE_WIDTH = 7f; + public readonly static float WIRE_CONTROL_POINT_DIST = 0.7f; + public readonly static float WIRE_CONTROL_POINT_DIST_INV = 1.7f; + + public readonly static float IconsLeftRightMargin = 5f; + public readonly static float PropertyPickerWidth = 16f; + public readonly static float PropertyPickerHeight = 16f; + public readonly static float PreviewExpanderWidth = 16f; + public readonly static float PreviewExpanderHeight = 16f; + public readonly static float TextFieldFontSize = 11f; + public readonly static float DefaultFontSize = 15f; + public readonly static float DefaultTitleFontSize = 13f; + public readonly static float PropertiesTitleFontSize = 11f; + public readonly static float MessageFontSize = 40f; + public readonly static float SelectedObjectFontSize = 30f; + + public readonly static float PORT_X_ADJUST = 10; + public readonly static float PORT_INITIAL_X = 10; + + public readonly static float PORT_INITIAL_Y = 40; + public readonly static float INPUT_PORT_DELTA_Y = 5; + public readonly static float PORT_TO_LABEL_SPACE_X = 5; + + public readonly static float NODE_HEADER_HEIGHT = 32; + public readonly static float NODE_HEADER_EXTRA_HEIGHT = 5; + public readonly static float NODE_HEADER_LEFTRIGHT_MARGIN = 10; + + public readonly static float MULTIPLE_SELECION_BOX_ALPHA = 0.5f; + public readonly static float RMB_CLICK_DELTA_TIME = 0.1f; + public readonly static float RMB_SCREEN_DIST = 10f; + + public readonly static float CAMERA_MAX_ZOOM = 2f; + public readonly static float CAMERA_MIN_ZOOM = 1f; + public readonly static float CAMERA_ZOOM_SPEED = 0.1f; + public readonly static float ALT_CAMERA_ZOOM_SPEED = -0.05f; + + public readonly static object INVALID_VALUE = null; + + public readonly static float HORIZONTAL_TANGENT_SIZE = 100f; + public readonly static float OUTSIDE_WIRE_MARGIN = 5f; + + public readonly static string SubTitleNameFormatStr = "Name( {0} )"; + public readonly static string SubTitleSpaceFormatStr = "Space( {0} )"; + public readonly static string SubTitleTypeFormatStr = "Type( {0} )"; + public readonly static string SubTitleValueFormatStr = "Value( {0} )"; + public readonly static string SubTitleConstFormatStr = "Const( {0} )"; + public readonly static string SubTitleVarNameFormatStr = "Var( {0} )"; + public readonly static string SubTitleRefNameFormatStr = "Ref( {0} )"; + + public readonly static string CodeWrapper = "( {0} )"; + public readonly static string InlineCodeWrapper = "{{\n{0}\n}}"; + + public readonly static string NodesDumpFormat = "{0}:,{1},{2}\n"; + public readonly static string TagFormat = " \"{0}\" = \"{1}\""; + + public readonly static string LocalVarIdentation = "\t\t\t"; + public readonly static string SimpleLocalValueDec = LocalVarIdentation + "{0} {1};\n"; + + public readonly static string LocalValueDec = LocalVarIdentation + LocalValueDecWithoutIdent + '\n'; + public readonly static string LocalValueDef = LocalVarIdentation + "{0} = {1};\n"; + public readonly static string CastHelper = "({0}).{1}"; + public readonly static string PropertyLocalVarDec = "{0} {1} = {0}({2});"; + public readonly static string[] UniformDec = { "uniform {0} {1};", "{0} {1};" }; + + public readonly static string PropertyValueLabel = "Value( {0} )"; + public readonly static string ConstantsValueLabel = "Const( {0} )"; + + public readonly static string PropertyFloatFormatLabel = "0.###"; + public readonly static string PropertyBigFloatFormatLabel = "0.###e+0"; + + public readonly static string PropertyIntFormatLabel = "0"; + public readonly static string PropertyBigIntFormatLabel = "0e+0"; + + + public readonly static string PropertyVectorFormatLabel = "0.##"; + public readonly static string PropertyBigVectorFormatLabel = "0.##e+0"; + + + public readonly static string PropertyMatrixFormatLabel = "0.#"; + public readonly static string PropertyBigMatrixFormatLabel = "0.#e+0"; + + public readonly static string NoPropertiesLabel = "No assigned properties"; + + public readonly static string ValueLabel = "Value"; + public readonly static string DefaultValueLabel = "Default Value"; + public readonly static string MaterialValueLabel = "Material Value"; + public readonly static GUIContent DefaultValueLabelContent = new GUIContent( "Default Value" ); + public readonly static GUIContent MaterialValueLabelContent = new GUIContent( "Material Value" ); + + public readonly static string InputVarStr = "i";//"input"; + public readonly static string OutputVarStr = "o";//"output"; + + public readonly static string CustomLightOutputVarStr = "s"; + public readonly static string CustomLightStructStr = "Custom"; + + public readonly static string VertexShaderOutputStr = "o"; + public readonly static string VertexShaderInputStr = "v";//"vertexData"; + public readonly static string VertexDataFunc = "vertexDataFunc"; + + public readonly static string VirtualCoordNameStr = "vcoord"; + + public readonly static string VertexVecNameStr = "vertexVec"; + public readonly static string VertexVecDecStr = "float3 " + VertexVecNameStr; + public readonly static string VertexVecVertStr = VertexShaderOutputStr + "." + VertexVecNameStr; + + public readonly static string NormalVecNameStr = "normalVec"; + public readonly static string NormalVecDecStr = "float3 " + NormalVecNameStr; + public readonly static string NormalVecFragStr = InputVarStr + "." + NormalVecNameStr; + public readonly static string NormalVecVertStr = VertexShaderOutputStr + "." + NormalVecNameStr; + + + public readonly static string IncidentVecNameStr = "incidentVec"; + public readonly static string IncidentVecDecStr = "float3 " + IncidentVecNameStr; + public readonly static string IncidentVecDefStr = VertexShaderOutputStr + "." + IncidentVecNameStr + " = normalize( " + VertexVecNameStr + " - _WorldSpaceCameraPos.xyz)"; + public readonly static string IncidentVecFragStr = InputVarStr + "." + IncidentVecNameStr; + public readonly static string IncidentVecVertStr = VertexShaderOutputStr + "." + IncidentVecNameStr; + public readonly static string WorldNormalLocalDecStr = "WorldNormalVector( " + Constants.InputVarStr + " , {0}( 0,0,1 ))"; + + public readonly static string VFaceVariable = "ASEVFace"; + public readonly static string VFaceInput = "half ASEVFace : VFACE"; + + public readonly static string ColorVariable = "vertexColor"; + public readonly static string ColorInput = "float4 vertexColor : COLOR"; + + public readonly static string NoStringValue = "None"; + public readonly static string EmptyPortValue = " "; + + public readonly static string[] OverallInvalidChars = { "\r", "\n", "\\", " ", ".", ">", ",", "<", "\'", "\"", ";", ":", "[", "{", "]", "}", "=", "+", "`", "~", "/", "?", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-" }; + public readonly static string[] ShaderInvalidChars = { "\r", "\n", "\\", "\'", "\"", }; + public readonly static string[] EnumInvalidChars = { "\r", "\n", "\\", ".", ">", ",", "<", "\'", "\"", ";", ":", "[", "{", "]", "}", "=", "+", "`", "~", "/", "?", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-" }; + public readonly static string[] AttrInvalidChars = { "\r", "\n", "\\", ">", "<", "\'", "\"", ";", ":", "[", "{", "]", "}", "=", "+", "`", "~", "/", "?", "!", "@", "#", "$", "%", "^", "&", "*" }; + public readonly static string[] HeaderInvalidChars = { "\r", "\n", "\\", ">", ",", "<", "\'", "\"", ";", ":", "[", "{", "]", "}", "=", "+", "`", "~", "/", "?", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-" }; + + public readonly static string[] WikiInvalidChars = { "#", "<", ">", "[", "]", "|", "{", "}", "%", "+", "?", "\\", "/", ",", ";", "." }; + + public readonly static string[,] UrlReplacementStringValues = + { + { " = ", "Equals" }, + { " == ", "Equals" }, + { " != ", "NotEqual" }, + { " \u2260 ", "NotEqual" }, + { " > ", "Greater" }, + { " \u2265 " , "GreaterOrEqual" }, + { " >= ", "GreaterOrEqual" }, + { " < ", "Less" }, + { " \u2264 ", "LessOrEqual" }, + { " <= ", "LessOrEqual" }, + { " ", "_" }, + { "[", string.Empty }, + { "]", string.Empty } + }; + + public readonly static int UrlReplacementStringValuesLen = UrlReplacementStringValues.Length / 2; + + public readonly static string[,] ReplacementStringValues = + { + { " = ", "Equals" }, + { " == ", "Equals" }, + { " != ", "NotEqual" }, + { " \u2260 ", "NotEqual" }, + { " > ", "Greater" }, + { " \u2265 ", "GreaterOrEqual" }, + { " >= ", "GreaterOrEqual" }, + { " < ", "Less" }, + { " \u2264 ", "LessOrEqual" }, + { " <= ", "LessOrEqual" } + }; + public readonly static int ReplacementStringValuesLen = ReplacementStringValues.Length / 2; + + public readonly static string InternalData = "INTERNAL_DATA"; + + + + public readonly static string NoMaterialStr = "None"; + + public readonly static string OptionalParametersSep = " "; + + public readonly static string NodeUndoId = "NODE_UNDO_ID"; + public readonly static string NodeCreateUndoId = "NODE_CREATE_UNDO_ID"; + public readonly static string NodeDestroyUndoId = "NODE_DESTROY_UNDO_ID"; + + // Custom node tags + //[InPortBegin:Id:Type:Name:InPortEnd] + public readonly static string CNIP = "#IP"; + + public readonly static float FLOAT_DRAW_HEIGHT_FIELD_SIZE = 16f; + public readonly static float FLOAT_DRAW_WIDTH_FIELD_SIZE = 45f; + public readonly static float FLOAT_WIDTH_SPACING = 3f; + + public readonly static Color LockedPortColor = new Color( 0.3f, 0.3f, 0.3f, 0.5f ); + +#if UNITY_2018_2_OR_NEWER + public readonly static int[] AvailableUVChannels = { 0, 1, 2, 3, 4, 5, 6, 7 }; + public readonly static string[] AvailableUVChannelsStr = { "0", "1", "2", "3", "4", "5", "6", "7"}; + public readonly static string AvailableUVChannelLabel = "UV Channel"; + + public readonly static int[] AvailableUVSets = { 0, 1, 2, 3, 4, 5, 6, 7 }; + public readonly static string[] AvailableUVSetsStr = { "1", "2", "3", "4","5", "6", "7", "8" }; + public readonly static string AvailableUVSetsLabel = "UV Set"; +#else + public readonly static int[] AvailableUVChannels = { 0, 1, 2, 3 }; + public readonly static string[] AvailableUVChannelsStr = { "0", "1", "2", "3" }; + public readonly static string AvailableUVChannelLabel = "UV Channel"; + + public readonly static int[] AvailableUVSets = { 0, 1, 2, 3 }; + public readonly static string[] AvailableUVSetsStr = { "1", "2", "3", "4" }; + public readonly static string AvailableUVSetsLabel = "UV Set"; +#endif + + public readonly static int[] AvailableUVSizes = { 2, 3, 4 }; + public readonly static string[] AvailableUVSizesStr = { "Float 2", "Float 3", "Float 4" }; + public readonly static string AvailableUVSizesLabel = "Coord Size"; + + + public readonly static string LineSeparator = "________________________________"; + + public readonly static Vector2 CopyPasteDeltaPos = new Vector2( 40, 40 ); + + public readonly static string[] VectorSuffixes = { ".x", ".y", ".z", ".w" }; + public readonly static string[] ColorSuffixes = { ".r", ".g", ".b", ".a" }; + + + public const string InternalDataLabelStr = "Internal Data"; + public const string AttributesLaberStr = "Attributes"; + public const string ParameterLabelStr = "Parameters"; + + public static readonly string[] ReferenceArrayLabels = { "Object", "Reference" }; + + public static readonly string[] ChannelNamesVector = { "X", "Y", "Z", "W" }; + public static readonly string[] ChannelNamesColor = { "R", "G", "B", "A" }; + + public static readonly string SamplerFormat = "sampler{0}"; + public static readonly string SamplerDeclFormat = "SamplerState {0}"; + public static readonly string SamplerDeclSRPFormat = "SAMPLER({0})"; + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Constants.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Constants.cs.meta new file mode 100644 index 0000000..59d7bad --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Constants.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d833dd0968f913f449477da6bcd56b48 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers.meta new file mode 100644 index 0000000..a217729 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2206c4bd7f3d18643a6a3452b0c070d1 +folderAsset: yes +timeCreated: 1522769470 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEBeginDecorator.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEBeginDecorator.cs new file mode 100644 index 0000000..6a82186 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEBeginDecorator.cs @@ -0,0 +1,32 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using AmplifyShaderEditor; + +public class ASEBeginDecorator : MaterialPropertyDrawer +{ + const int Separator = 2; + public override void OnGUI( Rect position, MaterialProperty prop, String label, MaterialEditor editor ) + { + Rect button = position; + button.height = EditorGUIUtility.singleLineHeight; + + if( GUI.Button( button, "Open in Shader Editor" ) ) + { + Material mat = editor.target as Material; +#if UNITY_2018_3_OR_NEWER + ASEPackageManagerHelper.SetupLateMaterial( mat ); +#else + AmplifyShaderEditorWindow.LoadMaterialToASE( mat ); +#endif + } + } + + public override float GetPropertyHeight( MaterialProperty prop, string label, MaterialEditor editor ) + { + return EditorGUIUtility.singleLineHeight + Separator; + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEBeginDecorator.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEBeginDecorator.cs.meta new file mode 100644 index 0000000..007b33e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEBeginDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 508788a7fa76e1d42ad5fdfb1c941ed2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEEndDecorator.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEEndDecorator.cs new file mode 100644 index 0000000..718b074 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEEndDecorator.cs @@ -0,0 +1,36 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using AmplifyShaderEditor; + +public class ASEEndDecorator : MaterialPropertyDrawer +{ + bool m_applyNext = false; + + public override void OnGUI( Rect position, MaterialProperty prop, String label, MaterialEditor editor ) + { + if( prop.applyPropertyCallback == null ) + prop.applyPropertyCallback = Testc; + + if( GUI.changed || m_applyNext ) + { + m_applyNext = false; + Material mat = editor.target as Material; + UIUtils.CopyValuesFromMaterial( mat ); + } + } + + bool Testc( MaterialProperty prop, int changeMask, object previousValue ) + { + m_applyNext = true; + return false; + } + + public override float GetPropertyHeight( MaterialProperty prop, string label, MaterialEditor editor ) + { + return 0; + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEEndDecorator.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEEndDecorator.cs.meta new file mode 100644 index 0000000..cfe07a1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/ASEEndDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fdf2e52babbbbf040b3b9f6df50243f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/EditableIf.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/EditableIf.cs new file mode 100644 index 0000000..e94e02e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/EditableIf.cs @@ -0,0 +1,294 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Donated by BinaryCats +// https://forum.unity.com/threads/best-tool-asset-store-award-amplify-shader-editor-node-based-shader-creation-tool.430959/page-60#post-3414465 +////////////////////// +// README / HOW TO USE +////////////////////// +// Examples: +// +// Floats: +// +// x Equals value +// EditableIf( _float1, Equalto, 1) +// This will allow the value to be edited, if the property _float1 is equal to 1. (_float1==1) +// Note: NotEqualTo is also a valid argument which will do the opposite of this example.EditableIf(_float1, NotEqualTo, 1) (NotEqualTo != 1) +// +// x Greater than value +// EditableIf(_Float1,GreaterThan,1) +// This will allow the value to be edited if the property _float1 is Greater than 1. (_float1>1) +// +// x Greater Than Or Equal to value +// EditableIf(_Float1,GreaterThanOrEqualTo,1) +// This will allow the value to be edited if the property _float1 is Greater than or equal to 1. (_float1>=1) +// +// +// x Less Than value +// EditableIf(_Float1,LessThan,1) +// This will allow the value to be edited if the property _float1 is Less than 1. (_float1<1) +// +// x Less Than Or Equal to value +// EditableIf(_Float1,LessThanOrEqualTo,1) +// This will allow the value to be edited if the property _float1 is Less than or equal to 1. (_float1<=1) +// +// +// Colour: +// +// x Equals r,g,b,a +// EditableIf(_Color0,EqualTo,255,255,255,255) +// This will allow the value to be edited, if the property _Color0 R,G,B and A value all Equal 255. (_Color0.R==255 && _Color0.G==255 & _Color0.B == 255 && _Color0.A == 255) +// +// x Equals alpha +// EditableIf(_Color0,EqualTo,null,null,null,255) +// This will allow the value to be edited, if the property _Color0 Alpha value is Equal to 255. (_Color0.A == 255) +// +// a Greater than blue +// EditableIf(_Color0,GreaterThan,null,null,125) +// This will allow the value to be edited, if the property _Color0 Blue value is Greater Than 125. (_Color0.B > 125) +// Note: as I do not want to check the Red or Green Values, i have entered "null" for the parameter +// Note: I have not inputted a value to check for Alpha, as i do not want to check it. Simularly, if I wanted to Only check the Red Value I could have used EditableIf(_Color0,GreaterThan,125) +// +// Like wise with floats GreaterThanOrEqualTo, LessThan, LessThanOrEqualTo +// +// Vector: +// Vector Checks work the same as colour checks +// +// Texture: +// x Does Not have a Texture +// EditableIf(_TextureSample0,Equals,null) +// This will allow the value to be edited, if the property _TextureSample0 does NOT have a texture +// +// x Does have a Texture +// EditableIf(_TextureSample0,NotEqualTo,null) +// This will allow the value to be edited, if the property _TextureSample0 does have a texture + +using UnityEngine; +using UnityEditor; +using System; + +public enum ComparisonOperators +{ + EqualTo, NotEqualTo, GreaterThan, LessThan, EqualsOrGreaterThan, EqualsOrLessThan, ContainsFlags, + DoesNotContainsFlags +} + +public class EditableIf : MaterialPropertyDrawer +{ + ComparisonOperators op; + string FieldName = ""; + object ExpectedValue; + bool InputError; + public EditableIf() + { + InputError = true; + } + public EditableIf( object fieldname, object comparison, object expectedvalue ) + { + if( expectedvalue.ToString().ToLower() == "true" ) + { + expectedvalue = (System.Single)1; + } + else if( expectedvalue.ToString().ToLower() == "false" ) + { + expectedvalue = (System.Single)0; + + } + Init( fieldname, comparison, expectedvalue ); + + } + public EditableIf( object fieldname, object comparison, object expectedvaluex, object expectedvaluey ) + { + float? x = expectedvaluex as float?; + float? y = expectedvaluey as float?; + float? z = float.NegativeInfinity; + float? w = float.NegativeInfinity; + x = GetVectorValue( x ); + y = GetVectorValue( y ); + + Init( fieldname, comparison, new Vector4( x.Value, y.Value, z.Value, w.Value ) ); + } + public EditableIf( object fieldname, object comparison, object expectedvaluex, object expectedvaluey, object expectedvaluez ) + { + float? x = expectedvaluex as float?; + float? y = expectedvaluey as float?; + float? z = expectedvaluez as float?; + float? w = float.NegativeInfinity; + x = GetVectorValue( x ); + y = GetVectorValue( y ); + z = GetVectorValue( z ); + + Init( fieldname, comparison, new Vector4( x.Value, y.Value, z.Value, w.Value ) ); + + } + public EditableIf( object fieldname, object comparison, object expectedvaluex, object expectedvaluey, object expectedvaluez, object expectedvaluew ) + { + var x = expectedvaluex as float?; + var y = expectedvaluey as float?; + var z = expectedvaluez as float?; + var w = expectedvaluew as float?; + x = GetVectorValue( x ); + y = GetVectorValue( y ); + z = GetVectorValue( z ); + w = GetVectorValue( w ); + + Init( fieldname, comparison, new Vector4( x.Value, y.Value, z.Value, w.Value ) ); + + } + + private void Init( object fieldname, object comparison, object expectedvalue ) + { + FieldName = fieldname.ToString(); + var names = Enum.GetNames( typeof( ComparisonOperators ) ); + var name = comparison.ToString().ToLower().Replace( " ", "" ); + + for( int i = 0; i < names.Length; i++ ) + { + if( names[ i ].ToLower() == name ) + { + op = (ComparisonOperators)i; + break; + } + } + + ExpectedValue = expectedvalue; + } + + private static float? GetVectorValue( float? x ) + { + if( x.HasValue == false ) + { + x = float.NegativeInfinity; + } + + return x; + } + + // Draw the property inside the given rect + public override void OnGUI( Rect position, MaterialProperty prop, String label, MaterialEditor editor ) + { + if( InputError ) + { + EditorGUI.LabelField( position, "EditableIf Attribute Error: Input parameters are invalid!" ); + return; + } + var LHSprop = MaterialEditor.GetMaterialProperty( prop.targets, FieldName ); + if( string.IsNullOrEmpty( LHSprop.name ) ) + { + LHSprop = MaterialEditor.GetMaterialProperty( prop.targets, "_" + FieldName.Replace( " ", "" ) ); + if( string.IsNullOrEmpty( LHSprop.name ) ) + { + EditorGUI.LabelField( position, "EditableIf Attribute Error: " + FieldName + " Does not exist!" ); + return; + } + } + object LHSVal = null; + + bool test = false; + switch( LHSprop.type ) + { + case MaterialProperty.PropType.Color: + case MaterialProperty.PropType.Vector: + LHSVal = LHSprop.type == MaterialProperty.PropType.Color ? (Vector4)LHSprop.colorValue : LHSprop.vectorValue; + var v4 = ExpectedValue as Vector4?; + v4 = v4.HasValue ? v4 : new Vector4( (System.Single)ExpectedValue, float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity ); + + if( LHSprop.type == MaterialProperty.PropType.Color ) + { + test = VectorCheck( (Vector4)LHSVal, op, v4 / 255 ); + + } + else + test = VectorCheck( (Vector4)LHSVal, op, v4 ); + break; + case MaterialProperty.PropType.Range: + case MaterialProperty.PropType.Float: + LHSVal = LHSprop.floatValue; + test = ( Check( LHSVal, op, ExpectedValue ) ); + break; + case MaterialProperty.PropType.Texture: + LHSVal = LHSprop.textureValue; + test = ( CheckObject( LHSVal, op, ExpectedValue ) ); + break; + } + + GUI.enabled = test; + editor.DefaultShaderProperty( position, prop, label ); + GUI.enabled = true; + } + + private bool VectorCheck( Vector4 LHS, ComparisonOperators op, object expectedValue ) + { + var RHS = (Vector4)expectedValue; + if( RHS.x != float.NegativeInfinity ) + { + if( !Check( LHS.x, op, RHS.x ) ) + return false; + } + if( RHS.y != float.NegativeInfinity ) + { + if( !Check( LHS.y, op, RHS.y ) ) + return false; + } + if( RHS.z != float.NegativeInfinity ) + { + if( !Check( LHS.z, op, RHS.z ) ) + return false; + } + if( RHS.w != float.NegativeInfinity ) + { + if( !Check( LHS.w, op, RHS.w ) ) + return false; + } + + return true; + } + + protected bool Check( object LHS, ComparisonOperators op, object RHS ) + { + if( !( LHS is IComparable ) || !( RHS is IComparable ) ) + throw new Exception( "Check using non basic type" ); + + switch( op ) + { + case ComparisonOperators.EqualTo: + return ( (IComparable)LHS ).CompareTo( RHS ) == 0; + + case ComparisonOperators.NotEqualTo: + return ( (IComparable)LHS ).CompareTo( RHS ) != 0; + + case ComparisonOperators.EqualsOrGreaterThan: + return ( (IComparable)LHS ).CompareTo( RHS ) >= 0; + + case ComparisonOperators.EqualsOrLessThan: + return ( (IComparable)LHS ).CompareTo( RHS ) <= 0; + + case ComparisonOperators.GreaterThan: + return ( (IComparable)LHS ).CompareTo( RHS ) > 0; + + case ComparisonOperators.LessThan: + return ( (IComparable)LHS ).CompareTo( RHS ) < 0; + case ComparisonOperators.ContainsFlags: + return ( (int)LHS & (int)RHS ) != 0; // Dont trust LHS values, it has been casted to a char and then to an int again, first bit will be the sign + case ComparisonOperators.DoesNotContainsFlags: + return ( ( (int)LHS & (int)RHS ) == (int)LHS ); // Dont trust LHS values, it has been casted to a char and then to an int again, first bit will be the sign + + default: + break; + } + return false; + } + private bool CheckObject( object LHS, ComparisonOperators comparasonOperator, object RHS ) + { + switch( comparasonOperator ) + { + case ComparisonOperators.EqualTo: + return ( LHS == null ); + + case ComparisonOperators.NotEqualTo: + return ( LHS != null ); + } + return true; + } + +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/EditableIf.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/EditableIf.cs.meta new file mode 100644 index 0000000..363e2ad --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/EditableIf.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7a5504a2b7d04a846978416748dc6e0a +timeCreated: 1520330108 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/NoKeywordToggle.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/NoKeywordToggle.cs new file mode 100644 index 0000000..dfce2c0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/NoKeywordToggle.cs @@ -0,0 +1,25 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +public class NoKeywordToggle : MaterialPropertyDrawer +{ + + public override void OnGUI(Rect position, MaterialProperty prop, String label, MaterialEditor editor) { + bool value = (prop.floatValue != 0.0f); + + EditorGUI.BeginChangeCheck(); + { + EditorGUI.showMixedValue = prop.hasMixedValue; + value = EditorGUI.Toggle( position, label, value ); + EditorGUI.showMixedValue = false; + } + if (EditorGUI.EndChangeCheck()) + { + prop.floatValue = value ? 1.0f : 0.0f; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/NoKeywordToggle.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/NoKeywordToggle.cs.meta new file mode 100644 index 0000000..6c25900 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/NoKeywordToggle.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e1a000d43a26286499b39a7571e5c61b +timeCreated: 1605540234 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSliders.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSliders.cs new file mode 100644 index 0000000..185077d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSliders.cs @@ -0,0 +1,36 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +public class RemapSliders : MaterialPropertyDrawer +{ + public override void OnGUI( Rect position, MaterialProperty prop, String label, MaterialEditor editor ) + { + EditorGUI.BeginChangeCheck(); + Vector4 value = prop.vectorValue; + + EditorGUI.showMixedValue = prop.hasMixedValue; + + var cacheLabel = EditorGUIUtility.labelWidth; + var cacheField = EditorGUIUtility.fieldWidth; + if( cacheField <= 64 ) + { + float total = position.width; + EditorGUIUtility.labelWidth = Mathf.Ceil( 0.45f * total ) - 30; + EditorGUIUtility.fieldWidth = Mathf.Ceil( 0.55f * total ) + 30; + } + + EditorGUI.MinMaxSlider(position, label, ref value.x, ref value.y, 0, 1 ); + + EditorGUIUtility.labelWidth = cacheLabel; + EditorGUIUtility.fieldWidth = cacheField; + EditorGUI.showMixedValue = false; + if( EditorGUI.EndChangeCheck() ) + { + prop.vectorValue = value; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSliders.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSliders.cs.meta new file mode 100644 index 0000000..4c45d1a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSliders.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 314af1bcecbba6c4d92cbb5843c221ba +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSlidersFull.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSlidersFull.cs new file mode 100644 index 0000000..2bc4438 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSlidersFull.cs @@ -0,0 +1,36 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +public class RemapSlidersFull : MaterialPropertyDrawer +{ + public override void OnGUI( Rect position, MaterialProperty prop, String label, MaterialEditor editor ) + { + EditorGUI.BeginChangeCheck(); + Vector4 value = prop.vectorValue; + + EditorGUI.showMixedValue = prop.hasMixedValue; + + var cacheLabel = EditorGUIUtility.labelWidth; + var cacheField = EditorGUIUtility.fieldWidth; + if( cacheField <= 64 ) + { + float total = position.width; + EditorGUIUtility.labelWidth = Mathf.Ceil( 0.45f * total ) - 30; + EditorGUIUtility.fieldWidth = Mathf.Ceil( 0.55f * total ) + 30; + } + + EditorGUI.MinMaxSlider( position, label, ref value.x, ref value.y, value.z, value.w ); + + EditorGUIUtility.labelWidth = cacheLabel; + EditorGUIUtility.fieldWidth = cacheField; + EditorGUI.showMixedValue = false; + if( EditorGUI.EndChangeCheck() ) + { + prop.vectorValue = value; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSlidersFull.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSlidersFull.cs.meta new file mode 100644 index 0000000..58e7813 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/RemapSlidersFull.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9a724dcf5c5ddef40bcef06f0b2c8ec0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/SingleLineTexture.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/SingleLineTexture.cs new file mode 100644 index 0000000..b2d6754 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/SingleLineTexture.cs @@ -0,0 +1,23 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +public class SingleLineTexture : MaterialPropertyDrawer +{ + public override void OnGUI( Rect position, MaterialProperty prop, String label, MaterialEditor editor ) + { + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = prop.hasMixedValue; + + Texture value = editor.TexturePropertyMiniThumbnail( position, prop, label, string.Empty ); + + EditorGUI.showMixedValue = false; + if( EditorGUI.EndChangeCheck() ) + { + prop.textureValue = value; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/SingleLineTexture.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/SingleLineTexture.cs.meta new file mode 100644 index 0000000..33bacf1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/CustomDrawers/SingleLineTexture.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 85da32683d237ac4f8665251e2ac38dc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateFunction.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateFunction.cs new file mode 100644 index 0000000..791b758 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateFunction.cs @@ -0,0 +1,17 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEditor; +using UnityEditor.ProjectWindowCallback; +namespace AmplifyShaderEditor +{ + public class DoCreateFunction : EndNameEditAction + { + public override void Action( int instanceId, string pathName, string resourceFile ) + { + UnityEngine.Object obj = EditorUtility.InstanceIDToObject( instanceId ); + AssetDatabase.CreateAsset( obj, AssetDatabase.GenerateUniqueAssetPath( pathName ) ); + AmplifyShaderEditorWindow.LoadShaderFunctionToASE( (AmplifyShaderFunction)obj, false ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateFunction.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateFunction.cs.meta new file mode 100644 index 0000000..3db405d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateFunction.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3f2c950b0ed192943b7484f6b551965f +timeCreated: 1493906087 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateShader.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateShader.cs new file mode 100644 index 0000000..5fa1424 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateShader.cs @@ -0,0 +1,48 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using UnityEditor.ProjectWindowCallback; +using System.IO; +namespace AmplifyShaderEditor +{ + public class DoCreateStandardShader : EndNameEditAction + { + public override void Action( int instanceId, string pathName, string resourceFile ) + { + string uniquePath = AssetDatabase.GenerateUniqueAssetPath( pathName ); + string shaderName = Path.GetFileName( uniquePath ); + + if( IOUtils.AllOpenedWindows.Count > 0 ) + { + EditorWindow openedWindow = AmplifyShaderEditorWindow.GetWindow(); + AmplifyShaderEditorWindow currentWindow = AmplifyShaderEditorWindow.CreateTab(); + WindowHelper.AddTab( openedWindow, currentWindow ); + UIUtils.CurrentWindow = currentWindow; + } + else + { + AmplifyShaderEditorWindow currentWindow = AmplifyShaderEditorWindow.OpenWindow( shaderName, UIUtils.ShaderIcon ); + UIUtils.CurrentWindow = currentWindow; + } + + Shader shader = UIUtils.CreateNewEmpty( uniquePath, shaderName ); + ProjectWindowUtil.ShowCreatedAsset( shader ); + } + } + + public class DoCreateTemplateShader : EndNameEditAction + { + public override void Action( int instanceId, string pathName, string resourceFile ) + { + string uniquePath = AssetDatabase.GenerateUniqueAssetPath( pathName ); + string shaderName = Path.GetFileName( uniquePath ); + if( !string.IsNullOrEmpty( UIUtils.NewTemplateGUID ) ) + { + Shader shader = AmplifyShaderEditorWindow.CreateNewTemplateShader( UIUtils.NewTemplateGUID, uniquePath, shaderName ); + ProjectWindowUtil.ShowCreatedAsset( shader ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateShader.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateShader.cs.meta new file mode 100644 index 0000000..f2573fb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/DoCreateShader.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2cfa7290f61ad684f99f8d81328ad52c +timeCreated: 1573664425 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/EditorOptions.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/EditorOptions.cs new file mode 100644 index 0000000..89cc8ed --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/EditorOptions.cs @@ -0,0 +1,67 @@ +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [System.Serializable] + public class OptionsWindow + { + private AmplifyShaderEditorWindow m_parentWindow = null; + + private bool m_coloredPorts = true; + private bool m_multiLinePorts = true; + private const string MultiLineId = "MultiLinePortsDefault"; + private const string ColorPortId = "ColoredPortsDefault"; + public OptionsWindow( AmplifyShaderEditorWindow parentWindow ) + { + m_parentWindow = parentWindow; + //Load (); + } + + public void Init() + { + Load(); + } + + public void Destroy() + { + Save(); + } + + public void Save() + { + EditorPrefs.SetBool( ColorPortId, ColoredPorts ); + EditorPrefs.SetBool( MultiLineId, m_multiLinePorts ); + } + + public void Load() + { + ColoredPorts = EditorPrefs.GetBool( ColorPortId, true ); + m_multiLinePorts = EditorPrefs.GetBool( MultiLineId, true ); + } + + public bool ColoredPorts + { + get { return m_coloredPorts; } + set + { + if ( m_coloredPorts != value ) + EditorPrefs.SetBool( ColorPortId, value ); + + m_coloredPorts = value; + } + } + + public bool MultiLinePorts + { + get { return m_multiLinePorts; } + set + { + if ( m_multiLinePorts != value ) + EditorPrefs.SetBool( MultiLineId, value ); + + m_multiLinePorts = value; + } + } + public AmplifyShaderEditorWindow ParentWindow { get { return m_parentWindow; } set { m_parentWindow = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/EditorOptions.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/EditorOptions.cs.meta new file mode 100644 index 0000000..18f0193 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/EditorOptions.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 44cb06bc7bfe6e84aa8b5e8b702eb2dd +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs.meta new file mode 100644 index 0000000..e542e0f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 52f451731ec183e43ab18f0896f7172a +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/NodeGrid.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/NodeGrid.cs new file mode 100644 index 0000000..748d28b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/NodeGrid.cs @@ -0,0 +1,283 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public class NodeGrid + { + private bool m_debugGrid = false; + private const float GRID_SIZE_X = 100; + private const float GRID_SIZE_Y = 100; + + private const float GRID_AREA_X = 1000; + private const float GRID_AREA_Y = 1000; + + private Dictionary>> m_grid; + + private int m_xMin = int.MaxValue; + private int m_yMin = int.MaxValue; + + private int m_xMax = int.MinValue; + private int m_yMax = int.MinValue; + + public NodeGrid() + { + m_grid = new Dictionary>>(); + } + + public void AddNodeToGrid( ParentNode node ) + { + Rect pos = node.Position; + if ( Mathf.Abs( pos.width ) < 0.001f || Mathf.Abs( pos.height ) < 0.001f ) + { + return; + } + + float initialXf = pos.x / GRID_SIZE_X; + float initialYf = pos.y / GRID_SIZE_Y; + + int endX = Mathf.CeilToInt( initialXf + pos.width / GRID_SIZE_X ); + int endY = Mathf.CeilToInt( initialYf + pos.height / GRID_SIZE_Y ); + + int initialX = Mathf.FloorToInt( initialXf ); + int initialY = Mathf.FloorToInt( initialYf ); + + + if ( initialX < m_xMin ) + { + m_xMin = initialX; + } + + if ( initialY < m_yMin ) + { + m_yMin = initialY; + } + + if ( endX > m_xMax ) + { + m_xMax = endX; + } + + if ( endY > m_yMax ) + { + m_yMax = endY; + } + + for ( int x = initialX; x < endX; x += 1 ) + { + for ( int y = initialY; y < endY; y += 1 ) + { + if ( !m_grid.ContainsKey( x ) ) + { + m_grid.Add( x, new Dictionary>() ); + + } + + if ( !m_grid[ x ].ContainsKey( y ) ) + { + m_grid[ x ].Add( y, new List() ); + } + + m_grid[ x ][ y ].Add( node ); + } + } + node.IsOnGrid = true; + //DebugLimits(); + } + + public void RemoveNodeFromGrid( ParentNode node, bool useCachedPos ) + { + Rect pos = useCachedPos ? node.CachedPos : node.Position; + if ( Mathf.Abs( pos.width ) < 0.001f || Mathf.Abs( pos.height ) < 0.001f ) + { + return; + } + + float initialXf = pos.x / GRID_SIZE_X; + float initialYf = pos.y / GRID_SIZE_Y; + + int endX = Mathf.CeilToInt( initialXf + pos.width / GRID_SIZE_X ); + int endY = Mathf.CeilToInt( initialYf + pos.height / GRID_SIZE_Y ); + + int initialX = Mathf.FloorToInt( initialXf ); + int initialY = Mathf.FloorToInt( initialYf ); + bool testLimits = false; + + int xMinCount = 0; + int xMaxCount = 0; + + int yMinCount = 0; + int yMaxCount = 0; + + + for ( int x = initialX; x < endX; x += 1 ) + { + for ( int y = initialY; y < endY; y += 1 ) + { + if ( m_grid.ContainsKey( x ) ) + { + if ( m_grid[ x ].ContainsKey( y ) ) + { + m_grid[ x ][ y ].Remove( node ); + node.IsOnGrid = false; + + if ( initialX == m_xMin && x == initialX ) + { + testLimits = true; + if ( m_grid[ x ][ y ].Count != 0 ) + { + xMinCount += 1; + } + } + + if ( endX == m_xMax && x == endX ) + { + testLimits = true; + if ( m_grid[ x ][ y ].Count != 0 ) + { + xMaxCount += 1; + } + } + + if ( initialY == m_yMin && y == initialY ) + { + testLimits = true; + if ( m_grid[ x ][ y ].Count != 0 ) + { + yMinCount += 1; + } + } + + if ( endY == m_yMax && y == endY ) + { + testLimits = true; + if ( m_grid[ x ][ y ].Count != 0 ) + { + yMaxCount += 1; + } + } + } + } + } + } + + + if ( testLimits ) + { + if ( xMinCount == 0 || xMaxCount == 0 || yMinCount == 0 || yMaxCount == 0 ) + { + m_xMin = int.MaxValue; + m_yMin = int.MaxValue; + + m_xMax = int.MinValue; + m_yMax = int.MinValue; + foreach ( KeyValuePair>> entryX in m_grid ) + { + foreach ( KeyValuePair> entryY in entryX.Value ) + { + if ( entryY.Value.Count > 0 ) + { + if ( entryX.Key < m_xMin ) + { + m_xMin = entryX.Key; + } + + if ( entryY.Key < m_yMin ) + { + m_yMin = entryY.Key; + } + + if ( entryX.Key > m_xMax ) + { + m_xMax = entryX.Key; + } + + if ( entryY.Key > m_yMax ) + { + m_yMax = entryY.Key; + } + } + } + } + // The += 1 is to maintain consistence with AddNodeToGrid() ceil op on max values + m_xMax += 1; + m_yMax += 1; + } + } + //DebugLimits(); + } + + public void DebugLimits() + { + Debug.Log( "[ " + m_xMin + " , " + m_yMin + " ] " + "[ " + m_xMax + " , " + m_yMax + " ] " ); + } + + //pos must be the transformed mouse position to local canvas coordinates + public List GetNodesOn( Vector2 pos ) + { + int x = Mathf.FloorToInt( pos.x / GRID_SIZE_X ); + int y = Mathf.FloorToInt( pos.y / GRID_SIZE_Y ); + + if ( m_grid.ContainsKey( x ) ) + { + if ( m_grid[ x ].ContainsKey( y ) ) + { + return m_grid[ x ][ y ]; + } + } + + return null; + } + + public List GetNodesOn( int x, int y ) + { + if ( m_grid.ContainsKey( x ) ) + { + if ( m_grid[ x ].ContainsKey( y ) ) + { + return m_grid[ x ][ y ]; + } + } + return null; + } + + public void DrawGrid( DrawInfo drawInfo ) + { + if ( m_debugGrid ) + { + Handles.CircleHandleCap( 0, drawInfo.InvertedZoom * ( new Vector3( drawInfo.CameraOffset.x, drawInfo.CameraOffset.y, 0f ) ), Quaternion.identity, 5,EventType.Layout ); + for ( int x = -( int ) GRID_AREA_X; x < GRID_AREA_X; x += ( int ) GRID_SIZE_X ) + { + Handles.DrawLine( drawInfo.InvertedZoom * ( new Vector3( x + drawInfo.CameraOffset.x, drawInfo.CameraOffset.y - GRID_AREA_Y, 0 ) ), drawInfo.InvertedZoom * ( new Vector3( drawInfo.CameraOffset.x + x, drawInfo.CameraOffset.y + GRID_AREA_Y, 0 ) ) ); + } + + for ( int y = -( int ) GRID_AREA_Y; y < GRID_AREA_X; y += ( int ) GRID_SIZE_Y ) + { + Handles.DrawLine( drawInfo.InvertedZoom * ( new Vector3( drawInfo.CameraOffset.x - GRID_AREA_X, drawInfo.CameraOffset.y + y, 0 ) ), drawInfo.InvertedZoom * ( new Vector3( drawInfo.CameraOffset.x + GRID_AREA_X, drawInfo.CameraOffset.y + y, 0 ) ) ); + } + } + } + + public void Destroy() + { + foreach ( KeyValuePair>> entryX in m_grid ) + { + foreach ( KeyValuePair> entryY in entryX.Value ) + { + entryY.Value.Clear(); + } + entryX.Value.Clear(); + } + m_grid.Clear(); + } + + public float MaxNodeDist + { + get { return Mathf.Max( ( m_xMax - m_xMin )*GRID_SIZE_X, ( m_yMax - m_yMin )*GRID_SIZE_Y ); } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/NodeGrid.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/NodeGrid.cs.meta new file mode 100644 index 0000000..46d9f0f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/NodeGrid.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6344917ce0eed6b43840632b98a2ed57 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/ParentGraph.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/ParentGraph.cs new file mode 100644 index 0000000..ff84003 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/ParentGraph.cs @@ -0,0 +1,4060 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class ParentGraph : ScriptableObject, ISerializationCallbackReceiver + { + private const int MasterNodeLODIncrement = 100; + private const int MaxLodAmount = 9; + + public enum NodeLOD + { + LOD0, + LOD1, + LOD2, + LOD3, + LOD4, + LOD5 + } + + [SerializeField] + private bool m_samplingThroughMacros = false; + + private NodeLOD m_lodLevel = NodeLOD.LOD0; + private GUIStyle nodeStyleOff; + private GUIStyle nodeStyleOn; + private GUIStyle nodeTitle; + private GUIStyle commentaryBackground; + + public delegate void LODMasterNodesAdded( int lod ); + public event LODMasterNodesAdded OnLODMasterNodesAddedEvent; + + public delegate void EmptyGraphDetected( ParentGraph graph ); + public event EmptyGraphDetected OnEmptyGraphDetectedEvt; + + public delegate void NodeEvent( ParentNode node ); + public event NodeEvent OnNodeEvent = null; + public event NodeEvent OnNodeRemovedEvent; + + public delegate void DuplicateEvent(); + public event DuplicateEvent OnDuplicateEvent; + + public event MasterNode.OnMaterialUpdated OnMaterialUpdatedEvent; + public event MasterNode.OnMaterialUpdated OnShaderUpdatedEvent; + + private bool m_afterDeserializeFlag = true; + private bool m_lateOptionsRefresh = false; + private bool m_foundDuplicates = false; + + //[SerializeField] + private AmplifyShaderEditorWindow m_parentWindow = null; + + [SerializeField] + private int m_validNodeId; + + [SerializeField] + private List m_nodes = new List(); + + // Sampler Nodes registry + [SerializeField] + private UsageListSamplerNodes m_samplerNodes = new UsageListSamplerNodes(); + + [SerializeField] + private UsageListFloatIntNodes m_floatNodes = new UsageListFloatIntNodes(); + + [SerializeField] + private UsageListTexturePropertyNodes m_texturePropertyNodes = new UsageListTexturePropertyNodes(); + + [SerializeField] + private UsageListTextureArrayNodes m_textureArrayNodes = new UsageListTextureArrayNodes(); + + [SerializeField] + private UsageListPropertyNodes m_propertyNodes = new UsageListPropertyNodes(); + + [SerializeField] + private UsageListPropertyNodes m_rawPropertyNodes = new UsageListPropertyNodes(); + + [SerializeField] + private UsageListScreenColorNodes m_screenColorNodes = new UsageListScreenColorNodes(); + + [SerializeField] + private UsageListRegisterLocalVarNodes m_localVarNodes = new UsageListRegisterLocalVarNodes(); + + [SerializeField] + private UsageListGlobalArrayNodes m_globalArrayNodes = new UsageListGlobalArrayNodes(); + + [SerializeField] + private UsageListFunctionInputNodes m_functionInputNodes = new UsageListFunctionInputNodes(); + + [SerializeField] + private UsageListFunctionNodes m_functionNodes = new UsageListFunctionNodes(); + + [SerializeField] + private UsageListFunctionOutputNodes m_functionOutputNodes = new UsageListFunctionOutputNodes(); + + [SerializeField] + private UsageListFunctionSwitchNodes m_functionSwitchNodes = new UsageListFunctionSwitchNodes(); + + [SerializeField] + private UsageListFunctionSwitchCopyNodes m_functionSwitchCopyNodes = new UsageListFunctionSwitchCopyNodes(); + + [SerializeField] + private UsageListTemplateMultiPassMasterNodes m_multiPassMasterNodes = new UsageListTemplateMultiPassMasterNodes(); + + [SerializeField] + private List m_lodMultiPassMasterNodes; + + [SerializeField] + private UsageListCustomExpressionsOnFunctionMode m_customExpressionsOnFunctionMode = new UsageListCustomExpressionsOnFunctionMode(); + + [SerializeField] + private UsageListStaticSwitchNodes m_staticSwitchNodes = new UsageListStaticSwitchNodes(); + + [SerializeField] + private int m_masterNodeId = Constants.INVALID_NODE_ID; + + [SerializeField] + private bool m_isDirty; + + [SerializeField] + private bool m_saveIsDirty = false; + + [SerializeField] + private int m_nodeClicked; + + [SerializeField] + private int m_loadedShaderVersion; + + [SerializeField] + private int m_instancePropertyCount = 0; + + [SerializeField] + private int m_virtualTextureCount = 0; + + [SerializeField] + private int m_graphId = 0; + + [SerializeField] + private PrecisionType m_currentPrecision = PrecisionType.Float; + + [SerializeField] + private NodeAvailability m_currentCanvasMode = NodeAvailability.SurfaceShader; + + [SerializeField] + private TemplateSRPType m_currentSRPType = TemplateSRPType.BuiltIn; + + //private List m_visibleNodes = new List(); + + private List m_nodePreviewList = new List(); + + private Dictionary m_nodesDict = new Dictionary(); + + [NonSerialized] + private List m_selectedNodes = new List(); + + [NonSerialized] + private List m_markedForDeletion = new List(); + + [SerializeField] + private List m_highlightedWires = new List(); + private System.Type m_masterNodeDefaultType; + + [SerializeField] + private List m_internalTemplateNodesList = new List(); + private Dictionary m_internalTemplateNodesDict = new Dictionary(); + + private NodeGrid m_nodeGrid; + + private bool m_markedToDeSelect = false; + private int m_markToSelect = -1; + private bool m_markToReOrder = false; + + private bool m_hasUnConnectedNodes = false; + + private bool m_checkSelectedWireHighlights = false; + + // Bezier info + [SerializeField] + private List m_bezierReferences; + private const int MaxBezierReferences = 50; + private int m_wireBezierCount = 0; + + protected int m_normalDependentCount = 0; + private bool m_forceCategoryRefresh = false; + + [SerializeField] + private bool m_forceRepositionCheck = false; + + private bool m_isLoading = false; + private bool m_isDuplicating = false; + + private bool m_changedLightingModel = false; + + public void ResetEvents() + { + OnNodeEvent = null; + OnMaterialUpdatedEvent = null; + OnShaderUpdatedEvent = null; + OnEmptyGraphDetectedEvt = null; + OnNodeRemovedEvent = null; + } + + public void Init() + { + Undo.undoRedoPerformed += OnUndoRedoCallback; + m_normalDependentCount = 0; + m_nodes = new List(); + m_samplerNodes = new UsageListSamplerNodes(); + m_samplerNodes.ContainerGraph = this; + m_samplerNodes.ReorderOnChange = true; + m_floatNodes = new UsageListFloatIntNodes(); + m_floatNodes.ContainerGraph = this; + m_texturePropertyNodes = new UsageListTexturePropertyNodes(); + m_texturePropertyNodes.ContainerGraph = this; + m_textureArrayNodes = new UsageListTextureArrayNodes(); + m_textureArrayNodes.ContainerGraph = this; + m_textureArrayNodes.ReorderOnChange = true; + m_propertyNodes = new UsageListPropertyNodes(); + m_propertyNodes.ContainerGraph = this; + m_rawPropertyNodes = new UsageListPropertyNodes(); + m_rawPropertyNodes.ContainerGraph = this; + m_customExpressionsOnFunctionMode = new UsageListCustomExpressionsOnFunctionMode(); + m_customExpressionsOnFunctionMode.ContainerGraph = this; + m_staticSwitchNodes = new UsageListStaticSwitchNodes(); + m_staticSwitchNodes.ContainerGraph = this; + m_staticSwitchNodes.ReorderOnChange = true; + m_screenColorNodes = new UsageListScreenColorNodes(); + m_screenColorNodes.ContainerGraph = this; + m_screenColorNodes.ReorderOnChange = true; + m_localVarNodes = new UsageListRegisterLocalVarNodes(); + m_localVarNodes.ContainerGraph = this; + m_localVarNodes.ReorderOnChange = true; + m_globalArrayNodes = new UsageListGlobalArrayNodes(); + m_globalArrayNodes.ContainerGraph = this; + m_functionInputNodes = new UsageListFunctionInputNodes(); + m_functionInputNodes.ContainerGraph = this; + m_functionNodes = new UsageListFunctionNodes(); + m_functionNodes.ContainerGraph = this; + m_functionOutputNodes = new UsageListFunctionOutputNodes(); + m_functionOutputNodes.ContainerGraph = this; + m_functionSwitchNodes = new UsageListFunctionSwitchNodes(); + m_functionSwitchNodes.ContainerGraph = this; + m_functionSwitchCopyNodes = new UsageListFunctionSwitchCopyNodes(); + m_functionSwitchCopyNodes.ContainerGraph = this; + m_multiPassMasterNodes = new UsageListTemplateMultiPassMasterNodes(); + m_multiPassMasterNodes.ContainerGraph = this; + m_lodMultiPassMasterNodes = new List( MaxLodAmount ); + for( int i = 0; i < MaxLodAmount; i++ ) + { + m_lodMultiPassMasterNodes.Add( new UsageListTemplateMultiPassMasterNodes() ); + } + m_selectedNodes = new List(); + m_markedForDeletion = new List(); + m_highlightedWires = new List(); + m_validNodeId = 0; + IsDirty = false; + SaveIsDirty = false; + m_masterNodeDefaultType = typeof( StandardSurfaceOutputNode ); + + m_bezierReferences = new List( MaxBezierReferences ); + for( int i = 0; i < MaxBezierReferences; i++ ) + { + m_bezierReferences.Add( new WireBezierReference() ); + } + } + + public void ActivatePreviews( bool value ) + { + int count = m_nodes.Count; + if( value ) + { + for( int i = 0 ; i < count ; i++ ) + { + m_nodes[ i ].PreviewIsDirty = true; + } + } + else + { + //for( int i = 0 ; i < count ; i++ ) + //{ + // m_nodes[ i ].DisablePreview(); + //} + } + } + + private void OnUndoRedoCallback() + { + DeSelectAll(); + } + + private void OnEnable() + { + hideFlags = HideFlags.HideAndDontSave; + m_nodeGrid = new NodeGrid(); + m_internalTemplateNodesDict = new Dictionary(); + m_nodesDict = new Dictionary(); + nodeStyleOff = UIUtils.GetCustomStyle( CustomStyle.NodeWindowOff ); + nodeStyleOn = UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ); + nodeTitle = UIUtils.GetCustomStyle( CustomStyle.NodeHeader ); + commentaryBackground = UIUtils.GetCustomStyle( CustomStyle.CommentaryBackground ); + } + + public void UpdateRegisters() + { + m_samplerNodes.UpdateNodeArr(); + m_propertyNodes.UpdateNodeArr(); + m_rawPropertyNodes.UpdateNodeArr(); + m_customExpressionsOnFunctionMode.UpdateNodeArr(); + m_staticSwitchNodes.UpdateNodeArr(); + m_functionInputNodes.UpdateNodeArr(); + m_functionNodes.UpdateNodeArr(); + m_functionOutputNodes.UpdateNodeArr(); + m_functionSwitchNodes.UpdateNodeArr(); + m_functionSwitchCopyNodes.UpdateNodeArr(); + m_multiPassMasterNodes.UpdateNodeArr(); + for( int i = 0; i < m_lodMultiPassMasterNodes.Count; i++ ) + { + m_lodMultiPassMasterNodes[ i ].UpdateNodeArr(); + } + m_texturePropertyNodes.UpdateNodeArr(); + m_textureArrayNodes.UpdateNodeArr(); + m_screenColorNodes.UpdateNodeArr(); + m_localVarNodes.UpdateNodeArr(); + m_globalArrayNodes.UpdateNodeArr(); + } + + public int GetValidId() + { + return m_validNodeId++; + } + + void UpdateIdFromNode( ParentNode node ) + { + if( node.UniqueId >= m_validNodeId ) + { + m_validNodeId = node.UniqueId + 1; + } + } + + public void ResetNodeConnStatus() + { + for( int i = 0; i < m_nodes.Count; i++ ) + { + if( m_nodes[ i ].ConnStatus == NodeConnectionStatus.Connected ) + { + m_nodes[ i ].ConnStatus = NodeConnectionStatus.Not_Connected; + } + } + } + + public void CleanUnusedNodes() + { + List unusedNodes = new List(); + for( int i = 0; i < m_nodes.Count; i++ ) + { + if( m_nodes[ i ].ConnStatus == NodeConnectionStatus.Not_Connected ) + { + unusedNodes.Add( m_nodes[ i ] ); + } + } + + for( int i = 0; i < unusedNodes.Count; i++ ) + { + DestroyNode( unusedNodes[ i ] ); + } + unusedNodes.Clear(); + unusedNodes = null; + + IsDirty = true; + } + + // Destroy all nodes excluding Master Node + public void ClearGraph() + { + List list = new List(); + int count = m_nodes.Count; + for( int i = 0; i < count; i++ ) + { + if( m_nodes[ i ].UniqueId != m_masterNodeId ) + { + list.Add( m_nodes[ i ] ); + } + } + + while( list.Count > 0 ) + { + DestroyNode( list[ 0 ] ); + list.RemoveAt( 0 ); + } + } + + public void CleanNodes() + { + for( int i = 0; i < m_nodes.Count; i++ ) + { + if( m_nodes[ i ] != null ) + { + Undo.ClearUndo( m_nodes[ i ] ); + m_nodes[ i ].Destroy(); + GameObject.DestroyImmediate( m_nodes[ i ] ); + } + } + ClearInternalTemplateNodes(); + + m_masterNodeId = Constants.INVALID_NODE_ID; + m_validNodeId = 0; + m_instancePropertyCount = 0; + m_virtualTextureCount = 0; + + m_nodesDict.Clear(); + m_nodes.Clear(); + m_samplerNodes.Clear(); + m_propertyNodes.Clear(); + m_rawPropertyNodes.Clear(); + m_customExpressionsOnFunctionMode.Clear(); + m_staticSwitchNodes.Clear(); + m_functionInputNodes.Clear(); + m_functionNodes.Clear(); + m_functionOutputNodes.Clear(); + m_functionSwitchNodes.Clear(); + m_functionSwitchCopyNodes.Clear(); + m_multiPassMasterNodes.Clear(); + for( int i = 0; i < m_lodMultiPassMasterNodes.Count; i++ ) + { + m_lodMultiPassMasterNodes[ i ].Clear(); + } + + m_texturePropertyNodes.Clear(); + m_textureArrayNodes.Clear(); + m_screenColorNodes.Clear(); + m_localVarNodes.Clear(); + m_globalArrayNodes.Clear(); + m_selectedNodes.Clear(); + m_markedForDeletion.Clear(); + } + + public void ResetHighlightedWires() + { + for( int i = 0; i < m_highlightedWires.Count; i++ ) + { + m_highlightedWires[ i ].WireStatus = WireStatus.Default; + } + m_highlightedWires.Clear(); + } + + public void HighlightWiresStartingNode( ParentNode node ) + { + for( int outputIdx = 0; outputIdx < node.OutputPorts.Count; outputIdx++ ) + { + for( int extIdx = 0; extIdx < node.OutputPorts[ outputIdx ].ExternalReferences.Count; extIdx++ ) + { + WireReference wireRef = node.OutputPorts[ outputIdx ].ExternalReferences[ extIdx ]; + ParentNode nextNode = GetNode( wireRef.NodeId ); + if( nextNode && nextNode.ConnStatus == NodeConnectionStatus.Connected ) + { + InputPort port = nextNode.GetInputPortByUniqueId( wireRef.PortId ); + if( port.ExternalReferences.Count == 0 || port.ExternalReferences[ 0 ].WireStatus == WireStatus.Highlighted ) + { + // if even one wire is already highlighted then this tells us that this node was already been analysed + return; + } + + port.ExternalReferences[ 0 ].WireStatus = WireStatus.Highlighted; + m_highlightedWires.Add( port.ExternalReferences[ 0 ] ); + HighlightWiresStartingNode( nextNode ); + } + } + } + + RegisterLocalVarNode regNode = node as RegisterLocalVarNode; + if( (object)regNode != null ) + { + int count = regNode.NodeReferences.Count; + for( int i = 0; i < count; i++ ) + { + HighlightWiresStartingNode( regNode.NodeReferences[ i ] ); + } + } + } + + void PropagateHighlightDeselection( ParentNode node, int portId = -1 ) + { + if( portId > -1 ) + { + InputPort port = node.GetInputPortByUniqueId( portId ); + port.ExternalReferences[ 0 ].WireStatus = WireStatus.Default; + } + + if( node.Selected ) + return; + + for( int i = 0; i < node.InputPorts.Count; i++ ) + { + if( node.InputPorts[ i ].ExternalReferences.Count > 0 && node.InputPorts[ i ].ExternalReferences[ 0 ].WireStatus == WireStatus.Highlighted ) + { + // even though node is deselected, it receives wire highlight from a previous one + return; + } + } + + for( int outputIdx = 0; outputIdx < node.OutputPorts.Count; outputIdx++ ) + { + for( int extIdx = 0; extIdx < node.OutputPorts[ outputIdx ].ExternalReferences.Count; extIdx++ ) + { + WireReference wireRef = node.OutputPorts[ outputIdx ].ExternalReferences[ extIdx ]; + ParentNode nextNode = GetNode( wireRef.NodeId ); + PropagateHighlightDeselection( nextNode, wireRef.PortId ); + } + } + + RegisterLocalVarNode regNode = node as RegisterLocalVarNode; + if( (object)regNode != null ) + { + int count = regNode.NodeReferences.Count; + for( int i = 0; i < count; i++ ) + { + PropagateHighlightDeselection( regNode.NodeReferences[ i ], -1 ); + } + } + } + + + public void ResetNodesData() + { + int count = m_nodes.Count; + for( int i = 0; i < count; i++ ) + { + m_nodes[ i ].ResetNodeData(); + } + } + + public void FullCleanUndoStack() + { + Undo.ClearUndo( this ); + int count = m_nodes.Count; + for( int i = 0; i < count; i++ ) + { + if( m_nodes[ i ] != null ) + { + Undo.ClearUndo( m_nodes[ i ] ); + } + } + } + + public void FullRegisterOnUndoStack() + { + Undo.RegisterCompleteObjectUndo( this, Constants.UndoRegisterFullGrapId ); + int count = m_nodes.Count; + for( int i = 0; i < count; i++ ) + { + if( m_nodes[ i ] != null ) + { + Undo.RegisterCompleteObjectUndo( m_nodes[ i ], Constants.UndoRegisterFullGrapId ); + } + } + } + + public void CheckPropertiesAutoRegister( ref MasterNodeDataCollector dataCollector ) + { + List propertyNodesList = m_rawPropertyNodes.NodesList; + int propertyCount = propertyNodesList.Count; + for( int i = 0; i < propertyCount; i++ ) + { + propertyNodesList[ i ].CheckIfAutoRegister( ref dataCollector ); + } + propertyNodesList = null; + + List globalArrayNodeList = m_globalArrayNodes.NodesList; + int globalArrayCount = globalArrayNodeList.Count; + for( int i = 0; i < globalArrayCount; i++ ) + { + globalArrayNodeList[ i ].CheckIfAutoRegister( ref dataCollector ); + } + globalArrayNodeList = null; + + //List propertyNodesList = m_propertyNodes.NodesList; + //int propertyCount = propertyNodesList.Count; + //for( int i = 0; i < propertyCount; i++ ) + //{ + // propertyNodesList[ i ].CheckIfAutoRegister( ref dataCollector ); + //} + //propertyNodesList = null; + + //List screenColorNodes = m_screenColorNodes.NodesList; + //int screenColorNodesCount = screenColorNodes.Count; + //for( int i = 0; i < screenColorNodesCount; i++ ) + //{ + // screenColorNodes[ i ].CheckIfAutoRegister( ref dataCollector ); + //} + //screenColorNodes = null; + } + + public void SoftDestroy() + { + OnNodeRemovedEvent = null; + + m_masterNodeId = Constants.INVALID_NODE_ID; + m_validNodeId = 0; + + m_nodeGrid.Destroy(); + //m_nodeGrid = null; + + ClearInternalTemplateNodes(); + + for( int i = 0; i < m_nodes.Count; i++ ) + { + if( m_nodes[ i ] != null ) + { + m_nodes[ i ].Destroy(); + GameObject.DestroyImmediate( m_nodes[ i ] ); + } + } + + m_instancePropertyCount = 0; + + m_nodes.Clear(); + //m_nodes = null; + + m_nodesDict.Clear(); + //m_nodesDict = null; + + m_samplerNodes.Clear(); + //m_samplerNodes = null; + + m_propertyNodes.Clear(); + m_rawPropertyNodes.Clear(); + //m_propertyNodes = null; + + m_customExpressionsOnFunctionMode.Clear(); + + m_staticSwitchNodes.Clear(); + + m_functionInputNodes.Clear(); + //m_functionInputNodes = null; + + m_functionNodes.Clear(); + //m_functionNodes = null; + + m_functionOutputNodes.Clear(); + //m_functionOutputNodes = null; + + m_functionSwitchNodes.Clear(); + //m_functionSwitchNodes = null; + + m_functionSwitchCopyNodes.Clear(); + //m_functionSwitchCopyNodes = null; + + m_texturePropertyNodes.Clear(); + //m_texturePropertyNodes = null; + + m_textureArrayNodes.Clear(); + //m_textureArrayNodes = null; + + m_screenColorNodes.Clear(); + //m_screenColorNodes = null; + + m_localVarNodes.Clear(); + //m_localVarNodes = null; + + m_globalArrayNodes.Clear(); + + m_selectedNodes.Clear(); + //m_selectedNodes = null; + + m_markedForDeletion.Clear(); + //m_markedForDeletion = null; + + m_nodePreviewList.Clear(); + //m_nodePreviewList = null; + + IsDirty = true; + + OnNodeEvent = null; + OnDuplicateEvent = null; + //m_currentShaderFunction = null; + + OnMaterialUpdatedEvent = null; + OnShaderUpdatedEvent = null; + OnEmptyGraphDetectedEvt = null; + + nodeStyleOff = null; + nodeStyleOn = null; + nodeTitle = null; + commentaryBackground = null; + OnLODMasterNodesAddedEvent = null; + } + + + + + public void Destroy() + { + Undo.undoRedoPerformed -= OnUndoRedoCallback; + for( int i = 0; i < m_nodes.Count; i++ ) + { + if( m_nodes[ i ] != null ) + { + Undo.ClearUndo( m_nodes[ i ] ); + m_nodes[ i ].Destroy(); + GameObject.DestroyImmediate( m_nodes[ i ] ); + } + } + + //Must be before m_propertyNodes.Destroy(); + ClearInternalTemplateNodes(); + m_internalTemplateNodesDict = null; + m_internalTemplateNodesList = null; + + OnNodeRemovedEvent = null; + + m_masterNodeId = Constants.INVALID_NODE_ID; + m_validNodeId = 0; + m_instancePropertyCount = 0; + + m_nodeGrid.Destroy(); + m_nodeGrid = null; + + m_nodes.Clear(); + m_nodes = null; + + m_samplerNodes.Destroy(); + m_samplerNodes = null; + + m_propertyNodes.Destroy(); + m_propertyNodes = null; + + m_rawPropertyNodes.Destroy(); + m_rawPropertyNodes = null; + + m_customExpressionsOnFunctionMode.Destroy(); + m_customExpressionsOnFunctionMode = null; + + m_staticSwitchNodes.Destroy(); + m_staticSwitchNodes = null; + + m_functionInputNodes.Destroy(); + m_functionInputNodes = null; + + m_functionNodes.Destroy(); + m_functionNodes = null; + + m_functionOutputNodes.Destroy(); + m_functionOutputNodes = null; + + m_functionSwitchNodes.Destroy(); + m_functionSwitchNodes = null; + + m_functionSwitchCopyNodes.Destroy(); + m_functionSwitchCopyNodes = null; + + m_multiPassMasterNodes.Destroy(); + m_multiPassMasterNodes = null; + + for( int i = 0; i < m_lodMultiPassMasterNodes.Count; i++ ) + { + m_lodMultiPassMasterNodes[ i ].Destroy(); + m_lodMultiPassMasterNodes[ i ] = null; + } + m_lodMultiPassMasterNodes.Clear(); + m_lodMultiPassMasterNodes = null; + + m_texturePropertyNodes.Destroy(); + m_texturePropertyNodes = null; + + m_textureArrayNodes.Destroy(); + m_textureArrayNodes = null; + + m_screenColorNodes.Destroy(); + m_screenColorNodes = null; + + m_localVarNodes.Destroy(); + m_localVarNodes = null; + + m_globalArrayNodes.Destroy(); + m_globalArrayNodes = null; + + m_selectedNodes.Clear(); + m_selectedNodes = null; + + m_markedForDeletion.Clear(); + m_markedForDeletion = null; + + + m_nodesDict.Clear(); + m_nodesDict = null; + + m_nodePreviewList.Clear(); + m_nodePreviewList = null; + + IsDirty = true; + + OnNodeEvent = null; + OnDuplicateEvent = null; + //m_currentShaderFunction = null; + + OnMaterialUpdatedEvent = null; + OnShaderUpdatedEvent = null; + OnEmptyGraphDetectedEvt = null; + + nodeStyleOff = null; + nodeStyleOn = null; + nodeTitle = null; + commentaryBackground = null; + + OnLODMasterNodesAddedEvent = null; + } + + void OnNodeChangeSizeEvent( ParentNode node ) + { + m_nodeGrid.RemoveNodeFromGrid( node, true ); + m_nodeGrid.AddNodeToGrid( node ); + } + + public void OnNodeFinishMoving( ParentNode node, bool testOnlySelected, InteractionMode interactionMode ) + { + if( OnNodeEvent != null ) + { + OnNodeEvent( node ); + SaveIsDirty = true; + } + + m_nodeGrid.RemoveNodeFromGrid( node, true ); + m_nodeGrid.AddNodeToGrid( node ); + + //if( testOnlySelected ) + //{ + // for( int i = m_visibleNodes.Count - 1; i > -1; i-- ) + // { + // if( node.UniqueId != m_visibleNodes[ i ].UniqueId ) + // { + // switch( interactionMode ) + // { + // case InteractionMode.Target: + // { + // node.OnNodeInteraction( m_visibleNodes[ i ] ); + // } + // break; + // case InteractionMode.Other: + // { + // m_visibleNodes[ i ].OnNodeInteraction( node ); + // } + // break; + // case InteractionMode.Both: + // { + // node.OnNodeInteraction( m_visibleNodes[ i ] ); + // m_visibleNodes[ i ].OnNodeInteraction( node ); + // } + // break; + // } + // } + // } + //} + //else + { + for( int i = m_nodes.Count - 1; i > -1; i-- ) + { + if( node.UniqueId != m_nodes[ i ].UniqueId ) + { + switch( interactionMode ) + { + case InteractionMode.Target: + { + node.OnNodeInteraction( m_nodes[ i ] ); + } + break; + case InteractionMode.Other: + { + m_nodes[ i ].OnNodeInteraction( node ); + } + break; + case InteractionMode.Both: + { + node.OnNodeInteraction( m_nodes[ i ] ); + m_nodes[ i ].OnNodeInteraction( node ); + } + break; + } + } + } + } + } + + + public void OnNodeReOrderEvent( ParentNode node, int index ) + { + if( node.Depth < index ) + { + Debug.LogWarning( "Reorder canceled: This is a specific method for when reordering needs to be done and a its original index is higher than the new one" ); + } + else + { + m_nodes.Remove( node ); + m_nodes.Insert( index, node ); + m_markToReOrder = true; + } + } + + public void AddNode( ParentNode node, bool updateId = false, bool addLast = true, bool registerUndo = true, bool fetchMaterialValues = true ) + { + if( registerUndo ) + { + UIUtils.MarkUndoAction(); + Undo.RegisterCompleteObjectUndo( ParentWindow, Constants.UndoCreateNodeId ); + Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateNodeId ); + Undo.RegisterCreatedObjectUndo( node, Constants.UndoCreateNodeId ); + } + + if( OnNodeEvent != null ) + { + OnNodeEvent( node ); + } + if( updateId ) + { + node.UniqueId = GetValidId(); + } + else + { + UpdateIdFromNode( node ); + } + + + + if( addLast ) + { + m_nodes.Add( node ); + node.Depth = m_nodes.Count; + } + else + { + m_nodes.Insert( 0, node ); + node.Depth = 0; + } + + if( m_nodesDict.ContainsKey( node.UniqueId ) ) + { + //m_nodesDict[ node.UniqueId ] = node; + m_foundDuplicates = true; + } + else + { + m_nodesDict.Add( node.UniqueId, node ); + node.SetMaterialMode( CurrentMaterial, fetchMaterialValues ); + } + + m_nodeGrid.AddNodeToGrid( node ); + node.OnNodeChangeSizeEvent += OnNodeChangeSizeEvent; + node.OnNodeReOrderEvent += OnNodeReOrderEvent; + IsDirty = true; + } + + public void CheckForDuplicates() + { + if( m_foundDuplicates ) + { + Debug.LogWarning( "Found duplicates:" ); + m_foundDuplicates = false; + m_nodesDict.Clear(); + int count = m_nodes.Count; + for( int i = 0; i < count; i++ ) + { + if( m_nodesDict.ContainsKey( m_nodes[ i ].UniqueId ) ) + { + m_nodes[ i ].UniqueId = GetValidId(); + m_nodesDict.Add( m_nodes[ i ].UniqueId, m_nodes[ i ] ); + Debug.LogWarning( "Assigning new ID to " + m_nodes[ i ].TypeName ); + } + else + { + m_nodesDict.Add( m_nodes[ i ].UniqueId, m_nodes[ i ] ); + } + } + } + } + + public ParentNode GetClickedNode() + { + if( m_nodeClicked < 0 ) + return null; + return GetNode( m_nodeClicked ); + } + + public PropertyNode GetInternalTemplateNode( int nodeId ) + { + if( m_internalTemplateNodesDict.Count != m_internalTemplateNodesList.Count ) + { + m_internalTemplateNodesDict.Clear(); + int count = m_internalTemplateNodesList.Count; + for( int i = 0; i < m_internalTemplateNodesList.Count; i++ ) + { + if( m_internalTemplateNodesList[ i ] != null ) + m_internalTemplateNodesDict.Add( m_internalTemplateNodesList[ i ].UniqueId, m_internalTemplateNodesList[ i ] ); + } + } + + if( m_internalTemplateNodesDict.ContainsKey( nodeId ) ) + return m_internalTemplateNodesDict[ nodeId ]; + + return null; + } + + public PropertyNode GetInternalTemplateNode( string propertyName ) + { + return m_internalTemplateNodesList.Find( ( x ) => x.PropertyName.Equals( propertyName ) ); + } + + public void AddInternalTemplateNode( TemplateShaderPropertyData data ) + { + PropertyNode propertyNode = null; + switch( data.PropertyDataType ) + { + case WirePortDataType.FLOAT: + propertyNode = CreateInstance(); break; + case WirePortDataType.FLOAT4: + propertyNode = CreateInstance(); + break; + case WirePortDataType.COLOR: + propertyNode = CreateInstance(); + break; + case WirePortDataType.INT: + propertyNode = CreateInstance(); break; + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + propertyNode = CreateInstance(); + break; + default: return; + } + + propertyNode.PropertyNameFromTemplate( data ); + + // Create a negative unique Id to separate it from + // the regular ids on the main nodes list + // Its begins at -2 since -1 is used to detect invalid values + int uniqueId = -( m_internalTemplateNodesList.Count + 2 ); + propertyNode.SetBaseUniqueId( uniqueId ); + + //Register into Float/Int Nodes list to be available inline + // Unique Id must be already set at this point to properly + // create array + if( data.PropertyDataType == WirePortDataType.FLOAT || + data.PropertyDataType == WirePortDataType.INT ) + m_floatNodes.AddNode( propertyNode ); + + m_internalTemplateNodesList.Add( propertyNode ); + m_internalTemplateNodesDict.Add( uniqueId, propertyNode ); + } + + public void ClearInternalTemplateNodes() + { + if( m_internalTemplateNodesList != null ) + { + int count = m_internalTemplateNodesList.Count; + for( int i = 0; i < count; i++ ) + { + m_internalTemplateNodesList[ i ].Destroy(); + GameObject.DestroyImmediate( m_internalTemplateNodesList[ i ] ); + } + + m_internalTemplateNodesList.Clear(); + m_internalTemplateNodesDict.Clear(); + } + } + + public ParentNode GetNode( int nodeId ) + { + if( m_nodesDict.Count != m_nodes.Count ) + { + m_nodesDict.Clear(); + int count = m_nodes.Count; + for( int i = 0; i < count; i++ ) + { + if( m_nodes[ i ] != null && !m_nodesDict.ContainsKey( m_nodes[ i ].UniqueId ) ) + m_nodesDict.Add( m_nodes[ i ].UniqueId, m_nodes[ i ] ); + } + } + + if( m_nodesDict.ContainsKey( nodeId ) ) + return m_nodesDict[ nodeId ]; + + return null; + } + + public void ForceReOrder() + { + m_nodes.Sort( ( x, y ) => x.Depth.CompareTo( y.Depth ) ); + } + + public bool Draw( DrawInfo drawInfo ) + { + MasterNode masterNode = GetNode( m_masterNodeId ) as MasterNode; + if( m_forceCategoryRefresh && masterNode != null ) + { + masterNode.RefreshAvailableCategories(); + m_forceCategoryRefresh = false; + } + + SaveIsDirty = false; + if( m_afterDeserializeFlag ) + { + // this is now done after logic update... templates needs it this way + //m_afterDeserializeFlag = false; + + CleanCorruptedNodes(); + if( m_nodes.Count == 0 ) + { + //TODO: remove this temp from here + NodeAvailability cachedCanvas = CurrentCanvasMode; + ParentWindow.CreateNewGraph( "Empty" ); + CurrentCanvasMode = cachedCanvas; + if( OnEmptyGraphDetectedEvt != null ) + { + OnEmptyGraphDetectedEvt( this ); + SaveIsDirty = false; + } + else + { + SaveIsDirty = true; + } + } + + //for( int i = 0; i < m_nodes.Count; i++ ) + //{ + // m_nodes[ i ].SetContainerGraph( this ); + //} + } + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + if( m_markedToDeSelect ) + DeSelectAll(); + + if( m_markToSelect > -1 ) + { + AddToSelectedNodes( GetNode( m_markToSelect ) ); + m_markToSelect = -1; + } + + if( m_markToReOrder ) + { + m_markToReOrder = false; + int nodesCount = m_nodes.Count; + for( int i = 0; i < nodesCount; i++ ) + { + m_nodes[ i ].Depth = i; + } + } + } + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + // Resizing Nods per LOD level + NodeLOD newLevel = NodeLOD.LOD0; + float referenceValue; + if( drawInfo.InvertedZoom > 0.5f ) + { + newLevel = NodeLOD.LOD0; + referenceValue = 4; + } + else if( drawInfo.InvertedZoom > 0.25f ) + { + newLevel = NodeLOD.LOD1; + referenceValue = 2; + } + else if( drawInfo.InvertedZoom > 0.15f ) + { + newLevel = NodeLOD.LOD2; + referenceValue = 1; + } + else if( drawInfo.InvertedZoom > 0.1f ) + { + newLevel = NodeLOD.LOD3; + referenceValue = 0; + } + else if( drawInfo.InvertedZoom > 0.07f ) + { + newLevel = NodeLOD.LOD4; + referenceValue = 0; + } + else + { + newLevel = NodeLOD.LOD5; + referenceValue = 0; + } + + // Just a sanity check + nodeStyleOff = UIUtils.GetCustomStyle( CustomStyle.NodeWindowOff ); + nodeStyleOn = UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn );//= UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ); + nodeTitle = UIUtils.GetCustomStyle( CustomStyle.NodeHeader ); + commentaryBackground = UIUtils.GetCustomStyle( CustomStyle.CommentaryBackground ); + + if( newLevel != m_lodLevel || ( UIUtils.MainSkin != null && UIUtils.MainSkin.textField.border.left != referenceValue ) ) + { + m_lodLevel = newLevel; + switch( m_lodLevel ) + { + default: + case NodeLOD.LOD0: + { + UIUtils.MainSkin.textField.border = UIUtils.RectOffsetFour; + nodeStyleOff.border = UIUtils.RectOffsetSix; + UIUtils.NodeWindowOffSquare.border = UIUtils.RectOffsetFour; + + nodeStyleOn.border = UIUtils.RectOffsetSix; + UIUtils.NodeWindowOnSquare.border = UIUtils.RectOffsetSix; + + nodeTitle.border.left = 6; + nodeTitle.border.right = 6; + nodeTitle.border.top = 6; + nodeTitle.border.bottom = 4; + + UIUtils.NodeHeaderSquare.border = UIUtils.RectOffsetFour; + commentaryBackground.border = UIUtils.RectOffsetSix; + } + break; + case NodeLOD.LOD1: + { + UIUtils.MainSkin.textField.border = UIUtils.RectOffsetTwo; + nodeStyleOff.border = UIUtils.RectOffsetFive; + UIUtils.NodeWindowOffSquare.border = UIUtils.RectOffsetFive; + + nodeStyleOn.border = UIUtils.RectOffsetFive; + UIUtils.NodeWindowOnSquare.border = UIUtils.RectOffsetFour; + + nodeTitle.border.left = 5; + nodeTitle.border.right = 5; + nodeTitle.border.top = 5; + nodeTitle.border.bottom = 2; + + UIUtils.NodeHeaderSquare.border = UIUtils.RectOffsetThree; + commentaryBackground.border = UIUtils.RectOffsetFive; + } + break; + case NodeLOD.LOD2: + { + UIUtils.MainSkin.textField.border = UIUtils.RectOffsetOne; + + nodeStyleOff.border.left = 2; + nodeStyleOff.border.right = 2; + nodeStyleOff.border.top = 2; + nodeStyleOff.border.bottom = 3; + + UIUtils.NodeWindowOffSquare.border = UIUtils.RectOffsetThree; + + nodeStyleOn.border.left = 4; + nodeStyleOn.border.right = 4; + nodeStyleOn.border.top = 4; + nodeStyleOn.border.bottom = 3; + + UIUtils.NodeWindowOnSquare.border = UIUtils.RectOffsetThree; + + nodeTitle.border = UIUtils.RectOffsetTwo; + UIUtils.NodeHeaderSquare.border = UIUtils.RectOffsetTwo; + + commentaryBackground.border.left = 2; + commentaryBackground.border.right = 2; + commentaryBackground.border.top = 2; + commentaryBackground.border.bottom = 3; + } + break; + case NodeLOD.LOD3: + case NodeLOD.LOD4: + case NodeLOD.LOD5: + { + UIUtils.MainSkin.textField.border = UIUtils.RectOffsetZero; + + nodeStyleOff.border.left = 1; + nodeStyleOff.border.right = 1; + nodeStyleOff.border.top = 1; + nodeStyleOff.border.bottom = 2; + + UIUtils.NodeWindowOffSquare.border = UIUtils.RectOffsetTwo; + + nodeStyleOn.border = UIUtils.RectOffsetTwo; + UIUtils.NodeWindowOnSquare.border = UIUtils.RectOffsetTwo; + + nodeTitle.border = UIUtils.RectOffsetOne; + UIUtils.NodeHeaderSquare.border = UIUtils.RectOffsetOne; + + commentaryBackground.border.left = 1; + commentaryBackground.border.right = 1; + commentaryBackground.border.top = 1; + commentaryBackground.border.bottom = 2; + } + break; + } + } + } + + //m_visibleNodes.Clear(); + //int nullCount = 0; + m_hasUnConnectedNodes = false; + bool repaint = false; + Material currentMaterial = masterNode != null ? masterNode.CurrentMaterial : null; + EditorGUI.BeginChangeCheck(); + bool repaintMaterialInspector = false; + + int nodeCount = m_nodes.Count; + for( int i = 0; i < nodeCount; i++ ) + { + m_nodes[ i ].OnNodeLogicUpdate( drawInfo ); + } + + if( m_afterDeserializeFlag || m_lateOptionsRefresh ) + { + m_afterDeserializeFlag = false; + m_lateOptionsRefresh = false; + if( CurrentCanvasMode == NodeAvailability.TemplateShader ) + { + RefreshLinkedMasterNodes( true ); + OnRefreshLinkedPortsComplete(); + //If clipboard has cached nodes then a master node replacement will take place + //We need to re-cache master nodes to ensure applied options are correctly cached + //As first cache happens before that + if( m_parentWindow.ClipboardInstance.HasCachedMasterNodes ) + { + m_parentWindow.ClipboardInstance.AddMultiPassNodesToClipboard( MultiPassMasterNodes.NodesList,true,-1 ); + for( int i = 0; i < m_lodMultiPassMasterNodes.Count; i++ ) + { + if( m_lodMultiPassMasterNodes[ i ].Count > 0 ) + m_parentWindow.ClipboardInstance.AddMultiPassNodesToClipboard( m_lodMultiPassMasterNodes[ i ].NodesList, false, i ); + } + } + //RepositionTemplateNodes( CurrentMasterNode ); + } + } + + if( m_forceRepositionCheck ) + { + RepositionTemplateNodes( CurrentMasterNode ); + } + + //for( int i = 0; i < m_functionNodes.NodesList.Count; i++ ) + //{ + // m_functionNodes.NodesList[ i ].LogicGraph(); + //} + + //for( int i = 0; i < UIUtils.FunctionSwitchCopyList().Count; i++ ) + //{ + // UIUtils.FunctionSwitchCopyList()[ i ].CheckReference(); + //} + + + + // Dont use nodeCount variable because node count can change in this loop??? + nodeCount = m_nodes.Count; + ParentNode node = null; + for( int i = 0; i < nodeCount; i++ ) + { + node = m_nodes[ i ]; + if( !node.IsOnGrid ) + { + m_nodeGrid.AddNodeToGrid( node ); + } + + node.MovingInFrame = false; + + if( drawInfo.CurrentEventType == EventType.Repaint ) + node.OnNodeLayout( drawInfo ); + + m_hasUnConnectedNodes = m_hasUnConnectedNodes || + ( node.ConnStatus != NodeConnectionStatus.Connected && node.ConnStatus != NodeConnectionStatus.Island ); + + if( node.RequireMaterialUpdate && currentMaterial != null ) + { + node.UpdateMaterial( currentMaterial ); + repaintMaterialInspector = true; + } + + //if( node.IsVisible ) + // m_visibleNodes.Add( node ); + + IsDirty = ( m_isDirty || node.IsDirty ); + SaveIsDirty = ( m_saveIsDirty || node.SaveIsDirty ); + } + + // Handles GUI controls + nodeCount = m_nodes.Count; + for( int i = nodeCount - 1; i >= 0; i-- ) + //for ( int i = 0; i < nodeCount; i++ ) + { + node = m_nodes[ i ]; + bool restoreMouse = false; + if( drawInfo.CurrentEventType == EventType.MouseDown && m_nodeClicked > -1 && node.UniqueId != m_nodeClicked ) + { + restoreMouse = true; + drawInfo.CurrentEventType = EventType.Ignore; + } + + node.DrawGUIControls( drawInfo ); + + if( restoreMouse ) + { + drawInfo.CurrentEventType = EventType.MouseDown; + } + } + + // Draw connection wires + if( drawInfo.CurrentEventType == EventType.Repaint ) + DrawWires( ParentWindow.WireTexture, drawInfo, ParentWindow.WindowContextPallete.IsActive, ParentWindow.WindowContextPallete.CurrentPosition ); + + // Master Draw + nodeCount = m_nodes.Count; + for( int i = 0; i < nodeCount; i++ ) + { + node = m_nodes[ i ]; + bool restoreMouse = false; + if( drawInfo.CurrentEventType == EventType.MouseDown && m_nodeClicked > -1 && node.UniqueId != m_nodeClicked ) + { + restoreMouse = true; + drawInfo.CurrentEventType = EventType.Ignore; + } + + node.Draw( drawInfo ); + + if( restoreMouse ) + { + drawInfo.CurrentEventType = EventType.MouseDown; + } + } + + // Draw Tooltip + if( drawInfo.CurrentEventType == EventType.Repaint || drawInfo.CurrentEventType == EventType.MouseDown ) + { + nodeCount = m_nodes.Count; + for( int i = nodeCount - 1; i >= 0; i-- ) + { + node = m_nodes[ i ]; + if( node.IsVisible && !node.IsMoving ) + { + bool showing = node.ShowTooltip( drawInfo ); + if( showing ) + break; + } + } + } + + if( repaintMaterialInspector ) + { + if( ASEMaterialInspector.Instance != null ) + { + ASEMaterialInspector.Instance.Repaint(); + } + } + + if( m_checkSelectedWireHighlights ) + { + m_checkSelectedWireHighlights = false; + ResetHighlightedWires(); + for( int i = 0; i < m_selectedNodes.Count; i++ ) + { + HighlightWiresStartingNode( m_selectedNodes[ i ] ); + } + } + + if( EditorGUI.EndChangeCheck() ) + { + SaveIsDirty = true; + repaint = true; + } + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + // Revert LOD changes to LOD0 (only if it's different) + if( UIUtils.MainSkin.textField.border.left != 4 ) + { + UIUtils.MainSkin.textField.border = UIUtils.RectOffsetFour; + nodeStyleOff.border = UIUtils.RectOffsetSix; + UIUtils.NodeWindowOffSquare.border = UIUtils.RectOffsetFour; + + nodeStyleOn.border = UIUtils.RectOffsetSix; + UIUtils.NodeWindowOnSquare.border = UIUtils.RectOffsetSix; + + nodeTitle.border.left = 6; + nodeTitle.border.right = 6; + nodeTitle.border.top = 6; + nodeTitle.border.bottom = 4; + + UIUtils.NodeHeaderSquare.border = UIUtils.RectOffsetFour; + commentaryBackground.border = UIUtils.RectOffsetSix; + } + } + + //if ( nullCount == m_nodes.Count ) + // m_nodes.Clear(); + + ChangedLightingModel = false; + + return repaint; + } + + public bool UpdateMarkForDeletion() + { + if( m_markedForDeletion.Count != 0 ) + { + DeleteMarkedForDeletionNodes(); + return true; + } + return false; + } + + public void DrawWires( Texture2D wireTex, DrawInfo drawInfo, bool contextPaletteActive, Vector3 contextPalettePos ) + { + //Handles.BeginGUI(); + //Debug.Log(GUI.depth); + // Draw connected node wires + m_wireBezierCount = 0; + for( int nodeIdx = 0; nodeIdx < m_nodes.Count; nodeIdx++ ) + { + ParentNode node = m_nodes[ nodeIdx ]; + if( (object)node == null ) + return; + + for( int inputPortIdx = 0; inputPortIdx < node.InputPorts.Count; inputPortIdx++ ) + { + InputPort inputPort = node.InputPorts[ inputPortIdx ]; + if( inputPort.ExternalReferences.Count > 0 && inputPort.Visible ) + { + bool cleanInvalidConnections = false; + for( int wireIdx = 0; wireIdx < inputPort.ExternalReferences.Count; wireIdx++ ) + { + WireReference reference = inputPort.ExternalReferences[ wireIdx ]; + if( reference.NodeId != -1 && reference.PortId != -1 ) + { + ParentNode outputNode = GetNode( reference.NodeId ); + if( outputNode != null ) + { + OutputPort outputPort = outputNode.GetOutputPortByUniqueId( reference.PortId ); + Vector3 endPos = new Vector3( inputPort.Position.x, inputPort.Position.y ); + Vector3 startPos = new Vector3( outputPort.Position.x, outputPort.Position.y ); + float x = ( startPos.x < endPos.x ) ? startPos.x : endPos.x; + float y = ( startPos.y < endPos.y ) ? startPos.y : endPos.y; + float width = Mathf.Abs( startPos.x - endPos.x ) + outputPort.Position.width; + float height = Mathf.Abs( startPos.y - endPos.y ) + outputPort.Position.height; + Rect portsBoundingBox = new Rect( x, y, width, height ); + + bool isVisible = node.IsVisible || outputNode.IsVisible; + if( !isVisible ) + { + isVisible = drawInfo.TransformedCameraArea.Overlaps( portsBoundingBox ); + } + + if( isVisible ) + { + + Rect bezierBB = DrawBezier( drawInfo.InvertedZoom, startPos, endPos, inputPort.DataType, outputPort.DataType, node.GetInputPortVisualDataTypeByArrayIdx( inputPortIdx ), outputNode.GetOutputPortVisualDataTypeById( reference.PortId ), reference.WireStatus, wireTex, node, outputNode ); + bezierBB.x -= Constants.OUTSIDE_WIRE_MARGIN; + bezierBB.y -= Constants.OUTSIDE_WIRE_MARGIN; + + bezierBB.width += Constants.OUTSIDE_WIRE_MARGIN * 2; + bezierBB.height += Constants.OUTSIDE_WIRE_MARGIN * 2; + + if( m_wireBezierCount < m_bezierReferences.Count ) + { + m_bezierReferences[ m_wireBezierCount ].UpdateInfo( ref bezierBB, inputPort.NodeId, inputPort.PortId, outputPort.NodeId, outputPort.PortId ); + } + else + { + m_bezierReferences.Add( new WireBezierReference( ref bezierBB, inputPort.NodeId, inputPort.PortId, outputPort.NodeId, outputPort.PortId ) ); + } + m_wireBezierCount++; + + } + } + else + { + if( DebugConsoleWindow.DeveloperMode ) + UIUtils.ShowMessage( "Detected Invalid connection from node " + node.UniqueId + " port " + inputPortIdx + " to Node " + reference.NodeId + " port " + reference.PortId, MessageSeverity.Error ); + cleanInvalidConnections = true; + inputPort.ExternalReferences[ wireIdx ].Invalidate(); + } + } + } + + if( cleanInvalidConnections ) + { + inputPort.RemoveInvalidConnections(); + } + } + } + } + + //Draw selected wire + if( m_parentWindow.WireReferenceUtils.ValidReferences() ) + { + if( m_parentWindow.WireReferenceUtils.InputPortReference.IsValid ) + { + InputPort inputPort = GetNode( m_parentWindow.WireReferenceUtils.InputPortReference.NodeId ).GetInputPortByUniqueId( m_parentWindow.WireReferenceUtils.InputPortReference.PortId ); + Vector3 endPos = Vector3.zero; + if( m_parentWindow.WireReferenceUtils.SnapEnabled ) + { + Vector2 pos = ( m_parentWindow.WireReferenceUtils.SnapPosition + drawInfo.CameraOffset ) * drawInfo.InvertedZoom; + endPos = new Vector3( pos.x, pos.y ) + UIUtils.ScaledPortsDelta; + } + else + { + endPos = contextPaletteActive ? contextPalettePos : new Vector3( Event.current.mousePosition.x, Event.current.mousePosition.y ); + } + + Vector3 startPos = new Vector3( inputPort.Position.x, inputPort.Position.y ); + DrawBezier( drawInfo.InvertedZoom, endPos, startPos, inputPort.DataType, inputPort.DataType, inputPort.DataType, inputPort.DataType, WireStatus.Default, wireTex ); + } + + if( m_parentWindow.WireReferenceUtils.OutputPortReference.IsValid ) + { + OutputPort outputPort = GetNode( m_parentWindow.WireReferenceUtils.OutputPortReference.NodeId ).GetOutputPortByUniqueId( m_parentWindow.WireReferenceUtils.OutputPortReference.PortId ); + Vector3 endPos = Vector3.zero; + if( m_parentWindow.WireReferenceUtils.SnapEnabled ) + { + Vector2 pos = ( m_parentWindow.WireReferenceUtils.SnapPosition + drawInfo.CameraOffset ) * drawInfo.InvertedZoom; + endPos = new Vector3( pos.x, pos.y ) + UIUtils.ScaledPortsDelta; + } + else + { + endPos = contextPaletteActive ? contextPalettePos : new Vector3( Event.current.mousePosition.x, Event.current.mousePosition.y ); + } + Vector3 startPos = new Vector3( outputPort.Position.x, outputPort.Position.y ); + DrawBezier( drawInfo.InvertedZoom, startPos, endPos, outputPort.DataType, outputPort.DataType, outputPort.DataType, outputPort.DataType, WireStatus.Default, wireTex ); + } + } + //Handles.EndGUI(); + } + + Rect DrawBezier( float invertedZoom, Vector3 startPos, Vector3 endPos, WirePortDataType inputDataType, WirePortDataType outputDataType, WirePortDataType inputVisualDataType, WirePortDataType outputVisualDataType, WireStatus wireStatus, Texture2D wireTex, ParentNode inputNode = null, ParentNode outputNode = null ) + { + startPos += UIUtils.ScaledPortsDelta; + endPos += UIUtils.ScaledPortsDelta; + + // Calculate the 4 points for bezier taking into account wire nodes and their automatic tangents + float mag = ( endPos - startPos ).magnitude; + float resizedMag = Mathf.Min( mag * 0.66f, Constants.HORIZONTAL_TANGENT_SIZE * invertedZoom ); + + Vector3 startTangent = new Vector3( startPos.x + resizedMag, startPos.y ); + Vector3 endTangent = new Vector3( endPos.x - resizedMag, endPos.y ); + + if( (object)inputNode != null && inputNode.GetType() == typeof( WireNode ) ) + endTangent = endPos + ( ( inputNode as WireNode ).TangentDirection ) * mag * 0.33f; + + if( (object)outputNode != null && outputNode.GetType() == typeof( WireNode ) ) + startTangent = startPos - ( ( outputNode as WireNode ).TangentDirection ) * mag * 0.33f; + + ///////////////Draw tangents + //Rect box1 = new Rect( new Vector2( startTangent.x, startTangent.y ), new Vector2( 10, 10 ) ); + //box1.x -= box1.width * 0.5f; + //box1.y -= box1.height * 0.5f; + //GUI.Label( box1, string.Empty, UIUtils.Box ); + + //Rect box2 = new Rect( new Vector2( endTangent.x, endTangent.y ), new Vector2( 10, 10 ) ); + //box2.x -= box2.width * 0.5f; + //box2.y -= box2.height * 0.5f; + //GUI.Label( box2, string.Empty, UIUtils.Box ); + + //m_auxRect.Set( 0, 0, UIUtils.CurrentWindow.position.width, UIUtils.CurrentWindow.position.height ); + //GLDraw.BeginGroup( m_auxRect ); + + int ty = 1; + float wireThickness = 0; + + + if( ParentWindow.Options.MultiLinePorts ) + { + GLDraw.MultiLine = true; + Shader.SetGlobalFloat( "_InvertedZoom", invertedZoom ); + + WirePortDataType smallest = ( (int)outputDataType < (int)inputDataType ? outputDataType : inputDataType ); + smallest = ( (int)smallest < (int)outputVisualDataType ? smallest : outputVisualDataType ); + smallest = ( (int)smallest < (int)inputVisualDataType ? smallest : inputVisualDataType ); + + switch( smallest ) + { + case WirePortDataType.FLOAT2: ty = 2; break; + case WirePortDataType.FLOAT3: ty = 3; break; + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + { + ty = 4; + } + break; + default: ty = 1; break; + } + wireThickness = Mathf.Lerp( Constants.WIRE_WIDTH * ( ty * invertedZoom * -0.05f + 0.15f ), Constants.WIRE_WIDTH * ( ty * invertedZoom * 0.175f + 0.3f ), invertedZoom + 0.4f ); + } + else + { + GLDraw.MultiLine = false; + wireThickness = Mathf.Lerp( Constants.WIRE_WIDTH * ( invertedZoom * -0.05f + 0.15f ), Constants.WIRE_WIDTH * ( invertedZoom * 0.175f + 0.3f ), invertedZoom + 0.4f ); + } + + Rect boundBox = new Rect(); + int segments = 11; + if( LodLevel <= ParentGraph.NodeLOD.LOD4 ) + segments = Mathf.Clamp( Mathf.FloorToInt( mag * 0.2f * invertedZoom ), 11, 35 ); + else + segments = (int)( invertedZoom * 14.28f * 11 ); + + if( ParentWindow.Options.ColoredPorts && wireStatus != WireStatus.Highlighted ) + boundBox = GLDraw.DrawBezier( startPos, startTangent, endPos, endTangent, UIUtils.GetColorForDataType( outputVisualDataType, false, false ), UIUtils.GetColorForDataType( inputVisualDataType, false, false ), wireThickness, segments, ty ); + else + boundBox = GLDraw.DrawBezier( startPos, startTangent, endPos, endTangent, UIUtils.GetColorFromWireStatus( wireStatus ), wireThickness, segments, ty ); + //GLDraw.EndGroup(); + + //GUI.Box( m_auxRect, string.Empty, UIUtils.CurrentWindow.CustomStylesInstance.Box ); + //GUI.Box( boundBox, string.Empty, UIUtils.CurrentWindow.CustomStylesInstance.Box ); + //if ( UIUtils.CurrentWindow.Options.ColoredPorts && wireStatus != WireStatus.Highlighted ) + // Handles.DrawBezier( startPos, endPos, startTangent, endTangent, UIUtils.GetColorForDataType( outputDataType, false, false ), wireTex, wiresTickness ); + //else + // Handles.DrawBezier( startPos, endPos, startTangent, endTangent, UIUtils.GetColorFromWireStatus( wireStatus ), wireTex, wiresTickness ); + + //Handles.DrawLine( startPos, startTangent ); + //Handles.DrawLine( endPos, endTangent ); + + float extraBound = 30 * invertedZoom; + boundBox.xMin -= extraBound; + boundBox.xMax += extraBound; + boundBox.yMin -= extraBound; + boundBox.yMax += extraBound; + + return boundBox; + } + + public void DrawBezierBoundingBox() + { + for( int i = 0; i < m_wireBezierCount; i++ ) + { + m_bezierReferences[ i ].DebugDraw(); + } + } + + public WireBezierReference GetWireBezierInPos( Vector2 position ) + { + for( int i = 0; i < m_wireBezierCount; i++ ) + { + if( m_bezierReferences[ i ].Contains( position ) ) + return m_bezierReferences[ i ]; + } + return null; + } + + + public List GetWireBezierListInPos( Vector2 position ) + { + List list = new List(); + for( int i = 0; i < m_wireBezierCount; i++ ) + { + if( m_bezierReferences[ i ].Contains( position ) ) + list.Add( m_bezierReferences[ i ] ); + } + + return list; + } + + + public void MoveSelectedNodes( Vector2 delta, bool snap = false ) + { + //bool validMovement = delta.magnitude > 0.001f; + //if ( validMovement ) + //{ + // Undo.RegisterCompleteObjectUndo( ParentWindow, Constants.UndoMoveNodesId ); + // for ( int i = 0; i < m_selectedNodes.Count; i++ ) + // { + // if ( !m_selectedNodes[ i ].MovingInFrame ) + // { + // Undo.RecordObject( m_selectedNodes[ i ], Constants.UndoMoveNodesId ); + // m_selectedNodes[ i ].Move( delta, snap ); + // } + // } + // IsDirty = true; + //} + + bool performUndo = delta.magnitude > 0.01f; + if( performUndo ) + { + Undo.RegisterCompleteObjectUndo( ParentWindow, Constants.UndoMoveNodesId ); + Undo.RegisterCompleteObjectUndo( this, Constants.UndoMoveNodesId ); + } + + for( int i = 0; i < m_selectedNodes.Count; i++ ) + { + if( !m_selectedNodes[ i ].MovingInFrame ) + { + if( performUndo ) + m_selectedNodes[ i ].RecordObject( Constants.UndoMoveNodesId ); + m_selectedNodes[ i ].Move( delta, snap ); + } + } + + IsDirty = true; + } + + public void SetConnection( int InNodeId, int InPortId, int OutNodeId, int OutPortId ) + { + ParentNode inNode = GetNode( InNodeId ); + ParentNode outNode = GetNode( OutNodeId ); + InputPort inputPort = null; + OutputPort outputPort = null; + if( inNode != null && outNode != null ) + { + inputPort = inNode.GetInputPortByUniqueId( InPortId ); + outputPort = outNode.GetOutputPortByUniqueId( OutPortId ); + if( inputPort != null && outputPort != null ) + { + if( inputPort.IsConnectedTo( OutNodeId, OutPortId ) || outputPort.IsConnectedTo( InNodeId, InPortId ) ) + { + if( DebugConsoleWindow.DeveloperMode ) + UIUtils.ShowMessage( "Node/Port already connected " + InNodeId, MessageSeverity.Error ); + return; + } + + if( !inputPort.CheckValidType( outputPort.DataType ) ) + { + if( DebugConsoleWindow.DeveloperMode ) + UIUtils.ShowIncompatiblePortMessage( true, inNode, inputPort, outNode, outputPort ); + return; + } + + if( !outputPort.CheckValidType( inputPort.DataType ) ) + { + + if( DebugConsoleWindow.DeveloperMode ) + UIUtils.ShowIncompatiblePortMessage( false, outNode, outputPort, inNode, inputPort ); + return; + } + if( !inputPort.Available || !outputPort.Available ) + { + if( DebugConsoleWindow.DeveloperMode ) + UIUtils.ShowMessage( "Ports not available to connection", MessageSeverity.Warning ); + + return; + } + + if( inputPort.ConnectTo( OutNodeId, OutPortId, outputPort.DataType, false ) ) + { + inNode.OnInputPortConnected( InPortId, OutNodeId, OutPortId ); + } + + + if( outputPort.ConnectTo( InNodeId, InPortId, inputPort.DataType, inputPort.TypeLocked ) ) + { + outNode.OnOutputPortConnected( OutPortId, InNodeId, InPortId ); + } + } + else if( (object)inputPort == null ) + { + if( DebugConsoleWindow.DeveloperMode ) + UIUtils.ShowMessage( "Input Port " + InPortId + " doesn't exist on node " + InNodeId, MessageSeverity.Error ); + } + else + { + if( DebugConsoleWindow.DeveloperMode ) + UIUtils.ShowMessage( "Output Port " + OutPortId + " doesn't exist on node " + OutNodeId, MessageSeverity.Error ); + } + } + else if( (object)inNode == null ) + { + if( DebugConsoleWindow.DeveloperMode ) + UIUtils.ShowMessage( "Input node " + InNodeId + " doesn't exist", MessageSeverity.Error ); + } + else + { + if( DebugConsoleWindow.DeveloperMode ) + UIUtils.ShowMessage( "Output node " + OutNodeId + " doesn't exist", MessageSeverity.Error ); + } + } + + public void CreateConnection( int inNodeId, int inPortId, int outNodeId, int outPortId, bool registerUndo = true ) + { + ParentNode outputNode = GetNode( outNodeId ); + if( outputNode != null ) + { + OutputPort outputPort = outputNode.GetOutputPortByUniqueId( outPortId ); + if( outputPort != null ) + { + ParentNode inputNode = GetNode( inNodeId ); + InputPort inputPort = inputNode.GetInputPortByUniqueId( inPortId ); + + if( !inputPort.CheckValidType( outputPort.DataType ) ) + { + UIUtils.ShowIncompatiblePortMessage( true, inputNode, inputPort, outputNode, outputPort ); + return; + } + + if( !outputPort.CheckValidType( inputPort.DataType ) ) + { + UIUtils.ShowIncompatiblePortMessage( false, outputNode, outputPort, inputNode, inputPort ); + return; + } + + inputPort.DummyAdd( outputPort.NodeId, outputPort.PortId ); + outputPort.DummyAdd( inNodeId, inPortId ); + + if( UIUtils.DetectNodeLoopsFrom( inputNode, new Dictionary() ) ) + { + inputPort.DummyRemove(); + outputPort.DummyRemove(); + m_parentWindow.WireReferenceUtils.InvalidateReferences(); + UIUtils.ShowMessage( "Infinite Loop detected" ); + Event.current.Use(); + return; + } + + inputPort.DummyRemove(); + outputPort.DummyRemove(); + + if( inputPort.IsConnected ) + { + DeleteConnection( true, inNodeId, inPortId, true, false, registerUndo ); + } + + //link output to input + if( outputPort.ConnectTo( inNodeId, inPortId, inputPort.DataType, inputPort.TypeLocked ) ) + outputNode.OnOutputPortConnected( outputPort.PortId, inNodeId, inPortId ); + + //link input to output + if( inputPort.ConnectTo( outputPort.NodeId, outputPort.PortId, outputPort.DataType, inputPort.TypeLocked ) ) + inputNode.OnInputPortConnected( inPortId, outputNode.UniqueId, outputPort.PortId ); + + MarkWireHighlights(); + } + SaveIsDirty = true; + //ParentWindow.ShaderIsModified = true; + } + } + + public void DeleteInvalidConnections() + { + int count = m_nodes.Count; + for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ ) + { + { + int inputCount = m_nodes[ nodeIdx ].InputPorts.Count; + for( int inputIdx = 0; inputIdx < inputCount; inputIdx++ ) + { + if( !m_nodes[ nodeIdx ].InputPorts[ inputIdx ].Visible && + m_nodes[ nodeIdx ].InputPorts[ inputIdx ].IsConnected && + !m_nodes[ nodeIdx ].InputPorts[ inputIdx ].IsDummy ) + { + DeleteConnection( true, m_nodes[ nodeIdx ].UniqueId, m_nodes[ nodeIdx ].InputPorts[ inputIdx ].PortId, true, true ); + } + } + } + { + int outputCount = m_nodes[ nodeIdx ].OutputPorts.Count; + for( int outputIdx = 0; outputIdx < outputCount; outputIdx++ ) + { + if( !m_nodes[ nodeIdx ].OutputPorts[ outputIdx ].Visible && m_nodes[ nodeIdx ].OutputPorts[ outputIdx ].IsConnected ) + { + DeleteConnection( false, m_nodes[ nodeIdx ].UniqueId, m_nodes[ nodeIdx ].OutputPorts[ outputIdx ].PortId, true, true ); + } + } + } + } + } + + public void DeleteAllConnectionFromNode( int nodeId, bool registerOnLog, bool propagateCallback, bool registerUndo ) + { + ParentNode node = GetNode( nodeId ); + if( (object)node == null ) + return; + DeleteAllConnectionFromNode( node, registerOnLog, propagateCallback, registerUndo ); + } + + public void DeleteAllConnectionFromNode( ParentNode node, bool registerOnLog, bool propagateCallback, bool registerUndo ) + { + + for( int i = 0; i < node.InputPorts.Count; i++ ) + { + if( node.InputPorts[ i ].IsConnected ) + DeleteConnection( true, node.UniqueId, node.InputPorts[ i ].PortId, registerOnLog, propagateCallback, registerUndo ); + } + + for( int i = 0; i < node.OutputPorts.Count; i++ ) + { + if( node.OutputPorts[ i ].IsConnected ) + DeleteConnection( false, node.UniqueId, node.OutputPorts[ i ].PortId, registerOnLog, propagateCallback, registerUndo ); + } + } + + public void DeleteConnection( bool isInput, int nodeId, int portId, bool registerOnLog, bool propagateCallback, bool registerUndo = true ) + { + ParentNode node = GetNode( nodeId ); + if( (object)node == null ) + return; + + if( registerUndo ) + { + UIUtils.MarkUndoAction(); + Undo.RegisterCompleteObjectUndo( ParentWindow, Constants.UndoDeleteConnectionId ); + Undo.RegisterCompleteObjectUndo( this, Constants.UndoDeleteConnectionId ); + node.RecordObject( Constants.UndoDeleteConnectionId ); + } + + if( isInput ) + { + InputPort inputPort = node.GetInputPortByUniqueId( portId ); + if( inputPort != null && inputPort.IsConnected ) + { + + if( node.ConnStatus == NodeConnectionStatus.Connected ) + { + node.DeactivateInputPortNode( portId, false ); + //inputPort.GetOutputNode().DeactivateNode( portId, false ); + m_checkSelectedWireHighlights = true; + } + + for( int i = 0; i < inputPort.ExternalReferences.Count; i++ ) + { + WireReference inputReference = inputPort.ExternalReferences[ i ]; + ParentNode outputNode = GetNode( inputReference.NodeId ); + if( registerUndo ) + outputNode.RecordObject( Constants.UndoDeleteConnectionId ); + outputNode.GetOutputPortByUniqueId( inputReference.PortId ).InvalidateConnection( inputPort.NodeId, inputPort.PortId ); + if( propagateCallback ) + outputNode.OnOutputPortDisconnected( inputReference.PortId ); + } + inputPort.InvalidateAllConnections(); + if( propagateCallback ) + node.OnInputPortDisconnected( portId ); + } + } + else + { + OutputPort outputPort = node.GetOutputPortByUniqueId( portId ); + if( outputPort != null && outputPort.IsConnected ) + { + if( propagateCallback ) + node.OnOutputPortDisconnected( portId ); + + for( int i = 0; i < outputPort.ExternalReferences.Count; i++ ) + { + WireReference outputReference = outputPort.ExternalReferences[ i ]; + ParentNode inputNode = GetNode( outputReference.NodeId ); + if( registerUndo ) + inputNode.RecordObject( Constants.UndoDeleteConnectionId ); + if( inputNode.ConnStatus == NodeConnectionStatus.Connected ) + { + node.DeactivateNode( portId, false ); + m_checkSelectedWireHighlights = true; + } + inputNode.GetInputPortByUniqueId( outputReference.PortId ).InvalidateConnection( outputPort.NodeId, outputPort.PortId ); + if( propagateCallback ) + { + // Removing WireNodes fires this after the rewiring ( and the OnInputPortConnected callback ) which causes incorrect behaviors + // If is connected is true then we're on that case so we don't fire the OnInputPortDisconnected + if( !inputNode.GetInputPortByUniqueId( outputReference.PortId ).IsConnected ) + inputNode.OnInputPortDisconnected( outputReference.PortId ); + } + } + outputPort.InvalidateAllConnections(); + } + } + IsDirty = true; + SaveIsDirty = true; + } + + //public void DeleteSelectedNodes() + //{ + // bool invalidateMasterNode = false; + // int count = m_selectedNodes.Count; + // for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ ) + // { + // ParentNode node = m_selectedNodes[ nodeIdx ]; + // if( node.UniqueId == m_masterNodeId ) + // { + // invalidateMasterNode = true; + // } + // else + // { + // DestroyNode( node ); + // } + // } + + // if( invalidateMasterNode ) + // { + // CurrentOutputNode.Selected = false; + // } + // //Clear all references + // m_selectedNodes.Clear(); + // IsDirty = true; + //} + + public void DeleteNodesOnArray( ref ParentNode[] nodeArray ) + { + bool invalidateMasterNode = false; + for( int nodeIdx = 0; nodeIdx < nodeArray.Length; nodeIdx++ ) + { + ParentNode node = nodeArray[ nodeIdx ]; + if( node.UniqueId == m_masterNodeId ) + { + FunctionOutput fout = node as FunctionOutput; + if( fout != null ) + { + for( int i = 0; i < m_nodes.Count; i++ ) + { + FunctionOutput secondfout = m_nodes[ i ] as FunctionOutput; + if( secondfout != null && secondfout != fout ) + { + secondfout.Function = fout.Function; + AssignMasterNode( secondfout, false ); + + DeselectNode( fout ); + DestroyNode( fout ); + break; + } + } + } + invalidateMasterNode = true; + } + else + { + DeselectNode( node ); + DestroyNode( node ); + } + nodeArray[ nodeIdx ] = null; + } + + if( invalidateMasterNode && CurrentMasterNode != null ) + { + CurrentMasterNode.Selected = false; + } + + //Clear all references + nodeArray = null; + IsDirty = true; + } + + public void MarkWireNodeSequence( WireNode node, bool isInput ) + { + if( node == null ) + { + return; + } + + if( m_markedForDeletion.Contains( node ) ) + return; + + m_markedForDeletion.Add( node ); + + if( isInput && node.InputPorts[ 0 ].IsConnected ) + { + MarkWireNodeSequence( GetNode( node.InputPorts[ 0 ].ExternalReferences[ 0 ].NodeId ) as WireNode, isInput ); + } + else if( !isInput && node.OutputPorts[ 0 ].IsConnected ) + { + MarkWireNodeSequence( GetNode( node.OutputPorts[ 0 ].ExternalReferences[ 0 ].NodeId ) as WireNode, isInput ); + } + } + + public void UndoableDeleteSelectedNodes( List nodeList ) + { + if( nodeList.Count == 0 ) + return; + + List validNode = new List(); + + for( int i = 0; i < nodeList.Count; i++ ) + { + if( nodeList[ i ] != null && nodeList[ i ].UniqueId != m_masterNodeId ) + { + validNode.Add( nodeList[ i ] ); + } + } + UIUtils.ClearUndoHelper(); + ParentNode[] selectedNodes = new ParentNode[ validNode.Count ]; + for( int i = 0; i < selectedNodes.Length; i++ ) + { + if( validNode[ i ] != null ) + { + selectedNodes[ i ] = validNode[ i ]; + UIUtils.CheckUndoNode( selectedNodes[ i ] ); + } + } + + //Check nodes connected to deleted nodes to preserve connections on undo + List extraNodes = new List(); + for( int selectedNodeIdx = 0; selectedNodeIdx < selectedNodes.Length; selectedNodeIdx++ ) + { + // Check inputs + if( selectedNodes[ selectedNodeIdx ] != null ) + { + int inputIdxCount = selectedNodes[ selectedNodeIdx ].InputPorts.Count; + if( inputIdxCount > 0 ) + { + for( int inputIdx = 0; inputIdx < inputIdxCount; inputIdx++ ) + { + if( selectedNodes[ selectedNodeIdx ].InputPorts[ inputIdx ].IsConnected ) + { + int nodeIdx = selectedNodes[ selectedNodeIdx ].InputPorts[ inputIdx ].ExternalReferences[ 0 ].NodeId; + if( nodeIdx > -1 ) + { + ParentNode node = GetNode( nodeIdx ); + if( node != null && UIUtils.CheckUndoNode( node ) ) + { + extraNodes.Add( node ); + } + } + } + } + } + } + + // Check outputs + if( selectedNodes[ selectedNodeIdx ] != null ) + { + int outputIdxCount = selectedNodes[ selectedNodeIdx ].OutputPorts.Count; + if( outputIdxCount > 0 ) + { + for( int outputIdx = 0; outputIdx < outputIdxCount; outputIdx++ ) + { + int inputIdxCount = selectedNodes[ selectedNodeIdx ].OutputPorts[ outputIdx ].ExternalReferences.Count; + if( inputIdxCount > 0 ) + { + for( int inputIdx = 0; inputIdx < inputIdxCount; inputIdx++ ) + { + int nodeIdx = selectedNodes[ selectedNodeIdx ].OutputPorts[ outputIdx ].ExternalReferences[ inputIdx ].NodeId; + if( nodeIdx > -1 ) + { + ParentNode node = GetNode( nodeIdx ); + if( UIUtils.CheckUndoNode( node ) ) + { + extraNodes.Add( node ); + } + } + } + } + } + } + + } + } + + UIUtils.ClearUndoHelper(); + //Record deleted nodes + UIUtils.MarkUndoAction(); + Undo.RegisterCompleteObjectUndo( ParentWindow, Constants.UndoDeleteNodeId ); + Undo.RegisterCompleteObjectUndo( this, Constants.UndoDeleteNodeId ); + Undo.RecordObjects( selectedNodes, Constants.UndoDeleteNodeId ); + Undo.RecordObjects( extraNodes.ToArray(), Constants.UndoDeleteNodeId ); + + //Record deleting connections + for( int i = 0; i < selectedNodes.Length; i++ ) + { + CurrentOutputNode.Selected = false; + selectedNodes[ i ].Alive = false; + DeleteAllConnectionFromNode( selectedNodes[ i ], false, true, true ); + } + //Delete + DeleteNodesOnArray( ref selectedNodes ); + + extraNodes.Clear(); + extraNodes = null; + + EditorUtility.SetDirty( ParentWindow ); + + ParentWindow.ForceRepaint(); + } + + public void DeleteMarkedForDeletionNodes() + { + UndoableDeleteSelectedNodes( m_markedForDeletion ); + m_markedForDeletion.Clear(); + IsDirty = true; + + //bool invalidateMasterNode = false; + //int count = m_markedForDeletion.Count; + //for ( int nodeIdx = 0; nodeIdx < count; nodeIdx++ ) + //{ + // ParentNode node = m_markedForDeletion[ nodeIdx ]; + // if ( node.UniqueId == m_masterNodeId ) + // { + // invalidateMasterNode = true; + // } + // else + // { + // if ( node.Selected ) + // { + // m_selectedNodes.Remove( node ); + // node.Selected = false; + // } + // DestroyNode( node ); + // } + //} + + //if ( invalidateMasterNode ) + //{ + // CurrentMasterNode.Selected = false; + //} + ////Clear all references + //m_markedForDeletion.Clear(); + //IsDirty = true; + } + + public void DestroyNode( int nodeId ) + { + ParentNode node = GetNode( nodeId ); + DestroyNode( node ); + } + + public void DestroyNode( ParentNode node, bool registerUndo = true, bool destroyMasterNode = false ) + { + if( node == null ) + { + UIUtils.ShowMessage( "Attempting to destroying a inexistant node ", MessageSeverity.Warning ); + return; + } + + if( node.ConnStatus == NodeConnectionStatus.Connected && !m_checkSelectedWireHighlights ) + { + ResetHighlightedWires(); + m_checkSelectedWireHighlights = true; + } + + //TODO: check better placement of this code (reconnects wires from wire nodes) + //if ( node.GetType() == typeof( WireNode ) ) + //{ + // if ( node.InputPorts[ 0 ].ExternalReferences != null && node.InputPorts[ 0 ].ExternalReferences.Count > 0 ) + // { + // WireReference backPort = node.InputPorts[ 0 ].ExternalReferences[ 0 ]; + // for ( int i = 0; i < node.OutputPorts[ 0 ].ExternalReferences.Count; i++ ) + // { + // UIUtils.CurrentWindow.ConnectInputToOutput( node.OutputPorts[ 0 ].ExternalReferences[ i ].NodeId, node.OutputPorts[ 0 ].ExternalReferences[ i ].PortId, backPort.NodeId, backPort.PortId ); + // } + // } + //} + if( destroyMasterNode || ( node.UniqueId != m_masterNodeId && !( node is TemplateMultiPassMasterNode )/*!m_multiPassMasterNodes.HasNode( node.UniqueId )*/ ) ) + { + m_nodeGrid.RemoveNodeFromGrid( node, false ); + //Send Deactivation signal if active + if( node.ConnStatus == NodeConnectionStatus.Connected ) + { + node.DeactivateNode( -1, true ); + } + + //Invalidate references + //Invalidate input references + for( int inputPortIdx = 0; inputPortIdx < node.InputPorts.Count; inputPortIdx++ ) + { + InputPort inputPort = node.InputPorts[ inputPortIdx ]; + if( inputPort.IsConnected ) + { + for( int wireIdx = 0; wireIdx < inputPort.ExternalReferences.Count; wireIdx++ ) + { + WireReference inputReference = inputPort.ExternalReferences[ wireIdx ]; + ParentNode outputNode = GetNode( inputReference.NodeId ); + outputNode.GetOutputPortByUniqueId( inputReference.PortId ).InvalidateConnection( inputPort.NodeId, inputPort.PortId ); + outputNode.OnOutputPortDisconnected( inputReference.PortId ); + } + inputPort.InvalidateAllConnections(); + } + } + + //Invalidate output reference + for( int outputPortIdx = 0; outputPortIdx < node.OutputPorts.Count; outputPortIdx++ ) + { + OutputPort outputPort = node.OutputPorts[ outputPortIdx ]; + if( outputPort.IsConnected ) + { + for( int wireIdx = 0; wireIdx < outputPort.ExternalReferences.Count; wireIdx++ ) + { + WireReference outputReference = outputPort.ExternalReferences[ wireIdx ]; + ParentNode outnode = GetNode( outputReference.NodeId ); + if( outnode != null ) + { + outnode.GetInputPortByUniqueId( outputReference.PortId ).InvalidateConnection( outputPort.NodeId, outputPort.PortId ); + outnode.OnInputPortDisconnected( outputReference.PortId ); + } + } + outputPort.InvalidateAllConnections(); + } + } + + //Remove node from main list + //Undo.RecordObject( node, "Destroying node " + ( node.Attributes != null? node.Attributes.Name: node.GetType().ToString() ) ); + if( registerUndo ) + { + UIUtils.MarkUndoAction(); + Undo.RegisterCompleteObjectUndo( ParentWindow, Constants.UndoDeleteNodeId ); + Undo.RegisterCompleteObjectUndo( this, Constants.UndoDeleteNodeId ); + node.RecordObjectOnDestroy( Constants.UndoDeleteNodeId ); + } + + if( OnNodeRemovedEvent != null ) + OnNodeRemovedEvent( node ); + + m_nodes.Remove( node ); + m_nodesDict.Remove( node.UniqueId ); + node.Destroy(); + if( registerUndo ) + Undo.DestroyObjectImmediate( node ); + else + DestroyImmediate( node ); + IsDirty = true; + m_markToReOrder = true; + } + //else if( node.UniqueId == m_masterNodeId && node.GetType() == typeof(FunctionOutput) ) + //{ + // Debug.Log( "Attempting to destroy a output node" ); + // DeselectNode( node ); + // UIUtils.ShowMessage( "Attempting to destroy a output node" ); + //} + else + { + TemplateMultiPassMasterNode templateMasterNode = node as TemplateMultiPassMasterNode; + if( templateMasterNode != null && templateMasterNode.InvalidNode ) + { + DestroyNode( node, false, true ); + return; + } + + DeselectNode( node ); + UIUtils.ShowMessage( "Attempting to destroy a master node" ); + } + } + + void AddToSelectedNodes( ParentNode node ) + { + node.Selected = true; + m_selectedNodes.Add( node ); + node.OnNodeStoppedMovingEvent += OnNodeFinishMoving; + if( node.ConnStatus == NodeConnectionStatus.Connected ) + { + HighlightWiresStartingNode( node ); + } + } + + void RemoveFromSelectedNodes( ParentNode node ) + { + node.Selected = false; + m_selectedNodes.Remove( node ); + node.OnNodeStoppedMovingEvent -= OnNodeFinishMoving; + } + + public void SelectNode( ParentNode node, bool append, bool reorder ) + { + if( node == null ) + return; + + if( append ) + { + if( !m_selectedNodes.Contains( node ) ) + { + AddToSelectedNodes( node ); + } + } + else + { + DeSelectAll(); + AddToSelectedNodes( node ); + } + if( reorder && !node.ReorderLocked ) + { + m_nodes.Remove( node ); + m_nodes.Add( node ); + m_markToReOrder = true; + } + } + + public void MultipleSelection( Rect selectionArea, bool appendSelection = true ) + { + if( !appendSelection ) + { + for( int i = 0; i < m_nodes.Count; i++ ) + { + if( selectionArea.Overlaps( m_nodes[ i ].Position, true ) ) + { + RemoveFromSelectedNodes( m_nodes[ i ] ); + } + } + + m_markedToDeSelect = false; + ResetHighlightedWires(); + } + else + { + for( int i = 0; i < m_nodes.Count; i++ ) + { + if( !m_nodes[ i ].Selected && selectionArea.Overlaps( m_nodes[ i ].Position, true ) ) + { + AddToSelectedNodes( m_nodes[ i ] ); + } + } + } + + // reorder nodes and highlight them + for( int i = 0; i < m_selectedNodes.Count; i++ ) + { + if( !m_selectedNodes[ i ].ReorderLocked ) + { + m_nodes.Remove( m_selectedNodes[ i ] ); + m_nodes.Add( m_selectedNodes[ i ] ); + m_markToReOrder = true; + if( m_selectedNodes[ i ].ConnStatus == NodeConnectionStatus.Connected ) + { + HighlightWiresStartingNode( m_selectedNodes[ i ] ); + } + } + } + } + + public void SelectAll() + { + for( int i = 0; i < m_nodes.Count; i++ ) + { + if( !m_nodes[ i ].Selected ) + AddToSelectedNodes( m_nodes[ i ] ); + } + } + + public void SelectMasterNode() + { + if( m_masterNodeId != Constants.INVALID_NODE_ID ) + { + SelectNode( CurrentMasterNode, false, false ); + } + } + + public void SelectOutputNode() + { + if( m_masterNodeId != Constants.INVALID_NODE_ID ) + { + SelectNode( CurrentOutputNode, false, false ); + } + } + + public void DeselectNode( int nodeId ) + { + ParentNode node = GetNode( nodeId ); + if( node ) + { + m_selectedNodes.Remove( node ); + node.Selected = false; + } + } + + public void DeselectNode( ParentNode node ) + { + m_selectedNodes.Remove( node ); + node.Selected = false; + PropagateHighlightDeselection( node ); + } + + + + public void DeSelectAll() + { + m_markedToDeSelect = false; + for( int i = 0; i < m_selectedNodes.Count; i++ ) + { + m_selectedNodes[ i ].Selected = false; + m_selectedNodes[ i ].OnNodeStoppedMovingEvent -= OnNodeFinishMoving; + } + m_selectedNodes.Clear(); + ResetHighlightedWires(); + } + + public void AssignMasterNode() + { + if( m_selectedNodes.Count == 1 ) + { + OutputNode newOutputNode = m_selectedNodes[ 0 ] as OutputNode; + MasterNode newMasterNode = newOutputNode as MasterNode; + if( newOutputNode != null ) + { + if( m_masterNodeId != Constants.INVALID_NODE_ID && m_masterNodeId != newOutputNode.UniqueId ) + { + OutputNode oldOutputNode = GetNode( m_masterNodeId ) as OutputNode; + MasterNode oldMasterNode = oldOutputNode as MasterNode; + if( oldOutputNode != null ) + { + oldOutputNode.IsMainOutputNode = false; + if( oldMasterNode != null ) + { + oldMasterNode.ClearUpdateEvents(); + } + } + } + m_masterNodeId = newOutputNode.UniqueId; + newOutputNode.IsMainOutputNode = true; + if( newMasterNode != null ) + { + newMasterNode.OnMaterialUpdatedEvent += OnMaterialUpdatedEvent; + newMasterNode.OnShaderUpdatedEvent += OnShaderUpdatedEvent; + } + } + } + + IsDirty = true; + } + + public void AssignMasterNode( OutputNode node, bool onlyUpdateGraphId ) + { + AssignMasterNode( node.UniqueId, onlyUpdateGraphId ); + MasterNode masterNode = node as MasterNode; + if( masterNode != null ) + { + masterNode.OnMaterialUpdatedEvent += OnMaterialUpdatedEvent; + masterNode.OnShaderUpdatedEvent += OnShaderUpdatedEvent; + } + } + + public void AssignMasterNode( int nodeId, bool onlyUpdateGraphId ) + { + if( nodeId < 0 || m_masterNodeId == nodeId ) + return; + + if( m_masterNodeId > Constants.INVALID_NODE_ID ) + { + OutputNode oldOutputNode = ( GetNode( nodeId ) as OutputNode ); + MasterNode oldMasterNode = oldOutputNode as MasterNode; + if( oldOutputNode != null ) + { + oldOutputNode.IsMainOutputNode = false; + if( oldMasterNode != null ) + { + oldMasterNode.ClearUpdateEvents(); + } + } + } + + if( onlyUpdateGraphId ) + { + m_masterNodeId = nodeId; + } + else + { + OutputNode outputNode = ( GetNode( nodeId ) as OutputNode ); + if( outputNode != null ) + { + outputNode.IsMainOutputNode = true; + m_masterNodeId = nodeId; + } + } + + IsDirty = true; + } + + public void RefreshOnUndo() + { + if( m_nodes != null ) + { + int count = m_nodes.Count; + for( int i = 0; i < count; i++ ) + { + if( m_nodes[ i ] != null ) + { + m_nodes[ i ].RefreshOnUndo(); + } + } + } + } + + public void DrawGrid( DrawInfo drawInfo ) + { + m_nodeGrid.DrawGrid( drawInfo ); + } + + public float MaxNodeDist + { + get { return m_nodeGrid.MaxNodeDist; } + } + + public List GetNodesInGrid( Vector2 transformedMousePos ) + { + return m_nodeGrid.GetNodesOn( transformedMousePos ); + } + + public void FireMasterNode( Shader selectedShader ) + { + ( GetNode( m_masterNodeId ) as MasterNode ).Execute( selectedShader ); + } + + public Shader FireMasterNode( string pathname, bool isFullPath ) + { + return ( GetNode( m_masterNodeId ) as MasterNode ).Execute( pathname, isFullPath ); + } + + private void ForceSignalPropagationOnMasterNodeInternal( UsageListTemplateMultiPassMasterNodes masterNodes ) + { + int mpCount = masterNodes.Count; + for( int i = 0; i < mpCount; i++ ) + { + masterNodes.NodesList[ i ].GenerateSignalPropagation(); + } + } + + public void ForceSignalPropagationOnMasterNode() + { + if( m_multiPassMasterNodes.Count > 0 ) + { + ForceSignalPropagationOnMasterNodeInternal( m_multiPassMasterNodes ); + for( int i = 0; i < m_lodMultiPassMasterNodes.Count; i++ ) + { + ForceSignalPropagationOnMasterNodeInternal( m_lodMultiPassMasterNodes[ i ] ); + } + } + else if( CurrentOutputNode != null ) + CurrentOutputNode.GenerateSignalPropagation(); + + List allOutputs = m_functionOutputNodes.NodesList; + for( int i = 0; i < allOutputs.Count; i++ ) + { + allOutputs[ i ].GenerateSignalPropagation(); + } + + //List localVarNodes = m_localVarNodes.NodesList; + //int count = localVarNodes.Count; + //for( int i = 0; i < count; i++ ) + //{ + // localVarNodes[ i ].GenerateSignalPropagation(); + //} + } + + public void UpdateShaderOnMasterNode( Shader newShader ) + { + MasterNode mainMasterNode = ( GetNode( m_masterNodeId ) as MasterNode ); + if( mainMasterNode == null ) + { + Debug.LogError( "No Master Node was detected. Aborting update!" ); + return; + } + mainMasterNode.UpdateFromShader( newShader ); + + if( HasLODs ) + { + int passIdx = ( (TemplateMultiPassMasterNode)mainMasterNode ).PassIdx; + for( int i = 0; i < m_lodMultiPassMasterNodes.Count; i++ ) + { + if( m_lodMultiPassMasterNodes.Count != 0 && m_lodMultiPassMasterNodes[ i ].NodesList.Count > 0 ) + { + if( m_lodMultiPassMasterNodes[ i ].NodesList[ passIdx ] != null ) + { + m_lodMultiPassMasterNodes[ i ].NodesList[ passIdx ].UpdateFromShader( newShader ); + } + else + { + Debug.LogError( "Null master node detected. Aborting update!" ); + return; + } + } + else break; + } + } + } + + public void CopyValuesFromMaterial( Material material ) + { + Material currMaterial = CurrentMaterial; + if( currMaterial == material ) + { + for( int i = 0; i < m_nodes.Count; i++ ) + { + m_nodes[ i ].ForceUpdateFromMaterial( material ); + } + } + } + + public void UpdateMaterialOnMasterNode( Material material ) + { + MasterNode mainMasterNode = ( GetNode( m_masterNodeId ) as MasterNode ); + mainMasterNode.UpdateMasterNodeMaterial( material ); + if( HasLODs ) + { + int passIdx = ( (TemplateMultiPassMasterNode)mainMasterNode ).PassIdx; + for( int i = 0; i < m_lodMultiPassMasterNodes.Count; i++ ) + { + if( m_lodMultiPassMasterNodes.Count != 0 && m_lodMultiPassMasterNodes[ i ].NodesList.Count > 0 ) + { + m_lodMultiPassMasterNodes[ i ].NodesList[ passIdx ].UpdateMasterNodeMaterial( material ); + } + else break; + } + } + } + + public void UpdateMaterialOnPropertyNodes( Material material ) + { + int propertyCount = m_propertyNodes.Count; + for(int i = 0;i< propertyCount;i++ ) + { + m_propertyNodes.NodesList[i].UpdateMaterial( material ); + } + } + + public void SetMaterialModeOnGraph( Material mat, bool fetchMaterialValues = true ) + { + for( int i = 0; i < m_nodes.Count; i++ ) + { + m_nodes[ i ].SetMaterialMode( mat, fetchMaterialValues ); + } + } + + public ParentNode CheckNodeAt( Vector3 pos, bool checkForRMBIgnore = false ) + { + ParentNode selectedNode = null; + + // this is checked on the inverse order to give priority to nodes that are drawn on top ( last on the list ) + for( int i = m_nodes.Count - 1; i > -1; i-- ) + { + if( m_nodes[ i ].Contains( pos ) ) + { + if( checkForRMBIgnore ) + { + if( !m_nodes[ i ].RMBIgnore ) + { + selectedNode = m_nodes[ i ]; + break; + } + } + else + { + selectedNode = m_nodes[ i ]; + break; + } + } + } + return selectedNode; + } + + public void ResetNodesLocalVariables() + { + for( int i = 0; i < m_nodes.Count; i++ ) + { + m_nodes[ i ].Reset(); + m_nodes[ i ].ResetOutputLocals(); + + FunctionNode fnode = m_nodes[ i ] as FunctionNode; + if( fnode != null ) + { + if( fnode.Function != null ) + fnode.FunctionGraph.ResetNodesLocalVariables(); + } + } + } + + public void ResetNodesLocalVariablesIfNot( MasterNodePortCategory category ) + { + for( int i = 0; i < m_nodes.Count; i++ ) + { + m_nodes[ i ].Reset(); + m_nodes[ i ].ResetOutputLocalsIfNot( category ); + + FunctionNode fnode = m_nodes[ i ] as FunctionNode; + if( fnode != null ) + { + if( fnode.Function != null ) + fnode.FunctionGraph.ResetNodesLocalVariablesIfNot( category ); + } + } + } + + public void ResetNodesLocalVariables( ParentNode node ) + { + if( node is GetLocalVarNode ) + { + GetLocalVarNode localVarNode = node as GetLocalVarNode; + if( localVarNode.CurrentSelected != null ) + { + node = localVarNode.CurrentSelected; + } + } + + node.Reset(); + node.ResetOutputLocals(); + int count = node.InputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( node.InputPorts[ i ].IsConnected ) + { + ResetNodesLocalVariables( m_nodesDict[ node.InputPorts[ i ].GetConnection().NodeId ] ); + } + } + } + + public void ResetNodesLocalVariablesIfNot( ParentNode node, MasterNodePortCategory category ) + { + if( node is GetLocalVarNode ) + { + GetLocalVarNode localVarNode = node as GetLocalVarNode; + if( localVarNode.CurrentSelected != null ) + { + node = localVarNode.CurrentSelected; + } + } + + node.Reset(); + node.ResetOutputLocalsIfNot( category ); + int count = node.InputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( node.InputPorts[ i ].IsConnected ) + { + ResetNodesLocalVariablesIfNot( m_nodesDict[ node.InputPorts[ i ].GetConnection().NodeId ], category ); + } + } + } + + + public override string ToString() + { + string dump = ( "Parent Graph \n" ); + for( int i = 0; i < m_nodes.Count; i++ ) + { + dump += ( m_nodes[ i ] + "\n" ); + } + return dump; + } + + public void OrderNodesByGraphDepth() + { + if( CurrentMasterNode != null ) + { + //CurrentMasterNode.SetupNodeCategories(); + int count = m_nodes.Count; + for( int i = 0; i < count; i++ ) + { + if( m_nodes[ i ].ConnStatus == NodeConnectionStatus.Island ) + { + m_nodes[ i ].CalculateCustomGraphDepth(); + } + } + } + else + { + //TODO: remove this dynamic list + List allOutputs = new List(); + for( int i = 0; i < AllNodes.Count; i++ ) + { + OutputNode temp = AllNodes[ i ] as OutputNode; + if( temp != null ) + allOutputs.Add( temp ); + } + + for( int j = 0; j < allOutputs.Count; j++ ) + { + allOutputs[ j ].SetupNodeCategories(); + int count = m_nodes.Count; + for( int i = 0; i < count; i++ ) + { + if( m_nodes[ i ].ConnStatus == NodeConnectionStatus.Island ) + { + m_nodes[ i ].CalculateCustomGraphDepth(); + } + } + } + } + + m_nodes.Sort( ( x, y ) => { return y.GraphDepth.CompareTo( x.GraphDepth ); } ); + } + + public void WriteToString( ref string nodesInfo, ref string connectionsInfo ) + { + for( int i = 0; i < m_nodes.Count; i++ ) + { + m_nodes[ i ].FullWriteToString( ref nodesInfo, ref connectionsInfo ); + IOUtils.AddLineTerminator( ref nodesInfo ); + } + } + + public void Reset() + { + SaveIsDirty = false; + IsDirty = false; + } + + public void OnBeforeSerialize() + { + //DeSelectAll(); + } + + public void OnAfterDeserialize() + { + m_afterDeserializeFlag = true; + } + + public void CleanCorruptedNodes() + { + for( int i = 0; i < m_nodes.Count; i++ ) + { + if( (object)m_nodes[ i ] == null ) + { + m_nodes.RemoveAt( i ); + CleanCorruptedNodes(); + } + } + } + + public void OnDuplicateEventWrapper() + { + if( OnDuplicateEvent != null ) + { + AmplifyShaderEditorWindow temp = UIUtils.CurrentWindow; + UIUtils.CurrentWindow = ParentWindow; + OnDuplicateEvent(); + UIUtils.CurrentWindow = temp; + } + } + + public ParentNode CreateNode( AmplifyShaderFunction shaderFunction, bool registerUndo, int nodeId = -1, bool addLast = true ) + { + FunctionNode newNode = ScriptableObject.CreateInstance(); + if( newNode ) + { + newNode.ContainerGraph = this; + newNode.CommonInit( shaderFunction, nodeId ); + newNode.UniqueId = nodeId; + AddNode( newNode, nodeId < 0, addLast, registerUndo ); + } + return newNode; + } + + public ParentNode CreateNode( AmplifyShaderFunction shaderFunction, bool registerUndo, Vector2 pos, int nodeId = -1, bool addLast = true ) + { + ParentNode newNode = CreateNode( shaderFunction, registerUndo, nodeId, addLast ); + if( newNode ) + { + newNode.Vec2Position = pos; + } + return newNode; + } + + public TemplateMultiPassMasterNode CreateMultipassMasterNode( int lodId, bool registerUndo, int nodeId = -1, bool addLast = true ) + { + TemplateMultiPassMasterNode newNode = ScriptableObject.CreateInstance(); + if( newNode ) + { + newNode.LODIndex = lodId; + newNode.ContainerGraph = this; + if( newNode.IsStubNode ) + { + TemplateMultiPassMasterNode stubNode = newNode.ExecuteStubCode() as TemplateMultiPassMasterNode; + ScriptableObject.DestroyImmediate( newNode, true ); + newNode = stubNode; + } + else + { + newNode.UniqueId = nodeId; + AddNode( newNode, nodeId < 0, addLast, registerUndo ); + } + } + return newNode; + } + + public ParentNode CreateNode( System.Type type, bool registerUndo, int nodeId = -1, bool addLast = true ) + { + ParentNode newNode = ScriptableObject.CreateInstance( type ) as ParentNode; + if( newNode ) + { + newNode.ContainerGraph = this; + if( newNode.IsStubNode ) + { + ParentNode stubNode = newNode.ExecuteStubCode(); + ScriptableObject.DestroyImmediate( newNode, true ); + newNode = stubNode; + } + else + { + newNode.UniqueId = nodeId; + AddNode( newNode, nodeId < 0, addLast, registerUndo ); + } + } + return newNode; + } + + public ParentNode CreateNode( System.Type type, bool registerUndo, Vector2 pos, int nodeId = -1, bool addLast = true ) + { + ParentNode newNode = CreateNode( type, registerUndo, nodeId, addLast ); + if( newNode ) + { + newNode.Vec2Position = pos; + } + return newNode; + } + + public void FireMasterNodeReplacedEvent() + { + MasterNode masterNode = CurrentMasterNode; + int count = m_nodes.Count; + for( int i = 0; i < count; i++ ) + { + if( m_nodes[ i ].UniqueId != m_masterNodeId ) + { + m_nodes[ i ].OnMasterNodeReplaced( masterNode ); + } + } + } + + //Used over shader functions to propagate signal into their graphs + public void FireMasterNodeReplacedEvent( MasterNode masterNode ) + { + int count = m_nodes.Count; + for( int i = 0; i < count; i++ ) + { + if( m_nodes[ i ].UniqueId != masterNode.UniqueId ) + { + m_nodes[ i ].OnMasterNodeReplaced( masterNode ); + } + } + } + + + public void CrossCheckTemplateNodes( TemplateDataParent templateData , List mpNodesList , int lodId ) + { + /*Paulo*/ + DeSelectAll(); + TemplateMultiPassMasterNode newMasterNode = null; + Dictionary nodesDict = new Dictionary(); + int mpNodeCount = mpNodesList.Count; + for( int i = 0; i < mpNodeCount; i++ ) + { + string masterNodeId = mpNodesList[ i ].InvalidNode ? mpNodesList[ i ].OriginalPassName + "ASEInvalidMasterNode" + i : mpNodesList[ i ].OriginalPassName; + nodesDict.Add( masterNodeId, new TemplateReplaceHelper( mpNodesList[ i ] ) ); + } + + TemplateMultiPassMasterNode currMasterNode = GetNode( m_masterNodeId ) as TemplateMultiPassMasterNode; + + TemplateMultiPass multipassData = templateData as TemplateMultiPass; + m_currentSRPType = multipassData.SubShaders[ 0 ].Modules.SRPType; + + bool sortTemplatesNodes = false; + Vector2 currentPosition = currMasterNode.Vec2Position; + for( int subShaderIdx = 0; subShaderIdx < multipassData.SubShaders.Count; subShaderIdx++ ) + { + for( int passIdx = 0; passIdx < multipassData.SubShaders[ subShaderIdx ].Passes.Count; passIdx++ ) + { + string currPassName = multipassData.SubShaders[ subShaderIdx ].Passes[ passIdx ].PassNameContainer.Data; + if( nodesDict.ContainsKey( currPassName ) ) + { + bool wasMainNode = nodesDict[ currPassName ].MasterNode.IsMainOutputNode; + + currentPosition.y += nodesDict[ currPassName ].MasterNode.Position.height + 10; + nodesDict[ currPassName ].Used = true; + nodesDict[ currPassName ].MasterNode.SetTemplate( multipassData, false, false, subShaderIdx, passIdx, SetTemplateSource.NewShader ); + if( wasMainNode && !nodesDict[ currPassName ].MasterNode.IsMainOutputNode ) + { + nodesDict[ currPassName ].MasterNode.ReleaseResources(); + } + else if( !wasMainNode && nodesDict[ currPassName ].MasterNode.IsMainOutputNode ) + { + newMasterNode = nodesDict[ currPassName ].MasterNode; + } + } + else + { + sortTemplatesNodes = true; + TemplateMultiPassMasterNode masterNode = CreateMultipassMasterNode( lodId, false ); + if( multipassData.SubShaders[ subShaderIdx ].Passes[ passIdx ].IsMainPass ) + { + newMasterNode = masterNode; + currMasterNode.ReleaseResources(); + } + masterNode.Vec2Position = currentPosition; + masterNode.SetTemplate( multipassData, true, true, subShaderIdx, passIdx, SetTemplateSource.NewShader ); + //currentPosition.y += masterNode.HeightEstimate + 10; + } + } + } + + foreach( KeyValuePair kvp in nodesDict ) + { + if( !kvp.Value.Used ) + DestroyNode( kvp.Value.MasterNode, false, true ); + } + nodesDict.Clear(); + + if( newMasterNode != null ) + { + if( lodId == -1 ) + { + m_masterNodeId = newMasterNode.UniqueId; + } + newMasterNode.OnMaterialUpdatedEvent += OnMaterialUpdatedEvent; + newMasterNode.OnShaderUpdatedEvent += OnShaderUpdatedEvent; + newMasterNode.IsMainOutputNode = true; + } + + if( sortTemplatesNodes ) + { + mpNodesList.Sort( ( x, y ) => ( x.PassIdx.CompareTo( y.PassIdx ) ) ); + } + } + + public void OnRefreshLinkedPortsComplete() + { + OnRefreshLinkedPortsCompleteInternal( m_multiPassMasterNodes ); + for( int i = 0; i < m_lodMultiPassMasterNodes.Count; i++ ) + { + OnRefreshLinkedPortsCompleteInternal( m_lodMultiPassMasterNodes[ i ] ); + } + } + + private void OnRefreshLinkedPortsCompleteInternal( UsageListTemplateMultiPassMasterNodes masterNodes ) + { + int mpCount = masterNodes.Count; + for( int i = 0; i < mpCount; i++ ) + { + masterNodes.NodesList[ i ].OnRefreshLinkedPortsComplete(); + } + } + + public void RefreshLinkedMasterNodes( bool optionsUpdate = false ) + { + if( DebugConsoleWindow.DeveloperMode ) + Debug.Log( "Refresh linked master nodes" ); + + RefreshLinkedMasterNodesInternal( m_multiPassMasterNodes, optionsUpdate ); + for( int i = 0; i < m_lodMultiPassMasterNodes.Count; i++ ) + { + RefreshLinkedMasterNodesInternal( m_lodMultiPassMasterNodes[i], optionsUpdate ); + } + } + + private void RefreshLinkedMasterNodesInternal( UsageListTemplateMultiPassMasterNodes masterNodes, bool optionsUpdate ) + { + int mpCount = masterNodes.Count; + if( mpCount > 1 ) + { + Dictionary> registeredLinks = new Dictionary>(); + for( int i = 0; i < mpCount; i++ ) + { + CheckLinkedPorts( ref registeredLinks, masterNodes.NodesList[ mpCount - 1 - i ] ); + } + + foreach( KeyValuePair> kvp in registeredLinks ) + { + int linkCount = kvp.Value.Count; + if( linkCount == 1 ) + { + kvp.Value[ 0 ].Visible = true; + } + else + { + kvp.Value[ 0 ].Visible = true; + for( int i = 1; i < linkCount; i++ ) + { + kvp.Value[ i ].SetExternalLink( kvp.Value[ 0 ].NodeId, kvp.Value[ 0 ].PortId ); + kvp.Value[ i ].Visible = false; + } + } + kvp.Value.Clear(); + } + registeredLinks.Clear(); + registeredLinks = null; + } + + masterNodes.NodesList.Sort( ( x, y ) => ( x.SubShaderIdx * 1000 + x.PassIdx ).CompareTo( y.SubShaderIdx * 1000 + y.PassIdx ) ); + masterNodes.UpdateNodeArr(); + + m_parentWindow.TemplatesManagerInstance.ResetOptionsSetupData(); + for( int i = 0; i < mpCount; i++ ) + { + int visiblePorts = 0; + for( int j = 0; j < masterNodes.NodesList[ i ].InputPorts.Count; j++ ) + { + if( masterNodes.NodesList[ i ].InputPorts[ j ].Visible ) + { + visiblePorts++; + } + } + + if( masterNodes.NodesList[ i ].VisiblePorts != visiblePorts ) + { + masterNodes.NodesList[ i ].VisiblePorts = visiblePorts; + ForceRepositionCheck = true; + } + + masterNodes.NodesList[ i ].Docking = visiblePorts <= 0; + if( optionsUpdate ) + { + masterNodes.NodesList[ i ].ForceOptionsRefresh(); + } + } + } + + void CheckLinkedPorts( ref Dictionary> registeredLinks, TemplateMultiPassMasterNode masterNode ) + { + if( masterNode.HasLinkPorts ) + { + int inputCount = masterNode.InputPorts.Count; + for( int i = 0; i < inputCount; i++ ) + { + if( !string.IsNullOrEmpty( masterNode.InputPorts[ i ].ExternalLinkId ) ) + { + string linkId = masterNode.InputPorts[ i ].ExternalLinkId; + if( !registeredLinks.ContainsKey( masterNode.InputPorts[ i ].ExternalLinkId ) ) + { + registeredLinks.Add( linkId, new List() ); + } + + if( masterNode.IsMainOutputNode ) + { + registeredLinks[ linkId ].Insert( 0, masterNode.InputPorts[ i ] ); + } + else + { + registeredLinks[ linkId ].Add( masterNode.InputPorts[ i ] ); + } + } + else + { + masterNode.InputPorts[ i ].Visible = true; + } + } + } + else + { + int inputCount = masterNode.InputPorts.Count; + for( int i = 0; i < inputCount; i++ ) + { + masterNode.InputPorts[ i ].Visible = true; + } + } + + } + + public MasterNode ReplaceMasterNode( AvailableShaderTypes newType, bool writeDefaultData = false, TemplateDataParent templateData = null ) + { + DeSelectAll(); + ResetNodeConnStatus(); + MasterNode newMasterNode = null; + List nodesToDelete = null; + int mpNodeCount = m_multiPassMasterNodes.NodesList.Count; + if( mpNodeCount > 0 ) + { + nodesToDelete = new List(); + for( int i = 0; i < mpNodeCount; i++ ) + { + if( m_multiPassMasterNodes.NodesList[ i ].UniqueId != m_masterNodeId ) + { + nodesToDelete.Add( m_multiPassMasterNodes.NodesList[ i ] ); + } + } + + for( int lod = 0; lod < m_lodMultiPassMasterNodes.Count; lod++ ) + { + int lodNodeCount = m_lodMultiPassMasterNodes[ lod ].Count; + for( int i = 0; i < lodNodeCount; i++ ) + { + nodesToDelete.Add( m_lodMultiPassMasterNodes[ lod ].NodesList[ i ] ); + } + } + } + + MasterNode currMasterNode = GetNode( m_masterNodeId ) as MasterNode; + if( currMasterNode != null ) + { + currMasterNode.ReleaseResources(); + } + + bool refreshLinkedMasterNodes = false; + switch( newType ) + { + default: + case AvailableShaderTypes.SurfaceShader: + { + CurrentCanvasMode = NodeAvailability.SurfaceShader; + m_currentSRPType = TemplateSRPType.BuiltIn; + newMasterNode = CreateNode( typeof( StandardSurfaceOutputNode ), false ) as MasterNode; + } + break; + case AvailableShaderTypes.Template: + { + CurrentCanvasMode = NodeAvailability.TemplateShader; + if( templateData.TemplateType == TemplateDataType.LegacySinglePass ) + { + newMasterNode = CreateNode( typeof( TemplateMasterNode ), false ) as MasterNode; + ( newMasterNode as TemplateMasterNode ).SetTemplate( templateData as TemplateData, writeDefaultData, false ); + m_currentSRPType = TemplateSRPType.BuiltIn; + } + else + { + /*Paulo*/ + TemplateMultiPass multipassData = templateData as TemplateMultiPass; + m_currentSRPType = multipassData.SubShaders[ 0 ].Modules.SRPType; + + Vector2 currentPosition = currMasterNode.Vec2Position; + + for( int subShaderIdx = 0; subShaderIdx < multipassData.SubShaders.Count; subShaderIdx++ ) + { + for( int passIdx = 0; passIdx < multipassData.SubShaders[ subShaderIdx ].Passes.Count; passIdx++ ) + { + TemplateMultiPassMasterNode masterNode = CreateNode( typeof( TemplateMultiPassMasterNode ), false ) as TemplateMultiPassMasterNode; + if( multipassData.SubShaders[ subShaderIdx ].Passes[ passIdx ].IsMainPass ) + { + newMasterNode = masterNode; + ParentWindow.IsShaderFunctionWindow = false; + CurrentCanvasMode = NodeAvailability.TemplateShader; + } + masterNode.Vec2Position = currentPosition; + masterNode.SetTemplate( multipassData, true, true, subShaderIdx, passIdx, SetTemplateSource.NewShader ); + //currentPosition.y += masterNode.HeightEstimate + 10; + } + } + refreshLinkedMasterNodes = true; + //RefreshLinkedMasterNodes(); + } + } + break; + } + + if( currMasterNode != null ) + { + newMasterNode.CopyFrom( currMasterNode ); + m_masterNodeId = -1; + DestroyNode( currMasterNode, false, true ); + } + + if( nodesToDelete != null ) + { + for( int i = 0; i < nodesToDelete.Count; i++ ) + { + DestroyNode( nodesToDelete[ i ], false, true ); + } + nodesToDelete.Clear(); + } + + m_masterNodeId = newMasterNode.UniqueId; + + if( refreshLinkedMasterNodes ) + RefreshLinkedMasterNodes( true ); + + newMasterNode.OnMaterialUpdatedEvent += OnMaterialUpdatedEvent; + newMasterNode.OnShaderUpdatedEvent += OnShaderUpdatedEvent; + newMasterNode.IsMainOutputNode = true; + OnRefreshLinkedPortsComplete(); + FullCleanUndoStack(); + return newMasterNode; + } + + private void RepositionTemplateNodes( MasterNode newMasterNode ) + { + m_forceRepositionCheck = false; + + int dockedElementsBefore = 0; + int dockedElementsAfter = 0; + int masterIndex = 0; + bool foundMaster = false; + for( int i = 0; i < MultiPassMasterNodes.Count; i++ ) + { + if( MultiPassMasterNodes.NodesList[ i ].UniqueId == m_masterNodeId ) + { + foundMaster = true; + masterIndex = i; + } + + if( !MultiPassMasterNodes.NodesList[ i ].IsInvisible && MultiPassMasterNodes.NodesList[ i ].Docking ) + { + if( foundMaster ) + dockedElementsAfter++; + else + dockedElementsBefore++; + } + } + + if( dockedElementsBefore > 0 ) + { + newMasterNode.UseSquareNodeTitle = true; + } + + for( int i = masterIndex - 1; i >= 0; i-- ) + { + float forwardTracking = 0; + for( int j = i + 1; j <= masterIndex; j++ ) + { + if( !MultiPassMasterNodes.NodesList[ i ].IsInvisible && !MultiPassMasterNodes.NodesList[ j ].Docking ) + { + forwardTracking += MultiPassMasterNodes.NodesList[ j ].HeightEstimate + 10; + } + } + MasterNode node = MultiPassMasterNodes.NodesList[ i ]; + node.Vec2Position = new Vector2( node.Vec2Position.x, newMasterNode.Position.y - forwardTracking - 33 * ( dockedElementsBefore ) ); + } + + for( int i = masterIndex + 1; i < MultiPassMasterNodes.Count; i++ ) + { + if( MultiPassMasterNodes.NodesList[ i ].UniqueId == newMasterNode.UniqueId || MultiPassMasterNodes.NodesList[ i ].Docking ) + continue; + + float backTracking = 0; + for( int j = i - 1; j >= masterIndex; j-- ) + { + if( !MultiPassMasterNodes.NodesList[ i ].IsInvisible && !MultiPassMasterNodes.NodesList[ j ].Docking ) + { + backTracking += MultiPassMasterNodes.NodesList[ j ].HeightEstimate + 10; + } + } + MasterNode node = MultiPassMasterNodes.NodesList[ i ]; + node.Vec2Position = new Vector2( node.Vec2Position.x, newMasterNode.Position.y + backTracking + 33 * ( dockedElementsAfter ) ); + } + } + + public void CreateNewEmpty( string name ) + { + CleanNodes(); + if( m_masterNodeDefaultType == null ) + m_masterNodeDefaultType = typeof( StandardSurfaceOutputNode ); + + MasterNode newMasterNode = CreateNode( m_masterNodeDefaultType, false ) as MasterNode; + newMasterNode.SetName( name ); + m_masterNodeId = newMasterNode.UniqueId; + + ParentWindow.IsShaderFunctionWindow = false; + CurrentCanvasMode = NodeAvailability.SurfaceShader; + + newMasterNode.OnMaterialUpdatedEvent += OnMaterialUpdatedEvent; + newMasterNode.OnShaderUpdatedEvent += OnShaderUpdatedEvent; + newMasterNode.IsMainOutputNode = true; + LoadedShaderVersion = VersionInfo.FullNumber; + } + + public void CreateNewEmptyTemplate( string templateGUID ) + { + CleanNodes(); + TemplateDataParent templateData = m_parentWindow.TemplatesManagerInstance.GetTemplate( templateGUID ); + if( templateData.TemplateType == TemplateDataType.LegacySinglePass ) + { + TemplateMasterNode newMasterNode = CreateNode( typeof( TemplateMasterNode ), false ) as TemplateMasterNode; + m_masterNodeId = newMasterNode.UniqueId; + + ParentWindow.IsShaderFunctionWindow = false; + CurrentCanvasMode = NodeAvailability.TemplateShader; + m_currentSRPType = TemplateSRPType.BuiltIn; + newMasterNode.OnMaterialUpdatedEvent += OnMaterialUpdatedEvent; + newMasterNode.OnShaderUpdatedEvent += OnShaderUpdatedEvent; + newMasterNode.IsMainOutputNode = true; + + newMasterNode.SetTemplate( templateData as TemplateData, true, true ); + } + else + { + /*Paulo*/ + TemplateMultiPass multipassData = templateData as TemplateMultiPass; + m_currentSRPType = multipassData.SubShaders[ 0 ].Modules.SRPType; + + Vector2 currentPosition = Vector2.zero; + for( int subShaderIdx = 0; subShaderIdx < multipassData.SubShaders.Count; subShaderIdx++ ) + { + for( int passIdx = 0; passIdx < multipassData.SubShaders[ subShaderIdx ].Passes.Count; passIdx++ ) + { + TemplateMultiPassMasterNode newMasterNode = CreateNode( typeof( TemplateMultiPassMasterNode ), false ) as TemplateMultiPassMasterNode; + if( multipassData.SubShaders[ subShaderIdx ].Passes[ passIdx ].IsMainPass ) + { + m_masterNodeId = newMasterNode.UniqueId; + + ParentWindow.IsShaderFunctionWindow = false; + CurrentCanvasMode = NodeAvailability.TemplateShader; + + newMasterNode.OnMaterialUpdatedEvent += OnMaterialUpdatedEvent; + newMasterNode.OnShaderUpdatedEvent += OnShaderUpdatedEvent; + newMasterNode.IsMainOutputNode = true; + } + newMasterNode.Vec2Position = currentPosition; + newMasterNode.SetTemplate( multipassData, true, true, subShaderIdx, passIdx, SetTemplateSource.NewShader ); + + //currentPosition.y += newMasterNode.HeightEstimate + 10; + } + } + + RefreshLinkedMasterNodes( false ); + OnRefreshLinkedPortsComplete(); + } + + LoadedShaderVersion = VersionInfo.FullNumber; + } + + public void CreateNewEmptyFunction( AmplifyShaderFunction shaderFunction ) + { + CleanNodes(); + FunctionOutput newOutputNode = CreateNode( typeof( FunctionOutput ), false ) as FunctionOutput; + m_masterNodeId = newOutputNode.UniqueId; + + ParentWindow.IsShaderFunctionWindow = true; + CurrentCanvasMode = NodeAvailability.ShaderFunction; + + newOutputNode.IsMainOutputNode = true; + } + + public void ForceCategoryRefresh() { m_forceCategoryRefresh = true; } + public void RefreshExternalReferences() + { + int count = m_nodes.Count; + for( int i = 0; i < count; i++ ) + { + m_nodes[ i ].RefreshExternalReferences(); + } + } + + public Vector2 SelectedNodesCentroid + { + get + { + if( m_selectedNodes.Count == 0 ) + return Vector2.zero; + Vector2 pos = new Vector2( 0, 0 ); + for( int i = 0; i < m_selectedNodes.Count; i++ ) + { + pos += m_selectedNodes[ i ].Vec2Position; + } + + pos /= m_selectedNodes.Count; + return pos; + } + } + + public void AddVirtualTextureCount() + { + m_virtualTextureCount += 1; + } + + public void RemoveVirtualTextureCount() + { + m_virtualTextureCount -= 1; + if( m_virtualTextureCount < 0 ) + { + Debug.LogWarning( "Invalid virtual texture count" ); + } + } + + public bool HasVirtualTexture { get { return m_virtualTextureCount > 0; } } + + public void AddInstancePropertyCount() + { + m_instancePropertyCount += 1; +// Debug.Log( "AddInstancePropertyCount "+this.GetInstanceID() + " " + m_instancePropertyCount ); + } + + public void RemoveInstancePropertyCount() + { + m_instancePropertyCount -= 1; + // Debug.Log( "RemoveInstancePropertyCount " + this.GetInstanceID() + " " + m_instancePropertyCount ); + + if( m_instancePropertyCount < 0 ) + { + Debug.LogWarning( "Invalid property instance count" ); + } + } + + public int InstancePropertyCount { get { return m_instancePropertyCount; } set { m_instancePropertyCount = value; } } + + public bool IsInstancedShader { get { return m_instancePropertyCount > 0; } } + + public void AddNormalDependentCount() { m_normalDependentCount += 1; } + + public void RemoveNormalDependentCount() + { + m_normalDependentCount -= 1; + if( m_normalDependentCount < 0 ) + { + Debug.LogWarning( "Invalid normal dependentCount count" ); + } + } + + public void SetModeFromMasterNode() + { + MasterNode masterNode = CurrentMasterNode; + if( masterNode != null ) + { + switch( masterNode.CurrentMasterNodeCategory ) + { + default: + case AvailableShaderTypes.SurfaceShader: + { + if( masterNode is StandardSurfaceOutputNode ) + CurrentCanvasMode = ParentWindow.CurrentNodeAvailability; + else + CurrentCanvasMode = NodeAvailability.SurfaceShader; + } + break; + case AvailableShaderTypes.Template: + { + CurrentCanvasMode = NodeAvailability.TemplateShader; + } + break; + } + } + else + { + + CurrentCanvasMode = NodeAvailability.SurfaceShader; + } + } + + public void MarkToDelete( ParentNode node ) + { + m_markedForDeletion.Add( node ); + } + public bool IsMasterNode( ParentNode node ) + { + return ( node.UniqueId == m_masterNodeId ) || + m_multiPassMasterNodes.HasNode( node.UniqueId ); + } + + public TemplateMultiPassMasterNode GetMainMasterNodeOfLOD( int lod ) + { + if( lod == -1 ) + return CurrentMasterNode as TemplateMultiPassMasterNode; + + return m_lodMultiPassMasterNodes[ lod ].NodesList.Find( x => x.IsMainOutputNode ); + } + + public TemplateMultiPassMasterNode GetMasterNodeOfPass( string passName, int lod ) + { + if( lod == -1 ) + return m_multiPassMasterNodes.NodesList.Find( x => x.PassName.Equals( passName ) ); + + return m_lodMultiPassMasterNodes[lod].NodesList.Find( x => x.PassName.Equals( passName ) ); + } + + public void ForceMultiPassMasterNodesRefresh() + { + int mainOutputId = 0; + int count = m_multiPassMasterNodes.Count; + for( int i = 0; i < count; i++ ) + { + m_multiPassMasterNodes.NodesList[ i ].ForceTemplateRefresh(); + if( m_multiPassMasterNodes.NodesList[ i ].IsMainOutputNode ) + mainOutputId = i; + } + + int lodCount = m_lodMultiPassMasterNodes.Count; + for( int i = 0; i < lodCount; i++ ) + { + if( m_lodMultiPassMasterNodes[ i ] != null ) + { + count = m_lodMultiPassMasterNodes[ i ].Count; + for( int j = 0; j < count; j++ ) + { + m_lodMultiPassMasterNodes[ i ].NodesList[ j ].ForceTemplateRefresh(); + } + } + } + + m_multiPassMasterNodes.NodesList[ mainOutputId ].CheckTemplateChanges(); + } + + public void SetLateOptionsRefresh() + { + m_lateOptionsRefresh = true; + } + + public void CreateLodMasterNodes( TemplateMultiPass templateMultiPass,int index, Vector2 initialPosition ) + { + for( int lod = 0; lod < m_lodMultiPassMasterNodes.Count; lod++ ) + { + if( m_lodMultiPassMasterNodes[ lod ].Count == 0 ) + { + TemplateMultiPassMasterNode reference = CurrentMasterNode as TemplateMultiPassMasterNode; + + int shaderLod = -1; + if( lod == 0 ) + { + shaderLod = reference.ShaderLOD - MasterNodeLODIncrement; + } + else + { + //index == -2 is when user clicks on +/- buttons over the foldout UI + if( index == -2 ) + { + shaderLod = m_lodMultiPassMasterNodes[ lod - 1 ].NodesList[ reference.PassIdx ].ShaderLOD - MasterNodeLODIncrement; + } + //index == -1 is when user clicks on + button over the main lod master node + else if( index == -1 ) + { + int mainShaderLOD = m_lodMultiPassMasterNodes[ 0 ].NodesList[ reference.PassIdx ].ShaderLOD; + shaderLod = ( reference.ShaderLOD + mainShaderLOD )/2; + } + else + { + if( m_lodMultiPassMasterNodes[ index ].Count > 0 ) + { + if( m_lodMultiPassMasterNodes[ index + 1 ].Count > 0 ) + { + shaderLod = (m_lodMultiPassMasterNodes[ index ].NodesList[ reference.PassIdx ].ShaderLOD + + m_lodMultiPassMasterNodes[ index + 1 ].NodesList[ reference.PassIdx ].ShaderLOD )/2; + } + else + { + shaderLod = m_lodMultiPassMasterNodes[ index ].NodesList[ reference.PassIdx ].ShaderLOD - MasterNodeLODIncrement; + } + } + } + } + + int nodeId = 0; + TemplateMultiPassMasterNode mainMasterNode = null; + for( int subShaderIdx = 0; subShaderIdx < templateMultiPass.SubShaders.Count; subShaderIdx++ ) + { + for( int passIdx = 0; passIdx < templateMultiPass.SubShaders[ subShaderIdx ].Passes.Count; passIdx++ ) + { + TemplateMultiPassMasterNode masterNode = ScriptableObject.CreateInstance( typeof( TemplateMultiPassMasterNode ) ) as TemplateMultiPassMasterNode; + masterNode.LODIndex = lod; + masterNode.ContainerGraph = this; + masterNode.Vec2Position = initialPosition; + AddNode( masterNode, true ); + masterNode.SetTemplate( templateMultiPass, true, true, subShaderIdx, passIdx, SetTemplateSource.NewShader ); + masterNode.CopyOptionsFrom( m_multiPassMasterNodes.NodesList[ nodeId++ ] ); + if( masterNode.IsMainOutputNode || ( subShaderIdx == 0 && passIdx == 0 ) ) + { + masterNode.SetShaderLODValueAndLabel( shaderLod ); + mainMasterNode = masterNode; + } + } + } + + mainMasterNode.ForceOptionsRefresh(); + SortLODMasterNodes(); + if( OnLODMasterNodesAddedEvent != null ) + { + OnLODMasterNodesAddedEvent( lod ); + } + + TemplateMultiPassMasterNode lodMainMasterNode = CurrentMasterNode as TemplateMultiPassMasterNode; + lodMainMasterNode.SetShaderLODValueAndLabel( lodMainMasterNode.ShaderLOD ); + return; + } + } + } + + public void DestroyLodMasterNodes( int index ) + { + if( index < 0 ) + { + for( int lod = m_lodMultiPassMasterNodes.Count - 1; lod >= 0; lod-- ) + { + if( m_lodMultiPassMasterNodes[ lod ].Count > 0 ) + { + while( m_lodMultiPassMasterNodes[ lod ].Count > 0 ) + { + DestroyNode( m_lodMultiPassMasterNodes[ lod ].NodesList[ 0 ], false, true ); + } + break; + } + } + } + else + { + while( m_lodMultiPassMasterNodes[ index ].Count > 0 ) + { + DestroyNode( m_lodMultiPassMasterNodes[ index ].NodesList[ 0 ], false, true ); + } + } + SortLODMasterNodes(); + TemplateMultiPassMasterNode lodMainMasterNode = CurrentMasterNode as TemplateMultiPassMasterNode; + lodMainMasterNode.SetShaderLODValueAndLabel( lodMainMasterNode.ShaderLOD ); + } + + public void SortLODMasterNodes() + { + int idx = (CurrentMasterNode as TemplateMultiPassMasterNode).PassIdx; + m_lodMultiPassMasterNodes.Sort( ( x, y ) => + { + if( x.Count > 0 ) + { + if( y.Count > 0 ) + { + return -x.NodesList[ idx ].ShaderLOD.CompareTo( y.NodesList[ idx ].ShaderLOD ); + } + else + { + return -1; + } + } + else + { + if( y.Count > 0 ) + { + return 1; + } + } + return 0; + }); + + for( int lodIdx = 0; lodIdx < m_lodMultiPassMasterNodes.Count; lodIdx++ ) + { + for( int nodeIdx = 0; nodeIdx < m_lodMultiPassMasterNodes[ lodIdx ].Count; nodeIdx++ ) + { + m_lodMultiPassMasterNodes[ lodIdx ].NodesList[ nodeIdx ].LODIndex = lodIdx; + } + } + } + + public List GetMultiPassMasterNodes( int lod ) + { + if( lod == -1 ) + return m_multiPassMasterNodes.NodesList; + + return m_lodMultiPassMasterNodes[ lod ].NodesList; + } + + public bool IsNormalDependent { get { return m_normalDependentCount > 0; } } + + public void MarkToDeselect() { m_markedToDeSelect = true; } + public void MarkToSelect( int nodeId ) { m_markToSelect = nodeId; } + public void MarkWireHighlights() { m_checkSelectedWireHighlights = true; } + public List SelectedNodes { get { return m_selectedNodes; } } + public List MarkedForDeletionNodes { get { return m_markedForDeletion; } } + public int CurrentMasterNodeId { get { return m_masterNodeId; } set { m_masterNodeId = value; } } + + public Shader CurrentShader + { + get + { + MasterNode masterNode = GetNode( m_masterNodeId ) as MasterNode; + if( masterNode != null ) + return masterNode.CurrentShader; + return null; + } + } + + public Material CurrentMaterial + { + get + { + MasterNode masterNode = GetNode( m_masterNodeId ) as MasterNode; + if( masterNode != null ) + return masterNode.CurrentMaterial; + return null; + } + } + + + + public NodeAvailability CurrentCanvasMode { get { return m_currentCanvasMode; } set { m_currentCanvasMode = value; ParentWindow.LateRefreshAvailableNodes(); } } + public OutputNode CurrentOutputNode { get { return GetNode( m_masterNodeId ) as OutputNode; } } + public FunctionOutput CurrentFunctionOutput { get { return GetNode( m_masterNodeId ) as FunctionOutput; } } + public MasterNode CurrentMasterNode { get { return GetNode( m_masterNodeId ) as MasterNode; } } + public StandardSurfaceOutputNode CurrentStandardSurface { get { return GetNode( m_masterNodeId ) as StandardSurfaceOutputNode; } } + public List AllNodes { get { return m_nodes; } } + public int NodeCount { get { return m_nodes.Count; } } + //public List VisibleNodes { get { return m_visibleNodes; } } + + public int NodeClicked + { + set { m_nodeClicked = value; } + get { return m_nodeClicked; } + } + + public bool IsDirty + { + set { m_isDirty = value && UIUtils.DirtyMask; } + get + { + bool value = m_isDirty; + m_isDirty = false; + return value; + } + } + + public bool SaveIsDirty + { + set { m_saveIsDirty = value && UIUtils.DirtyMask; } + get { return m_saveIsDirty; } + } + public int LoadedShaderVersion + { + get { return m_loadedShaderVersion; } + set { m_loadedShaderVersion = value; } + } + + public AmplifyShaderFunction CurrentShaderFunction + { + get { if( CurrentFunctionOutput != null ) return CurrentFunctionOutput.Function; else return null; } + set { if( CurrentFunctionOutput != null ) CurrentFunctionOutput.Function = value; } + } + + public bool HasUnConnectedNodes { get { return m_hasUnConnectedNodes; } } + public UsageListSamplerNodes SamplerNodes { get { return m_samplerNodes; } } + public UsageListFloatIntNodes FloatIntNodes { get { return m_floatNodes; } } + public UsageListTexturePropertyNodes TexturePropertyNodes { get { return m_texturePropertyNodes; } } + public UsageListTextureArrayNodes TextureArrayNodes { get { return m_textureArrayNodes; } } + public UsageListPropertyNodes PropertyNodes { get { return m_propertyNodes; } } + public UsageListPropertyNodes RawPropertyNodes { get { return m_rawPropertyNodes; } } + public UsageListCustomExpressionsOnFunctionMode CustomExpressionOnFunctionMode { get { return m_customExpressionsOnFunctionMode; } } + public UsageListStaticSwitchNodes StaticSwitchNodes { get { return m_staticSwitchNodes; } } + public UsageListScreenColorNodes ScreenColorNodes { get { return m_screenColorNodes; } } + public UsageListRegisterLocalVarNodes LocalVarNodes { get { return m_localVarNodes; } } + public UsageListGlobalArrayNodes GlobalArrayNodes { get { return m_globalArrayNodes; } } + public UsageListFunctionInputNodes FunctionInputNodes { get { return m_functionInputNodes; } } + public UsageListFunctionNodes FunctionNodes { get { return m_functionNodes; } } + public UsageListFunctionOutputNodes FunctionOutputNodes { get { return m_functionOutputNodes; } } + public UsageListFunctionSwitchNodes FunctionSwitchNodes { get { return m_functionSwitchNodes; } } + public UsageListFunctionSwitchCopyNodes FunctionSwitchCopyNodes { get { return m_functionSwitchCopyNodes; } } + public UsageListTemplateMultiPassMasterNodes MultiPassMasterNodes { get { return m_multiPassMasterNodes; } set { m_multiPassMasterNodes = value; } } + public List LodMultiPassMasternodes { get { return m_lodMultiPassMasterNodes; } } + + + public PrecisionType CurrentPrecision + { + get { return m_currentPrecision; } + set { m_currentPrecision = value; } + } + + public NodeLOD LodLevel + { + get { return m_lodLevel; } + } + + public List NodePreviewList { get { return m_nodePreviewList; } set { m_nodePreviewList = value; } } + + public void SetGraphId( int id ) + { + m_graphId = id; + } + + public int GraphId + { + get { return m_graphId; } + } + + public AmplifyShaderEditorWindow ParentWindow + { + get { return m_parentWindow; } + set { m_parentWindow = value; } + } + + + public bool ChangedLightingModel + { + get { return m_changedLightingModel; } + set { m_changedLightingModel = value; } + } + + public bool ForceRepositionCheck + { + get { return m_forceRepositionCheck; } + set { m_forceRepositionCheck = value; } + } + + public bool IsLoading { get { return m_isLoading; } set { m_isLoading = value; } } + public bool IsDuplicating { get { return m_isDuplicating; } set { m_isDuplicating = value; } } + public TemplateSRPType CurrentSRPType { get { return m_currentSRPType; }set { m_currentSRPType = value; } } + public bool IsSRP { get { return m_currentSRPType == TemplateSRPType.Lightweight || m_currentSRPType == TemplateSRPType.HD; } } + public bool IsHDRP { get { return m_currentSRPType == TemplateSRPType.HD; } } + public bool IsLWRP { get { return m_currentSRPType == TemplateSRPType.Lightweight; } } + public bool IsStandardSurface { get { return GetNode( m_masterNodeId ) is StandardSurfaceOutputNode; } } + + public bool SamplingMacros { + get { return m_samplingThroughMacros; } + set { m_samplingThroughMacros = value; } + } + public bool HasLODs { get { return m_lodMultiPassMasterNodes[ 0 ].Count > 0; } } + //public bool HasLodMultiPassNodes + //{ + // get + // { + // for( int i = 0; i < m_lodMultiPassMasterNodes.Count; i++ ) + // { + // if( m_lodMultiPassMasterNodes[ i ].Count > 0 ) + // return true; + // } + // return false; + // } + //} + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/ParentGraph.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/ParentGraph.cs.meta new file mode 100644 index 0000000..dd5b308 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Graphs/ParentGraph.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0b814c2a3cbebc047a566a92ed9d4340 +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu.meta new file mode 100644 index 0000000..a627578 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3b28c70161e2aec4787239fba546bd25 +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderEditorWindow.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderEditorWindow.cs new file mode 100644 index 0000000..06346af --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderEditorWindow.cs @@ -0,0 +1,6110 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using UnityEditor.Callbacks; +using System; +using System.Collections; +using System.Threading; +using System.Globalization; +using System.Collections.Generic; +using UnityEngine.Networking; + +namespace AmplifyShaderEditor +{ + // Disabling Substance Deprecated warning + + public class AmplifyShaderEditorWindow : SearchableEditorWindow, ISerializationCallbackReceiver + { + public const string PreviewSizeGlobalVariable = "_ASEPreviewSize"; + + public const double InactivitySaveTime = 1.0; + + public const string CopyCommand = "Copy"; + public const string PasteCommand = "Paste"; + public const string SelectAll = "SelectAll"; + public const string Duplicate = "Duplicate"; + public const string ObjectSelectorClosed = "ObjectSelectorClosed"; + public const string LiveShaderError = "Live Shader only works with an assigned Master Node on the graph"; + + public const string AsyncMessage = "Detected Asynchronous Shader Compilation. This can cause slowdowns when saving not only ASE shaders but other shaders as well.\n" + + "Please consider turning it off ( Project Settings > Editor > Asynchronous Shader Compilation ) if detecting big slowdowns on shader save.\n" + + "This message can be turned off via Preferences > Amplify Shader Editor > Show Async Message."; + //public Texture2D MasterNodeOnTexture = null; + //public Texture2D MasterNodeOffTexture = null; + + //public Texture2D GPUInstancedOnTexture = null; + //public Texture2D GPUInstancedOffTexture = null; + + private bool m_initialized = false; + private bool m_checkInvalidConnections = false; + private bool m_afterDeserializeFlag = true; + + + [SerializeField] + private ParentGraph m_customGraph = null; + + // UI + private Rect m_graphArea; + private Texture2D m_graphBgTexture; + private Texture2D m_graphFgTexture; + private GUIStyle m_graphFontStyle; + //private GUIStyle _borderStyle; + private Texture2D m_wireTexture; + + [SerializeField] + TemplatesManager m_templatesManager; + + [SerializeField] + private InnerWindowEditorVariables m_innerEditorVariables; + + [SerializeField] + private string m_lastpath; + + [SerializeField] + private ASESelectionMode m_selectionMode = ASESelectionMode.Shader; + + [SerializeField] + private DuplicatePreventionBuffer m_duplicatePreventionBuffer; + + [SerializeField] + private double m_inactivityTime = 0; + + // Prevent save ops every tick when on live mode + [SerializeField] + private double m_lastTimeSaved = 0; + + [SerializeField] + private bool m_cacheSaveOp = false; + private const double SaveTime = 1; + + private bool m_markedToSave = false; + + // Graph logic + [SerializeField] + private ParentGraph m_mainGraphInstance; + + // Camera control + [SerializeField] + private Vector2 m_cameraOffset; + + private float m_cameraSpeed = 1; + + private Rect m_cameraInfo; + + [SerializeField] + private float m_cameraZoom; + + [SerializeField] + private Vector2 m_minNodePos; + + [SerializeField] + private Vector2 m_maxNodePos; + + [SerializeField] + private bool m_isDirty; + + [SerializeField] + private bool m_saveIsDirty; + + [SerializeField] + private bool m_repaintIsDirty; + + [SerializeField] + private bool m_liveShaderEditing = false; + + [SerializeField] + private bool m_shaderIsModified = false; + + [SerializeField] + private string m_lastOpenedLocation = string.Empty; + + [SerializeField] + private bool m_zoomChanged = true; + + [SerializeField] + private float m_lastWindowWidth = 0; + + [SerializeField] + private int m_graphCount = 0; + + [SerializeField] + private double m_currentInactiveTime = 0; + + private bool m_ctrlSCallback = false; + + private bool m_altBoxSelection = false; + private bool m_altDragStarted = false; + private bool m_altPressDown = false; + private bool m_altAvailable = true; + + // Events + private Vector3 m_currentMousePos; + private Vector2 m_keyEvtMousePos2D; + private Vector2 m_currentMousePos2D; + private Event m_currentEvent; + private string m_currentCommandName = string.Empty; + private bool m_insideEditorWindow; + + private bool m_lostFocus = false; + // Selection box for multiple node selection + private bool m_multipleSelectionActive = false; + private bool m_lmbPressed = false; + private Vector2 m_multipleSelectionStart; + private Rect m_multipleSelectionArea = new Rect( 0, 0, 0, 0 ); + private bool m_autoPanDirActive = false; + private bool m_forceAutoPanDir = false; + private bool m_refreshOnUndo = false; + private bool m_loadShaderOnSelection = false; + private bool m_refreshAvailableNodes = false; + private double m_time; + + //Context Menu + private Vector2 m_rmbStartPos; + private Vector2 m_altKeyStartPos; + private GraphContextMenu m_contextMenu; + private ShortcutsManager m_shortcutManager; + + [SerializeField] + private NodeAvailability m_currentNodeAvailability = NodeAvailability.SurfaceShader; + //Clipboard + private Clipboard m_clipboard; + + //Node Parameters Window + [SerializeField] + private bool m_nodeParametersWindowMaximized = true; + private NodeParametersWindow m_nodeParametersWindow; + + // Tools Window + private ToolsWindow m_toolsWindow; + + private ConsoleLogWindow m_consoleLogWindow; + + //Editor Options + private OptionsWindow m_optionsWindow; + + // Mode Window + private ShaderEditorModeWindow m_modeWindow; + + // Tools Window + private TipsWindow m_tipsWindow; + + //Palette Window + [SerializeField] + private bool m_paletteWindowMaximized = true; + private PaletteWindow m_paletteWindow; + + private ContextPalette m_contextPalette; + private PalettePopUp m_palettePopup; + private System.Type m_paletteChosenType; + private AmplifyShaderFunction m_paletteChosenFunction; + + // In-Editor Message System + GenericMessageUI m_genericMessageUI; + private GUIContent m_genericMessageContent; + + // Drag&Drop Tool + private DragAndDropTool m_dragAndDropTool; + + //Custom Styles + //private CustomStylesContainer m_customStyles; + + private AmplifyShaderFunction m_previousShaderFunction; + + private List m_registeredMenus; + + private PreMadeShaders m_preMadeShaders; + + private AutoPanData[] m_autoPanArea; + + private DrawInfo m_drawInfo; + private KeyCode m_lastKeyPressed = KeyCode.None; + private System.Type m_commentaryTypeNode; + + private int m_onLoadDone = 0; + + private float m_copyPasteDeltaMul = 0; + private Vector2 m_copyPasteInitialPos = Vector2.zero; + private Vector2 m_copyPasteDeltaPos = Vector2.zero; + + private int m_repaintCount = 0; + private bool m_forceUpdateFromMaterialFlag = false; + + private UnityEngine.Object m_delayedLoadObject = null; + private double m_focusOnSelectionTimestamp; + private double m_focusOnMasterNodeTimestamp; + private double m_wiredDoubleTapTimestamp; + + private bool m_globalPreview = false; + private bool m_globalShowInternalData = true; + + private const double AutoZoomTime = 0.25; + private const double ToggleTime = 0.25; + private const double WiredDoubleTapTime = 0.25; + private const double DoubleClickTime = 0.25; + + private Material m_delayedMaterialSet = null; + + private bool m_mouseDownOnValidArea = false; + + private bool m_removedKeyboardFocus = false; + + private int m_lastHotControl = -1; + + [SerializeField] + private bool m_isShaderFunctionWindow = false; + + private string m_currentTitle = string.Empty; + private bool m_currentTitleMod = false; + + //private Material m_maskingMaterial = null; + //private int m_cachedProjectInLinearId = -1; + private int m_cachedEditorTimeId = -1; + private int m_cachedEditorDeltaTimeId = -1; + //private float m_repaintFrequency = 15; + //private double m_repaintTimestamp = 0; + + // Smooth Zoom + private bool m_smoothZoom = false; + private float m_targetZoom; + private double m_zoomTime; + private Vector2 m_zoomPivot; + private float m_targetZoomIncrement; + private float m_zoomVelocity = 0; + + // Smooth Pan + private bool m_smoothOffset = false; + private double m_offsetTime; + private Vector2 m_targetOffset; + private Vector2 m_camVelocity = Vector2.zero; + + // Auto-Compile samples + private bool m_forcingMaterialUpdateFlag = false; + private bool m_forcingMaterialUpdateOp = false; + private List m_materialsToUpdate = new List(); + + private NodeExporterUtils m_nodeExporterUtils; + private bool m_performFullUndoRegister = true; + + [SerializeField] + private AmplifyShaderFunction m_openedShaderFunction; + + [SerializeField] + private bool m_openedAssetFromNode = false; + + private bool m_nodesLoadedCorrectly = false; + private GUIContent NodesExceptionMessage = new GUIContent( "ASE is unable to load correctly due to some faulty other classes/plugin in your project. We advise to review all your imported plugins." ); + + + private bool m_outdatedShaderFromTemplateLoaded = false; + private bool m_replaceMasterNode = false; + private AvailableShaderTypes m_replaceMasterNodeType; + private string m_replaceMasterNodeData; + private bool m_replaceMasterNodeDataFromCache; + private NodeWireReferencesUtils m_wireReferenceUtils = new NodeWireReferencesUtils(); + + private ParentNode m_nodeToFocus = null; + private float m_zoomToFocus = 1.0f; + private bool m_selectNodeToFocus = true; + + [NonSerialized] + public Dictionary VisitedChanged = new Dictionary(); + + [SerializeField] + private List m_messages = new List(); + + [SerializeField] + private float m_maxMsgWidth = 100; + + [SerializeField] + private bool m_maximizeMessages = false; + + [NonSerialized] + private Dictionary m_savedList = new Dictionary(); + + public int m_frameCounter = 0; + public double m_fpsTime = 0; + public string m_fpsDisplay = string.Empty; + +#if UNITY_EDITOR_WIN + // ScreenShot vars + IntPtr m_aseHandle; + private Rect m_prevWindowRect; + private Vector2 m_prevCameraOffset; + private float m_prevCameraZoom; + private bool m_openSavedFolder = false; + private bool m_takeScreenShot = false; +#endif + public bool CheckFunctions = false; + + // Unity Menu item + [MenuItem( "Window/Amplify Shader Editor/Open Canvas", false, 1000 )] + static void OpenMainShaderGraph() + { + if( IOUtils.AllOpenedWindows.Count > 0 ) + { + AmplifyShaderEditorWindow currentWindow = CreateTab( "Empty", UIUtils.ShaderIcon ); + UIUtils.CurrentWindow = currentWindow; + currentWindow.CreateNewGraph( "Empty" ); + currentWindow.Show(); + } + else + { + AmplifyShaderEditorWindow currentWindow = OpenWindow( "Empty", UIUtils.ShaderIcon ); + currentWindow.CreateNewGraph( "Empty" ); + //currentWindow.Show(); + } + } + + public static string GenerateTabTitle( string original, bool modified = false ) + { + GUIContent content = new GUIContent( original ); + GUIStyle tabStyle = new GUIStyle( (GUIStyle)"dragtabdropwindow" );// GUI.skin.FindStyle( "dragtabdropwindow" ); + string finalTitle = string.Empty; + bool addEllipsis = false; + for( int i = 1; i <= original.Length; i++ ) + { + content.text = original.Substring( 0, i ); + Vector2 titleSize = tabStyle.CalcSize( content ); + int maxSize = modified ? 62 : 69; + if( titleSize.x > maxSize ) + { + addEllipsis = true; + break; + } + else + { + finalTitle = content.text; + } + } + if( addEllipsis ) + finalTitle += ".."; + if( modified ) + finalTitle += "*"; + return finalTitle; + } + + public static void ConvertShaderToASE( Shader shader ) + { + if( UIUtils.IsUnityNativeShader( shader ) ) + { + Debug.LogWarningFormat( "Action not allowed. Attempting to load the native {0} shader into Amplify Shader Editor", shader.name ); + return; + } + + string guid = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( shader ) ); + if( IOUtils.AllOpenedWindows.Count > 0 ) + { + AmplifyShaderEditorWindow openedTab = null; + for( int i = 0; i < IOUtils.AllOpenedWindows.Count; i++ ) + { + //if( AssetDatabase.GetAssetPath( shader ).Equals( IOUtils.AllOpenedWindows[ i ].LastOpenedLocation ) ) + if( guid.Equals( IOUtils.AllOpenedWindows[ i ].GUID ) ) + { + openedTab = IOUtils.AllOpenedWindows[ i ]; + break; + } + } + + if( openedTab != null ) + { + openedTab.wantsMouseMove = true; + openedTab.ShowTab(); + UIUtils.CurrentWindow = openedTab; + } + else + { + EditorWindow openedWindow = AmplifyShaderEditorWindow.GetWindow(); + AmplifyShaderEditorWindow currentWindow = CreateTab(); + WindowHelper.AddTab( openedWindow, currentWindow ); + UIUtils.CurrentWindow = currentWindow; + } + } + else + { + AmplifyShaderEditorWindow currentWindow = OpenWindow( shader.name, UIUtils.ShaderIcon ); + UIUtils.CurrentWindow = currentWindow; + } + + if( IOUtils.IsASEShader( shader ) ) + { + UIUtils.CurrentWindow.LoadProjectSelected( shader ); + } + else + { + UIUtils.CreateEmptyFromInvalid( shader ); + UIUtils.ShowMessage( "Trying to open shader not created on ASE!\nBEWARE, old data will be lost if saving it here!", MessageSeverity.Warning ); + if( UIUtils.CurrentWindow.LiveShaderEditing ) + { + UIUtils.ShowMessage( "Disabling Live Shader Editing. Must manually re-enable it.", MessageSeverity.Warning ); + UIUtils.CurrentWindow.LiveShaderEditing = false; + } + } + } + + public static void LoadMaterialToASE( Material material ) + { + string guid = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( material.shader ) ); + + if( IOUtils.AllOpenedWindows.Count > 0 ) + { + AmplifyShaderEditorWindow openedTab = null; + for( int i = 0; i < IOUtils.AllOpenedWindows.Count; i++ ) + { + //if( AssetDatabase.GetAssetPath( material.shader ).Equals( IOUtils.AllOpenedWindows[ i ].LastOpenedLocation ) ) + if( guid.Equals( IOUtils.AllOpenedWindows[ i ].GUID ) ) + { + openedTab = IOUtils.AllOpenedWindows[ i ]; + break; + } + } + + if( openedTab != null ) + { + openedTab.wantsMouseMove = true; + openedTab.ShowTab(); + UIUtils.CurrentWindow = openedTab; + } + else + { + EditorWindow openedWindow = AmplifyShaderEditorWindow.GetWindow(); + AmplifyShaderEditorWindow currentWindow = CreateTab(); + WindowHelper.AddTab( openedWindow, currentWindow ); + UIUtils.CurrentWindow = currentWindow; + } + } + else + { + AmplifyShaderEditorWindow currentWindow = OpenWindow( material.name, UIUtils.MaterialIcon ); + UIUtils.CurrentWindow = currentWindow; + } + + if( IOUtils.IsASEShader( material.shader ) ) + { + UIUtils.CurrentWindow.LoadProjectSelected( material ); + } + else + { + UIUtils.CreateEmptyFromInvalid( material.shader ); + UIUtils.SetDelayedMaterialMode( material ); + } + } + + public static void LoadShaderFunctionToASE( AmplifyShaderFunction shaderFunction, bool openedAssetFromNode ) + { + string guid = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( shaderFunction ) ); + + if( IOUtils.AllOpenedWindows.Count > 0 ) + { + AmplifyShaderEditorWindow openedTab = null; + for( int i = 0; i < IOUtils.AllOpenedWindows.Count; i++ ) + { + //if( AssetDatabase.GetAssetPath( shaderFunction ).Equals( IOUtils.AllOpenedWindows[ i ].LastOpenedLocation ) ) + if( guid.Equals( IOUtils.AllOpenedWindows[ i ].GUID ) ) + { + openedTab = IOUtils.AllOpenedWindows[ i ]; + break; + } + } + + if( openedTab != null ) + { + openedTab.wantsMouseMove = true; + openedTab.ShowTab(); + UIUtils.CurrentWindow = openedTab; + } + else + { + EditorWindow openedWindow = AmplifyShaderEditorWindow.GetWindow(); + AmplifyShaderEditorWindow currentWindow = CreateTab(); + WindowHelper.AddTab( openedWindow, currentWindow ); + UIUtils.CurrentWindow = currentWindow; + } + } + else + { + AmplifyShaderEditorWindow currentWindow = OpenWindow( shaderFunction.FunctionName, UIUtils.ShaderFunctionIcon ); + UIUtils.CurrentWindow = currentWindow; + } + + UIUtils.CurrentWindow.OpenedAssetFromNode = openedAssetFromNode; + if( IOUtils.IsShaderFunction( shaderFunction.FunctionInfo ) ) + { + UIUtils.CurrentWindow.LoadProjectSelected( shaderFunction ); + } + else + { + UIUtils.CurrentWindow.titleContent.text = GenerateTabTitle( shaderFunction.FunctionName ); + UIUtils.CurrentWindow.titleContent.image = UIUtils.ShaderFunctionIcon; + UIUtils.CreateEmptyFunction( shaderFunction ); + } + } + + public static void LoadAndSaveList( string[] assetList ) + { + EditorPrefs.SetString( "ASEfileList", string.Join( ",", assetList ) ); + if( assetList[ 0 ].EndsWith( ".asset" ) ) + { + var obj = AssetDatabase.LoadAssetAtPath( assetList[ 0 ] ); + AmplifyShaderEditorWindow.LoadShaderFunctionToASE( obj, false ); + } + else + { + var obj = AssetDatabase.LoadAssetAtPath( assetList[ 0 ] ); + AmplifyShaderEditorWindow.ConvertShaderToASE( obj ); + } + + UIUtils.CurrentWindow.State = AmplifyShaderEditorWindow.OpenSaveState.OPEN; + UIUtils.CurrentWindow.Repaint(); + } + + public static AmplifyShaderEditorWindow OpenWindow( string title = null, Texture icon = null ) + { + AmplifyShaderEditorWindow currentWindow = (AmplifyShaderEditorWindow)AmplifyShaderEditorWindow.GetWindow( typeof( AmplifyShaderEditorWindow ), false ); + currentWindow.minSize = new Vector2( ( Constants.MINIMIZE_WINDOW_LOCK_SIZE - 150 ), 270 ); + currentWindow.wantsMouseMove = true; + if( title != null ) + currentWindow.titleContent.text = GenerateTabTitle( title ); + if( icon != null ) + currentWindow.titleContent.image = icon; + return currentWindow; + } + + public static AmplifyShaderEditorWindow CreateTab( string title = null, Texture icon = null ) + { + AmplifyShaderEditorWindow currentWindow = EditorWindow.CreateInstance(); + currentWindow.minSize = new Vector2( ( Constants.MINIMIZE_WINDOW_LOCK_SIZE - 150 ), 270 ); + currentWindow.wantsMouseMove = true; + if( title != null ) + currentWindow.titleContent.text = GenerateTabTitle( title ); + if( icon != null ) + currentWindow.titleContent.image = icon; + return currentWindow; + } + + public double CalculateInactivityTime() + { + double currTime = EditorApplication.timeSinceStartup; + switch( Event.current.type ) + { + case EventType.MouseDown: + case EventType.MouseUp: + //case EventType.MouseMove: + case EventType.MouseDrag: + case EventType.KeyDown: + case EventType.KeyUp: + case EventType.ScrollWheel: + case EventType.DragUpdated: + case EventType.DragPerform: + case EventType.DragExited: + case EventType.ValidateCommand: + case EventType.ExecuteCommand: + { + m_inactivityTime = currTime; + return 0; + } + } + return currTime - m_inactivityTime; + } + + public void ActivatePreviews( bool value ) + { + m_mainGraphInstance.ActivatePreviews( value ); + } + + // Shader Graph window + public override void OnEnable() + { + base.OnEnable(); + + Preferences.LoadDefaults(); + +#if UNITY_2018_3_OR_NEWER + ASEPackageManagerHelper.RequestInfo(); + ASEPackageManagerHelper.Update(); +#endif + + Shader.SetGlobalVector( PreviewSizeGlobalVariable, new Vector4( Constants.PreviewSize , Constants.PreviewSize , 0, 0 ) ); + + if( m_templatesManager == null ) + { + m_templatesManager = IOUtils.FirstValidTemplatesManager; + if( m_templatesManager == null ) + { + m_templatesManager = ScriptableObject.CreateInstance(); + m_templatesManager.Init(); + if( TemplatesManager.ShowDebugMessages ) + Debug.Log( "Creating Manager" ); + } + else + { + if( TemplatesManager.ShowDebugMessages ) + Debug.Log( "Assigning Manager" ); + } + } + else if( !m_templatesManager.Initialized ) + { + if( TemplatesManager.ShowDebugMessages ) + Debug.Log( "Re-Initializing Manager" ); + m_templatesManager.Init(); + } + TemplatePostProcessor.Destroy(); + if( m_innerEditorVariables == null ) + { + m_innerEditorVariables = new InnerWindowEditorVariables(); + m_innerEditorVariables.Initialize(); + } + + if( m_mainGraphInstance == null ) + { + m_mainGraphInstance = CreateInstance(); + m_mainGraphInstance.Init(); + m_mainGraphInstance.ParentWindow = this; + m_mainGraphInstance.SetGraphId( 0 ); + } + m_mainGraphInstance.ResetEvents(); + m_mainGraphInstance.OnNodeEvent += OnNodeStoppedMovingEvent; + m_mainGraphInstance.OnMaterialUpdatedEvent += OnMaterialUpdated; + m_mainGraphInstance.OnShaderUpdatedEvent += OnShaderUpdated; + m_mainGraphInstance.OnEmptyGraphDetectedEvt += OnEmptyGraphDetected; + m_mainGraphInstance.OnNodeRemovedEvent += m_toolsWindow.OnNodeRemovedFromGraph; + GraphCount = 1; + + IOUtils.Init(); + IOUtils.AllOpenedWindows.Add( this ); + + // Only runs once for multiple windows + EditorApplication.update -= IOUtils.UpdateIO; + EditorApplication.update += IOUtils.UpdateIO; + + //EditorApplication.update -= UpdateTime; + EditorApplication.update -= UpdateNodePreviewListAndTime; + //EditorApplication.update += UpdateTime; + + EditorApplication.update += UpdateNodePreviewListAndTime; + + + if( CurrentSelection == ASESelectionMode.ShaderFunction ) + { + IsShaderFunctionWindow = true; + } + else + { + IsShaderFunctionWindow = false; + } + + m_optionsWindow = new OptionsWindow( this ); + m_optionsWindow.Init(); + + m_contextMenu = new GraphContextMenu( m_mainGraphInstance ); + m_nodesLoadedCorrectly = m_contextMenu.CorrectlyLoaded; + + m_paletteWindow = new PaletteWindow( this ) + { + Resizable = true + }; + m_paletteWindow.OnPaletteNodeCreateEvt += OnPaletteNodeCreate; + m_registeredMenus.Add( m_paletteWindow ); + + m_contextPalette = new ContextPalette( this ); + m_contextPalette.OnPaletteNodeCreateEvt += OnContextPaletteNodeCreate; + m_registeredMenus.Add( m_contextPalette ); + + m_genericMessageUI = new GenericMessageUI(); + m_genericMessageUI.OnMessageDisplayEvent += ShowMessageImmediately; + + Selection.selectionChanged += OnProjectSelectionChanged; +#if UNITY_2018_1_OR_NEWER + EditorApplication.projectChanged += OnProjectWindowChanged; +#else + EditorApplication.projectWindowChanged += OnProjectWindowChanged; +#endif + m_focusOnSelectionTimestamp = EditorApplication.timeSinceStartup; + m_focusOnMasterNodeTimestamp = EditorApplication.timeSinceStartup; + + m_nodeParametersWindow.IsMaximized = m_innerEditorVariables.NodeParametersMaximized; + if( DebugConsoleWindow.UseShaderPanelsInfo ) + m_nodeParametersWindow.IsMaximized = m_nodeParametersWindowMaximized; + + m_paletteWindow.IsMaximized = m_innerEditorVariables.NodePaletteMaximized; + if( DebugConsoleWindow.UseShaderPanelsInfo ) + m_paletteWindow.IsMaximized = m_paletteWindowMaximized; + + m_shortcutManager = new ShortcutsManager(); + // REGISTER NODE SHORTCUTS + foreach( KeyValuePair kvp in m_contextMenu.NodeShortcuts ) + { + m_shortcutManager.RegisterNodesShortcuts( kvp.Key, kvp.Value.Name ); + } + + // REGISTER EDITOR SHORTCUTS + + m_shortcutManager.RegisterEditorShortcut( true, EventModifiers.FunctionKey, KeyCode.F1, "Open Selected Node Wiki page", () => + { + List selectedNodes = m_mainGraphInstance.SelectedNodes; + if( selectedNodes != null && selectedNodes.Count == 1 ) + { + Application.OpenURL( selectedNodes[ 0 ].Attributes.NodeUrl ); + } + } ); + + + m_shortcutManager.RegisterEditorShortcut( true, KeyCode.C, "Create Commentary", () => + { + // Create commentary + ParentNode[] selectedNodes = m_mainGraphInstance.SelectedNodes.ToArray(); + UIUtils.MarkUndoAction(); + Undo.RegisterCompleteObjectUndo( this, "Adding Commentary Node" ); + CommentaryNode node = m_mainGraphInstance.CreateNode( m_commentaryTypeNode, true, -1, false ) as CommentaryNode; + node.CreateFromSelectedNodes( TranformedMousePos, selectedNodes ); + node.Focus(); + m_mainGraphInstance.DeSelectAll(); + m_mainGraphInstance.SelectNode( node, false, false ); + SetSaveIsDirty(); + ForceRepaint(); + } ); + + + m_shortcutManager.RegisterEditorShortcut( true, KeyCode.F, "Focus On Selection", () => + { + OnToolButtonPressed( ToolButtonType.FocusOnSelection ); + ForceRepaint(); + } ); + + //m_shortcutManager.RegisterEditorShortcut( true, EventModifiers.None, KeyCode.B, "New Master Node", () => + //{ + // OnToolButtonPressed( ToolButtonType.MasterNode ); + // ForceRepaint(); + //} ); + + m_shortcutManager.RegisterEditorShortcut( true, EventModifiers.None, KeyCode.Space, "Open Node Palette", null, () => + { + m_contextPalette.Show( m_currentMousePos2D, m_cameraInfo ); + } ); + + + m_shortcutManager.RegisterEditorShortcut( true, KeyCode.W, "Toggle Colored Line Mode", () => + { + m_optionsWindow.ColoredPorts = !m_optionsWindow.ColoredPorts; + ForceRepaint(); + + } ); + + m_shortcutManager.RegisterEditorShortcut( true, EventModifiers.Control, KeyCode.W, "Toggle Multi-Line Mode", () => + { + m_optionsWindow.MultiLinePorts = !m_optionsWindow.MultiLinePorts; + ForceRepaint(); + } ); + + m_shortcutManager.RegisterEditorShortcut( true, KeyCode.P, "Global Preview", () => + { + GlobalPreview = !GlobalPreview; + EditorPrefs.SetBool( "GlobalPreview", GlobalPreview ); + + ForceRepaint(); + } ); + + GlobalShowInternalData = EditorPrefs.GetBool( "ASEGlobalShowInternalData", true ); + m_shortcutManager.RegisterEditorShortcut( true, KeyCode.I, "Global Show Internal Data", () => + { + GlobalShowInternalData = !GlobalShowInternalData; + EditorPrefs.SetBool( "ASEGlobalShowInternalData", GlobalShowInternalData ); + ForceRepaint(); + } ); + + m_shortcutManager.RegisterEditorShortcut( true, EventModifiers.FunctionKey, KeyCode.Delete, "Delete selected nodes", DeleteSelectedNodeWithRepaint ); + m_shortcutManager.RegisterEditorShortcut( true, EventModifiers.FunctionKey, KeyCode.Backspace, "Delete selected nodes", DeleteSelectedNodeWithRepaint ); + + m_liveShaderEditing = m_innerEditorVariables.LiveMode; + + UpdateLiveUI(); + } + + + public AmplifyShaderEditorWindow() + { + m_minNodePos = new Vector2( float.MaxValue, float.MaxValue ); + m_maxNodePos = new Vector2( float.MinValue, float.MinValue ); + + m_duplicatePreventionBuffer = new DuplicatePreventionBuffer(); + m_commentaryTypeNode = typeof( CommentaryNode ); + titleContent = new GUIContent( "Shader Editor" ); + autoRepaintOnSceneChange = true; + + m_currentMousePos = new Vector3( 0, 0, 0 ); + m_keyEvtMousePos2D = new Vector2( 0, 0 ); + m_multipleSelectionStart = new Vector2( 0, 0 ); + m_initialized = false; + m_graphBgTexture = null; + m_graphFgTexture = null; + + m_cameraOffset = new Vector2( 0, 0 ); + CameraZoom = 1; + + m_registeredMenus = new List(); + + m_nodeParametersWindow = new NodeParametersWindow( this ) + { + Resizable = true + }; + m_registeredMenus.Add( m_nodeParametersWindow ); + + m_modeWindow = new ShaderEditorModeWindow( this ); + //_registeredMenus.Add( _modeWindow ); + + m_toolsWindow = new ToolsWindow( this ); + m_toolsWindow.ToolButtonPressedEvt += OnToolButtonPressed; + + m_consoleLogWindow = new ConsoleLogWindow( this ); + + m_tipsWindow = new TipsWindow( this ); + + m_registeredMenus.Add( m_toolsWindow ); + //m_registeredMenus.Add( m_consoleLogWindow ); + + m_palettePopup = new PalettePopUp(); + + m_clipboard = new Clipboard(); + + m_genericMessageContent = new GUIContent(); + m_dragAndDropTool = new DragAndDropTool(); + m_dragAndDropTool.OnValidDropObjectEvt += OnValidObjectsDropped; + + //_confirmationWindow = new ConfirmationWindow( 100, 100, 300, 100 ); + + m_saveIsDirty = false; + + m_preMadeShaders = new PreMadeShaders(); + + Undo.undoRedoPerformed += UndoRedoPerformed; + + float autoPanSpeed = 2; + m_autoPanArea = new AutoPanData[ 4 ]; + m_autoPanArea[ 0 ] = new AutoPanData( AutoPanLocation.TOP, 25, autoPanSpeed * Vector2.up ); + m_autoPanArea[ 1 ] = new AutoPanData( AutoPanLocation.BOTTOM, 25, autoPanSpeed * Vector2.down ); + m_autoPanArea[ 2 ] = new AutoPanData( AutoPanLocation.LEFT, 25, autoPanSpeed * Vector2.right ); + m_autoPanArea[ 3 ] = new AutoPanData( AutoPanLocation.RIGHT, 25, autoPanSpeed * Vector2.left ); + + m_drawInfo = new DrawInfo(); + UIUtils.CurrentWindow = this; + + m_nodeExporterUtils = new NodeExporterUtils( this ); + m_repaintIsDirty = false; + m_initialized = false; + } + + public void SetStandardShader() + { + m_mainGraphInstance.ReplaceMasterNode( AvailableShaderTypes.SurfaceShader ); + m_mainGraphInstance.FireMasterNodeReplacedEvent(); + } + + public void SetTemplateShader( string templateName, bool writeDefaultData ) + { + TemplateDataParent templateData = m_templatesManager.GetTemplate( ( string.IsNullOrEmpty( templateName ) ? "6e114a916ca3e4b4bb51972669d463bf" : templateName ) ); + m_mainGraphInstance.ReplaceMasterNode( AvailableShaderTypes.Template, writeDefaultData, templateData ); + } + + public void DeleteSelectedNodeWithRepaint() + { + DeleteSelectedNodes(); + SetSaveIsDirty(); + } + + + void UndoRedoPerformed() + { + m_repaintIsDirty = true; + m_saveIsDirty = true; + m_removedKeyboardFocus = true; + m_refreshOnUndo = true; + } + + void Destroy() + { + Undo.ClearUndo( this ); + + m_initialized = false; + + m_nodeExporterUtils.Destroy(); + m_nodeExporterUtils = null; + + m_delayedMaterialSet = null; + + m_materialsToUpdate.Clear(); + m_materialsToUpdate = null; + + GLDraw.Destroy(); + + UIUtils.Destroy(); + m_preMadeShaders.Destroy(); + m_preMadeShaders = null; + + m_registeredMenus.Clear(); + m_registeredMenus = null; + + m_mainGraphInstance.Destroy(); + ScriptableObject.DestroyImmediate( m_mainGraphInstance ); + m_mainGraphInstance = null; + + Resources.UnloadAsset( m_graphBgTexture ); + m_graphBgTexture = null; + + Resources.UnloadAsset( m_graphFgTexture ); + m_graphFgTexture = null; + + Resources.UnloadAsset( m_wireTexture ); + m_wireTexture = null; + + m_contextMenu.Destroy(); + m_contextMenu = null; + + m_shortcutManager.Destroy(); + m_shortcutManager = null; + + m_nodeParametersWindow.Destroy(); + m_nodeParametersWindow = null; + + + m_modeWindow.Destroy(); + m_modeWindow = null; + + m_toolsWindow.Destroy(); + m_toolsWindow = null; + + m_consoleLogWindow.Destroy(); + m_consoleLogWindow = null; + + m_tipsWindow.Destroy(); + m_tipsWindow = null; + + m_optionsWindow.Destroy(); + m_optionsWindow = null; + + m_paletteWindow.Destroy(); + m_paletteWindow = null; + + m_palettePopup.Destroy(); + m_palettePopup = null; + + m_contextPalette.Destroy(); + m_contextPalette = null; + + m_clipboard.ClearClipboard(); + m_clipboard = null; + + m_genericMessageUI.Destroy(); + m_genericMessageUI = null; + m_genericMessageContent = null; + + m_dragAndDropTool.Destroy(); + m_dragAndDropTool = null; + + m_openedShaderFunction = null; + + UIUtils.CurrentWindow = null; + m_duplicatePreventionBuffer.ReleaseAllData(); + m_duplicatePreventionBuffer = null; +#if UNITY_2018_1_OR_NEWER + EditorApplication.projectChanged -= OnProjectWindowChanged; +#else + EditorApplication.projectWindowChanged -= OnProjectWindowChanged; +#endif + Selection.selectionChanged -= OnProjectSelectionChanged; + + IOUtils.AllOpenedWindows.Remove( this ); + + if( IOUtils.AllOpenedWindows.Count == 0 ) + { + m_templatesManager.Destroy(); + ScriptableObject.DestroyImmediate( m_templatesManager ); + } + m_templatesManager = null; + + IOUtils.Destroy(); + + Resources.UnloadUnusedAssets(); + GC.Collect(); + } + + void Init() + { + // = AssetDatabase.LoadAssetAtPath( Constants.ASEPath + "", typeof( Texture2D ) ) as Texture2D; + m_graphBgTexture = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( IOUtils.GraphBgTextureGUID ), typeof( Texture2D ) ) as Texture2D; + if( m_graphBgTexture != null ) + { + m_graphFgTexture = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( IOUtils.GraphFgTextureGUID ), typeof( Texture2D ) ) as Texture2D; + + //Setup usable area + m_cameraInfo = position; + m_graphArea = new Rect( 0, 0, m_cameraInfo.width, m_cameraInfo.height ); + + // Creating style state to show current selected object + m_graphFontStyle = new GUIStyle() + { + fontSize = 32, + alignment = TextAnchor.MiddleCenter, + fixedWidth = m_cameraInfo.width, + fixedHeight = 50, + stretchWidth = true, + stretchHeight = true + }; + m_graphFontStyle.normal.textColor = Color.white; + + m_wireTexture = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( IOUtils.WireTextureGUID ), typeof( Texture2D ) ) as Texture2D; + + m_initialized = m_graphBgTexture != null && + m_graphFgTexture != null && + m_wireTexture != null; + } + } +#if UNITY_2018_3_OR_NEWER + + +#endif + [OnOpenAssetAttribute()] + static bool OnOpenAsset( int instanceID, int line ) + { + if( line > -1 ) + { + return false; + } + Preferences.LoadDefaults(); +#if UNITY_2018_3_OR_NEWER + ASEPackageManagerHelper.RequestInfo(); + ASEPackageManagerHelper.Update(); + if( ASEPackageManagerHelper.IsProcessing ) + { + Shader selectedShader = Selection.activeObject as Shader; + if( selectedShader != null ) + { + if( IOUtils.IsASEShader( selectedShader ) ) + { + ASEPackageManagerHelper.SetupLateShader( selectedShader ); + return true; + } + } + else + { + Material mat = Selection.activeObject as Material; + if( mat != null ) + { + if( IOUtils.IsASEShader( mat.shader ) ) + { + ASEPackageManagerHelper.SetupLateMaterial( mat ); + return true; + } + } + else + { + AmplifyShaderFunction shaderFunction = Selection.activeObject as AmplifyShaderFunction; + if( shaderFunction != null ) + { + if( IOUtils.IsShaderFunction( shaderFunction.FunctionInfo ) ) + { + ASEPackageManagerHelper.SetupLateShaderFunction( shaderFunction ); + return true; + } + } + } + } + } + else +#endif + { + Shader selectedShader = Selection.activeObject as Shader; + if( selectedShader != null ) + { + if( IOUtils.IsASEShader( selectedShader ) ) + { + ConvertShaderToASE( selectedShader ); + return true; + } + } + else + { + Material mat = Selection.activeObject as Material; + if( mat != null ) + { + if( IOUtils.IsASEShader( mat.shader ) ) + { + LoadMaterialToASE( mat ); + return true; + } + } + else + { + AmplifyShaderFunction shaderFunction = Selection.activeObject as AmplifyShaderFunction; + if( shaderFunction != null ) + { + if( IOUtils.IsShaderFunction( shaderFunction.FunctionInfo ) ) + { + LoadShaderFunctionToASE( shaderFunction, false ); + return true; + } + } + } + } + } + + return false; + } + + [MenuItem( "Assets/Create/Amplify Shader/Surface", false, 84 )] + [MenuItem( "Assets/Create/Shader/Amplify Surface Shader" )] + static void CreateConfirmationStandardShader() + { + //string path = AssetDatabase.GetAssetPath( Selection.activeObject ); + //if( path == "" ) + //{ + // path = "Assets"; + //} + //else if( System.IO.Path.GetExtension( path ) != "" ) + //{ + // path = path.Replace( System.IO.Path.GetFileName( AssetDatabase.GetAssetPath( Selection.activeObject ) ), "" ); + //} + + //string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath( path + "/New Amplify Shader.shader" ); + var endNameEditAction = ScriptableObject.CreateInstance(); + ProjectWindowUtil.StartNameEditingIfProjectWindowExists( 0, endNameEditAction, "New Amplify Shader.shader"/*assetPathAndName*/, AssetPreview.GetMiniTypeThumbnail( typeof( Shader ) ), null ); + } + //static void CreateNewShader( ) + //{ + // CreateNewShader( null, null ); + //} + + static void CreateNewShader( string customPath , string customShaderName ) + { + + string path = string.Empty; + if( string.IsNullOrEmpty( customPath ) ) + { + if( Selection.activeObject != null ) + { + path = ( IOUtils.dataPath + AssetDatabase.GetAssetPath( Selection.activeObject ) ); + } + else + { + UnityEngine.Object[] selection = Selection.GetFiltered( typeof( UnityEngine.Object ), SelectionMode.DeepAssets ); + if( selection.Length > 0 && selection[ 0 ] != null ) + { + path = ( IOUtils.dataPath + AssetDatabase.GetAssetPath( selection[ 0 ] ) ); + } + else + { + path = Application.dataPath; + } + + } + + if( path.IndexOf( '.' ) > -1 ) + { + path = path.Substring( 0, path.LastIndexOf( '/' ) ); + } + path += "/"; + } + else + { + path = customPath; + } + + if( IOUtils.AllOpenedWindows.Count > 0 ) + { + EditorWindow openedWindow = AmplifyShaderEditorWindow.GetWindow(); + AmplifyShaderEditorWindow currentWindow = CreateTab(); + WindowHelper.AddTab( openedWindow, currentWindow ); + UIUtils.CurrentWindow = currentWindow; + Shader shader = UIUtils.CreateNewEmpty( path, customShaderName ); + Selection.activeObject = shader; + } + else + { + AmplifyShaderEditorWindow currentWindow = OpenWindow(); + UIUtils.CurrentWindow = currentWindow; + Shader shader = UIUtils.CreateNewEmpty( path, customShaderName ); + Selection.activeObject = shader; + } + //Selection.objects = new UnityEngine.Object[] { shader }; + } + + public static void CreateConfirmationTemplateShader( string templateGuid ) + { + UIUtils.NewTemplateGUID = templateGuid; + //string path = AssetDatabase.GetAssetPath( Selection.activeObject ); + //if( path == "" ) + //{ + // path = "Assets"; + //} + //else if( System.IO.Path.GetExtension( path ) != "" ) + //{ + // path = path.Replace( System.IO.Path.GetFileName( AssetDatabase.GetAssetPath( Selection.activeObject ) ), "" ); + //} + + //string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath( path + "/New Amplify Shader.shader" ); + var endNameEditAction = ScriptableObject.CreateInstance(); + ProjectWindowUtil.StartNameEditingIfProjectWindowExists( 0, endNameEditAction, "New Amplify Shader.shader"/*assetPathAndName*/, AssetPreview.GetMiniTypeThumbnail( typeof( Shader ) ), null ); + } + + public static Shader CreateNewTemplateShader( string templateGUID , string customPath = null, string customShaderName = null ) + { + string path = string.Empty; + if( string.IsNullOrEmpty( customPath ) ) + { + path = Selection.activeObject == null ? Application.dataPath : ( IOUtils.dataPath + AssetDatabase.GetAssetPath( Selection.activeObject ) ); + if( path.IndexOf( '.' ) > -1 ) + { + path = path.Substring( 0, path.LastIndexOf( '/' ) ); + } + path += "/"; + } + else + { + path = customPath; + } + Shader shader = null; + if( IOUtils.AllOpenedWindows.Count > 0 ) + { + EditorWindow openedWindow = AmplifyShaderEditorWindow.GetWindow(); + AmplifyShaderEditorWindow currentWindow = CreateTab(); + WindowHelper.AddTab( openedWindow, currentWindow ); + UIUtils.CurrentWindow = currentWindow; + shader = UIUtils.CreateNewEmptyTemplate( templateGUID, path, customShaderName ); + Selection.activeObject = shader; + } + else + { + AmplifyShaderEditorWindow currentWindow = OpenWindow(); + UIUtils.CurrentWindow = currentWindow; + shader = UIUtils.CreateNewEmptyTemplate( templateGUID, path, customShaderName ); + Selection.activeObject = shader; + } + + //Selection.objects = new UnityEngine.Object[] { shader }; + return shader; + } + + [MenuItem( "Assets/Create/Amplify Shader Function", false, 84 )] + [MenuItem( "Assets/Create/Shader/Amplify Shader Function" )] + static void CreateNewShaderFunction() + { + AmplifyShaderFunction asset = ScriptableObject.CreateInstance(); + + //string path = AssetDatabase.GetAssetPath( Selection.activeObject ); + //if( path == "" ) + //{ + // path = "Assets"; + //} + //else if( System.IO.Path.GetExtension( path ) != "" ) + //{ + // path = path.Replace( System.IO.Path.GetFileName( AssetDatabase.GetAssetPath( Selection.activeObject ) ), "" ); + //} + + //string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath( path + "/New ShaderFunction.asset" ); + + var endNameEditAction = ScriptableObject.CreateInstance(); + ProjectWindowUtil.StartNameEditingIfProjectWindowExists( asset.GetInstanceID(), endNameEditAction, "New ShaderFunction.asset"/*assetPathAndName*/, AssetPreview.GetMiniThumbnail( asset ), null ); + } + + public void UpdateTabTitle( string newTitle, bool modified ) + { + string[] titleArray = newTitle.Split( '/' ); + newTitle = titleArray[ titleArray.Length - 1 ]; + + if( !( m_currentTitle.Equals( newTitle ) && m_currentTitleMod == modified ) ) + { + this.titleContent.text = GenerateTabTitle( newTitle, modified ); + } + m_currentTitle = newTitle; + m_currentTitleMod = modified; + } + + public void OnProjectWindowChanged() + { + Shader selectedShader = Selection.activeObject as Shader; + if( selectedShader != null ) + { + if( m_mainGraphInstance != null && m_mainGraphInstance.CurrentMasterNode != null && selectedShader == m_mainGraphInstance.CurrentMasterNode.CurrentShader ) + { + m_lastOpenedLocation = AssetDatabase.GetAssetPath( selectedShader ); + } + } + } + + public void LoadProjectSelected( UnityEngine.Object selectedObject = null ) + { + bool hasFocus = true; + if( EditorWindow.focusedWindow != this ) + { + hasFocus = false; + } + + if( hasFocus && m_mainGraphInstance != null && m_mainGraphInstance.CurrentMasterNode != null ) + { + LoadObject( selectedObject ?? Selection.activeObject ); + } + else + { + m_delayedLoadObject = selectedObject ?? Selection.activeObject; + } + + if( !hasFocus ) + Focus(); + } + + public void LoadObject( UnityEngine.Object objToLoad ) + { + Shader selectedShader = objToLoad as Shader; + Material selectedMaterial = objToLoad as Material; + AmplifyShaderFunction selectedFunction = objToLoad as AmplifyShaderFunction; + + if( selectedFunction != null ) + { + IsShaderFunctionWindow = true; + m_mainGraphInstance.CurrentCanvasMode = NodeAvailability.ShaderFunction; + } + else + { + IsShaderFunctionWindow = false; + } + + ASESelectionMode selectedFileType = ASESelectionMode.Shader; + if( selectedShader != null ) + { + selectedFileType = ASESelectionMode.Shader; + } + else if( selectedMaterial != null ) + { + selectedFileType = ASESelectionMode.Material; + } + else if( selectedFunction != null ) + { + selectedFileType = ASESelectionMode.ShaderFunction; + } + + + switch( CurrentSelection ) + { + case ASESelectionMode.Shader: + { + if( ShaderIsModified ) + { + Shader currShader = m_mainGraphInstance.CurrentMasterNode.CurrentShader; + bool savePrevious = UIUtils.DisplayDialog( AssetDatabase.GetAssetPath( currShader ) ); + OnSaveShader( savePrevious, currShader, null, null ); + } + } + break; + case ASESelectionMode.Material: + { + if( ShaderIsModified ) + { + Shader currShader = m_mainGraphInstance.CurrentMasterNode.CurrentShader; + bool savePrevious = UIUtils.DisplayDialog( AssetDatabase.GetAssetPath( currShader ) ); + OnSaveShader( savePrevious, currShader, m_mainGraphInstance.CurrentMasterNode.CurrentMaterial, null ); + } + } + break; + case ASESelectionMode.ShaderFunction: + { + if( ShaderIsModified ) + { + bool savePrevious = UIUtils.DisplayDialog( AssetDatabase.GetAssetPath( m_openedShaderFunction ) ); + OnSaveShader( savePrevious, null, null, selectedFunction ); + } + } + break; + } + + switch( selectedFileType ) + { + case ASESelectionMode.Shader: + { + LoadDroppedObject( true, selectedShader, null ); + } + break; + case ASESelectionMode.Material: + { + LoadDroppedObject( true, selectedMaterial.shader, selectedMaterial ); + } + break; + case ASESelectionMode.ShaderFunction: + { + LoadDroppedObject( true, null, null, selectedFunction ); + } + break; + } + + m_openedShaderFunction = m_mainGraphInstance.CurrentShaderFunction; + + //Need to force one graph draw because it wont call OnGui propertly since its focuses somewhere else + // Focus() doesn't fix this since it only changes keyboard focus + m_drawInfo.InvertedZoom = 1 / m_cameraZoom; + + m_mainGraphInstance.IsLoading = true; + m_mainGraphInstance.Draw( m_drawInfo ); + m_mainGraphInstance.IsLoading = false; + ShaderIsModified = false; + Focus(); + Repaint(); + } + + public void OnProjectSelectionChanged() + { + if( m_loadShaderOnSelection ) + { + LoadProjectSelected(); + } + } + + ShaderLoadResult OnSaveShader( bool value, Shader shader, Material material, AmplifyShaderFunction function ) + { + if( value ) + { + SaveToDisk( false ); + } + + return value ? ShaderLoadResult.LOADED : ShaderLoadResult.FILE_NOT_FOUND; + } + + public void ResetCameraSettings() + { + m_cameraInfo = position; + m_cameraOffset = new Vector2( m_cameraInfo.width * 0.5f, m_cameraInfo.height * 0.5f ); + CameraZoom = 1; + } + + public void Reset() + { + if( m_mainGraphInstance == null ) + { + m_mainGraphInstance = CreateInstance(); + m_mainGraphInstance.Init(); + m_mainGraphInstance.ParentWindow = this; + m_mainGraphInstance.SetGraphId( 0 ); + } + m_mainGraphInstance.ResetEvents(); + m_mainGraphInstance.OnNodeEvent += OnNodeStoppedMovingEvent; + m_mainGraphInstance.OnMaterialUpdatedEvent += OnMaterialUpdated; + m_mainGraphInstance.OnShaderUpdatedEvent += OnShaderUpdated; + m_mainGraphInstance.OnEmptyGraphDetectedEvt += OnEmptyGraphDetected; + m_mainGraphInstance.OnNodeRemovedEvent += m_toolsWindow.OnNodeRemovedFromGraph; + m_outdatedShaderFromTemplateLoaded = false; + GraphCount = 1; + + FullCleanUndoStack(); + m_performFullUndoRegister = true; + m_toolsWindow.BorderStyle = null; + m_selectionMode = ASESelectionMode.Shader; + ResetCameraSettings(); + UIUtils.ResetMainSkin(); + m_duplicatePreventionBuffer.ReleaseAllData(); + if( m_genericMessageUI != null ) + m_genericMessageUI.CleanUpMessageStack(); + } + + + public Shader CreateNewGraph( string name ) + { + Reset(); + UIUtils.DirtyMask = false; + m_mainGraphInstance.CreateNewEmpty( name ); + m_lastOpenedLocation = string.Empty; + UIUtils.DirtyMask = true; + return m_mainGraphInstance.CurrentMasterNode.CurrentShader; + } + + public Shader CreateNewTemplateGraph( string templateGUID ) + { + Reset(); + UIUtils.DirtyMask = false; + m_mainGraphInstance.CreateNewEmptyTemplate( templateGUID ); + m_lastOpenedLocation = string.Empty; + UIUtils.DirtyMask = true; + return m_mainGraphInstance.CurrentMasterNode.CurrentShader; + } + + public Shader CreateNewGraph( Shader shader ) + { + Reset(); + UIUtils.DirtyMask = false; + m_mainGraphInstance.CreateNewEmpty( shader.name ); + m_mainGraphInstance.CurrentMasterNode.CurrentShader = shader; + + m_lastOpenedLocation = string.Empty; + UIUtils.DirtyMask = true; + return m_mainGraphInstance.CurrentMasterNode.CurrentShader; + } + + public void CreateNewFunctionGraph( AmplifyShaderFunction shaderFunction ) + { + Reset(); + UIUtils.DirtyMask = false; + m_mainGraphInstance.CreateNewEmptyFunction( shaderFunction ); + m_mainGraphInstance.CurrentShaderFunction = shaderFunction; + + m_lastOpenedLocation = AssetDatabase.GetAssetPath( shaderFunction ); //string.Empty; + UIUtils.DirtyMask = true; + //return m_mainGraphInstance.CurrentMasterNode.CurrentShader; + } + + public bool SaveToDisk( bool checkTimestamp ) + { + if( checkTimestamp ) + { + if( !m_cacheSaveOp ) + { + m_lastTimeSaved = EditorApplication.timeSinceStartup; + m_cacheSaveOp = true; + } + return false; + } + + + System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; + + m_customGraph = null; + m_cacheSaveOp = false; + ShaderIsModified = false; + m_mainGraphInstance.LoadedShaderVersion = VersionInfo.FullNumber; + m_lastTimeSaved = EditorApplication.timeSinceStartup; + + if( m_mainGraphInstance.CurrentMasterNodeId == Constants.INVALID_NODE_ID ) + { + Shader currentShader = m_mainGraphInstance.CurrentMasterNode != null ? m_mainGraphInstance.CurrentMasterNode.CurrentShader : null; + string newShader; + if( !String.IsNullOrEmpty( m_lastOpenedLocation ) ) + { + newShader = m_lastOpenedLocation; + } + else if( currentShader != null ) + { + newShader = AssetDatabase.GetAssetPath( currentShader ); + } + else + { + newShader = EditorUtility.SaveFilePanel( "Select Shader to save", Application.dataPath, "MyShader", "shader" ); + } + + if( !String.IsNullOrEmpty( newShader ) ) + { + ShowMessage( "No Master node assigned.\nShader file will only have node info" ); + IOUtils.StartSaveThread( GenerateGraphInfo(), newShader ); + AssetDatabase.Refresh(); + LoadFromDisk( newShader ); + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + return true; + } + } + else if( m_mainGraphInstance.CurrentMasterNode != null ) + { + //m_mainGraphInstance.CurrentStandardSurface.ForceReordering(); + Shader currShader = m_mainGraphInstance.CurrentMasterNode.CurrentShader; + if( currShader != null ) + { + m_mainGraphInstance.FireMasterNode( currShader ); + Material material = m_mainGraphInstance.CurrentMaterial; + m_lastpath = ( material != null ) ? AssetDatabase.GetAssetPath( material ) : AssetDatabase.GetAssetPath( currShader ); + EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, m_lastpath ); + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + if( IOUtils.OnShaderSavedEvent != null ) + { + string info = string.Empty; + if( !m_mainGraphInstance.IsStandardSurface ) + { + TemplateMultiPassMasterNode masterNode = m_mainGraphInstance.GetMainMasterNodeOfLOD( -1 ); + if( masterNode != null ) + { + info = masterNode.CurrentTemplate.GUID; + } + } + IOUtils.OnShaderSavedEvent( currShader, !m_mainGraphInstance.IsStandardSurface, info ); + } + return true; + } + else + { + + string shaderName; + string pathName; + IOUtils.GetShaderName( out shaderName, out pathName, Constants.DefaultShaderName, UIUtils.LatestOpenedFolder ); + if( !String.IsNullOrEmpty( pathName ) ) + { + UIUtils.CurrentWindow.CurrentGraph.CurrentMasterNode.SetName( shaderName ); + m_mainGraphInstance.FireMasterNode( pathName, true ); + m_lastpath = pathName; + EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, pathName ); + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + return true; + } + } + } + else + { + //m_nodeParametersWindow.ForceReordering(); + m_mainGraphInstance.ResetNodesLocalVariables(); + + List functionInputNodes = UIUtils.FunctionInputList(); + functionInputNodes.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + for( int i = 0; i < functionInputNodes.Count; i++ ) + { + functionInputNodes[ i ].OrderIndex = i; + } + + List functionOutputNodes = UIUtils.FunctionOutputList(); + functionOutputNodes.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + for( int i = 0; i < functionOutputNodes.Count; i++ ) + { + functionOutputNodes[ i ].OrderIndex = i; + } + + m_mainGraphInstance.CurrentShaderFunction.AdditionalDirectives.UpdateSaveItemsFromDirectives(); + m_mainGraphInstance.CurrentShaderFunction.FunctionInfo = GenerateGraphInfo(); + m_mainGraphInstance.CurrentShaderFunction.FunctionInfo = IOUtils.AddAdditionalInfo( m_mainGraphInstance.CurrentShaderFunction.FunctionInfo ); + + if( AssetDatabase.IsMainAsset( m_mainGraphInstance.CurrentShaderFunction ) ) + { + EditorUtility.SetDirty( m_mainGraphInstance.CurrentShaderFunction ); + } + else + { + //Debug.Log( LastOpenedLocation ); + //AssetDatabase.CreateAsset( m_mainGraphInstance.CurrentShaderFunction, LastOpenedLocation ); + } + + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + m_mainGraphInstance.CurrentShaderFunction.AdditionalDirectives.UpdateDirectivesFromSaveItems(); + IOUtils.FunctionNodeChanged = true; + m_lastpath = AssetDatabase.GetAssetPath( m_mainGraphInstance.CurrentShaderFunction ); + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + //EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, AssetDatabase.GetAssetPath( m_mainGraphInstance.CurrentShaderFunction ) ); + return true; + } + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + return false; + } + + public void OnToolButtonPressed( ToolButtonType type ) + { + switch( type ) + { + case ToolButtonType.New: + { + UIUtils.CreateNewEmpty(); + } + break; + case ToolButtonType.Open: + { + UIUtils.OpenFile(); + } + break; + case ToolButtonType.Save: + { + SaveToDisk( false ); + } + break; + case ToolButtonType.Library: + { + ShowShaderLibrary(); + } + break; + case ToolButtonType.Options: { } break; + case ToolButtonType.Update: + { + if( Preferences.GlobalClearLog ) + { + m_consoleLogWindow.ClearMessages(); + } +#if UNITY_2019_4_OR_NEWER + if( EditorSettings.asyncShaderCompilation && Preferences.GlobalShowAsyncMsg ) + { + ShowMessage( AsyncMessage ); + } +#endif + SaveToDisk( false ); + } + break; + case ToolButtonType.Live: + { + m_liveShaderEditing = !m_liveShaderEditing; + m_innerEditorVariables.LiveMode = m_liveShaderEditing; + // 0 off + // 1 on + // 2 pending + if( m_liveShaderEditing && m_mainGraphInstance.CurrentMasterNode != null && m_mainGraphInstance.CurrentMasterNode.CurrentShader == null ) + { + m_liveShaderEditing = false; + m_innerEditorVariables.LiveMode = false; + } + + UpdateLiveUI(); + + if( m_liveShaderEditing ) + { + SaveToDisk( false ); + } + } + break; + case ToolButtonType.OpenSourceCode: + { + AssetDatabase.OpenAsset( m_mainGraphInstance.CurrentMasterNode.CurrentShader, 1 ); + } + break; + case ToolButtonType.MasterNode: + { + m_mainGraphInstance.AssignMasterNode(); + } + break; + + case ToolButtonType.FocusOnMasterNode: + { + double currTime = EditorApplication.timeSinceStartup; + bool autoZoom = ( currTime - m_focusOnMasterNodeTimestamp ) < AutoZoomTime; + m_focusOnMasterNodeTimestamp = currTime; + FocusOnNode( m_mainGraphInstance.CurrentMasterNode, autoZoom ? 1 : m_cameraZoom, true ); + } + break; + + case ToolButtonType.FocusOnSelection: + { + FocusZoom( false, true, true ); + } + break; + case ToolButtonType.ShowInfoWindow: + { + PortLegendInfo.OpenWindow(); + } + break; + case ToolButtonType.ShowTipsWindow: + { + TipsWindow.ShowWindow( true ); + } + break; + case ToolButtonType.ShowConsole: + { + m_consoleLogWindow.Toggle(); + } + break; + case ToolButtonType.Share: + { + List selectedNodes = m_mainGraphInstance.SelectedNodes; + if( selectedNodes.Count > 0 ) + { + CopyToClipboard(); + StartPasteRequest(); + } + else + { + ShowMessage( "No nodes selected to share" ); + } + } + break; + case ToolButtonType.TakeScreenshot: + { +#if UNITY_EDITOR_WIN + this.Focus(); + m_aseHandle = WindowsUtil.GetActiveWindow(); + //m_aseHandle = FindASEWindowHandle(); + + bool takeit = EditorUtility.DisplayDialog( "Take Screenshot", "This is a work in progress feature that will undock itself if needed, increase the window outside of your screen resolution to take the shot, if something fails (ie: graph too big) you may need to restart Unity, do you wish to continue?", "Yes", "Cancel" ); + if( !takeit ) + break; + + if( this.IsDocked() ) + { + this.Undock(); + this.Focus(); + m_aseHandle = WindowsUtil.GetActiveWindow(); + } + + int windowLong = WindowsUtil.GetWindowLong( m_aseHandle, WindowsUtil.GWL_STYLE ); + + List selectedNodes = m_mainGraphInstance.AllNodes; + + Vector2 minPos = new Vector2( float.MaxValue, float.MaxValue ); + Vector2 maxPos = new Vector2( float.MinValue, float.MinValue ); + Vector2 centroid = Vector2.zero; + + for( int i = 0; i < selectedNodes.Count; i++ ) + { + Rect currPos = selectedNodes[ i ].TruePosition; + minPos.x = ( currPos.x < minPos.x ) ? currPos.x : minPos.x; + minPos.y = ( currPos.y < minPos.y ) ? currPos.y : minPos.y; + + maxPos.x = ( ( currPos.x + currPos.width ) > maxPos.x ) ? ( currPos.x + currPos.width ) : maxPos.x; + maxPos.y = ( ( currPos.y + currPos.height ) > maxPos.y ) ? ( currPos.y + currPos.height ) : maxPos.y; + } + + centroid = ( maxPos - minPos ); + + m_prevCameraOffset = m_cameraOffset; + m_prevCameraZoom = CameraZoom; + + WindowsUtil.SetWindowLong( m_aseHandle, WindowsUtil.GWL_STYLE, (int)( windowLong & ~( WindowsUtil.WS_SIZEBOX ) ) ); + var rect = new WindowsUtil.Rect(); + WindowsUtil.GetWindowRect( m_aseHandle, ref rect ); + m_prevWindowRect = new Rect( rect.Left, rect.Top, rect.Width, rect.Height ); + + WindowsUtil.SetWindowPos( m_aseHandle, 0, (int)m_prevWindowRect.xMin, (int)m_prevWindowRect.yMin, (int)centroid.x, (int)centroid.y, 0x0040 ); + WindowsUtil.SetWindowLong( m_aseHandle, WindowsUtil.GWL_STYLE, (int)( windowLong ) ); + + m_takeScreenShot = true; +#else + EditorUtility.DisplayDialog( "Take Screenshot", "This is a work in progress feature that only works in Windows environment", "Ok" ); +#endif + } + break; + case ToolButtonType.CleanUnusedNodes: + { + m_mainGraphInstance.CleanUnusedNodes(); + } + break; + case ToolButtonType.Help: + { + Application.OpenURL( Constants.HelpURL ); + } + break; + } + } + +#if UNITY_EDITOR_WIN + IntPtr FindASEWindowHandle() + { + System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess(); + + IntPtr[] winPtrs = WindowsUtil.GetProcessWindows( process.Id ); + m_aseHandle = IntPtr.Zero; + bool found = false; + for( int i = 0; i < winPtrs.Length; i++ ) + { + WindowsUtil.EnumChildWindows( winPtrs[ i ], delegate ( System.IntPtr hwnd, System.IntPtr param ) + { + System.Text.StringBuilder Title = new System.Text.StringBuilder( 256 ); + WindowsUtil.GetWindowText( hwnd, Title, Title.Capacity ); + + if( Title.ToString().Contains( "AmplifyShaderEditor.AmplifyShaderEditorWindow" ) ) + { + if( !found ) + { + m_aseHandle = winPtrs[ i ]; + found = true; + } + } + + return true; + }, System.IntPtr.Zero ); + } + + return m_aseHandle; + } + + void OpenSavedFolder() + { + m_openSavedFolder = false; + + var path = System.IO.Path.GetFullPath( Application.dataPath + "\\..\\ScreenshotASE.png" ); + EditorUtility.RevealInFinder( path ); + GUIUtility.ExitGUI(); + } + + void TakeScreenShot() + { + m_takeScreenShot = false; + + var cacher = RenderTexture.active; + RenderTexture.active = null; + + Texture2D m_screenshotTex2D = new Texture2D( (int)position.width, (int)position.height, TextureFormat.RGB24, false ); + m_screenshotTex2D.ReadPixels( new Rect( 0, 0, m_screenshotTex2D.width, m_screenshotTex2D.height ), 0, 0 ); + m_screenshotTex2D.Apply(); + + byte[] bytes = m_screenshotTex2D.EncodeToPNG(); + + var path = System.IO.Path.GetFullPath( Application.dataPath + "\\..\\ScreenshotASE.png" ); + System.IO.File.WriteAllBytes( path, bytes ); + + RenderTexture.active = cacher; + + ShowMessage( "[AmplifyShaderEditor] Screenshot successfully taken and saved at: " + path, consoleLog:true ); + + WindowsUtil.SetWindowPos( m_aseHandle, 0, (int)m_prevWindowRect.xMin, (int)m_prevWindowRect.yMin, (int)m_prevWindowRect.width, (int)m_prevWindowRect.height, 0x0040 ); + m_cameraOffset = m_prevCameraOffset; + CameraZoom = m_prevCameraZoom; + + m_openSavedFolder = true; + } +#endif + + + void UpdateLiveUI() + { + if( m_toolsWindow != null ) + { + m_toolsWindow.SetStateOnButton( ToolButtonType.Live, ( m_liveShaderEditing ) ? 1 : 0 ); + } + } + + void FocusZoom( bool forceAllNodes, bool doubleTap, bool smooth = true ) + { + List selectedNodes = ( m_mainGraphInstance.SelectedNodes.Count > 0 ) && !forceAllNodes ? m_mainGraphInstance.SelectedNodes : m_mainGraphInstance.AllNodes; + + Vector2 minPos = new Vector2( float.MaxValue, float.MaxValue ); + Vector2 maxPos = new Vector2( float.MinValue, float.MinValue ); + Vector2 centroid = Vector2.zero; + + for( int i = 0; i < selectedNodes.Count; i++ ) + { + Rect currPos = selectedNodes[ i ].TruePosition; + + minPos.x = ( currPos.x < minPos.x ) ? currPos.x : minPos.x; + minPos.y = ( currPos.y < minPos.y ) ? currPos.y : minPos.y; + + maxPos.x = ( ( currPos.x + currPos.width ) > maxPos.x ) ? ( currPos.x + currPos.width ) : maxPos.x; + maxPos.y = ( ( currPos.y + currPos.height ) > maxPos.y ) ? ( currPos.y + currPos.height ) : maxPos.y; + + } + + centroid = ( maxPos - minPos ); + + double currTime = EditorApplication.timeSinceStartup; + bool autoZoom = ( currTime - m_focusOnSelectionTimestamp ) < AutoZoomTime; + if( !doubleTap ) + autoZoom = true; + m_focusOnSelectionTimestamp = currTime; + + float zoom = m_cameraZoom; + if( autoZoom ) + { + zoom = 1f; + float canvasWidth = m_cameraInfo.width; + if( m_nodeParametersWindow.IsMaximized ) + canvasWidth -= m_nodeParametersWindow.RealWidth; + if( m_paletteWindow.IsMaximized ) + canvasWidth -= m_paletteWindow.RealWidth; + canvasWidth -= 40; + //float canvasWidth = AvailableCanvasWidth;// - 20; + float canvasHeight = AvailableCanvasHeight - 60; + if( centroid.x > canvasWidth || + centroid.y > canvasHeight ) + { + float hZoom = float.MinValue; + float vZoom = float.MinValue; + if( centroid.x > canvasWidth ) + { + hZoom = ( centroid.x ) / canvasWidth; + } + + if( centroid.y > canvasHeight ) + { + vZoom = ( centroid.y ) / canvasHeight; + } + zoom = ( hZoom > vZoom ) ? hZoom : vZoom; + } + } + + minPos.y -= 20 * zoom; + if( m_nodeParametersWindow.IsMaximized ) + minPos.x -= m_nodeParametersWindow.RealWidth * 0.5f * zoom; + if( m_paletteWindow.IsMaximized ) + minPos.x += m_paletteWindow.RealWidth * 0.5f * zoom; + + FocusOnPoint( minPos + centroid * 0.5f, zoom, smooth ); + } + + public void FocusOnNode( int nodeId, float zoom, bool selectNode, bool late = false ) + { + ParentNode node = m_mainGraphInstance.GetNode( nodeId ); + if( node != null ) + { + FocusOnNode( node, zoom, selectNode, late ); + } + } + + public void FocusOnNode( ParentNode node, float zoom, bool selectNode, bool late = false ) + { + if( late ) + { + m_nodeToFocus = node; + m_zoomToFocus = zoom; + m_selectNodeToFocus = selectNode; + return; + } + + if( selectNode ) + { + m_mainGraphInstance.SelectNode( node, false, false ); + } + + Vector2 nodePoint = node.CenterPosition; + nodePoint.x = nodePoint.x - ( m_nodeParametersWindow.RealWidth * 0.5f + m_paletteWindow.RealWidth * 0.5f ) * ( zoom > 0.999f ? zoom : CameraZoom ); + FocusOnPoint( nodePoint, zoom ); + } + + public void FocusOnPoint( Vector2 point, float zoom, bool smooth = true ) + { + if( zoom > 0.999f ) + { + if( smooth ) + SmoothZoom( zoom ); + else + CameraZoom = zoom; + } + + if( smooth ) + SmoothCameraOffset( -point + new Vector2( ( m_cameraInfo.width ) * 0.5f, m_cameraInfo.height * 0.5f ) * CameraZoom ); + else + m_cameraOffset = -point + new Vector2( ( m_cameraInfo.width ) * 0.5f, m_cameraInfo.height * 0.5f ) * CameraZoom; + } + + void SmoothZoom( float newZoom ) + { + m_smoothZoom = true; + m_zoomTime = 0; + m_targetZoom = newZoom; + m_zoomPivot = m_graphArea.center; + } + + void SmoothCameraOffset( Vector2 newOffset ) + { + m_smoothOffset = true; + m_offsetTime = 0; + m_targetOffset = newOffset; + } + + void PreTestLeftMouseDown() + { + if( m_currentEvent.type == EventType.MouseDown && m_currentEvent.button == ButtonClickId.LeftMouseButton ) + { + ParentNode node = m_mainGraphInstance.CheckNodeAt( m_currentMousePos ); + if( node != null ) + { + m_mainGraphInstance.NodeClicked = node.UniqueId; + return; + } + } + + m_mainGraphInstance.NodeClicked = -1; + } + + + + void OnLeftMouseDown() + { + Focus(); + + if( m_lastKeyPressed == KeyCode.Q ) + { + m_rmbStartPos = m_currentMousePos2D; + UseCurrentEvent(); + return; + } + + m_mouseDownOnValidArea = true; + m_lmbPressed = true; + if( m_currentEvent.alt ) + { + m_altBoxSelection = true; + } + + UIUtils.ShowContextOnPick = true; + ParentNode node = ( m_mainGraphInstance.NodeClicked < 0 ) ? m_mainGraphInstance.CheckNodeAt( m_currentMousePos ) : m_mainGraphInstance.GetClickedNode(); + if( node != null ) + { + m_mainGraphInstance.NodeClicked = node.UniqueId; + m_altBoxSelection = false; + + if( m_contextMenu.CheckShortcutKey() ) + { + if( node.ConnStatus == NodeConnectionStatus.Island ) + { + if( !m_multipleSelectionActive ) + { + ParentNode newNode = m_contextMenu.CreateNodeFromShortcutKey(); + if( newNode != null ) + { + newNode.ContainerGraph = m_mainGraphInstance; + newNode.Vec2Position = TranformedMousePos; + m_mainGraphInstance.AddNode( newNode, true ); + m_mainGraphInstance.SelectNode( newNode, false, false ); + ForceRepaint(); + } + ( node as CommentaryNode ).AddNodeToCommentary( newNode ); + } + } + } + else + { + if( node.OnClick( m_currentMousePos2D ) ) + { + if( !node.Selected ) + { + m_mainGraphInstance.SelectNode( node, ( m_currentEvent.modifiers == EventModifiers.Shift || m_currentEvent.modifiers == EventModifiers.Control ), true ); + } + else if( m_currentEvent.modifiers == EventModifiers.Shift || m_currentEvent.modifiers == EventModifiers.Control ) + { + m_mainGraphInstance.DeselectNode( node ); + } + + if( m_currentEvent.alt ) + { + int conn = 0; + for( int i = 0; i < node.InputPorts.Count; i++ ) + { + if( node.InputPorts[ i ].IsConnected ) + conn++; + } + + if( node.InputPorts.Count > 0 && node.OutputPorts.Count > 0 && conn > 0 && node.OutputPorts[ 0 ].IsConnected ) + { + m_altDragStarted = true; + } + } + + } + + if( m_currentEvent.alt ) + { + if( node.InputPorts.Count > 0 && node.OutputPorts.Count > 0 && node.InputPorts[ 0 ].IsConnected && node.OutputPorts[ 0 ].IsConnected ) + { + m_altDragStarted = true; + } + } + + return; + } + } + else if( !m_multipleSelectionActive ) + { + ParentNode newNode = m_contextMenu.CreateNodeFromShortcutKey(); + if( newNode != null ) + { + newNode.ContainerGraph = m_mainGraphInstance; + newNode.Vec2Position = TranformedMousePos; + m_mainGraphInstance.AddNode( newNode, true ); + m_mainGraphInstance.SelectNode( newNode, false, false ); + SetSaveIsDirty(); + ForceRepaint(); + } + else + { + List wireRefs = m_mainGraphInstance.GetWireBezierListInPos( m_currentMousePos2D ); + if( wireRefs != null && wireRefs.Count > 0 ) + { + for( int i = 0; i < wireRefs.Count; i++ ) + { + // Place wire code here + ParentNode outNode = m_mainGraphInstance.GetNode( wireRefs[ i ].OutNodeId ); + ParentNode inNode = m_mainGraphInstance.GetNode( wireRefs[ i ].InNodeId ); + + OutputPort outputPort = outNode.GetOutputPortByUniqueId( wireRefs[ i ].OutPortId ); + InputPort inputPort = inNode.GetInputPortByUniqueId( wireRefs[ i ].InPortId ); + + // Calculate the 4 points for bezier taking into account wire nodes and their automatic tangents + Vector3 endPos = new Vector3( inputPort.Position.x, inputPort.Position.y ); + Vector3 startPos = new Vector3( outputPort.Position.x, outputPort.Position.y ); + + float mag = ( endPos - startPos ).magnitude; + float resizedMag = Mathf.Min( mag, Constants.HORIZONTAL_TANGENT_SIZE * m_drawInfo.InvertedZoom ); + + Vector3 startTangent = new Vector3( startPos.x + resizedMag, startPos.y ); + Vector3 endTangent = new Vector3( endPos.x - resizedMag, endPos.y ); + + if( inNode != null && inNode.GetType() == typeof( WireNode ) ) + endTangent = endPos + ( ( inNode as WireNode ).TangentDirection ) * mag * 0.33f; + + if( outNode != null && outNode.GetType() == typeof( WireNode ) ) + startTangent = startPos - ( ( outNode as WireNode ).TangentDirection ) * mag * 0.33f; + + float dist = HandleUtility.DistancePointBezier( m_currentMousePos, startPos, endPos, startTangent, endTangent ); + if( dist < 10 ) + { + double doubleTapTime = EditorApplication.timeSinceStartup; + bool doubleTap = ( doubleTapTime - m_wiredDoubleTapTimestamp ) < WiredDoubleTapTime; + m_wiredDoubleTapTimestamp = doubleTapTime; + + if( doubleTap ) + { + Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateConnectionId ); + Undo.RegisterCompleteObjectUndo( m_mainGraphInstance, Constants.UndoCreateConnectionId ); + Undo.RecordObject( outNode, Constants.UndoCreateConnectionId ); + Undo.RecordObject( inNode, Constants.UndoCreateConnectionId ); + + ParentNode wireNode = m_mainGraphInstance.CreateNode( typeof( WireNode ), true ); + if( wireNode != null ) + { + wireNode.Vec2Position = TranformedMousePos; + + m_mainGraphInstance.CreateConnection( wireNode.InputPorts[ 0 ].NodeId, wireNode.InputPorts[ 0 ].PortId, outputPort.NodeId, outputPort.PortId ); + m_mainGraphInstance.CreateConnection( inputPort.NodeId, inputPort.PortId, wireNode.OutputPorts[ 0 ].NodeId, wireNode.OutputPorts[ 0 ].PortId ); + + SetSaveIsDirty(); + ForceRepaint(); + Undo.IncrementCurrentGroup(); + } + } + + break; + } + } + } + //Reset focus from any textfield which may be selected at this time + GUIUtility.keyboardControl = 0; + } + } + + if( m_currentEvent.modifiers != EventModifiers.Shift && m_currentEvent.modifiers != EventModifiers.Control && !m_altBoxSelection ) + m_mainGraphInstance.DeSelectAll(); + + if( m_wireReferenceUtils.ValidReferences() ) + { + m_wireReferenceUtils.InvalidateReferences(); + return; + } + + if( !m_contextMenu.CheckShortcutKey() && m_currentEvent.modifiers != EventModifiers.Shift && m_currentEvent.modifiers != EventModifiers.Control || m_altBoxSelection ) + { + // Only activate multiple selection if no node is selected and shift key not pressed + m_multipleSelectionActive = true; + + m_multipleSelectionStart = TranformedMousePos; + m_multipleSelectionArea.position = m_multipleSelectionStart; + m_multipleSelectionArea.size = Vector2.zero; + } + + UseCurrentEvent(); + } + + void OnLeftMouseDrag() + { + if( m_lostFocus ) + { + m_lostFocus = false; + return; + } + + if( m_lastKeyPressed == KeyCode.Q ) + { + if( m_currentEvent.alt ) + { + ModifyZoom( Constants.ALT_CAMERA_ZOOM_SPEED * ( m_currentEvent.delta.x + m_currentEvent.delta.y ), m_altKeyStartPos ); + } + else + { + m_cameraOffset += m_cameraZoom * m_currentEvent.delta; + } + UseCurrentEvent(); + return; + } + + if( m_altDragStarted ) + { + m_altDragStarted = false; + + if( m_currentEvent.modifiers == EventModifiers.Alt && CurrentGraph.SelectedNodes.Count == 1 ) + { + ParentNode node = CurrentGraph.SelectedNodes[ 0 ]; + int lastId = 0; + int conn = 0; + for( int i = 0; i < node.InputPorts.Count; i++ ) + { + if( node.InputPorts[ i ].IsConnected ) + { + conn++; + lastId = i; + } + } + + if( conn > 1 ) + lastId = 0; + + + + OutputPort outputPort = node.InputPorts[ lastId ].GetOutputConnection( 0 ); + ParentNode outputNode = m_mainGraphInstance.GetNode( outputPort.NodeId ); + bool outputIsWireNode = outputNode is WireNode; + + Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateConnectionId ); + node.RecordObject( Constants.UndoCreateConnectionId ); + outputNode.RecordObject( Constants.UndoCreateConnectionId ); + + List inputPorts = new List(); + for( int i = 0; i < node.OutputPorts[ 0 ].ConnectionCount; i++ ) + { + InputPort inputPort = node.OutputPorts[ 0 ].GetInputConnection( i ); + ParentNode inputNode = m_mainGraphInstance.GetNode( inputPort.NodeId ); + inputNode.RecordObject( Constants.UndoCreateConnectionId ); + inputPorts.Add( inputPort ); + } + + for( int i = 0; i < inputPorts.Count; i++ ) + { + if( outputIsWireNode ) + { + if( i == 0 ) + { + m_mainGraphInstance.CreateConnection( inputPorts[ i ].NodeId, inputPorts[ i ].PortId, outputPort.NodeId, outputPort.PortId ); + } + else + { + UIUtils.DeleteConnection( true, inputPorts[ i ].NodeId, inputPorts[ i ].PortId, false, true ); + } + } + else + { + m_mainGraphInstance.CreateConnection( inputPorts[ i ].NodeId, inputPorts[ i ].PortId, outputPort.NodeId, outputPort.PortId ); + } + } + + UIUtils.DeleteConnection( true, node.UniqueId, node.InputPorts[ lastId ].PortId, false, true ); + + SetSaveIsDirty(); + ForceRepaint(); + } + } + + if( !m_wireReferenceUtils.ValidReferences() && !m_altBoxSelection ) + { + if( m_mouseDownOnValidArea && m_insideEditorWindow ) + { + if( m_currentEvent.control ) + { + m_mainGraphInstance.MoveSelectedNodes( m_cameraZoom * m_currentEvent.delta, true ); + } + else + { + m_mainGraphInstance.MoveSelectedNodes( m_cameraZoom * m_currentEvent.delta ); + } + //m_mainGraphInstance.MoveSelectedNodes( m_cameraZoom * m_currentEvent.delta ); + m_autoPanDirActive = true; + } + } + else + { + List nodes = m_mainGraphInstance.GetNodesInGrid( m_drawInfo.TransformedMousePos ); + if( nodes != null && nodes.Count > 0 ) + { + Vector2 currentPortPos = new Vector2(); + Vector2 mousePos = TranformedMousePos; + + if( m_wireReferenceUtils.InputPortReference.IsValid ) + { + OutputPort currentPort = null; + float smallestDistance = float.MaxValue; + Vector2 smallestPosition = Vector2.zero; + for( int nodeIdx = 0; nodeIdx < nodes.Count; nodeIdx++ ) + { + List outputPorts = nodes[ nodeIdx ].OutputPorts; + if( outputPorts != null ) + { + for( int o = 0; o < outputPorts.Count; o++ ) + { + if( outputPorts[ o ].Available ) + { + currentPortPos.x = outputPorts[ o ].Position.x; + currentPortPos.y = outputPorts[ o ].Position.y; + + currentPortPos = currentPortPos * m_cameraZoom - m_cameraOffset; + float dist = ( mousePos - currentPortPos ).sqrMagnitude; + if( dist < smallestDistance ) + { + smallestDistance = dist; + smallestPosition = currentPortPos; + currentPort = outputPorts[ o ]; + } + } + } + } + } + + if( currentPort != null && currentPort.Available && ( smallestDistance < Constants.SNAP_SQR_DIST || currentPort.InsideActiveArea( ( mousePos + m_cameraOffset ) / m_cameraZoom ) ) ) + { + m_wireReferenceUtils.ActivateSnap( smallestPosition, currentPort ); + } + else + { + m_wireReferenceUtils.DeactivateSnap(); + } + } + + if( m_wireReferenceUtils.OutputPortReference.IsValid ) + { + InputPort currentPort = null; + float smallestDistance = float.MaxValue; + Vector2 smallestPosition = Vector2.zero; + for( int nodeIdx = 0; nodeIdx < nodes.Count; nodeIdx++ ) + { + List inputPorts = nodes[ nodeIdx ].InputPorts; + if( inputPorts != null ) + { + for( int i = 0; i < inputPorts.Count; i++ ) + { + if( inputPorts[ i ].Available ) + { + currentPortPos.x = inputPorts[ i ].Position.x; + currentPortPos.y = inputPorts[ i ].Position.y; + + currentPortPos = currentPortPos * m_cameraZoom - m_cameraOffset; + float dist = ( mousePos - currentPortPos ).sqrMagnitude; + if( dist < smallestDistance ) + { + smallestDistance = dist; + smallestPosition = currentPortPos; + currentPort = inputPorts[ i ]; + } + } + } + } + } + if( currentPort != null && currentPort.Available && ( smallestDistance < Constants.SNAP_SQR_DIST || currentPort.InsideActiveArea( ( mousePos + m_cameraOffset ) / m_cameraZoom ) ) ) + { + m_wireReferenceUtils.ActivateSnap( smallestPosition, currentPort ); + } + else + { + m_wireReferenceUtils.DeactivateSnap(); + } + } + } + else if( m_wireReferenceUtils.SnapEnabled ) + { + m_wireReferenceUtils.DeactivateSnap(); + } + } + UseCurrentEvent(); + } + + public void OnLeftMouseUp() + { + m_lmbPressed = false; + if( m_multipleSelectionActive ) + { + //m_multipleSelectionActive = false; + UpdateSelectionArea(); + //m_mainGraphInstance.MultipleSelection( m_multipleSelectionArea, ( m_currentEvent.modifiers == EventModifiers.Shift || m_currentEvent.modifiers == EventModifiers.Control ), true ); + if( m_currentEvent.alt && m_altBoxSelection ) + { + m_mainGraphInstance.MultipleSelection( m_multipleSelectionArea, !m_currentEvent.shift ); + } + else + { + m_mainGraphInstance.DeSelectAll(); + m_mainGraphInstance.MultipleSelection( m_multipleSelectionArea ); + } + } + + if( m_wireReferenceUtils.ValidReferences() ) + { + //Check if there is some kind of port beneath the mouse ... if so connect to it + ParentNode targetNode = m_wireReferenceUtils.SnapEnabled ? m_mainGraphInstance.GetNode( m_wireReferenceUtils.SnapPort.NodeId ) : m_mainGraphInstance.CheckNodeAt( m_currentMousePos ); + if( targetNode != null && targetNode.ConnStatus != NodeConnectionStatus.Island ) + { + if( m_wireReferenceUtils.InputPortReference.IsValid && m_wireReferenceUtils.InputPortReference.NodeId != targetNode.UniqueId ) + { + OutputPort outputPort = m_wireReferenceUtils.SnapEnabled ? targetNode.GetOutputPortByUniqueId( m_wireReferenceUtils.SnapPort.PortId ) : targetNode.CheckOutputPortAt( m_currentMousePos ); + if( outputPort != null && !outputPort.Locked && ( !m_wireReferenceUtils.InputPortReference.TypeLocked || + m_wireReferenceUtils.InputPortReference.DataType == WirePortDataType.OBJECT || + ( m_wireReferenceUtils.InputPortReference.TypeLocked && outputPort.DataType == m_wireReferenceUtils.InputPortReference.DataType ) ) ) + { + + ParentNode originNode = m_mainGraphInstance.GetNode( m_wireReferenceUtils.InputPortReference.NodeId ); + InputPort inputPort = originNode.GetInputPortByUniqueId( m_wireReferenceUtils.InputPortReference.PortId ); + UIUtils.MarkUndoAction(); + Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateConnectionId ); + originNode.RecordObject( Constants.UndoCreateConnectionId ); + targetNode.RecordObject( Constants.UndoCreateConnectionId ); + + if( inputPort.NotFreeForAllTypes && outputPort.NotFreeForAllTypes ) + { + if( !inputPort.CheckValidType( outputPort.DataType ) ) + { + UIUtils.ShowIncompatiblePortMessage( true, originNode, inputPort, targetNode, outputPort ); + m_wireReferenceUtils.InvalidateReferences(); + UseCurrentEvent(); + return; + } + + if( !outputPort.CheckValidType( inputPort.DataType ) ) + { + UIUtils.ShowIncompatiblePortMessage( false, targetNode, outputPort, originNode, inputPort ); + m_wireReferenceUtils.InvalidateReferences(); + UseCurrentEvent(); + return; + } + } + + inputPort.DummyAdd( outputPort.NodeId, outputPort.PortId ); + outputPort.DummyAdd( m_wireReferenceUtils.InputPortReference.NodeId, m_wireReferenceUtils.InputPortReference.PortId ); + + if( UIUtils.DetectNodeLoopsFrom( originNode, new Dictionary() ) ) + { + inputPort.DummyRemove(); + outputPort.DummyRemove(); + m_wireReferenceUtils.InvalidateReferences(); + ShowMessage( "Infinite Loop detected" ); + UseCurrentEvent(); + return; + } + + inputPort.DummyRemove(); + outputPort.DummyRemove(); + + if( inputPort.IsConnected ) + { + DeleteConnection( true, m_wireReferenceUtils.InputPortReference.NodeId, m_wireReferenceUtils.InputPortReference.PortId, true, false ); + } + + //link output to input + if( outputPort.ConnectTo( m_wireReferenceUtils.InputPortReference.NodeId, m_wireReferenceUtils.InputPortReference.PortId, m_wireReferenceUtils.InputPortReference.DataType, m_wireReferenceUtils.InputPortReference.TypeLocked ) ) + targetNode.OnOutputPortConnected( outputPort.PortId, m_wireReferenceUtils.InputPortReference.NodeId, m_wireReferenceUtils.InputPortReference.PortId ); + + //link input to output + if( inputPort.ConnectTo( outputPort.NodeId, outputPort.PortId, outputPort.DataType, m_wireReferenceUtils.InputPortReference.TypeLocked ) ) + originNode.OnInputPortConnected( m_wireReferenceUtils.InputPortReference.PortId, targetNode.UniqueId, outputPort.PortId ); + m_mainGraphInstance.MarkWireHighlights(); + } + else if( outputPort != null && m_wireReferenceUtils.InputPortReference.TypeLocked && m_wireReferenceUtils.InputPortReference.DataType != outputPort.DataType ) + { + ShowMessage( "Attempting to connect a port locked to type " + m_wireReferenceUtils.InputPortReference.DataType + " into a port of type " + outputPort.DataType ); + } + ShaderIsModified = true; + SetSaveIsDirty(); + } + + if( m_wireReferenceUtils.OutputPortReference.IsValid && m_wireReferenceUtils.OutputPortReference.NodeId != targetNode.UniqueId ) + { + InputPort inputPort = m_wireReferenceUtils.SnapEnabled ? targetNode.GetInputPortByUniqueId( m_wireReferenceUtils.SnapPort.PortId ) : targetNode.CheckInputPortAt( m_currentMousePos ); + if( inputPort != null && !inputPort.Locked && ( !inputPort.TypeLocked || + inputPort.DataType == WirePortDataType.OBJECT || + ( inputPort.TypeLocked && inputPort.DataType == m_wireReferenceUtils.OutputPortReference.DataType ) ) ) + { + ParentNode originNode = m_mainGraphInstance.GetNode( m_wireReferenceUtils.OutputPortReference.NodeId ); + OutputPort outputPort = originNode.GetOutputPortByUniqueId( m_wireReferenceUtils.OutputPortReference.PortId ); + + UIUtils.MarkUndoAction(); + Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateConnectionId ); + originNode.RecordObject( Constants.UndoCreateConnectionId ); + targetNode.RecordObject( Constants.UndoCreateConnectionId ); + + if( inputPort.NotFreeForAllTypes && outputPort.NotFreeForAllTypes ) + { + if( !inputPort.CheckValidType( outputPort.DataType ) ) + { + UIUtils.ShowIncompatiblePortMessage( true, targetNode, inputPort, originNode, outputPort ); + m_wireReferenceUtils.InvalidateReferences(); + UseCurrentEvent(); + return; + } + + if( !outputPort.CheckValidType( inputPort.DataType ) ) + { + UIUtils.ShowIncompatiblePortMessage( false, originNode, outputPort, targetNode, inputPort ); + m_wireReferenceUtils.InvalidateReferences(); + UseCurrentEvent(); + return; + } + } + + inputPort.DummyAdd( m_wireReferenceUtils.OutputPortReference.NodeId, m_wireReferenceUtils.OutputPortReference.PortId ); + outputPort.DummyAdd( inputPort.NodeId, inputPort.PortId ); + if( UIUtils.DetectNodeLoopsFrom( targetNode, new Dictionary() ) ) + { + inputPort.DummyRemove(); + outputPort.DummyRemove(); + m_wireReferenceUtils.InvalidateReferences(); + ShowMessage( "Infinite Loop detected" ); + UseCurrentEvent(); + return; + } + + inputPort.DummyRemove(); + outputPort.DummyRemove(); + + if( inputPort.IsConnected ) + { + if( m_currentEvent.control && m_wireReferenceUtils.SwitchPortReference.IsValid ) + { + ParentNode oldOutputNode = UIUtils.GetNode( inputPort.GetConnection( 0 ).NodeId ); + OutputPort oldOutputPort = oldOutputNode.GetOutputPortByUniqueId( inputPort.GetConnection( 0 ).PortId ); + + ParentNode switchNode = UIUtils.GetNode( m_wireReferenceUtils.SwitchPortReference.NodeId ); + InputPort switchPort = switchNode.GetInputPortByUniqueId( m_wireReferenceUtils.SwitchPortReference.PortId ); + + switchPort.DummyAdd( oldOutputPort.NodeId, oldOutputPort.PortId ); + oldOutputPort.DummyAdd( switchPort.NodeId, switchPort.PortId ); + if( UIUtils.DetectNodeLoopsFrom( switchNode, new Dictionary() ) ) + { + switchPort.DummyRemove(); + oldOutputPort.DummyRemove(); + m_wireReferenceUtils.InvalidateReferences(); + ShowMessage( "Infinite Loop detected" ); + UseCurrentEvent(); + return; + } + + switchPort.DummyRemove(); + oldOutputPort.DummyRemove(); + + DeleteConnection( true, inputPort.NodeId, inputPort.PortId, true, false ); + ConnectInputToOutput( switchPort.NodeId, switchPort.PortId, oldOutputPort.NodeId, oldOutputPort.PortId ); + } + else + { + DeleteConnection( true, inputPort.NodeId, inputPort.PortId, true, false ); + } + } + inputPort.InvalidateAllConnections(); + + + //link input to output + if( inputPort.ConnectTo( m_wireReferenceUtils.OutputPortReference.NodeId, m_wireReferenceUtils.OutputPortReference.PortId, m_wireReferenceUtils.OutputPortReference.DataType, inputPort.TypeLocked ) ) + targetNode.OnInputPortConnected( inputPort.PortId, m_wireReferenceUtils.OutputPortReference.NodeId, m_wireReferenceUtils.OutputPortReference.PortId ); + //link output to input + + if( outputPort.ConnectTo( inputPort.NodeId, inputPort.PortId, inputPort.DataType, inputPort.TypeLocked ) ) + originNode.OnOutputPortConnected( m_wireReferenceUtils.OutputPortReference.PortId, targetNode.UniqueId, inputPort.PortId ); + m_mainGraphInstance.MarkWireHighlights(); + } + else if( inputPort != null && inputPort.TypeLocked && inputPort.DataType != m_wireReferenceUtils.OutputPortReference.DataType ) + { + ShowMessage( "Attempting to connect a " + m_wireReferenceUtils.OutputPortReference.DataType + " to a port locked to type " + inputPort.DataType ); + } + ShaderIsModified = true; + SetSaveIsDirty(); + } + m_wireReferenceUtils.InvalidateReferences(); + } + else + { + if( UIUtils.ShowContextOnPick ) + m_contextPalette.Show( m_currentMousePos2D, m_cameraInfo ); + else + m_wireReferenceUtils.InvalidateReferences(); + } + } + else if( m_currentEvent.modifiers == EventModifiers.Alt && m_altAvailable && CurrentGraph.SelectedNodes.Count == 1 && !m_altBoxSelection && !m_multipleSelectionActive ) + { + List wireRefs = m_mainGraphInstance.GetWireBezierListInPos( m_currentMousePos2D ); + if( wireRefs != null && wireRefs.Count > 0 ) + { + float closestDist = 50; + int closestId = 0; + + for( int i = 0; i < wireRefs.Count; i++ ) + { + ParentNode outNode = m_mainGraphInstance.GetNode( wireRefs[ i ].OutNodeId ); + ParentNode inNode = m_mainGraphInstance.GetNode( wireRefs[ i ].InNodeId ); + + if( outNode == CurrentGraph.SelectedNodes[ 0 ] || inNode == CurrentGraph.SelectedNodes[ 0 ] ) + continue; + + OutputPort outputPort = outNode.GetOutputPortByUniqueId( wireRefs[ i ].OutPortId ); + InputPort inputPort = inNode.GetInputPortByUniqueId( wireRefs[ i ].InPortId ); + + // Calculate the 4 points for bezier taking into account wire nodes and their automatic tangents + Vector3 endPos = new Vector3( inputPort.Position.x, inputPort.Position.y ); + Vector3 startPos = new Vector3( outputPort.Position.x, outputPort.Position.y ); + + float mag = ( endPos - startPos ).magnitude; + float resizedMag = Mathf.Min( mag, Constants.HORIZONTAL_TANGENT_SIZE * m_drawInfo.InvertedZoom ); + + Vector3 startTangent = new Vector3( startPos.x + resizedMag, startPos.y ); + Vector3 endTangent = new Vector3( endPos.x - resizedMag, endPos.y ); + + if( inNode != null && inNode.GetType() == typeof( WireNode ) ) + endTangent = endPos + ( ( inNode as WireNode ).TangentDirection ) * mag * 0.33f; + + if( outNode != null && outNode.GetType() == typeof( WireNode ) ) + startTangent = startPos - ( ( outNode as WireNode ).TangentDirection ) * mag * 0.33f; + + //Vector2 pos = ( CurrentGraph.SelectedNodes[0].CenterPosition + m_cameraOffset ) / m_cameraZoom; + + float dist = HandleUtility.DistancePointBezier( /*pos*/ m_currentMousePos, startPos, endPos, startTangent, endTangent ); + if( dist < 40 ) + { + if( dist < closestDist ) + { + closestDist = dist; + closestId = i; + } + } + } + + if( closestDist < 40 ) + { + ParentNode outNode = m_mainGraphInstance.GetNode( wireRefs[ closestId ].OutNodeId ); + ParentNode inNode = m_mainGraphInstance.GetNode( wireRefs[ closestId ].InNodeId ); + + OutputPort outputPort = outNode.GetOutputPortByUniqueId( wireRefs[ closestId ].OutPortId ); + InputPort inputPort = inNode.GetInputPortByUniqueId( wireRefs[ closestId ].InPortId ); + + ParentNode selectedNode = CurrentGraph.SelectedNodes[ 0 ]; + if( selectedNode.InputPorts.Count > 0 && selectedNode.OutputPorts.Count > 0 ) + { + Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateConnectionId ); + selectedNode.RecordObject( Constants.UndoCreateConnectionId ); + inNode.RecordObject( Constants.UndoCreateConnectionId ); + outNode.RecordObject( Constants.UndoCreateConnectionId ); + + m_mainGraphInstance.CreateConnection( selectedNode.UniqueId, selectedNode.InputPorts[ 0 ].PortId, outputPort.NodeId, outputPort.PortId ); + m_mainGraphInstance.CreateConnection( inputPort.NodeId, inputPort.PortId, selectedNode.UniqueId, selectedNode.OutputPorts[ 0 ].PortId ); + } + + SetSaveIsDirty(); + ForceRepaint(); + } + } + } + UIUtils.ShowContextOnPick = true; + m_altBoxSelection = false; + m_multipleSelectionActive = false; + UseCurrentEvent(); + } + + public void ConnectInputToOutput( int inNodeId, int inPortId, int outNodeId, int outPortId, bool registerUndo = true ) + { + ParentNode inNode = m_mainGraphInstance.GetNode( inNodeId ); + ParentNode outNode = m_mainGraphInstance.GetNode( outNodeId ); + if( inNode != null && outNode != null ) + { + InputPort inPort = inNode.GetInputPortByUniqueId( inPortId ); + OutputPort outPort = outNode.GetOutputPortByUniqueId( outPortId ); + if( inPort != null && outPort != null ) + { + if( registerUndo ) + { + Undo.RegisterCompleteObjectUndo( this, Constants.UndoCreateConnectionId ); + inNode.RecordObject( Constants.UndoCreateConnectionId ); + outNode.RecordObject( Constants.UndoCreateConnectionId ); + } + + if( inPort.ConnectTo( outNodeId, outPortId, outPort.DataType, inPort.TypeLocked ) ) + { + inNode.OnInputPortConnected( inPortId, outNodeId, outPortId ); + } + + if( outPort.ConnectTo( inNodeId, inPortId, inPort.DataType, inPort.TypeLocked ) ) + { + outNode.OnOutputPortConnected( outPortId, inNodeId, inPortId ); + } + } + m_mainGraphInstance.MarkWireHighlights(); + ShaderIsModified = true; + } + } + + void OnRightMouseDown() + { + Focus(); + m_rmbStartPos = m_currentMousePos2D; + UseCurrentEvent(); + } + + void OnRightMouseDrag() + { + // We look at the control to detect when user hits a tooltip ( which has a hot control of 0 ) + // This needs to be checked because on this first "frame" of hitting a tooltip because it generates incorrect mouse delta values + if( GUIUtility.hotControl == 0 && m_lastHotControl != 0 ) + { + m_lastHotControl = GUIUtility.hotControl; + return; + } + + m_lastHotControl = GUIUtility.hotControl; + if( m_currentEvent.alt ) + { + ModifyZoom( Constants.ALT_CAMERA_ZOOM_SPEED * ( m_currentEvent.delta.x + m_currentEvent.delta.y ), m_altKeyStartPos ); + } + else + { + m_cameraOffset += m_cameraZoom * m_currentEvent.delta; + } + UseCurrentEvent(); + } + + void OnRightMouseUp() + { + //Resetting the hot control test variable so it can be used again on right mouse drag detection ( if we did not do this then m_lastHotControl could be left with a a value of 0 and wouldn't be able to be correctly used on rthe drag ) + m_lastHotControl = -1; + + if( ( m_rmbStartPos - m_currentMousePos2D ).sqrMagnitude < Constants.RMB_SCREEN_DIST ) + { + ParentNode node = m_mainGraphInstance.CheckNodeAt( m_currentMousePos, true ); + if( node == null ) + { + m_contextPalette.Show( m_currentMousePos2D, m_cameraInfo ); + } + } + UseCurrentEvent(); + } + + void UpdateSelectionArea() + { + m_multipleSelectionArea.size = TranformedMousePos - m_multipleSelectionStart; + } + + public void OnValidObjectsDropped( UnityEngine.Object[] droppedObjs ) + { + bool propagateDraggedObjsToNode = true; + // Only supporting single drag&drop object selection + if( droppedObjs.Length == 1 ) + { + ShaderIsModified = true; + SetSaveIsDirty(); + // Check if its a shader, material or game object and if so load the shader graph code from it + Shader newShader = droppedObjs[ 0 ] as Shader; + Material newMaterial = null; + if( newShader == null ) + { + newMaterial = droppedObjs[ 0 ] as Material; +#if UNITY_2018_1_OR_NEWER + bool isProcedural = ( newMaterial != null ); +#else + // Disabling Substance Deprecated warning +#pragma warning disable 0618 + bool isProcedural = ( newMaterial != null && newMaterial is ProceduralMaterial ); +#pragma warning restore 0618 +#endif + if( newMaterial != null && !isProcedural ) + { + if( UIUtils.IsUnityNativeShader( AssetDatabase.GetAssetPath( newMaterial.shader ) ) ) + { + return; + } + //newShader = newMaterial.shader; + LoadMaterialToASE( newMaterial ); + //m_mainGraphInstance.UpdateMaterialOnMasterNode( newMaterial ); + } + else + { + GameObject go = droppedObjs[ 0 ] as GameObject; + if( go != null ) + { + Renderer renderer = go.GetComponent(); + if( renderer ) + { + newMaterial = renderer.sharedMaterial; + newShader = newMaterial.shader; + } + } + } + } + + if( newShader != null ) + { + ConvertShaderToASE( newShader ); + + propagateDraggedObjsToNode = false; + } + + // if not shader loading then propagate the seletion to whats below the mouse + if( propagateDraggedObjsToNode ) + { + ParentNode node = m_mainGraphInstance.CheckNodeAt( m_currentMousePos ); + if( node != null ) + { + // if there's a node then pass the object into it to see if there's a setup with it + node.OnObjectDropped( droppedObjs[ 0 ] ); + } + else + { + // If not then check if there's a node that can be created through the dropped object + ParentNode newNode = m_contextMenu.CreateNodeFromCastType( droppedObjs[ 0 ].GetType() ); + if( newNode ) + { + newNode.ContainerGraph = m_mainGraphInstance; + newNode.Vec2Position = TranformedMousePos; + m_mainGraphInstance.AddNode( newNode, true ); + newNode.SetupFromCastObject( droppedObjs[ 0 ] ); + m_mainGraphInstance.SelectNode( newNode, false, false ); + ForceRepaint(); + bool find = false; + if( newNode is FunctionNode && CurrentGraph.CurrentShaderFunction != null ) + find = SearchFunctionNodeRecursively( CurrentGraph.CurrentShaderFunction ); + + if( find ) + { + DestroyNode( newNode, false ); + ShowMessage( "Shader Function loop detected, new node was removed to prevent errors." ); + } + } + } + } + } + } + + public bool SearchFunctionNodeRecursively( AmplifyShaderFunction function ) + { + List graphList = UIUtils.FunctionList(); + + bool nodeFind = false; + + for( int i = 0; i < graphList.Count; i++ ) + { + ParentGraph temp = CustomGraph; + CustomGraph = graphList[ i ].FunctionGraph; + nodeFind = SearchFunctionNodeRecursively( function ); + CustomGraph = temp; + + //Debug.Log( "tested = " + node.Function.FunctionName + " : " + function.FunctionName ); + + if( graphList[ i ].Function == function ) + return true; + } + + return nodeFind; + } + + public void SetDelayedMaterialMode( Material material ) + { + if( material == null ) + return; + m_delayedMaterialSet = material; + } + + public ShaderLoadResult LoadDroppedObject( bool value, Shader shader, Material material, AmplifyShaderFunction shaderFunction = null ) + { + UIUtils.CurrentWindow = this; + ShaderLoadResult result; + if( shaderFunction != null ) + { + string assetDatapath = AssetDatabase.GetAssetPath( shaderFunction ); + string latestOpenedFolder = Application.dataPath + assetDatapath.Substring( 6 ); + UIUtils.LatestOpenedFolder = latestOpenedFolder.Substring( 0, latestOpenedFolder.LastIndexOf( '/' ) + 1 ); + result = LoadFromDisk( assetDatapath, shaderFunction ); + CurrentSelection = ASESelectionMode.ShaderFunction; + IsShaderFunctionWindow = true; + titleContent.text = GenerateTabTitle( shaderFunction.FunctionName ); + titleContent.image = UIUtils.ShaderFunctionIcon; + m_lastpath = assetDatapath; + m_nodeParametersWindow.OnShaderFunctionLoad(); + //EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, assetDatapath ); + } + else if( value && shader != null ) + { + string assetDatapath = AssetDatabase.GetAssetPath( shader ); + string latestOpenedFolder = Application.dataPath + assetDatapath.Substring( 6 ); + UIUtils.LatestOpenedFolder = latestOpenedFolder.Substring( 0, latestOpenedFolder.LastIndexOf( '/' ) + 1 ); + result = LoadFromDisk( assetDatapath ); + switch( result ) + { + case ShaderLoadResult.LOADED: + { + m_mainGraphInstance.UpdateShaderOnMasterNode( shader ); + } + break; + case ShaderLoadResult.ASE_INFO_NOT_FOUND: + { + ShowMessage( "Loaded shader wasn't created with ASE. Saving it will remove previous data." ); + UIUtils.CreateEmptyFromInvalid( shader ); + } + break; + case ShaderLoadResult.FILE_NOT_FOUND: + case ShaderLoadResult.UNITY_NATIVE_PATHS: + { + UIUtils.CreateEmptyFromInvalid( shader ); + } + break; + } + + m_mainGraphInstance.UpdateMaterialOnMasterNode( material ); + m_mainGraphInstance.SetMaterialModeOnGraph( material ); + + if( material != null ) + { + CurrentSelection = ASESelectionMode.Material; + IsShaderFunctionWindow = false; + titleContent.text = GenerateTabTitle( material.name ); + titleContent.image = UIUtils.MaterialIcon; + if( material.HasProperty( IOUtils.DefaultASEDirtyCheckId ) ) + { + material.SetInt( IOUtils.DefaultASEDirtyCheckId, 1 ); + } + m_lastpath = AssetDatabase.GetAssetPath( material ); + EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, m_lastpath ); + } + else + { + CurrentSelection = ASESelectionMode.Shader; + IsShaderFunctionWindow = false; + titleContent.text = GenerateTabTitle( shader.name ); + titleContent.image = UIUtils.ShaderIcon; + m_lastpath = AssetDatabase.GetAssetPath( shader ); + EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, m_lastpath ); + } + } + else + { + result = ShaderLoadResult.FILE_NOT_FOUND; + } + return result; + } + + bool InsideMenus( Vector2 position ) + { + for( int i = 0; i < m_registeredMenus.Count; i++ ) + { + if( m_registeredMenus[ i ].IsInside( position ) ) + { + return true; + } + } + return false; + } + + void HandleGUIEvents() + { + if( m_currentEvent.type == EventType.KeyDown ) + { + m_contextMenu.UpdateKeyPress( m_currentEvent.keyCode ); + } + else if( m_currentEvent.type == EventType.KeyUp ) + { + m_contextMenu.UpdateKeyReleased( m_currentEvent.keyCode ); + } + + if( InsideMenus( m_currentMousePos2D ) ) + { + if( m_currentEvent.type == EventType.Used ) + m_mouseDownOnValidArea = false; + + if( m_currentEvent.type == EventType.MouseDown ) + { + m_mouseDownOnValidArea = false; + UseCurrentEvent(); + } + return; + } + else if( m_nodeParametersWindow.IsResizing || m_paletteWindow.IsResizing ) + { + m_mouseDownOnValidArea = false; + } + + int controlID = GUIUtility.GetControlID( FocusType.Passive ); + switch( m_currentEvent.GetTypeForControl( controlID ) ) + { + case EventType.MouseDown: + { + GUIUtility.hotControl = controlID; + switch( m_currentEvent.button ) + { + case ButtonClickId.LeftMouseButton: + { + OnLeftMouseDown(); + } + break; + case ButtonClickId.RightMouseButton: + case ButtonClickId.MiddleMouseButton: + { + OnRightMouseDown(); + } + break; + } + } + break; + case EventType.MouseMove: + { + m_keyEvtMousePos2D = m_currentEvent.mousePosition; + } + break; + case EventType.MouseUp: + { + GUIUtility.hotControl = 0; + switch( m_currentEvent.button ) + { + case ButtonClickId.LeftMouseButton: + { + OnLeftMouseUp(); + } + break; + case ButtonClickId.MiddleMouseButton: break; + case ButtonClickId.RightMouseButton: + { + OnRightMouseUp(); + } + break; + } + } + break; + case EventType.MouseDrag: + { + switch( m_currentEvent.button ) + { + case ButtonClickId.LeftMouseButton: + { + OnLeftMouseDrag(); + } + break; + case ButtonClickId.MiddleMouseButton: + case ButtonClickId.RightMouseButton: + { + OnRightMouseDrag(); + } + break; + } + } + break; + case EventType.ScrollWheel: + { + OnScrollWheel(); + } + break; + case EventType.KeyDown: + { + OnKeyboardDown(); + } + break; + case EventType.KeyUp: + { + OnKeyboardUp(); + } + break; + case EventType.ValidateCommand: + { + switch( m_currentEvent.commandName ) + { + case CopyCommand: + case PasteCommand: + case SelectAll: + case Duplicate: + { + m_currentEvent.Use(); + } + break; + case ObjectSelectorClosed: + { + m_mouseDownOnValidArea = false; + } + break; + } + } + break; + case EventType.ExecuteCommand: + { + m_currentEvent.Use(); + switch( m_currentEvent.commandName ) + { + case CopyCommand: + { + CopyToClipboard(); + } + break; + case PasteCommand: + { + PasteFromClipboard( true ); + } + break; + case SelectAll: + { + m_mainGraphInstance.SelectAll(); + ForceRepaint(); + } + break; + case Duplicate: + { + CopyToClipboard(); + PasteFromClipboard( true ); + } + break; + case ObjectSelectorClosed: + { + m_mouseDownOnValidArea = false; + } + break; + } + } + break; + case EventType.Repaint: + { + } + break; + } + + m_dragAndDropTool.TestDragAndDrop( m_graphArea ); + + } + + public void DeleteConnection( bool isInput, int nodeId, int portId, bool registerOnLog, bool propagateCallback ) + { + m_mainGraphInstance.DeleteConnection( isInput, nodeId, portId, registerOnLog, propagateCallback ); + } + + void DeleteSelectedNodes() + { + if( m_mainGraphInstance.SelectedNodes.Count == 0 ) + return; + + UIUtils.ClearUndoHelper(); + ParentNode[] selectedNodes = new ParentNode[ m_mainGraphInstance.SelectedNodes.Count ]; + for( int i = 0; i < selectedNodes.Length; i++ ) + { + selectedNodes[ i ] = m_mainGraphInstance.SelectedNodes[ i ]; + selectedNodes[ i ].Rewire(); + UIUtils.CheckUndoNode( selectedNodes[ i ] ); + } + + //Check nodes connected to deleted nodes to preserve connections on undo + List extraNodes = new List(); + for( int selectedNodeIdx = 0; selectedNodeIdx < selectedNodes.Length; selectedNodeIdx++ ) + { + // Check inputs + { + int inputIdxCount = selectedNodes[ selectedNodeIdx ].InputPorts.Count; + if( inputIdxCount > 0 ) + { + for( int inputIdx = 0; inputIdx < inputIdxCount; inputIdx++ ) + { + if( selectedNodes[ selectedNodeIdx ].InputPorts[ inputIdx ].IsConnected ) + { + int nodeIdx = selectedNodes[ selectedNodeIdx ].InputPorts[ inputIdx ].ExternalReferences[ 0 ].NodeId; + if( nodeIdx > -1 ) + { + ParentNode node = m_mainGraphInstance.GetNode( nodeIdx ); + if( node != null && UIUtils.CheckUndoNode( node ) ) + { + extraNodes.Add( node ); + } + } + } + } + } + } + + // Check outputs + int outputIdxCount = selectedNodes[ selectedNodeIdx ].OutputPorts.Count; + if( outputIdxCount > 0 ) + { + for( int outputIdx = 0; outputIdx < outputIdxCount; outputIdx++ ) + { + int inputIdxCount = selectedNodes[ selectedNodeIdx ].OutputPorts[ outputIdx ].ExternalReferences.Count; + if( inputIdxCount > 0 ) + { + for( int inputIdx = 0; inputIdx < inputIdxCount; inputIdx++ ) + { + int nodeIdx = selectedNodes[ selectedNodeIdx ].OutputPorts[ outputIdx ].ExternalReferences[ inputIdx ].NodeId; + if( nodeIdx > -1 ) + { + ParentNode node = m_mainGraphInstance.GetNode( nodeIdx ); + if( UIUtils.CheckUndoNode( node ) ) + { + extraNodes.Add( node ); + } + } + } + } + } + } + } + + UIUtils.ClearUndoHelper(); + //Undo.IncrementCurrentGroup(); + //Record deleted nodes + UIUtils.MarkUndoAction(); + Undo.RegisterCompleteObjectUndo( this, Constants.UndoDeleteNodeId ); + Undo.RegisterCompleteObjectUndo( m_mainGraphInstance, Constants.UndoDeleteNodeId ); + Undo.RecordObjects( selectedNodes, Constants.UndoDeleteNodeId ); + Undo.RecordObjects( extraNodes.ToArray(), Constants.UndoDeleteNodeId ); + + //Record deleting connections + for( int i = 0; i < selectedNodes.Length; i++ ) + { + selectedNodes[ i ].Alive = false; + m_mainGraphInstance.DeleteAllConnectionFromNode( selectedNodes[ i ], false, true, true ); + } + //Delete + m_mainGraphInstance.DeleteNodesOnArray( ref selectedNodes ); + + + //Undo.IncrementCurrentGroup(); + extraNodes.Clear(); + extraNodes = null; + + EditorUtility.SetDirty( this ); + + ForceRepaint(); + } + + void OnKeyboardUp() + { + CheckKeyboardCameraUp(); + + if( m_altPressDown ) + { + m_altPressDown = false; + } + + if( m_shortcutManager.ActivateShortcut( m_currentEvent.modifiers, m_lastKeyPressed, false ) ) + { + ForceRepaint(); + } + m_lastKeyPressed = KeyCode.None; + } + + bool OnKeyboardPress( KeyCode code ) + { + return ( m_currentEvent.keyCode == code && m_lastKeyPressed == KeyCode.None ); + } + + void CheckKeyboardCameraDown() + { + if( m_contextPalette.IsActive ) + return; + if( m_currentEvent.alt ) + { + bool foundKey = false; + float dir = 0; + switch( m_currentEvent.keyCode ) + { + case KeyCode.UpArrow: foundKey = true; dir = 1; break; + case KeyCode.DownArrow: foundKey = true; dir = -1; break; + case KeyCode.LeftArrow: foundKey = true; dir = 1; break; + case KeyCode.RightArrow: foundKey = true; dir = -1; break; + } + if( foundKey ) + { + ModifyZoom( Constants.ALT_CAMERA_ZOOM_SPEED * dir * m_cameraSpeed, new Vector2( m_cameraInfo.width * 0.5f, m_cameraInfo.height * 0.5f ) ); + if( m_cameraSpeed < 15 ) + m_cameraSpeed += 0.2f; + UseCurrentEvent(); + } + + + } + else + { + bool foundKey = false; + Vector2 dir = Vector2.zero; + switch( m_currentEvent.keyCode ) + { + case KeyCode.UpArrow: foundKey = true; dir = Vector2.up; break; + case KeyCode.DownArrow: foundKey = true; dir = Vector2.down; break; + case KeyCode.LeftArrow: foundKey = true; dir = Vector2.right; break; + case KeyCode.RightArrow: foundKey = true; dir = Vector2.left; break; + } + if( foundKey ) + { + m_cameraOffset += m_cameraZoom * m_cameraSpeed * dir; + if( m_cameraSpeed < 15 ) + m_cameraSpeed += 0.2f; + + UseCurrentEvent(); + } + } + } + + void CheckKeyboardCameraUp() + { + switch( m_currentEvent.keyCode ) + { + case KeyCode.UpArrow: + case KeyCode.DownArrow: + case KeyCode.LeftArrow: + case KeyCode.RightArrow: m_cameraSpeed = 1; break; + } + } + + void OnKeyboardDown() + { + //if( DebugConsoleWindow.DeveloperMode ) + //{ + // if( OnKeyboardPress( KeyCode.F8 ) ) + // { + // Shader currShader = CurrentGraph.CurrentShader; + // ShaderUtilEx.OpenCompiledShader( currShader, ShaderInspectorPlatformsPopupEx.GetCurrentMode(), ShaderInspectorPlatformsPopupEx.GetCurrentPlatformMask(), ShaderInspectorPlatformsPopupEx.GetCurrentVariantStripping() == 0 ); + + // string filename = Application.dataPath; + // filename = filename.Replace( "Assets", "Temp/Compiled-" ); + // string shaderFilename = AssetDatabase.GetAssetPath( currShader ); + // int lastIndex = shaderFilename.LastIndexOf( '/' ) + 1; + // filename = filename + shaderFilename.Substring( lastIndex ); + + // string compiledContents = IOUtils.LoadTextFileFromDisk( filename ); + // Debug.Log( compiledContents ); + // } + + // if( OnKeyboardPress( KeyCode.F9 ) ) + // { + // m_nodeExporterUtils.CalculateShaderInstructions( CurrentGraph.CurrentShader ); + // } + //} + + CheckKeyboardCameraDown(); + + if( m_lastKeyPressed == KeyCode.None ) + { + m_shortcutManager.ActivateShortcut( m_currentEvent.modifiers, m_currentEvent.keyCode, true ); + } + + if( m_currentEvent.control && m_currentEvent.shift && m_currentEvent.keyCode == KeyCode.V ) + { + PasteFromClipboard( false ); + } + + if( !m_altPressDown && ( OnKeyboardPress( KeyCode.LeftAlt ) || OnKeyboardPress( KeyCode.RightAlt ) || OnKeyboardPress( KeyCode.AltGr ) ) ) + { + m_altPressDown = true; + m_altAvailable = true; + m_altKeyStartPos = m_currentMousePos2D; + } + + if( m_currentEvent.keyCode != KeyCode.None && m_currentEvent.modifiers == EventModifiers.None ) + { + m_lastKeyPressed = m_currentEvent.keyCode; + } + } + + IEnumerator m_coroutine; + + private void StartPasteRequest() + { + m_coroutine = SendPostCoroutine( "http://paste.amplify.pt/api/create" ); + EditorApplication.update += PasteRequest; + } + + IEnumerator SendPostCoroutine( string url ) + { + WWWForm form = new WWWForm(); + form.AddField( "text", Clipboard.ClipboardId + ";" + EditorPrefs.GetString( Clipboard.ClipboardId, string.Empty ) ); + form.AddField( "title", "ASE Copy" ); + form.AddField( "name", "ASE" ); + form.AddField( "private", "1" ); + form.AddField( "lang", "text" ); + form.AddField( "expire", "0" ); + + UnityWebRequest www = UnityWebRequest.Post( url, form ); +#if UNITY_2017_2_OR_NEWER + www.SendWebRequest(); +#else + www.Send(); +#endif + + yield return www; + } + + public void PasteRequest() + { + UnityWebRequest www = (UnityWebRequest)m_coroutine.Current; + if( !m_coroutine.MoveNext() ) + { + if( !www.isDone ) + { + m_coroutine.MoveNext(); + } + else + { +#if UNITY_2020_1_OR_NEWER + if( www.result == UnityWebRequest.Result.ConnectionError ) +#elif UNITY_2017_1_OR_NEWER + if( www.isNetworkError ) +#else + if( www.isError ) +#endif + { + Debug.Log( "[AmplifyShaderEditor]\n" + www.error ); + } + else + { + // Print Body + string finalURL = www.downloadHandler.text; + + if( finalURL.IndexOf( "paste.amplify.pt/view/" ) > -1 ) + { + System.Text.RegularExpressions.Regex parser = new System.Text.RegularExpressions.Regex( @".*(http:\/\/paste.amplify.pt\/view\/)([0-9a-z]*).*", System.Text.RegularExpressions.RegexOptions.Singleline ); + finalURL = parser.Replace( finalURL, "$1raw/$2" ); + + ShowMessage( "Link copied to clipboard\n"+ finalURL, consoleLog:false ); + Debug.Log( "[AmplifyShaderEditor] Link copied to clipboard\n"+ finalURL+"\n" ); + // Copy Paste to clipboard + EditorGUIUtility.systemCopyBuffer = finalURL; + } + else + { + Debug.Log( "[AmplifyShaderEditor] Failed to generate paste:\n" + finalURL ); + } + } + EditorApplication.update -= PasteRequest; + } + } + } + + void OnScrollWheel() + { + ModifyZoomSmooth( m_currentEvent.delta.y, m_currentMousePos2D ); + UseCurrentEvent(); + } + + void ModifyZoom( float zoomIncrement, Vector2 pivot ) + { + float minCam = Mathf.Min( ( m_cameraInfo.width - ( m_nodeParametersWindow.RealWidth + m_paletteWindow.RealWidth ) ), ( m_cameraInfo.height - ( m_toolsWindow.Height ) ) ); + if( minCam < 1 ) + minCam = 1; + + float dynamicMaxZoom = m_mainGraphInstance.MaxNodeDist / minCam; + + Vector2 canvasPos = TranformPosition( pivot ); + if( zoomIncrement < 0 ) + CameraZoom = Mathf.Max( m_cameraZoom + zoomIncrement * Constants.CAMERA_ZOOM_SPEED, Constants.CAMERA_MIN_ZOOM ); + else if( CameraZoom < Mathf.Max( Constants.CAMERA_MAX_ZOOM, dynamicMaxZoom ) ) + CameraZoom = m_cameraZoom + zoomIncrement * Constants.CAMERA_ZOOM_SPEED;// Mathf.Min( m_cameraZoom + zoomIncrement * Constants.CAMERA_ZOOM_SPEED, Mathf.Max( Constants.CAMERA_MAX_ZOOM, dynamicMaxZoom ) ); + m_cameraOffset.x = pivot.x * m_cameraZoom - canvasPos.x; + m_cameraOffset.y = pivot.y * m_cameraZoom - canvasPos.y; + } + + void ModifyZoomSmooth( float zoomIncrement, Vector2 pivot ) + { + if( m_smoothZoom && Mathf.Sign( m_targetZoomIncrement * zoomIncrement ) >= 0 ) + m_targetZoomIncrement += zoomIncrement; + else + m_targetZoomIncrement = zoomIncrement; + + m_smoothZoom = true; + m_zoomTime = 0; + + float minCam = Mathf.Min( ( m_cameraInfo.width - ( m_nodeParametersWindow.RealWidth + m_paletteWindow.RealWidth ) ), ( m_cameraInfo.height - ( m_toolsWindow.Height ) ) ); + if( minCam < 1 ) + minCam = 1; + + float dynamicMaxZoom = m_mainGraphInstance.MaxNodeDist / minCam; + if( m_targetZoomIncrement < 0 ) + m_targetZoom = Mathf.Max( m_cameraZoom + m_targetZoomIncrement * Constants.CAMERA_ZOOM_SPEED, Constants.CAMERA_MIN_ZOOM ); + else if( CameraZoom < Mathf.Max( Constants.CAMERA_MAX_ZOOM, dynamicMaxZoom ) ) + m_targetZoom = m_cameraZoom + m_targetZoomIncrement * Constants.CAMERA_ZOOM_SPEED;// Mathf.Min( m_cameraZoom + zoomIncrement * Constants.CAMERA_ZOOM_SPEED, Mathf.Max( Constants.CAMERA_MAX_ZOOM, dynamicMaxZoom ) ); + + m_zoomPivot = pivot; + } + + void OnSelectionChange() + { + ForceRepaint(); + } + + private void OnFocus() + { + EditorGUI.FocusTextInControl( null ); +//#if UNITY_2019_1_OR_NEWER +// m_fixOnFocus = true; +//#endif + } + + void OnLostFocus() + { + m_lostFocus = true; + m_multipleSelectionActive = false; + m_wireReferenceUtils.InvalidateReferences(); + if( m_genericMessageUI != null ) + m_genericMessageUI.CleanUpMessageStack(); + m_nodeParametersWindow.OnLostFocus(); + m_paletteWindow.OnLostFocus(); + m_contextMenu.ResetShortcutKeyStates(); + } + + void CopyToClipboard() + { + m_copyPasteDeltaMul = 0; + m_copyPasteDeltaPos = new Vector2( float.MaxValue, float.MaxValue ); + m_clipboard.ClearClipboard(); + m_copyPasteInitialPos = m_mainGraphInstance.SelectedNodesCentroid; + m_clipboard.AddToClipboard( m_mainGraphInstance.SelectedNodes, m_copyPasteInitialPos, m_mainGraphInstance ); + } + + ParentNode CreateNodeFromClipboardData( int clipId ) + { + string[] parameters = m_clipboard.CurrentClipboardStrData[ clipId ].Data.Split( IOUtils.FIELD_SEPARATOR ); + System.Type nodeType = System.Type.GetType( parameters[ IOUtils.NodeTypeId ] ); + NodeAttributes attributes = m_contextMenu.GetNodeAttributesForType( nodeType ); + if( attributes != null && !UIUtils.GetNodeAvailabilityInBitArray( attributes.NodeAvailabilityFlags, m_mainGraphInstance.CurrentCanvasMode ) && !UIUtils.GetNodeAvailabilityInBitArray( attributes.NodeAvailabilityFlags, m_currentNodeAvailability ) ) + return null; + + ParentNode newNode = (ParentNode)ScriptableObject.CreateInstance( nodeType ); + newNode.IsNodeBeingCopied = true; + if( newNode != null ) + { + newNode.ContainerGraph = m_mainGraphInstance; + newNode.ClipboardFullReadFromString( ref parameters ); + m_mainGraphInstance.AddNode( newNode, true, true, true, false ); + newNode.IsNodeBeingCopied = false; + m_clipboard.CurrentClipboardStrData[ clipId ].NewNodeId = newNode.UniqueId; + return newNode; + } + return null; + } + + void CreateConnectionsFromClipboardData( int clipId ) + { + if( String.IsNullOrEmpty( m_clipboard.CurrentClipboardStrData[ clipId ].Connections ) ) + return; + string[] lines = m_clipboard.CurrentClipboardStrData[ clipId ].Connections.Split( IOUtils.LINE_TERMINATOR ); + + for( int lineIdx = 0; lineIdx < lines.Length; lineIdx++ ) + { + string[] parameters = lines[ lineIdx ].Split( IOUtils.FIELD_SEPARATOR ); + + int InNodeId = 0; + int InPortId = 0; + int OutNodeId = 0; + int OutPortId = 0; + + try + { + InNodeId = Convert.ToInt32( parameters[ IOUtils.InNodeId ] ); + InPortId = Convert.ToInt32( parameters[ IOUtils.InPortId ] ); + + OutNodeId = Convert.ToInt32( parameters[ IOUtils.OutNodeId ] ); + OutPortId = Convert.ToInt32( parameters[ IOUtils.OutPortId ] ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + + int newInNodeId = m_clipboard.GeNewNodeId( InNodeId ); + int newOutNodeId = m_clipboard.GeNewNodeId( OutNodeId ); + + if( newInNodeId > -1 && newOutNodeId > -1 ) + { + ParentNode inNode = m_mainGraphInstance.GetNode( newInNodeId ); + ParentNode outNode = m_mainGraphInstance.GetNode( newOutNodeId ); + + InputPort inputPort = null; + OutputPort outputPort = null; + + if( inNode != null && outNode != null ) + { + inNode.IsNodeBeingCopied = true; + outNode.IsNodeBeingCopied = true; + inputPort = inNode.GetInputPortByUniqueId( InPortId ); + outputPort = outNode.GetOutputPortByUniqueId( OutPortId ); + if( inputPort != null && outputPort != null ) + { + inputPort.ConnectTo( newOutNodeId, OutPortId, outputPort.DataType, false ); + outputPort.ConnectTo( newInNodeId, InPortId, inputPort.DataType, inputPort.TypeLocked ); + + inNode.OnInputPortConnected( InPortId, newOutNodeId, OutPortId ); + outNode.OnOutputPortConnected( OutPortId, newInNodeId, InPortId ); + } + + inNode.IsNodeBeingCopied = false; + outNode.IsNodeBeingCopied = false; + } + } + } + } + + private void StartGetRequest( string url ) + { + m_coroutine = SendGetCoroutine( url ); + EditorApplication.update += GetRequest; + } + + IEnumerator SendGetCoroutine( string url ) + { + UnityWebRequest www = UnityWebRequest.Get( url ); +#if UNITY_2017_2_OR_NEWER + www.SendWebRequest(); +#else + www.Send(); +#endif + + yield return www; + } + + public void GetRequest() + { + UnityWebRequest www = (UnityWebRequest)m_coroutine.Current; + if( !m_coroutine.MoveNext() ) + { + if( !www.isDone ) + { + m_coroutine.MoveNext(); + } + else + { +#if UNITY_2020_1_OR_NEWER + if( www.result == UnityWebRequest.Result.ConnectionError ) +#elif UNITY_2017_1_OR_NEWER + if( www.isNetworkError ) +#else + if( www.isError ) +#endif + { + Debug.Log( "[AmplifyShaderEditor]\n" + www.error ); + } + else + { + string data = www.downloadHandler.text; + if( data.IndexOf( Clipboard.ClipboardId + ";" ) > -1 ) + { + data = www.downloadHandler.text.Replace( Clipboard.ClipboardId + ";", "" ); + if( data.IndexOf( "
-1 ) + { + System.Text.RegularExpressions.Regex parser = new System.Text.RegularExpressions.Regex( @"(.*)
-1 ) + { + StartGetRequest( result ); + return; + } + + if( result.IndexOf( Clipboard.ClipboardId + ";" ) > -1 ) + { + result = result.Replace( Clipboard.ClipboardId + ";", "" ); + EditorPrefs.SetString( Clipboard.ClipboardId, result ); + } + + m_mainGraphInstance.IsDuplicating = true; + m_copyPasteInitialPos = m_clipboard.GetDataFromEditorPrefs(); + if( m_clipboard.CurrentClipboardStrData.Count == 0 ) + { + return; + } + + Vector2 deltaPos = TranformedKeyEvtMousePos - m_copyPasteInitialPos; + if( ( m_copyPasteDeltaPos - deltaPos ).magnitude > 5.0f ) + { + m_copyPasteDeltaMul = 0; + } + else + { + m_copyPasteDeltaMul += 1; + } + m_copyPasteDeltaPos = deltaPos; + + m_mainGraphInstance.DeSelectAll(); + UIUtils.InhibitMessages = true; + + if( m_clipboard.CurrentClipboardStrData.Count > 0 ) + { + UIUtils.MarkUndoAction(); + Undo.RegisterCompleteObjectUndo( this, Constants.UndoPasteNodeId ); + } + + List createdNodes = new List(); + for( int i = 0; i < m_clipboard.CurrentClipboardStrData.Count; i++ ) + { + ParentNode node = CreateNodeFromClipboardData( i ); + if( node != null ) + { + m_clipboard.CurrentClipboardStrData[ i ].NewNodeId = node.UniqueId; + Vector2 pos = node.Vec2Position; + node.Vec2Position = pos + deltaPos + m_copyPasteDeltaMul * Constants.CopyPasteDeltaPos; + //node.RefreshExternalReferences(); + node.AfterDuplication(); + createdNodes.Add( node ); + m_mainGraphInstance.SelectNode( node, true, false ); + } + } + + if( copyConnections ) + { + for( int i = 0; i < m_clipboard.CurrentClipboardStrData.Count; i++ ) + { + CreateConnectionsFromClipboardData( i ); + } + } + + // Refresh external references must always be called after all nodes are created + for( int i = 0; i < createdNodes.Count; i++ ) + { + createdNodes[ i ].RefreshExternalReferences(); + } + createdNodes.Clear(); + createdNodes = null; + //Need to force increment on Undo because if not Undo may incorrectly group consecutive pastes + Undo.IncrementCurrentGroup(); + + UIUtils.InhibitMessages = false; + ShaderIsModified = true; + SetSaveIsDirty(); + ForceRepaint(); + m_mainGraphInstance.IsDuplicating = false; + } + + public string GenerateGraphInfo() + { + string graphInfo = IOUtils.ShaderBodyBegin + '\n'; + string nodesInfo = ""; + string connectionsInfo = ""; + graphInfo += VersionInfo.FullLabel + '\n'; + graphInfo += ( + m_cameraInfo.x.ToString() + IOUtils.FIELD_SEPARATOR + + m_cameraInfo.y.ToString() + IOUtils.FIELD_SEPARATOR + + m_cameraInfo.width.ToString() + IOUtils.FIELD_SEPARATOR + + m_cameraInfo.height.ToString() + IOUtils.FIELD_SEPARATOR + + m_cameraOffset.x.ToString() + IOUtils.FIELD_SEPARATOR + + m_cameraOffset.y.ToString() + IOUtils.FIELD_SEPARATOR + + m_cameraZoom.ToString() + IOUtils.FIELD_SEPARATOR + + m_nodeParametersWindow.IsMaximized + IOUtils.FIELD_SEPARATOR + + m_paletteWindow.IsMaximized + '\n' + ); + m_mainGraphInstance.OrderNodesByGraphDepth(); + m_mainGraphInstance.WriteToString( ref nodesInfo, ref connectionsInfo ); + graphInfo += nodesInfo; + graphInfo += connectionsInfo; + graphInfo += IOUtils.ShaderBodyEnd + '\n'; + + return graphInfo; + } + + // TODO: this need to be fused to the main load function somehow + public static void LoadFromMeta( ref ParentGraph graph, GraphContextMenu contextMenu, string meta ) + { + graph.IsLoading = true; + graph.CleanNodes(); + + int checksumId = meta.IndexOf( IOUtils.CHECKSUM ); + if( checksumId > -1 ) + { + string checkSumStoredValue = meta.Substring( checksumId ); + string trimmedBuffer = meta.Remove( checksumId ); + + string[] typeValuePair = checkSumStoredValue.Split( IOUtils.VALUE_SEPARATOR ); + if( typeValuePair != null && typeValuePair.Length == 2 ) + { + // Check read checksum and compare with the actual shader body to detect external changes + string currentChecksumValue = IOUtils.CreateChecksum( trimmedBuffer ); + if( DebugConsoleWindow.DeveloperMode && !currentChecksumValue.Equals( typeValuePair[ 1 ] ) ) + { + //ShowMessage( "Wrong checksum" ); + } + + trimmedBuffer = trimmedBuffer.Replace( "\r", string.Empty ); + // find node info body + int shaderBodyId = trimmedBuffer.IndexOf( IOUtils.ShaderBodyBegin ); + if( shaderBodyId > -1 ) + { + trimmedBuffer = trimmedBuffer.Substring( shaderBodyId ); + //Find set of instructions + string[] instructions = trimmedBuffer.Split( IOUtils.LINE_TERMINATOR ); + // First line is to be ignored and second line contains version + string[] versionParams = instructions[ 1 ].Split( IOUtils.VALUE_SEPARATOR ); + if( versionParams.Length == 2 ) + { + int version = 0; + try + { + version = Convert.ToInt32( versionParams[ 1 ] ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + //if( version > versionInfo.FullNumber ) + //{ + //ShowMessage( "This shader was created on a new ASE version\nPlease install v." + version ); + //} + + if( DebugConsoleWindow.DeveloperMode ) + { + //if( version < versionInfo.FullNumber ) + //{ + //ShowMessage( "This shader was created on a older ASE version\nSaving will update it to the new one." ); + //} + } + + graph.LoadedShaderVersion = version; + } + else + { + //ShowMessage( "Corrupted version" ); + } + + // Dummy values,camera values can only be applied after node loading is complete + Rect dummyCameraInfo = new Rect(); + Vector2 dummyCameraOffset = new Vector2(); + //float dummyCameraZoom = 0; + //bool applyDummy = false; + //bool dummyNodeParametersWindowMaximized = false; + //bool dummyPaletteWindowMaximized = false; + + //Second line contains camera information ( position, size, offset and zoom ) + string[] cameraParams = instructions[ 2 ].Split( IOUtils.FIELD_SEPARATOR ); + if( cameraParams.Length == 9 ) + { + //applyDummy = true; + try + { + dummyCameraInfo.x = Convert.ToSingle( cameraParams[ 0 ] ); + dummyCameraInfo.y = Convert.ToSingle( cameraParams[ 1 ] ); + dummyCameraInfo.width = Convert.ToSingle( cameraParams[ 2 ] ); + dummyCameraInfo.height = Convert.ToSingle( cameraParams[ 3 ] ); + dummyCameraOffset.x = Convert.ToSingle( cameraParams[ 4 ] ); + dummyCameraOffset.y = Convert.ToSingle( cameraParams[ 5 ] ); + + //dummyCameraZoom = Convert.ToSingle( cameraParams[ 6 ] ); + //dummyNodeParametersWindowMaximized = Convert.ToBoolean( cameraParams[ 7 ] ); + //dummyPaletteWindowMaximized = Convert.ToBoolean( cameraParams[ 8 ] ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + else + { + //ShowMessage( "Camera parameters are corrupted" ); + } + + // valid instructions are only between the line after version and the line before the last one ( which contains ShaderBodyEnd ) + for( int instructionIdx = 3; instructionIdx < instructions.Length - 1; instructionIdx++ ) + { + //TODO: After all is working, convert string parameters to ints in order to speed up reading + string[] parameters = instructions[ instructionIdx ].Split( IOUtils.FIELD_SEPARATOR ); + + // All nodes must be created before wiring the connections ... + // Since all nodes on the save op are written before the wires, we can safely create them + // If that order is not maintained the it's because of external editing and its the users responsability + switch( parameters[ 0 ] ) + { + case IOUtils.NodeParam: + { + string typeStr = parameters[ IOUtils.NodeTypeId ]; + typeStr = IOUtils.NodeTypeReplacer.ContainsKey( typeStr ) ? IOUtils.NodeTypeReplacer[ typeStr ] : typeStr; + System.Type type = System.Type.GetType( typeStr ); + if( type == null ) + { +#if UNITY_2017_3_OR_NEWER + try + { + var editorAssembly = System.Reflection.Assembly.Load( "Assembly-CSharp-Editor" ); + if( editorAssembly != null ) + { + type = editorAssembly.GetType( typeStr ); + } + } + catch( Exception ) + { + + } +#endif + } + if( type != null ) + { + System.Type oldType = type; + NodeAttributes attribs = contextMenu.GetNodeAttributesForType( type ); + if( attribs == null ) + { + attribs = contextMenu.GetDeprecatedNodeAttributesForType( type ); + if( attribs != null ) + { + if( attribs.Deprecated && attribs.DeprecatedAlternativeType != null ) + { + type = attribs.DeprecatedAlternativeType; + //ShowMessage( string.Format( "Node {0} is deprecated and was replaced by {1} ", attribs.Name, attribs.DeprecatedAlternative ) ); + } + } + } + + ParentNode newNode = (ParentNode)ScriptableObject.CreateInstance( type ); + if( newNode != null ) + { + try + { + newNode.ContainerGraph = graph; + if( oldType != type ) + { + newNode.ParentReadFromString( ref parameters ); + newNode.ReadFromDeprecated( ref parameters, oldType ); + newNode.WasDeprecated = true; + } + else + newNode.ReadFromString( ref parameters ); + + + if( oldType == type ) + { + newNode.ReadInputDataFromString( ref parameters ); + if( UIUtils.CurrentShaderVersion() > 5107 ) + { + newNode.ReadOutputDataFromString( ref parameters ); + } + } + } + catch( Exception e ) + { + Debug.LogException( e, newNode ); + } + graph.AddNode( newNode, false, true, false ); + } + } + else + { + UIUtils.ShowMessage( string.Format( "{0} is not a valid ASE node ", parameters[ IOUtils.NodeTypeId ] ), MessageSeverity.Error ); + } + } + break; + case IOUtils.WireConnectionParam: + { + int InNodeId = 0; + int InPortId = 0; + int OutNodeId = 0; + int OutPortId = 0; + + try + { + InNodeId = Convert.ToInt32( parameters[ IOUtils.InNodeId ] ); + InPortId = Convert.ToInt32( parameters[ IOUtils.InPortId ] ); + OutNodeId = Convert.ToInt32( parameters[ IOUtils.OutNodeId ] ); + OutPortId = Convert.ToInt32( parameters[ IOUtils.OutPortId ] ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + ParentNode inNode = graph.GetNode( InNodeId ); + ParentNode outNode = graph.GetNode( OutNodeId ); + + //if ( UIUtils.CurrentShaderVersion() < 5002 ) + //{ + // InPortId = inNode.VersionConvertInputPortId( InPortId ); + // OutPortId = outNode.VersionConvertOutputPortId( OutPortId ); + //} + + InputPort inputPort = null; + OutputPort outputPort = null; + if( inNode != null && outNode != null ) + { + + if( UIUtils.CurrentShaderVersion() < 5002 ) + { + InPortId = inNode.VersionConvertInputPortId( InPortId ); + OutPortId = outNode.VersionConvertOutputPortId( OutPortId ); + + if( inNode.WasDeprecated ) + InPortId = inNode.InputIdFromDeprecated( InPortId ); + if( outNode.WasDeprecated ) + OutPortId = outNode.OutputIdFromDeprecated( OutPortId ); + + inputPort = inNode.GetInputPortByArrayId( InPortId ); + outputPort = outNode.GetOutputPortByArrayId( OutPortId ); + } + else + { + if( inNode.WasDeprecated ) + InPortId = inNode.InputIdFromDeprecated( InPortId ); + if( outNode.WasDeprecated ) + OutPortId = outNode.OutputIdFromDeprecated( OutPortId ); + + inputPort = inNode.GetInputPortByUniqueId( InPortId ); + outputPort = outNode.GetOutputPortByUniqueId( OutPortId ); + } + + if( inputPort != null && outputPort != null ) + { + bool inputCompatible = inputPort.CheckValidType( outputPort.DataType ); + bool outputCompatible = outputPort.CheckValidType( inputPort.DataType ); + if( inputCompatible && outputCompatible ) + { + inputPort.ConnectTo( OutNodeId, OutPortId, outputPort.DataType, false ); + outputPort.ConnectTo( InNodeId, InPortId, inputPort.DataType, inputPort.TypeLocked ); + + inNode.OnInputPortConnected( InPortId, OutNodeId, OutPortId, false ); + outNode.OnOutputPortConnected( OutPortId, InNodeId, InPortId ); + } + else if( DebugConsoleWindow.DeveloperMode ) + { + if( !inputCompatible ) + UIUtils.ShowIncompatiblePortMessage( true, inNode, inputPort, outNode, outputPort ); + + if( !outputCompatible ) + UIUtils.ShowIncompatiblePortMessage( true, outNode, outputPort, inNode, inputPort ); + } + } + else if( DebugConsoleWindow.DeveloperMode ) + { + if( inputPort == null ) + { + UIUtils.ShowMessage( "Input Port " + InPortId + " doesn't exist on node " + InNodeId, MessageSeverity.Error ); + } + else + { + UIUtils.ShowMessage( "Output Port " + OutPortId + " doesn't exist on node " + OutNodeId, MessageSeverity.Error ); + } + } + } + else if( DebugConsoleWindow.DeveloperMode ) + { + if( inNode == null ) + { + UIUtils.ShowMessage( "Input node " + InNodeId + " doesn't exist", MessageSeverity.Error ); + } + else + { + UIUtils.ShowMessage( "Output node " + OutNodeId + " doesn't exist", MessageSeverity.Error ); + } + } + } + break; + } + } + } + } + } + + graph.CheckForDuplicates(); + graph.UpdateRegisters(); + graph.RefreshExternalReferences(); + graph.ForceSignalPropagationOnMasterNode(); + graph.LoadedShaderVersion = VersionInfo.FullNumber; + //Reset(); + graph.IsLoading = false; + } + + public ShaderLoadResult LoadFromDisk( string pathname, AmplifyShaderFunction shaderFunction = null ) + { + m_mainGraphInstance.IsLoading = true; + System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; + + FullCleanUndoStack(); + m_performFullUndoRegister = true; + + UIUtils.DirtyMask = false; + if( UIUtils.IsUnityNativeShader( pathname ) ) + { + ShowMessage( "Cannot edit native unity shaders.\nReplacing by a new one." ); + return ShaderLoadResult.UNITY_NATIVE_PATHS; + } + + m_lastOpenedLocation = pathname; + Lastpath = pathname; + + string buffer = string.Empty; + if( shaderFunction == null ) + buffer = IOUtils.LoadTextFileFromDisk( pathname ); + else + buffer = shaderFunction.FunctionInfo; + + if( String.IsNullOrEmpty( buffer ) ) + { + ShowMessage( "Could not open file " + pathname ); + return ShaderLoadResult.FILE_NOT_FOUND; + } + + if( !IOUtils.HasValidShaderBody( ref buffer ) ) + { + return ShaderLoadResult.ASE_INFO_NOT_FOUND; + } + + m_mainGraphInstance.CleanNodes(); + Reset(); + + Shader shader = null; + ShaderLoadResult loadResult = ShaderLoadResult.LOADED; + // Find checksum value on body + int checksumId = buffer.IndexOf( IOUtils.CHECKSUM ); + if( checksumId > -1 ) + { + string checkSumStoredValue = buffer.Substring( checksumId ); + string trimmedBuffer = buffer.Remove( checksumId ); + + string[] typeValuePair = checkSumStoredValue.Split( IOUtils.VALUE_SEPARATOR ); + if( typeValuePair != null && typeValuePair.Length == 2 ) + { + // Check read checksum and compare with the actual shader body to detect external changes + string currentChecksumValue = IOUtils.CreateChecksum( trimmedBuffer ); + if( DebugConsoleWindow.DeveloperMode && !currentChecksumValue.Equals( typeValuePair[ 1 ] ) ) + { + ShowMessage( "Wrong checksum" ); + } + + trimmedBuffer = trimmedBuffer.Replace( "\r", string.Empty ); + // find node info body + int shaderBodyId = trimmedBuffer.IndexOf( IOUtils.ShaderBodyBegin ); + if( shaderBodyId > -1 ) + { + trimmedBuffer = trimmedBuffer.Substring( shaderBodyId ); + //Find set of instructions + string[] instructions = trimmedBuffer.Split( IOUtils.LINE_TERMINATOR ); + // First line is to be ignored and second line contains version + string[] versionParams = instructions[ 1 ].Split( IOUtils.VALUE_SEPARATOR ); + if( versionParams.Length == 2 ) + { + int version = 0; + try + { + version = Convert.ToInt32( versionParams[ 1 ] ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + if( version > VersionInfo.FullNumber ) + { + ShowMessage( "This shader was created on a new ASE version\nPlease install v." + version ); + } + + if( DebugConsoleWindow.DeveloperMode ) + { + if( version < VersionInfo.FullNumber ) + { + ShowMessage( "This shader was created on a older ASE version\nSaving will update it to the new one." ); + } + } + + m_mainGraphInstance.LoadedShaderVersion = version; + } + else + { + ShowMessage( "Corrupted version" ); + } + + // Dummy values,camera values can only be applied after node loading is complete + Rect dummyCameraInfo = new Rect(); + Vector2 dummyCameraOffset = new Vector2(); + float dummyCameraZoom = 0; + bool applyDummy = false; + bool dummyNodeParametersWindowMaximized = false; + bool dummyPaletteWindowMaximized = false; + + //Second line contains camera information ( position, size, offset and zoom ) + string[] cameraParams = instructions[ 2 ].Split( IOUtils.FIELD_SEPARATOR ); + if( cameraParams.Length == 9 ) + { + applyDummy = true; + try + { + dummyCameraInfo.x = Convert.ToSingle( cameraParams[ 0 ] ); + dummyCameraInfo.y = Convert.ToSingle( cameraParams[ 1 ] ); + dummyCameraInfo.width = Convert.ToSingle( cameraParams[ 2 ] ); + dummyCameraInfo.height = Convert.ToSingle( cameraParams[ 3 ] ); + dummyCameraOffset.x = Convert.ToSingle( cameraParams[ 4 ] ); + dummyCameraOffset.y = Convert.ToSingle( cameraParams[ 5 ] ); + dummyCameraZoom = Convert.ToSingle( cameraParams[ 6 ] ); + + float centerWidth = ( this.position.width - dummyCameraInfo.width ) * 0.5f * dummyCameraZoom; + float centerHeight = ( this.position.height - dummyCameraInfo.height ) * 0.5f * dummyCameraZoom; + + dummyCameraInfo.x += centerWidth; + dummyCameraOffset.x += centerWidth; + dummyCameraInfo.y += centerHeight; + dummyCameraOffset.y += centerHeight; + dummyNodeParametersWindowMaximized = Convert.ToBoolean( cameraParams[ 7 ] ); + dummyPaletteWindowMaximized = Convert.ToBoolean( cameraParams[ 8 ] ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + else + { + ShowMessage( "Camera parameters are corrupted" ); + } + + // valid instructions are only between the line after version and the line before the last one ( which contains ShaderBodyEnd ) + for( int instructionIdx = 3; instructionIdx < instructions.Length - 1; instructionIdx++ ) + { + //TODO: After all is working, convert string parameters to ints in order to speed up reading + string[] parameters = instructions[ instructionIdx ].Split( IOUtils.FIELD_SEPARATOR ); + + // All nodes must be created before wiring the connections ... + // Since all nodes on the save op are written before the wires, we can safely create them + // If that order is not maintained the it's because of external editing and its the users responsability + switch( parameters[ 0 ] ) + { + case IOUtils.NodeParam: + { + string typeStr = parameters[ IOUtils.NodeTypeId ]; + typeStr = IOUtils.NodeTypeReplacer.ContainsKey( typeStr ) ? IOUtils.NodeTypeReplacer[ typeStr ] : typeStr; + System.Type type = System.Type.GetType( typeStr ); + if( type == null ) + { +#if UNITY_2017_3_OR_NEWER + try + { + var editorAssembly = System.Reflection.Assembly.Load( "Assembly-CSharp-Editor" ); + if( editorAssembly != null ) + { + type = editorAssembly.GetType( typeStr ); + } + } + catch( Exception ) + { + + } +#endif + } + + if( type != null ) + { + System.Type oldType = type; + NodeAttributes attribs = m_contextMenu.GetNodeAttributesForType( type ); + if( attribs == null ) + { + attribs = m_contextMenu.GetDeprecatedNodeAttributesForType( type ); + if( attribs != null ) + { + if( attribs.Deprecated ) + { + if( attribs.DeprecatedAlternativeType != null ) + { + type = attribs.DeprecatedAlternativeType; + ShowMessage( string.Format( "Node {0} is deprecated and was replaced by {1} ", attribs.Name, attribs.DeprecatedAlternative ) ); + } + else + { + if( string.IsNullOrEmpty( attribs.DeprecatedAlternative ) ) + ShowMessage( string.Format( Constants.DeprecatedNoAlternativeMessageStr, attribs.Name, attribs.DeprecatedAlternative ), MessageSeverity.Normal, false ); + else + ShowMessage( string.Format( Constants.DeprecatedMessageStr, attribs.Name, attribs.DeprecatedAlternative ), MessageSeverity.Normal, false ); + } + } + } + } + + ParentNode newNode = (ParentNode)ScriptableObject.CreateInstance( type ); + if( newNode != null ) + { + try + { + newNode.ContainerGraph = m_mainGraphInstance; + if( oldType != type ) + { + newNode.ParentReadFromString( ref parameters ); + newNode.ReadFromDeprecated( ref parameters, oldType ); + newNode.WasDeprecated = true; + } + else + newNode.ReadFromString( ref parameters ); + + + if( oldType == type ) + { + newNode.ReadInputDataFromString( ref parameters ); + if( UIUtils.CurrentShaderVersion() > 5107 ) + { + newNode.ReadOutputDataFromString( ref parameters ); + } + } + } + catch( Exception e ) + { + Debug.LogException( e, newNode ); + } + m_mainGraphInstance.AddNode( newNode, false, true, false ); + } + } + else + { + ShowMessage( string.Format( "{0} is not a valid ASE node ", parameters[ IOUtils.NodeTypeId ] ), MessageSeverity.Error ); + } + } + break; + case IOUtils.WireConnectionParam: + { + int InNodeId = 0; + int InPortId = 0; + int OutNodeId = 0; + int OutPortId = 0; + + try + { + InNodeId = Convert.ToInt32( parameters[ IOUtils.InNodeId ] ); + InPortId = Convert.ToInt32( parameters[ IOUtils.InPortId ] ); + OutNodeId = Convert.ToInt32( parameters[ IOUtils.OutNodeId ] ); + OutPortId = Convert.ToInt32( parameters[ IOUtils.OutPortId ] ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + ParentNode inNode = m_mainGraphInstance.GetNode( InNodeId ); + ParentNode outNode = m_mainGraphInstance.GetNode( OutNodeId ); + + //if ( UIUtils.CurrentShaderVersion() < 5002 ) + //{ + // InPortId = inNode.VersionConvertInputPortId( InPortId ); + // OutPortId = outNode.VersionConvertOutputPortId( OutPortId ); + //} + + InputPort inputPort = null; + OutputPort outputPort = null; + if( inNode != null && outNode != null ) + { + + if( UIUtils.CurrentShaderVersion() < 5002 ) + { + InPortId = inNode.VersionConvertInputPortId( InPortId ); + OutPortId = outNode.VersionConvertOutputPortId( OutPortId ); + + if( inNode.WasDeprecated ) + InPortId = inNode.InputIdFromDeprecated( InPortId ); + if( outNode.WasDeprecated ) + OutPortId = outNode.OutputIdFromDeprecated( OutPortId ); + + inputPort = inNode.GetInputPortByArrayId( InPortId ); + outputPort = outNode.GetOutputPortByArrayId( OutPortId ); + } + else + { + if( inNode.WasDeprecated ) + InPortId = inNode.InputIdFromDeprecated( InPortId ); + if( outNode.WasDeprecated ) + OutPortId = outNode.OutputIdFromDeprecated( OutPortId ); + + inputPort = inNode.GetInputPortByUniqueId( InPortId ); + outputPort = outNode.GetOutputPortByUniqueId( OutPortId ); + } + + if( inputPort != null && outputPort != null ) + { + bool inputCompatible = inputPort.CheckValidType( outputPort.DataType ); + bool outputCompatible = outputPort.CheckValidType( inputPort.DataType ); + if( inputCompatible && outputCompatible ) + { + inputPort.ConnectTo( OutNodeId, OutPortId, outputPort.DataType, false ); + outputPort.ConnectTo( InNodeId, InPortId, inputPort.DataType, inputPort.TypeLocked ); + + inNode.OnInputPortConnected( InPortId, OutNodeId, OutPortId, false ); + outNode.OnOutputPortConnected( OutPortId, InNodeId, InPortId ); + } + else if( DebugConsoleWindow.DeveloperMode ) + { + if( !inputCompatible ) + UIUtils.ShowIncompatiblePortMessage( true, inNode, inputPort, outNode, outputPort ); + + if( !outputCompatible ) + UIUtils.ShowIncompatiblePortMessage( true, outNode, outputPort, inNode, inputPort ); + } + } + else if( DebugConsoleWindow.DeveloperMode ) + { + if( inputPort == null ) + { + UIUtils.ShowMessage( "Input Port " + InPortId + " doesn't exist on node " + InNodeId, MessageSeverity.Error ); + } + else + { + UIUtils.ShowMessage( "Output Port " + OutPortId + " doesn't exist on node " + OutNodeId, MessageSeverity.Error ); + } + } + } + else if( DebugConsoleWindow.DeveloperMode ) + { + if( inNode == null ) + { + UIUtils.ShowMessage( "Input node " + InNodeId + " doesn't exist", MessageSeverity.Error ); + } + else + { + UIUtils.ShowMessage( "Output node " + OutNodeId + " doesn't exist", MessageSeverity.Error ); + } + } + } + break; + } + } + + if( shaderFunction != null ) + { + m_onLoadDone = 2; + if( applyDummy ) + { + m_cameraInfo = dummyCameraInfo; + m_cameraOffset = dummyCameraOffset; + CameraZoom = dummyCameraZoom; + if( DebugConsoleWindow.UseShaderPanelsInfo ) + { + m_nodeParametersWindowMaximized = m_nodeParametersWindow.IsMaximized = dummyNodeParametersWindowMaximized; + m_paletteWindowMaximized = m_paletteWindow.IsMaximized = dummyPaletteWindowMaximized; + } + } + + } + else + { + shader = AssetDatabase.LoadAssetAtPath( pathname ); + if( shader ) + { + + m_onLoadDone = 2; + if( applyDummy ) + { + m_cameraInfo = dummyCameraInfo; + m_cameraOffset = dummyCameraOffset; + CameraZoom = dummyCameraZoom; + if( DebugConsoleWindow.UseShaderPanelsInfo ) + { + m_nodeParametersWindowMaximized = m_nodeParametersWindow.IsMaximized = dummyNodeParametersWindowMaximized; + m_paletteWindowMaximized = m_paletteWindow.IsMaximized = dummyPaletteWindowMaximized; + } + } + } + else + { + ShowMessage( "Could not load shader asset" ); + } + } + } + else + { + ShowMessage( "Graph info not found" ); + } + } + else + { + ShowMessage( "Corrupted checksum" ); + } + } + else + { + ShowMessage( "Checksum not found" ); + } + + //m_mainGraphInstance.LoadedShaderVersion = m_versionInfo.FullNumber; + if( UIUtils.CurrentMasterNode() ) + UIUtils.CurrentMasterNode().ForcePortType(); + + UIUtils.DirtyMask = true; + m_checkInvalidConnections = true; + + m_mainGraphInstance.CheckForDuplicates(); + m_mainGraphInstance.UpdateRegisters(); + m_mainGraphInstance.RefreshExternalReferences(); + m_mainGraphInstance.ForceSignalPropagationOnMasterNode(); + + if( shaderFunction != null ) + { + //if( CurrentGraph.CurrentFunctionOutput == null ) + //{ + // //Fix in case a function output node is not marked as main node + // CurrentGraph.AssignMasterNode( UIUtils.FunctionOutputList()[ 0 ], false ); + //} + shaderFunction.ResetDirectivesOrigin(); + CurrentGraph.CurrentShaderFunction = shaderFunction; + } + else + { + if( shader != null ) + { + m_mainGraphInstance.UpdateShaderOnMasterNode( shader ); + if( m_mainGraphInstance.CurrentCanvasMode == NodeAvailability.TemplateShader ) + { + m_mainGraphInstance.RefreshLinkedMasterNodes( false ); + m_mainGraphInstance.OnRefreshLinkedPortsComplete(); + //m_mainGraphInstance.SetLateOptionsRefresh(); + } + } + } + + + m_mainGraphInstance.LoadedShaderVersion = VersionInfo.FullNumber; + + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + + m_mainGraphInstance.IsLoading = false; + //Remove focus from UI elements so no UI is incorrectly selected from previous loads + //Shader Name textfield was sometimes incorrectly selected + GUI.FocusControl( null ); + return loadResult; + } + + public void FullCleanUndoStack() + { + Undo.ClearUndo( this ); + m_mainGraphInstance.FullCleanUndoStack(); + } + + public void FullRegisterOnUndoStack() + { + Undo.RegisterCompleteObjectUndo( this, Constants.UndoRegisterFullGrapId ); + m_mainGraphInstance.FullRegisterOnUndoStack(); + } + + public void ShowPortInfo() + { + GetWindow(); + } + + public void ShowShaderLibrary() + { + GetWindow(); + } + + public void ShowMessage( string message, MessageSeverity severity = MessageSeverity.Normal, bool registerTimestamp = true, bool consoleLog = false ) + { + ShowMessage( -1, message, severity, registerTimestamp, consoleLog ); + } + + public void ShowMessage( int messageOwner, string message, MessageSeverity severity = MessageSeverity.Normal, bool registerTimestamp = true, bool consoleLog = false ) + { + if( UIUtils.InhibitMessages || m_genericMessageUI == null ) + return; + + m_consoleLogWindow.AddMessage( severity, message , messageOwner); + + MarkToRepaint(); + + if( consoleLog ) + { + switch( severity ) + { + case MessageSeverity.Normal: + { + Debug.Log( message ); + } + break; + case MessageSeverity.Warning: + { + Debug.LogWarning( message ); + } + break; + case MessageSeverity.Error: + { + Debug.LogError( message ); + } + break; + } + } + } + + // NOTE: this can probably be removed safely + public void ShowMessageImmediately( string message, MessageSeverity severity = MessageSeverity.Normal, bool consoleLog = true ) + { + if( UIUtils.InhibitMessages ) + return; + + switch( severity ) + { + case MessageSeverity.Normal: + { + m_genericMessageContent.text = message; + if( consoleLog ) + { + Debug.Log( message ); + } + } + break; + case MessageSeverity.Warning: + { + m_genericMessageContent.text = "Warning!\n" + message; + if( consoleLog ) + { + Debug.LogWarning( message ); + } + } + break; + case MessageSeverity.Error: + { + m_genericMessageContent.text = "Error!!!\n" + message; + if( consoleLog ) + { + Debug.LogError( message ); + } + } + break; + } + + try + { + ShowNotification( m_genericMessageContent ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + + public bool MouseInteracted = false; + + void OnGUI() + { +#if UNITY_2018_3_OR_NEWER + if( ASEPackageManagerHelper.CheckImporter ) + return; +#endif + +#if UNITY_EDITOR_WIN + if( m_openSavedFolder && Event.current.type == EventType.Repaint ) + { + OpenSavedFolder(); + return; + } +#endif + AmplifyShaderEditorWindow cacheWindow = UIUtils.CurrentWindow; + UIUtils.CurrentWindow = this; + + if( !m_initialized || (object)UIUtils.MainSkin == null || !UIUtils.Initialized ) + { + UIUtils.InitMainSkin(); + Init(); + } + + m_currentEvent = Event.current; + if( m_currentEvent.type == EventType.ExecuteCommand || m_currentEvent.type == EventType.ValidateCommand ) + m_currentCommandName = m_currentEvent.commandName; + else + m_currentCommandName = string.Empty; + + System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; + + MouseInteracted = false; + + if( m_refreshOnUndo ) + { + m_refreshOnUndo = false; + m_mainGraphInstance.RefreshOnUndo(); + } + + if( m_refreshAvailableNodes ) + { + RefreshAvaibleNodes(); + } + + if( m_previousShaderFunction != CurrentGraph.CurrentShaderFunction ) + { + m_nodeParametersWindow.ForceUpdate = true; + m_previousShaderFunction = CurrentGraph.CurrentShaderFunction; + } + + if( m_nodeToFocus != null && m_currentEvent.type == EventType.Layout ) + { + FocusOnNode( m_nodeToFocus, m_zoomToFocus, m_selectNodeToFocus ); + m_nodeToFocus = null; + } + + m_mainGraphInstance.OnDuplicateEventWrapper(); + + m_currentInactiveTime = CalculateInactivityTime(); + + if( m_nodeParametersWindow != null && m_innerEditorVariables.NodeParametersMaximized != m_nodeParametersWindow.IsMaximized ) + m_innerEditorVariables.NodeParametersMaximized = m_nodeParametersWindow.IsMaximized; + if( m_paletteWindow != null && m_innerEditorVariables.NodePaletteMaximized != m_paletteWindow.IsMaximized ) + m_innerEditorVariables.NodePaletteMaximized = m_paletteWindow.IsMaximized; + + if( m_checkInvalidConnections ) + { + m_checkInvalidConnections = false; + m_mainGraphInstance.DeleteInvalidConnections(); + } + + //if ( m_repaintIsDirty ) + //{ + // m_repaintIsDirty = false; + // ForceRepaint(); + //} + + if( m_forcingMaterialUpdateFlag ) + { + Focus(); + if( m_materialsToUpdate.Count > 0 ) + { + float percentage = 100.0f * (float)( UIUtils.TotalExampleMaterials - m_materialsToUpdate.Count ) / (float)UIUtils.TotalExampleMaterials; + if( m_forcingMaterialUpdateOp ) // Read + { + Debug.Log( percentage + "% Recompiling " + m_materialsToUpdate[ 0 ].name ); + LoadDroppedObject( true, m_materialsToUpdate[ 0 ].shader, m_materialsToUpdate[ 0 ] ); + } + else // Write + { + Debug.Log( percentage + "% Saving " + m_materialsToUpdate[ 0 ].name ); + SaveToDisk( false ); + m_materialsToUpdate.RemoveAt( 0 ); + } + m_forcingMaterialUpdateOp = !m_forcingMaterialUpdateOp; + } + else + { + Debug.Log( "100% - All Materials compiled " ); + m_forcingMaterialUpdateFlag = false; + } + } + + + if( m_removedKeyboardFocus ) + { + m_removedKeyboardFocus = false; + GUIUtility.keyboardControl = 0; + } + + + Vector2 pos = m_currentEvent.mousePosition; + pos.x += position.x; + pos.y += position.y; + m_insideEditorWindow = position.Contains( pos ); + + if( m_delayedLoadObject != null && m_mainGraphInstance.CurrentMasterNode != null ) + { + m_mainGraphInstance.SetLateOptionsRefresh(); + LoadObject( m_delayedLoadObject ); + m_delayedLoadObject = null; + } + else if( m_delayedLoadObject != null && m_mainGraphInstance.CurrentOutputNode != null ) + { + m_mainGraphInstance.SetLateOptionsRefresh(); + LoadObject( m_delayedLoadObject ); + m_delayedLoadObject = null; + } + + if( m_delayedMaterialSet != null && m_mainGraphInstance.CurrentMasterNode != null ) + { + m_mainGraphInstance.UpdateMaterialOnMasterNode( m_delayedMaterialSet ); + m_mainGraphInstance.SetMaterialModeOnGraph( m_delayedMaterialSet ); + CurrentSelection = ASESelectionMode.Material; + IsShaderFunctionWindow = false; + m_delayedMaterialSet = null; + } + + Material currentMaterial = m_mainGraphInstance.CurrentMaterial; + if( m_forceUpdateFromMaterialFlag ) + { + Focus(); + m_forceUpdateFromMaterialFlag = false; + if( currentMaterial != null ) + { + m_mainGraphInstance.CopyValuesFromMaterial( currentMaterial ); + m_repaintIsDirty = true; + } + } + + m_repaintCount = 0; + m_cameraInfo = position; + + //if( m_currentEvent.type == EventType.keyDown ) + if( m_currentEvent.type == EventType.Repaint ) + m_keyEvtMousePos2D = m_currentEvent.mousePosition; + + m_currentMousePos2D = m_currentEvent.mousePosition; + m_currentMousePos.x = m_currentMousePos2D.x; + m_currentMousePos.y = m_currentMousePos2D.y; + + m_graphArea.width = m_cameraInfo.width; + m_graphArea.height = m_cameraInfo.height; + + m_autoPanDirActive = m_lmbPressed || m_forceAutoPanDir || m_multipleSelectionActive || m_wireReferenceUtils.ValidReferences(); + + + // Need to use it in order to prevent Mismatched LayoutGroup on ValidateCommand when rendering nodes + //if( Event.current.type == EventType.ValidateCommand ) + //{ + // Event.current.Use(); + //} + + // Nodes Graph background area + //GUILayout.BeginArea( m_graphArea, "Nodes" ); + { + // Camera movement is simulated by grabing the current camera offset, transforming it into texture space and manipulating the tiled texture uv coords + GUI.DrawTextureWithTexCoords( m_graphArea, m_graphBgTexture, + new Rect( ( -m_cameraOffset.x / m_graphBgTexture.width ), + ( m_cameraOffset.y / m_graphBgTexture.height ) - m_cameraZoom * m_cameraInfo.height / m_graphBgTexture.height, + m_cameraZoom * m_cameraInfo.width / m_graphBgTexture.width, + m_cameraZoom * m_cameraInfo.height / m_graphBgTexture.height ) ); + + Color col = GUI.color; + GUI.color = new Color( 1, 1, 1, 0.7f ); + GUI.DrawTexture( m_graphArea, m_graphFgTexture, ScaleMode.StretchToFill, true ); + GUI.color = col; + } + //GUILayout.EndArea(); + + if( DebugConsoleWindow.DeveloperMode && m_currentEvent.type == EventType.Repaint ) + { + GUI.Label( new Rect(Screen.width - 60, 40, 60, 50), m_fpsDisplay ); + } + + bool restoreMouse = false; + if( InsideMenus( m_currentMousePos2D ) /*|| _confirmationWindow.IsActive*/ ) + { + if( Event.current.type == EventType.MouseDown ) + { + restoreMouse = true; + Event.current.type = EventType.Ignore; + } + + // Must guarantee that mouse up ops on menus will reset auto pan if it is set + if( m_currentEvent.type == EventType.MouseUp && m_currentEvent.button == ButtonClickId.LeftMouseButton ) + { + m_lmbPressed = false; + } + + } + // Nodes + //GUILayout.BeginArea( m_graphArea ); + { + m_drawInfo.CameraArea = m_cameraInfo; + m_drawInfo.TransformedCameraArea = m_graphArea; + + m_drawInfo.MousePosition = m_currentMousePos2D; + m_drawInfo.CameraOffset = m_cameraOffset; + m_drawInfo.InvertedZoom = 1 / m_cameraZoom; + m_drawInfo.LeftMouseButtonPressed = m_currentEvent.button == ButtonClickId.LeftMouseButton; + m_drawInfo.CurrentEventType = m_currentEvent.type; + m_drawInfo.ZoomChanged = m_zoomChanged; + + m_drawInfo.TransformedMousePos = m_currentMousePos2D * m_cameraZoom - m_cameraOffset; + + if( m_drawInfo.CurrentEventType == EventType.Repaint ) + UIUtils.UpdateMainSkin( m_drawInfo ); + + // Draw mode indicator + m_modeWindow.Draw( m_graphArea, m_currentMousePos2D, m_mainGraphInstance.CurrentShader, currentMaterial, + 0.5f * ( m_graphArea.width - m_paletteWindow.RealWidth - m_nodeParametersWindow.RealWidth ), + ( m_nodeParametersWindow.IsMaximized ? m_nodeParametersWindow.RealWidth : 0 ), + ( m_paletteWindow.IsMaximized ? m_paletteWindow.RealWidth : 0 )/*, m_openedAssetFromNode*/ ); + + PreTestLeftMouseDown(); + //m_consoleLogWindow.Draw( m_graphArea, m_currentMousePos2D, m_currentEvent.button, false, m_paletteWindow.IsMaximized ? m_paletteWindow.RealWidth : 0 ); + //m_mainGraphInstance.DrawBezierBoundingBox(); + //CheckNodeReplacement(); + + // Main Graph Draw + m_repaintIsDirty = m_mainGraphInstance.Draw( m_drawInfo ) || m_repaintIsDirty; + + m_mainGraphInstance.DrawGrid( m_drawInfo ); + bool hasUnusedConnNodes = m_mainGraphInstance.HasUnConnectedNodes; + m_toolsWindow.SetStateOnButton( ToolButtonType.CleanUnusedNodes, hasUnusedConnNodes ? 1 : 0 ); + + m_zoomChanged = false; + + MasterNode masterNode = m_mainGraphInstance.CurrentMasterNode; + if( masterNode != null ) + { + m_toolsWindow.DrawShaderTitle( m_nodeParametersWindow, m_paletteWindow, AvailableCanvasWidth, m_graphArea.height, masterNode.CroppedShaderName ); + } + else if( m_mainGraphInstance.CurrentOutputNode != null ) + { + string functionName = string.Empty; + + if( m_mainGraphInstance.CurrentShaderFunction != null ) + functionName = m_mainGraphInstance.CurrentShaderFunction.FunctionName; + m_toolsWindow.DrawShaderTitle( m_nodeParametersWindow, m_paletteWindow, AvailableCanvasWidth, m_graphArea.height, functionName ); + } + } + //m_consoleLogWindow.Draw( m_graphArea, m_currentMousePos2D, m_currentEvent.button, false, m_paletteWindow.IsMaximized ? m_paletteWindow.RealWidth : 0 ); + //GUILayout.EndArea(); + + if( restoreMouse ) + { + Event.current.type = EventType.MouseDown; + m_drawInfo.CurrentEventType = EventType.MouseDown; + } + + m_toolsWindow.InitialX = m_nodeParametersWindow.RealWidth; + m_toolsWindow.Width = m_cameraInfo.width - ( m_nodeParametersWindow.RealWidth + m_paletteWindow.RealWidth ); + m_toolsWindow.Draw( m_cameraInfo, m_currentMousePos2D, m_currentEvent.button, false ); + + m_tipsWindow.Draw( m_cameraInfo, m_currentMousePos2D, m_currentEvent.button, false ); + + bool autoMinimize = false; + if( position.width < m_lastWindowWidth && position.width < Constants.MINIMIZE_WINDOW_LOCK_SIZE ) + { + autoMinimize = true; + } + + if( autoMinimize ) + m_nodeParametersWindow.IsMaximized = false; + + ParentNode selectedNode = ( m_mainGraphInstance.SelectedNodes.Count == 1 ) ? m_mainGraphInstance.SelectedNodes[ 0 ] : m_mainGraphInstance.CurrentMasterNode; + m_repaintIsDirty = m_nodeParametersWindow.Draw( m_cameraInfo, selectedNode, m_currentMousePos2D, m_currentEvent.button, false ) || m_repaintIsDirty; //TODO: If multiple nodes from the same type are selected also show a parameters window which modifies all of them + if( m_nodeParametersWindow.IsResizing ) + m_repaintIsDirty = true; + + // Test to ignore mouse on main palette when inside context palette ... IsInside also takes active state into account + bool ignoreMouseForPalette = m_contextPalette.IsInside( m_currentMousePos2D ); + if( ignoreMouseForPalette && Event.current.type == EventType.MouseDown ) + { + Event.current.type = EventType.Ignore; + m_drawInfo.CurrentEventType = EventType.Ignore; + } + if( autoMinimize ) + m_paletteWindow.IsMaximized = false; + + m_paletteWindow.Draw( m_cameraInfo, m_currentMousePos2D, m_currentEvent.button, !m_contextPalette.IsActive ); + if( m_paletteWindow.IsResizing ) + { + m_repaintIsDirty = true; + } + + if( ignoreMouseForPalette ) + { + if( restoreMouse ) + { + Event.current.type = EventType.MouseDown; + m_drawInfo.CurrentEventType = EventType.MouseDown; + } + } + + m_consoleLogWindow.Draw( m_graphArea, m_currentMousePos2D, m_currentEvent.button, false, m_paletteWindow.IsMaximized ? m_paletteWindow.RealWidth : 0 ); + + if( m_contextPalette.IsActive ) + { + m_contextPalette.Draw( m_cameraInfo, m_currentMousePos2D, m_currentEvent.button, m_contextPalette.IsActive ); + } + + if( m_palettePopup.IsActive ) + { + m_palettePopup.Draw( m_currentMousePos2D ); + m_repaintIsDirty = true; + int controlID = GUIUtility.GetControlID( FocusType.Passive ); + if( m_currentEvent.GetTypeForControl( controlID ) == EventType.MouseUp ) + { + if( m_currentEvent.button == ButtonClickId.LeftMouseButton ) + { + m_palettePopup.Deactivate(); + if( !InsideMenus( m_currentMousePos2D ) ) + { + ParentNode newNode = CreateNode( m_paletteChosenType, TranformedMousePos, m_paletteChosenFunction ); + //Debug.Log("created menu"); + m_mainGraphInstance.SelectNode( newNode, false, false ); + + bool find = false; + if( newNode is FunctionNode && CurrentGraph.CurrentShaderFunction != null ) + find = SearchFunctionNodeRecursively( CurrentGraph.CurrentShaderFunction ); + + if( find ) + { + DestroyNode( newNode, false ); + ShowMessage( "Shader Function loop detected, new node was removed to prevent errors." ); + } + else + { + newNode.RefreshExternalReferences(); + } + } + } + } + } + + // Handle all events ( mouse interaction + others ) + if( !MouseInteracted ) + HandleGUIEvents(); + + if( m_currentEvent.type == EventType.Repaint ) + { + m_mainGraphInstance.UpdateMarkForDeletion(); + } + // UI Overlay + // Selection Box + if( m_multipleSelectionActive ) + { + UpdateSelectionArea(); + Rect transformedArea = m_multipleSelectionArea; + transformedArea.position = ( transformedArea.position + m_cameraOffset ) / m_cameraZoom; + transformedArea.size /= m_cameraZoom; + + if( transformedArea.width < 0 ) + { + transformedArea.width = -transformedArea.width; + transformedArea.x -= transformedArea.width; + } + + if( transformedArea.height < 0 ) + { + transformedArea.height = -transformedArea.height; + transformedArea.y -= transformedArea.height; + } + Color original = GUI.color; + GUI.color = Constants.BoxSelectionColor; + GUI.Label( transformedArea, "", UIUtils.Box ); + GUI.color = original; + //GUI.backgroundColor = original; + } + + bool isResizing = m_nodeParametersWindow.IsResizing || m_paletteWindow.IsResizing; + //Test boundaries for auto-pan + if( !isResizing && m_autoPanDirActive ) + { + m_autoPanArea[ (int)AutoPanLocation.LEFT ].AdjustInitialX = m_nodeParametersWindow.IsMaximized ? m_nodeParametersWindow.RealWidth : 0; + m_autoPanArea[ (int)AutoPanLocation.RIGHT ].AdjustInitialX = m_paletteWindow.IsMaximized ? -m_paletteWindow.RealWidth : 0; + Vector2 autoPanDir = Vector2.zero; + for( int i = 0; i < m_autoPanArea.Length; i++ ) + { + if( m_autoPanArea[ i ].CheckArea( m_currentMousePos2D, m_cameraInfo, false ) ) + { + autoPanDir += m_autoPanArea[ i ].Velocity; + } + } + m_cameraOffset += autoPanDir; + if( !m_wireReferenceUtils.ValidReferences() && m_insideEditorWindow && !m_altBoxSelection ) + { + m_mainGraphInstance.MoveSelectedNodes( -autoPanDir ); + } + + m_repaintIsDirty = true; + } + + m_isDirty = m_isDirty || m_mainGraphInstance.IsDirty; + if( m_isDirty ) + { + m_isDirty = false; + //ShaderIsModified = true; + EditorUtility.SetDirty( this ); + } + + m_saveIsDirty = m_saveIsDirty || m_mainGraphInstance.SaveIsDirty; + if( m_liveShaderEditing ) + { + if( m_saveIsDirty ) + { + if( focusedWindow == this && m_currentInactiveTime > InactivitySaveTime && !(EditorGUIUtility.editingTextField && EditorGUIUtility.keyboardControl!=0) ) + { + m_saveIsDirty = false; + if( m_mainGraphInstance.CurrentMasterNodeId != Constants.INVALID_NODE_ID ) + { + SaveToDisk( true ); + } + else + { + ShowMessage( LiveShaderError ); + } + } + } + } + else if( m_saveIsDirty ) + { + ShaderIsModified = true; + m_saveIsDirty = false; + } + + if( m_onLoadDone > 0 ) + { + m_onLoadDone--; + if( m_onLoadDone == 0 ) + { + ShaderIsModified = false; + } + } + + if( m_cacheSaveOp ) + { + if( ( EditorApplication.timeSinceStartup - m_lastTimeSaved ) > SaveTime ) + { + SaveToDisk( false ); + } + } + m_genericMessageUI.CheckForMessages(); + + if( m_ctrlSCallback ) + { + m_ctrlSCallback = false; + OnToolButtonPressed( ToolButtonType.Update ); + } + + m_lastWindowWidth = position.width; + m_nodeExporterUtils.Update(); + + if( m_markedToSave ) + { + m_markedToSave = false; + SaveToDisk( false ); + } + if( m_performFullUndoRegister ) + { + m_performFullUndoRegister = false; + FullRegisterOnUndoStack(); + } + + if( CheckFunctions ) + CheckFunctions = false; + + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + + UIUtils.CurrentWindow = cacheWindow; + if( !m_nodesLoadedCorrectly ) + { + try + { + ShowNotification( NodesExceptionMessage ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + + CheckNodeReplacement(); +#if UNITY_EDITOR_WIN + if( m_takeScreenShot ) + FocusZoom( true, false, false ); + + if( m_takeScreenShot && Event.current.type == EventType.Repaint ) + TakeScreenShot(); +#endif + + if( Event.current.type == EventType.Layout ) + { + switch( State ) + { + default: + case OpenSaveState.NONE: + break; + case OpenSaveState.OPEN: + { + State = OpenSaveState.WAIT; + string list = EditorPrefs.GetString( "ASEfileList", "" ); + m_assetPaths = new List( list.Split( ',' ) ); + Repaint(); + } + break; + case OpenSaveState.WAIT: + { + // we wait one frame to give time for the editor to properly initialize everything + State = OpenSaveState.SAVE; + Repaint(); + } + break; + case OpenSaveState.SAVE: + { + State = OpenSaveState.CLOSE; + try + { + SaveToDisk( false ); + } + catch( Exception e ) + { + State = OpenSaveState.NONE; + throw e; + } + + Repaint(); + } + break; + case OpenSaveState.CLOSE: + { + State = OpenSaveState.NONE; + m_assetPaths.RemoveAt( 0 ); + if( m_assetPaths.Count > 0 ) + { + AmplifyShaderEditorWindow.LoadAndSaveList( m_assetPaths.ToArray() ); + } + else + { + EditorPrefs.DeleteKey( "ASEfileList" ); + } +#if UNITY_2018_3_OR_NEWER + this.Close(); +#else + m_markToClose = true; +#endif + } + break; + } + } + } + + bool m_markToClose = false; + private List m_assetPaths = new List(); + public OpenSaveState State = OpenSaveState.NONE; + public enum OpenSaveState + { + NONE, + OPEN, + WAIT, + SAVE, + CLOSE + } + + void OnInspectorUpdate() + { + Preferences.LoadDefaults(); +#if UNITY_2018_3_OR_NEWER + ASEPackageManagerHelper.Update(); +#endif + + if( m_afterDeserializeFlag ) + { + m_afterDeserializeFlag = false; + //m_mainGraphInstance.ParentWindow = this; + } + + if( (IsShaderFunctionWindow && CurrentGraph.CurrentShaderFunction == null) || m_markToClose ) + { + Close(); + } + } + + public void SetCtrlSCallback( bool imediate ) + { + //MasterNode node = _mainGraphInstance.CurrentMasterNode; + if( /*node != null && node.CurrentShader != null && */m_shaderIsModified ) + { + if( imediate ) + { + OnToolButtonPressed( ToolButtonType.Update ); + } + else + { + m_ctrlSCallback = true; + } + } + } + + public void SetSaveIsDirty() + { + m_saveIsDirty = true && UIUtils.DirtyMask; + } + + public void OnPaletteNodeCreate( System.Type type, string name, AmplifyShaderFunction function ) + { + m_mainGraphInstance.DeSelectAll(); + m_paletteChosenType = type; + m_paletteChosenFunction = function; + m_palettePopup.Activate( name ); + } + + public void OnContextPaletteNodeCreate( System.Type type, string name, AmplifyShaderFunction function ) + { + m_mainGraphInstance.DeSelectAll(); + ParentNode newNode = CreateNode( type, m_contextPalette.StartDropPosition * m_cameraZoom - m_cameraOffset, function ); + //Debug.Log( "created context" ); + m_mainGraphInstance.SelectNode( newNode, false, false ); + bool find = false; + if( newNode is FunctionNode && CurrentGraph.CurrentShaderFunction != null ) + find = SearchFunctionNodeRecursively( CurrentGraph.CurrentShaderFunction ); + + if( find ) + { + DestroyNode( newNode, false ); + ShowMessage( "Shader Function loop detected, new node was removed to prevent errors." ); + } + else + { + newNode.RefreshExternalReferences(); + } + } + + void OnNodeStoppedMovingEvent( ParentNode node ) + { + CheckZoomBoundaries( node.Vec2Position ); + //ShaderIsModified = true; + } + + void OnRefreshFunctionNodeEvent( FunctionNode node ) + { + Debug.Log( node ); + } + + private const string ShaderIsModifiedMessage = "Click to save changes."; + private const string ShaderIsNotModified = "No changes to save, up-to-date."; + void OnMaterialUpdated( MasterNode masterNode ) + { + if( masterNode != null ) + { + if( masterNode.CurrentMaterial ) + { + m_toolsWindow.SetStateOnButton( ToolButtonType.Update, ShaderIsModified ? 0 : 2, ShaderIsModified ? ShaderIsModifiedMessage : ShaderIsNotModified); + } + else + { + m_toolsWindow.SetStateOnButton( ToolButtonType.Update, 1, "Set an active Material in the Master Node." ); + } + UpdateLiveUI(); + } + else + { + m_toolsWindow.SetStateOnButton( ToolButtonType.Update, 1, "Set an active Material in the Master Node." ); + } + } + + void OnShaderUpdated( MasterNode masterNode ) + { + m_toolsWindow.SetStateOnButton( ToolButtonType.OpenSourceCode, masterNode.CurrentShader != null ? 1 : 0 ); + } + + public void CheckZoomBoundaries( Vector2 newPosition ) + { + if( newPosition.x < m_minNodePos.x ) + { + m_minNodePos.x = newPosition.x; + } + else if( newPosition.x > m_maxNodePos.x ) + { + m_maxNodePos.x = newPosition.x; + } + + if( newPosition.y < m_minNodePos.y ) + { + m_minNodePos.y = newPosition.y; + } + else if( newPosition.y > m_maxNodePos.y ) + { + m_maxNodePos.y = newPosition.y; + } + } + public void DestroyNode( ParentNode node, bool registerUndo = true ) { m_mainGraphInstance.DestroyNode( node, registerUndo ); } + public ParentNode CreateNode( System.Type type, Vector2 position, AmplifyShaderFunction function = null, bool selectNode = true ) + { + ParentNode node; + if( function == null ) + node = m_mainGraphInstance.CreateNode( type, true ); + else + node = m_mainGraphInstance.CreateNode( function, true ); + + Vector2 newPosition = position; + node.Vec2Position = newPosition; + CheckZoomBoundaries( newPosition ); + + // Connect node if a wire is active + if( m_wireReferenceUtils.ValidReferences() ) + { + if( m_wireReferenceUtils.InputPortReference.IsValid ) + { + ParentNode originNode = m_mainGraphInstance.GetNode( m_wireReferenceUtils.InputPortReference.NodeId ); + InputPort originPort = originNode.GetInputPortByUniqueId( m_wireReferenceUtils.InputPortReference.PortId ); + OutputPort outputPort = node.GetFirstOutputPortOfType( m_wireReferenceUtils.InputPortReference.DataType, true ); + if( outputPort != null && originPort.CheckValidType( outputPort.DataType ) && ( !m_wireReferenceUtils.InputPortReference.TypeLocked || + m_wireReferenceUtils.InputPortReference.DataType == WirePortDataType.OBJECT || + ( m_wireReferenceUtils.InputPortReference.TypeLocked && outputPort.DataType == m_wireReferenceUtils.InputPortReference.DataType ) ) ) + { + + //link output to input + if( outputPort.ConnectTo( m_wireReferenceUtils.InputPortReference.NodeId, m_wireReferenceUtils.InputPortReference.PortId, m_wireReferenceUtils.InputPortReference.DataType, m_wireReferenceUtils.InputPortReference.TypeLocked ) ) + node.OnOutputPortConnected( outputPort.PortId, m_wireReferenceUtils.InputPortReference.NodeId, m_wireReferenceUtils.InputPortReference.PortId ); + + //link input to output + if( originPort.ConnectTo( outputPort.NodeId, outputPort.PortId, outputPort.DataType, m_wireReferenceUtils.InputPortReference.TypeLocked ) ) + originNode.OnInputPortConnected( m_wireReferenceUtils.InputPortReference.PortId, node.UniqueId, outputPort.PortId ); + } + } + + if( m_wireReferenceUtils.OutputPortReference.IsValid ) + { + ParentNode originNode = m_mainGraphInstance.GetNode( m_wireReferenceUtils.OutputPortReference.NodeId ); + InputPort inputPort = node.GetFirstInputPortOfType( m_wireReferenceUtils.OutputPortReference.DataType, true ); + + if( inputPort != null && ( !inputPort.TypeLocked || + inputPort.DataType == WirePortDataType.OBJECT || + ( inputPort.TypeLocked && inputPort.DataType == m_wireReferenceUtils.OutputPortReference.DataType ) ) ) + { + + inputPort.InvalidateAllConnections(); + //link input to output + if( inputPort.ConnectTo( m_wireReferenceUtils.OutputPortReference.NodeId, m_wireReferenceUtils.OutputPortReference.PortId, m_wireReferenceUtils.OutputPortReference.DataType, inputPort.TypeLocked ) ) + node.OnInputPortConnected( inputPort.PortId, m_wireReferenceUtils.OutputPortReference.NodeId, m_wireReferenceUtils.OutputPortReference.PortId ); + //link output to input + + if( originNode.GetOutputPortByUniqueId( m_wireReferenceUtils.OutputPortReference.PortId ).ConnectTo( inputPort.NodeId, inputPort.PortId, m_wireReferenceUtils.OutputPortReference.DataType, inputPort.TypeLocked ) ) + originNode.OnOutputPortConnected( m_wireReferenceUtils.OutputPortReference.PortId, node.UniqueId, inputPort.PortId ); + } + } + m_wireReferenceUtils.InvalidateReferences(); + + //for ( int i = 0; i < m_mainGraphInstance.VisibleNodes.Count; i++ ) + //{ + // m_mainGraphInstance.VisibleNodes[ i ].OnNodeInteraction( node ); + //} + } + + if( selectNode ) + m_mainGraphInstance.SelectNode( node, false, false ); + //_repaintIsDirty = true + + SetSaveIsDirty(); + ForceRepaint(); + return node; + } + + public void UpdateNodePreviewListAndTime() + { + if( UIUtils.CurrentWindow != this ) + return; + + double deltaTime = Time.realtimeSinceStartup - m_time; + m_time = Time.realtimeSinceStartup; + + if( DebugConsoleWindow.DeveloperMode ) + { + m_frameCounter++; + if( m_frameCounter >= 60 ) + { + m_fpsDisplay = ( 60 / ( Time.realtimeSinceStartup - m_fpsTime ) ).ToString( "N2" ); + m_fpsTime = Time.realtimeSinceStartup; + m_frameCounter = 0; + } + } + + if( m_smoothZoom ) + { + m_repaintIsDirty = true; + if( Mathf.Abs( m_targetZoom - m_cameraZoom ) < 0.001f ) + { + m_smoothZoom = false; + m_cameraZoom = m_targetZoom; + m_zoomTime = 0; + } + else + { + m_zoomTime += deltaTime; + Vector2 canvasPos = m_zoomPivot * m_cameraZoom; + m_cameraZoom = Mathf.SmoothDamp( m_cameraZoom, m_targetZoom, ref m_zoomVelocity, 0.1f, 10000, (float)deltaTime * 1.5f ); + canvasPos = canvasPos - m_zoomPivot * m_cameraZoom; + m_cameraOffset = m_cameraOffset - canvasPos; + m_targetOffset = m_targetOffset - canvasPos; + } + + } + + if( m_smoothOffset ) + { + m_repaintIsDirty = true; + if( ( m_targetOffset - m_cameraOffset ).SqrMagnitude() < 1f ) + { + m_smoothOffset = false; + m_offsetTime = 0; + } + else + { + m_offsetTime += deltaTime; + m_cameraOffset = Vector2.SmoothDamp( m_cameraOffset, m_targetOffset, ref m_camVelocity, 0.1f, 100000, (float)deltaTime * 1.5f ); + } + } + + if( m_cachedEditorTimeId == -1 ) + m_cachedEditorTimeId = Shader.PropertyToID( "_EditorTime" ); + + if( m_cachedEditorDeltaTimeId == -1 ) + m_cachedEditorDeltaTimeId = Shader.PropertyToID( "_EditorDeltaTime" ); + + //Update Game View? + //Shader.SetGlobalVector( "_Time", new Vector4( Time.realtimeSinceStartup / 20, Time.realtimeSinceStartup, Time.realtimeSinceStartup * 2, Time.realtimeSinceStartup * 3 ) ); + + //System.Type T = System.Type.GetType( "UnityEditor.GameView,UnityEditor" ); + //UnityEngine.Object[] array = Resources.FindObjectsOfTypeAll( T ); + //EditorWindow gameView = ( array.Length <= 0 ) ? null : ( ( EditorWindow ) array[ 0 ] ); + //gameView.Repaint(); + + if( RenderSettings.sun != null ) + { + Vector3 lightdir = -RenderSettings.sun.transform.forward;//.rotation.eulerAngles; + + Shader.SetGlobalVector( "_EditorWorldLightPos", new Vector4( lightdir.x, lightdir.y, lightdir.z, 0 ) ); + Shader.SetGlobalColor( "_EditorLightColor", RenderSettings.sun.color.linear ); + } + Shader.SetGlobalFloat( "_EditorTime", (float)m_time ); + Shader.SetGlobalFloat( "_EditorDeltaTime", (float)deltaTime ); + + /////////// UPDATE PREVIEWS ////////////// + UIUtils.CheckNullMaterials(); + //CurrentGraph.AllNodes.Sort( ( x, y ) => { return x.Depth.CompareTo( y.Depth ); } ); + int nodeCount = CurrentGraph.AllNodes.Count; + for( int i = nodeCount - 1; i >= 0; i-- ) + { + ParentNode node = CurrentGraph.AllNodes[ i ]; + if( node != null && !VisitedChanged.ContainsKey( node.OutputId ) ) + { + bool result = node.RecursivePreviewUpdate(); + if( result ) + m_repaintIsDirty = true; + } + } + + VisitedChanged.Clear(); + if( m_repaintIsDirty ) + { + m_repaintIsDirty = false; + Repaint(); + } + } + + public void ForceRepaint() + { + m_repaintCount += 1; + m_repaintIsDirty = true; + //Repaint(); + } + + public void ForceUpdateFromMaterial() { m_forceUpdateFromMaterialFlag = true; } + void UseCurrentEvent() + { + m_currentEvent.Use(); + } + + + + public void OnBeforeSerialize() + { + //if ( !UIUtils.SerializeFromUndo() ) + //{ + // m_mainGraphInstance.DeSelectAll(); + //} + + if( DebugConsoleWindow.UseShaderPanelsInfo ) + { + if( m_nodeParametersWindow != null ) + m_nodeParametersWindowMaximized = m_nodeParametersWindow.IsMaximized; + + if( m_paletteWindow != null ) + m_paletteWindowMaximized = m_paletteWindow.IsMaximized; + } + } + + public void OnAfterDeserialize() + { + m_afterDeserializeFlag = true; + + //m_customGraph = null; + if( DebugConsoleWindow.UseShaderPanelsInfo ) + { + if( m_nodeParametersWindow != null ) + m_nodeParametersWindow.IsMaximized = m_nodeParametersWindowMaximized; + + if( m_paletteWindow != null ) + m_paletteWindow.IsMaximized = m_paletteWindowMaximized; + } + } + + void OnDestroy() + { + m_ctrlSCallback = false; + Destroy(); + } + + public override void OnDisable() + { + base.OnDisable(); + m_ctrlSCallback = false; + //EditorApplication.update -= UpdateTime; + EditorApplication.update -= UpdateNodePreviewListAndTime; + + EditorApplication.update -= IOUtils.UpdateIO; + + for( int i = 0; i < IOUtils.AllOpenedWindows.Count; i++ ) + { + if( IOUtils.AllOpenedWindows[ i ] != this ) + { + EditorApplication.update += IOUtils.UpdateIO; + break; + } + } + } + + void OnEmptyGraphDetected( ParentGraph graph ) + { + if( m_delayedLoadObject != null ) + { + LoadObject( m_delayedLoadObject ); + m_delayedLoadObject = null; + Repaint(); + } + else + { + if( !string.IsNullOrEmpty( Lastpath ) ) + { + Shader shader = AssetDatabase.LoadAssetAtPath( Lastpath ); + if( shader == null ) + { + Material material = AssetDatabase.LoadAssetAtPath( Lastpath ); + if( material != null ) + { + LoadDroppedObject( true, material.shader, material, null ); + } + else + { + AmplifyShaderFunction function = AssetDatabase.LoadAssetAtPath( Lastpath ); + if( function != null ) + { + LoadDroppedObject( true, null, null, function ); + } + } + } + else + { + LoadDroppedObject( true, shader, null, null ); + } + Repaint(); + } + } + } + + + public void ForceMaterialsToUpdate( ref Dictionary availableMaterials ) + { + m_forcingMaterialUpdateOp = true; + m_forcingMaterialUpdateFlag = true; + m_materialsToUpdate.Clear(); + foreach( KeyValuePair kvp in availableMaterials ) + { + Material material = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( kvp.Value ) ); + if( material != null ) + { + m_materialsToUpdate.Add( material ); + } + } + } + + public void SetOutdatedShaderFromTemplate() + { + m_outdatedShaderFromTemplateLoaded = true; + } + + public void ReplaceMasterNode( MasterNodeCategoriesData data, bool cacheMasterNodes ) + { + // save connection list before switching + m_savedList.Clear(); + int count = m_mainGraphInstance.CurrentMasterNode.InputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_mainGraphInstance.CurrentMasterNode.InputPorts[ i ].IsConnected ) + { + string name = m_mainGraphInstance.CurrentMasterNode.InputPorts[ i ].Name; + OutputPort op = m_mainGraphInstance.CurrentMasterNode.InputPorts[ i ].GetOutputConnection(); + if( !m_savedList.ContainsKey( name ) ) + { + m_savedList.Add( name, op ); + } + } + } + + m_replaceMasterNodeType = data.Category; + m_replaceMasterNode = true; + m_replaceMasterNodeData = data.Name; + m_replaceMasterNodeDataFromCache = cacheMasterNodes; + if( cacheMasterNodes ) + { + m_clipboard.AddMultiPassNodesToClipboard( m_mainGraphInstance.MultiPassMasterNodes.NodesList, true, -1 ); + for( int i = 0; i < m_mainGraphInstance.LodMultiPassMasternodes.Count; i++ ) + { + if( m_mainGraphInstance.LodMultiPassMasternodes[ i ].Count > 0 ) + m_clipboard.AddMultiPassNodesToClipboard( m_mainGraphInstance.LodMultiPassMasternodes[ i ].NodesList, false, i ); + } + } + } + + void CheckNodeReplacement() + { + if( m_replaceMasterNode ) + { + m_replaceMasterNode = false; + switch( m_replaceMasterNodeType ) + { + default: + case AvailableShaderTypes.SurfaceShader: + { + SetStandardShader(); + if( IOUtils.OnShaderTypeChangedEvent != null ) + { + IOUtils.OnShaderTypeChangedEvent( m_mainGraphInstance.CurrentShader, false, string.Empty ); + } + } + break; + case AvailableShaderTypes.Template: + { + + TemplateDataParent templateData = m_templatesManager.GetTemplate( m_replaceMasterNodeData ); + if( m_replaceMasterNodeDataFromCache ) + { + m_mainGraphInstance.CrossCheckTemplateNodes( templateData, m_mainGraphInstance.MultiPassMasterNodes.NodesList , -1 ); + for( int i = 0; i < m_mainGraphInstance.LodMultiPassMasternodes.Count; i++ ) + { + if( m_mainGraphInstance.LodMultiPassMasternodes[ i ].Count > 0 ) + m_mainGraphInstance.CrossCheckTemplateNodes( templateData, m_mainGraphInstance.LodMultiPassMasternodes[ i ].NodesList, i ); + } + + //Getting data from clipboard must be done after cross check all lists + m_clipboard.GetMultiPassNodesFromClipboard( m_mainGraphInstance.MultiPassMasterNodes.NodesList,-1 ); + for( int i = 0; i < m_mainGraphInstance.LodMultiPassMasternodes.Count; i++ ) + { + if( m_mainGraphInstance.LodMultiPassMasternodes[ i ].Count > 0 ) + m_clipboard.GetMultiPassNodesFromClipboard( m_mainGraphInstance.LodMultiPassMasternodes[i].NodesList, i ); + } + m_clipboard.ResetMultipassNodesData(); + } + else + { + SetTemplateShader( m_replaceMasterNodeData, false ); + } + + if( IOUtils.OnShaderTypeChangedEvent != null ) + { + IOUtils.OnShaderTypeChangedEvent( m_mainGraphInstance.CurrentShader, true, templateData.GUID ); + } + } + break; + } + } + else if( m_outdatedShaderFromTemplateLoaded ) + { + m_outdatedShaderFromTemplateLoaded = false; + TemplateMultiPassMasterNode masterNode = m_mainGraphInstance.CurrentMasterNode as TemplateMultiPassMasterNode; + if( masterNode != null ) + { + ReplaceMasterNode( masterNode.CurrentCategoriesData, true ); + } + } + + // restore possible connections by name + if( m_savedList.Count > 0 ) + { + foreach( var item in m_savedList ) + { + string name = item.Key; + OutputPort op = item.Value; + InputPort ip = m_mainGraphInstance.CurrentMasterNode.InputPorts.Find( x => x.Name == name ); + + if( op != null && ip != null && ip.Visible ) + { + var iNode = UIUtils.GetNode( ip.NodeId ); + var oNode = UIUtils.GetNode( op.NodeId ); + ip.ConnectTo( oNode.UniqueId, op.PortId, op.DataType, false ); + op.ConnectTo( iNode.UniqueId, ip.PortId, ip.DataType, ip.TypeLocked ); + + iNode.OnInputPortConnected( ip.PortId, oNode.UniqueId, op.PortId ); + oNode.OnOutputPortConnected( op.PortId, iNode.UniqueId, ip.PortId ); + } + } + } + m_savedList.Clear(); + } + + public Vector2 TranformPosition( Vector2 pos ) + { + return pos * m_cameraZoom - m_cameraOffset; + } + + public void UpdateTabTitle() + { + if( m_isShaderFunctionWindow ) + { + if( m_openedShaderFunction != null ) + { + this.titleContent.text = GenerateTabTitle( m_openedShaderFunction.FunctionName ); + } + } + else + { + if( m_selectionMode == ASESelectionMode.Material ) + { + this.titleContent.text = GenerateTabTitle( m_mainGraphInstance.CurrentMaterial.name ); + } + else + { + this.titleContent.text = GenerateTabTitle( m_mainGraphInstance.CurrentShader.name ); + } + } + } + + public ParentGraph CustomGraph + { + get { return m_customGraph; } + set { m_customGraph = value; } + } + + public ParentGraph CurrentGraph + { + get + { + if( m_customGraph != null ) + return m_customGraph; + + return m_mainGraphInstance; + } + } + + public void RefreshAvaibleNodes() + { + if( m_contextMenu != null && m_mainGraphInstance != null ) + { + m_contextMenu.RefreshNodes( m_mainGraphInstance ); + m_paletteWindow.ForceUpdate = true; + m_contextPalette.ForceUpdate = true; + m_refreshAvailableNodes = false; + } + } + + public void LateRefreshAvailableNodes() + { + m_refreshAvailableNodes = true; + } + + public ParentGraph OutsideGraph { get { return m_mainGraphInstance; } } + + public bool ShaderIsModified + { + get { return m_shaderIsModified; } + set + { + m_shaderIsModified = value && UIUtils.DirtyMask; + + m_toolsWindow.SetStateOnButton( ToolButtonType.Save, m_shaderIsModified ? 1 : 0 ); + if( !IsShaderFunctionWindow ) + { + MasterNode masterNode = m_mainGraphInstance.CurrentMasterNode; + if( masterNode != null && masterNode.CurrentShader != null ) + { + m_toolsWindow.SetStateOnButton( ToolButtonType.Update, ShaderIsModified ? 0 : 2, ShaderIsModified ? ShaderIsModifiedMessage : ShaderIsNotModified ); + UpdateTabTitle( masterNode.ShaderName, m_shaderIsModified ); + } + else + { + m_toolsWindow.SetStateOnButton( ToolButtonType.Update, 1 ); + } + + //if( m_mainGraphInstance.CurrentStandardSurface != null ) + // UpdateTabTitle( m_mainGraphInstance.CurrentStandardSurface.ShaderName, m_shaderIsModified ); + } + else + { + m_toolsWindow.SetStateOnButton( ToolButtonType.Update, m_shaderIsModified ? 0 : 2 ); + if( m_mainGraphInstance.CurrentShaderFunction != null ) + UpdateTabTitle( m_mainGraphInstance.CurrentShaderFunction.FunctionName, m_shaderIsModified ); + } + + } + } + public void MarkToRepaint() { m_repaintIsDirty = true; } + public void RequestSave() { m_markedToSave = true; } + public void RequestRepaint() { m_repaintIsDirty = true; } + public OptionsWindow Options { get { return m_optionsWindow; } } + public GraphContextMenu ContextMenuInstance { get { return m_contextMenu; } set { m_contextMenu = value; } } + public ShortcutsManager ShortcutManagerInstance { get { return m_shortcutManager; } } + + public bool GlobalPreview + { + get { return m_globalPreview; } + set { m_globalPreview = value; } + } + + public bool GlobalShowInternalData + { + get { return m_globalShowInternalData; } + set { m_globalShowInternalData = value; } + } + + public double EditorTime + { + get { return m_time; } + set { m_time = value; } + } + + public ASESelectionMode CurrentSelection + { + get { return m_selectionMode; } + set + { + m_selectionMode = value; + switch( m_selectionMode ) + { + default: + case ASESelectionMode.Shader: + { + m_toolsWindow.BorderStyle = UIUtils.GetCustomStyle( CustomStyle.ShaderBorder ); + } + break; + case ASESelectionMode.Material: + { + m_toolsWindow.BorderStyle = UIUtils.GetCustomStyle( CustomStyle.MaterialBorder ); + } + break; + case ASESelectionMode.ShaderFunction: + { + m_toolsWindow.BorderStyle = UIUtils.GetCustomStyle( CustomStyle.ShaderFunctionBorder ); + } + break; + } + } + } + + public bool LiveShaderEditing + { + get { return m_liveShaderEditing; } + set + { + m_liveShaderEditing = value; + m_innerEditorVariables.LiveMode = m_liveShaderEditing; + UpdateLiveUI(); + } + } + + public NodeAvailability CurrentNodeAvailability + { + get { return m_currentNodeAvailability; } + set + { + NodeAvailability cache = m_currentNodeAvailability; + m_currentNodeAvailability = value; + + if( cache != value ) + RefreshAvaibleNodes(); + } + } + public string GUID + { + get + { + if( m_isShaderFunctionWindow ) + { + return m_openedShaderFunction != null ? AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_openedShaderFunction ) ) : string.Empty; + } + else + { + return m_mainGraphInstance.CurrentShader != null ? AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_mainGraphInstance.CurrentShader ) ) : string.Empty; + } + } + } + public List Messages { get { return m_messages; } set { m_messages = value; } } + public float MaxMsgWidth { get { return m_maxMsgWidth; } set { m_maxMsgWidth = value; } } + public bool MaximizeMessages { get { return m_maximizeMessages; } set { m_maximizeMessages = value; } } + public void InvalidateAlt() { m_altAvailable = false; } + public PaletteWindow CurrentPaletteWindow { get { return m_paletteWindow; } } + public PreMadeShaders PreMadeShadersInstance { get { return m_preMadeShaders; } } + public Rect CameraInfo { get { return m_cameraInfo; } } + public Vector2 TranformedMousePos { get { return m_currentMousePos2D * m_cameraZoom - m_cameraOffset; } } + public Vector2 TranformedKeyEvtMousePos { get { return m_keyEvtMousePos2D * m_cameraZoom - m_cameraOffset; } } + public PalettePopUp PalettePopUpInstance { get { return m_palettePopup; } } + public DuplicatePreventionBuffer DuplicatePrevBufferInstance { get { return m_duplicatePreventionBuffer; } } + public NodeParametersWindow ParametersWindow { get { return m_nodeParametersWindow; } } + public NodeExporterUtils CurrentNodeExporterUtils { get { return m_nodeExporterUtils; } } + public AmplifyShaderFunction OpenedShaderFunction { get { return m_openedShaderFunction; } } + public DrawInfo CameraDrawInfo { get { return m_drawInfo; } } + public string Lastpath { get { return m_lastpath; } set { m_lastpath = value; } } + public string LastOpenedLocation { get { return m_lastOpenedLocation; } set { m_lastOpenedLocation = value; } } + public float AvailableCanvasWidth { get { return ( m_cameraInfo.width - m_paletteWindow.RealWidth - m_nodeParametersWindow.RealWidth ); } } + public float AvailableCanvasHeight { get { return ( m_cameraInfo.height ); } } + public float CameraZoom { get { return m_cameraZoom; } set { m_cameraZoom = value; m_zoomChanged = true; } } + public int GraphCount { get { return m_graphCount; } set { m_graphCount = value; } } + public bool ForceAutoPanDir { get { return m_forceAutoPanDir; } set { m_forceAutoPanDir = value; } } + public bool OpenedAssetFromNode { get { return m_openedAssetFromNode; } set { m_openedAssetFromNode = value; } } + public bool IsShaderFunctionWindow { get { return m_isShaderFunctionWindow; } set { m_isShaderFunctionWindow = value; } } + public bool NodesLoadedCorrectly { get { return m_nodesLoadedCorrectly; } set { m_nodesLoadedCorrectly = value; } } + public double CurrentInactiveTime { get { return m_currentInactiveTime; } } + public string ReplaceMasterNodeData { get { return m_replaceMasterNodeData; } } + public AvailableShaderTypes ReplaceMasterNodeType { get { return m_replaceMasterNodeType; } } + public NodeWireReferencesUtils WireReferenceUtils { get { return m_wireReferenceUtils; } } + public ContextPalette WindowContextPallete { get { return m_contextPalette; } } + // This needs to go to UIUtils + public Texture2D WireTexture { get { return m_wireTexture; } } + public Event CurrentEvent { get { return m_currentEvent; } } + public string CurrentCommandName { get { return m_currentCommandName; } } + public InnerWindowEditorVariables InnerWindowVariables { get { return m_innerEditorVariables; } } + public TemplatesManager TemplatesManagerInstance { get { return m_templatesManager; } } + public Material CurrentMaterial { get { return CurrentGraph.CurrentMaterial; } } + public Clipboard ClipboardInstance { get { return m_clipboard; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderEditorWindow.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderEditorWindow.cs.meta new file mode 100644 index 0000000..6ce8e71 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderEditorWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c8bcac0d66f920e49803925a85beb0ed +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunction.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunction.cs new file mode 100644 index 0000000..df83bed --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunction.cs @@ -0,0 +1,189 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; +using AmplifyShaderEditor; + +[Serializable] +public class AmplifyShaderFunction : ScriptableObject +{ + [SerializeField] + private string m_functionInfo = string.Empty; + public string FunctionInfo + { + get { return m_functionInfo; } + set { m_functionInfo = value; } + } + + [SerializeField] + private string m_functionName = string.Empty; + public string FunctionName + { + get { if( m_functionName.Length == 0 ) return name; else return m_functionName; } + set { m_functionName = value; } + } + + [SerializeField] + [TextArea( 5, 15 )] + private string m_description = string.Empty; + public string Description + { + get { return m_description; } + set { m_description = value; } + } + + [SerializeField] + private AdditionalIncludesHelper m_additionalIncludes = new AdditionalIncludesHelper(); + //public AdditionalIncludesHelper AdditionalIncludes + //{ + // get { return m_additionalIncludes; } + // set { m_additionalIncludes = value; } + //} + + [SerializeField] + private AdditionalPragmasHelper m_additionalPragmas = new AdditionalPragmasHelper(); + //public AdditionalPragmasHelper AdditionalPragmas + //{ + // get { return m_additionalPragmas; } + // set { m_additionalPragmas = value; } + //} + + [SerializeField] + private TemplateAdditionalDirectivesHelper m_additionalDirectives = new TemplateAdditionalDirectivesHelper( " Additional Directives" ); + public TemplateAdditionalDirectivesHelper AdditionalDirectives + { + get { return m_additionalDirectives; } + set { m_additionalDirectives = value; } + } + + [SerializeField] + private FunctionNodeCategories m_nodeCategory = FunctionNodeCategories.Functions; + public FunctionNodeCategories NodeCategory + { + get { return m_nodeCategory; } + set { m_nodeCategory = value; } + } + + [SerializeField] + private string m_customNodeCategory = string.Empty; + public string CustomNodeCategory + { + get + { + if( m_nodeCategory == FunctionNodeCategories.Custom ) + { + if( string.IsNullOrEmpty( m_customNodeCategory ) ) + return "Functions"; + else + return m_customNodeCategory; + } + else + { + return UIUtils.CategoryPresets[ (int)m_nodeCategory ]; + //return new SerializedObject( this ).FindProperty( "m_nodeCategory" ).enumDisplayNames[ (int)m_nodeCategory ]; + } + } + } + + [SerializeField] + private PreviewLocation m_previewPosition = PreviewLocation.Auto; + public PreviewLocation PreviewPosition + { + get { return m_previewPosition; } + set { m_previewPosition = value; } + } + + [SerializeField] + private bool m_hidden = false; + public bool Hidden + { + get { return m_hidden; } + set { m_hidden = value; } + } + + public void UpdateDirectivesList() + { + m_additionalDirectives.CleanNullDirectives(); + m_additionalDirectives.UpdateDirectivesFromSaveItems(); + + if( m_additionalIncludes.IncludeList.Count > 0 ) + { + m_additionalDirectives.AddItems( AdditionalLineType.Include, m_additionalIncludes.IncludeList ); + m_additionalIncludes.IncludeList.Clear(); + } + + if( m_additionalPragmas.PragmaList.Count > 0 ) + { + m_additionalDirectives.AddItems( AdditionalLineType.Pragma, m_additionalPragmas.PragmaList ); + m_additionalPragmas.PragmaList.Clear(); + } + } + + public void ResetDirectivesOrigin() + { + //if( UIUtils.CurrentShaderVersion() < 16807 ) + // Although the correct version was 1.6.7 rev 07 this issue was only detected on v1.7.1. rev 00 + // So to avoid potential incorrect saves over shader functions, I decided to broaden up the version range + if( UIUtils.CurrentShaderVersion() < 17101 ) + { + m_additionalDirectives.ResetDirectivesOrigin(); + } + } +} + +public class ShaderFunctionDetector : AssetPostprocessor +{ + static void OnPostprocessAllAssets( string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths ) + { + if( UIUtils.CurrentWindow == null ) + return; + + bool markForRefresh = false; + AmplifyShaderFunction function = null; + for( int i = 0; i < importedAssets.Length; i++ ) + { + function = AssetDatabase.LoadAssetAtPath( importedAssets[ i ] ); + if( function != null ) + { + markForRefresh = true; + break; + } + } + + if( deletedAssets.Length > 0 ) + markForRefresh = true; + + for( int i = 0; i < movedAssets.Length; i++ ) + { + function = AssetDatabase.LoadAssetAtPath( movedAssets[ i ] ); + if( function != null ) + { + markForRefresh = true; + break; + } + } + + for( int i = 0; i < movedFromAssetPaths.Length; i++ ) + { + function = AssetDatabase.LoadAssetAtPath( movedFromAssetPaths[ i ] ); + if( function != null ) + { + markForRefresh = true; + break; + } + } + + if( markForRefresh ) + { + markForRefresh = false; + if( function != null ) + { + IOUtils.UpdateSFandRefreshWindows( function ); + } + UIUtils.CurrentWindow.LateRefreshAvailableNodes(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunction.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunction.cs.meta new file mode 100644 index 0000000..35a9310 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunction.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 78b2425a2284af743826c689403a4924 +timeCreated: 1492703397 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 50be8291f9514914aa55c66c49da67cf, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunctionEditor.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunctionEditor.cs new file mode 100644 index 0000000..010294d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunctionEditor.cs @@ -0,0 +1,168 @@ +using UnityEngine; +using UnityEditor; +using System; +using System.Text.RegularExpressions; +using System.IO; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [CustomEditor( typeof( AmplifyShaderFunction ) )] + public class AmplifyShaderFunctionEditor : Editor + { + class FunctionDependency + { + public string AssetName; + public string AssetPath; + public FunctionDependency(string name, string path) + { + AssetName = name; + AssetPath = path; + } + } + + AmplifyShaderFunction m_target; + List m_dependencies = new List(); + + void OnEnable() + { + m_target = ( target as AmplifyShaderFunction ); + } + + public override void OnInspectorGUI() + { + //base.OnInspectorGUI(); + //base.serializedObject.Update(); + if( GUILayout.Button( "Open in Shader Editor" ) ) + { +#if UNITY_2018_3_OR_NEWER + ASEPackageManagerHelper.SetupLateShaderFunction( m_target ); +#else + AmplifyShaderEditorWindow.LoadShaderFunctionToASE( m_target, false ); +#endif + } + //EditorGUILayout.Separator(); + //m_target.FunctionInfo = EditorGUILayout.TextArea( m_target.FunctionInfo ); + + if( m_target.Description.Length > 0 ) + { + EditorGUILayout.HelpBox( m_target.Description, MessageType.Info ); + } + + EditorGUILayout.Space(); + if( GUILayout.Button( "Search Direct Dependencies" ) ) + { + m_dependencies.Clear(); + string guid = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_target ) ); + + string[] allSFs = AssetDatabase.FindAssets( "t:AmplifyShaderFunction", null ); + foreach( string guid1 in allSFs ) + { + string sfPath = AssetDatabase.GUIDToAssetPath( guid1 ); + bool found = SearchForGUID( guid, sfPath ); + if( found ) + { + //string n = Regex.Replace( sfPath, @"(\.\w+|[\w\d\/]+\/)", "" ); + string n = Regex.Replace( sfPath, @"[\w\d\/]+\/", "" ); + m_dependencies.Add(new FunctionDependency( n, sfPath ) ); + } + } + + string[] allSHs = AssetDatabase.FindAssets( "t:Shader", null ); + foreach( string guid1 in allSHs ) + { + string shPath = AssetDatabase.GUIDToAssetPath( guid1 ); + bool found = SearchForGUID( guid, shPath ); + if( found ) + { + string n = Regex.Replace( shPath, @"[\w\d\/]+\/", "" ); + m_dependencies.Add( new FunctionDependency( n, shPath ) ); + } + } + } + EditorGUILayout.Space(); + for( int i = 0; i < m_dependencies.Count; i++ ) + { + EditorGUILayout.BeginHorizontal(); + if( GUILayout.Button( m_dependencies[ i ].AssetName, "minibuttonleft" ) ) + { + SelectAtPath( m_dependencies[ i ].AssetPath ); + } + if( GUILayout.Button( "edit", "minibuttonright", GUILayout.Width(100) ) ) + { + if( m_dependencies[ i ].AssetName.EndsWith( ".asset" ) ) + { + var obj = AssetDatabase.LoadAssetAtPath( m_dependencies[ i ].AssetPath ); + AmplifyShaderEditorWindow.LoadShaderFunctionToASE( obj, false ); + } + else + { + var obj = AssetDatabase.LoadAssetAtPath( m_dependencies[ i ].AssetPath ); + AmplifyShaderEditorWindow.ConvertShaderToASE( obj ); + } + } + EditorGUILayout.EndHorizontal(); + } + + if( m_dependencies.Count > 0 ) + { + List assetPaths = new List(); + for( int i = 0; i < m_dependencies.Count; i++ ) + { + assetPaths.Add( m_dependencies[ i ].AssetPath ); + } + + if( GUILayout.Button( "Open and Save All" ) ) + { + bool doit = EditorUtility.DisplayDialog( "Open and Save All", "This will try to open all shader function and shaders that use this shader function and save them in quick succession, this may irreversibly break your files if something goes wrong. Are you sure you want to try?", "Yes, I'll take the risk", "No, I'll do it myself" ); + if( doit ) + AmplifyShaderEditorWindow.LoadAndSaveList( assetPaths.ToArray() ); + } + } + } + + public void SelectAtPath( string path ) + { + var obj = AssetDatabase.LoadAssetAtPath( path ); + EditorGUIUtility.PingObject( obj ); + } + + public static bool SearchForGUID( string guid, string pathName ) + { + bool result = false; + int count = 0; + if( !string.IsNullOrEmpty( pathName ) && File.Exists( pathName ) ) + { + StreamReader fileReader = null; + try + { + fileReader = new StreamReader( pathName ); + + string line; + int index = -1; + while( ( line = fileReader.ReadLine() ) != null ) + { + index = line.IndexOf( guid ); + count++; + + if( index > -1 ) + { + result = true; + break; + } + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + finally + { + if( fileReader != null ) + fileReader.Close(); + } + } + return result; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunctionEditor.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunctionEditor.cs.meta new file mode 100644 index 0000000..99b80bb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AmplifyShaderFunctionEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8b2d6d1320661374db53aeb8057312b2 +timeCreated: 1491909065 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AutoPanData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AutoPanData.cs new file mode 100644 index 0000000..9f028f3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AutoPanData.cs @@ -0,0 +1,94 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public enum AutoPanLocation + { + TOP = 0, + BOTTOM, + LEFT, + RIGHT + } + + public class AutoPanData + { + private Rect m_area; + private float m_size; + private Vector2 m_velocity; + + private GUIStyle m_style; + private Color m_color = new Color( 1f, 0f, 0f, 0.5f ); + + private AutoPanLocation m_location; + private float m_adjustWidth = 0; + private float m_adjustInitialX = 0; + + public AutoPanData( AutoPanLocation location, float size, Vector2 vel ) + { + m_area = new Rect(); + m_size = size; + m_velocity = vel; + m_location = location; + } + + public bool CheckArea( Vector2 mousePosition, Rect window, bool draw ) + { + float totalSize = m_size + m_adjustWidth; + switch ( m_location ) + { + case AutoPanLocation.TOP: + { + m_area.x = m_adjustInitialX; + m_area.y = 0; + m_area.width = window.width; + m_area.height = totalSize; + } + break; + case AutoPanLocation.BOTTOM: + { + m_area.x = m_adjustInitialX; + m_area.y = window.height - totalSize; + m_area.width = window.width; + m_area.height = totalSize; + } + break; + case AutoPanLocation.LEFT: + { + m_area.x = m_adjustInitialX; + m_area.y = 0; + m_area.width = totalSize; + m_area.height = window.height; + } + break; + case AutoPanLocation.RIGHT: + { + m_area.x = m_adjustInitialX + window.width - totalSize; + m_area.y = 0; + m_area.width = totalSize; + m_area.height = window.height; + } + break; + } + + if ( draw ) + { + if ( m_style == null ) + { + m_style = UIUtils.Box; + } + Color bufferedColor = GUI.color; + GUI.color = m_color; + GUI.Label( m_area, string.Empty, m_style ); + GUI.color = bufferedColor; + } + return m_area.Contains( mousePosition ); + } + + public float AdjustWidth { set { m_adjustWidth = value; } } + public float AdjustInitialX { set { m_adjustInitialX = value; } } + public Vector2 Velocity { get { return m_velocity; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AutoPanData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AutoPanData.cs.meta new file mode 100644 index 0000000..17e6b86 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/AutoPanData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 711db07e8265cb740940568c4bc7345f +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Clipboard.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Clipboard.cs new file mode 100644 index 0000000..1b4d4fa --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Clipboard.cs @@ -0,0 +1,262 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; +using UnityEngine; +using System.Collections.Generic; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + + public class ClipboardData + { + public string Data = string.Empty; + public string Connections = string.Empty; + public int OldNodeId = -1; + public int NewNodeId = -1; + + public ClipboardData( string data, string connections, int oldNodeId ) + { + Data = data; + Connections = connections; + OldNodeId = oldNodeId; + } + + public override string ToString() + { + return Data + IOUtils.CLIPBOARD_DATA_SEPARATOR + Connections + IOUtils.CLIPBOARD_DATA_SEPARATOR + OldNodeId + IOUtils.CLIPBOARD_DATA_SEPARATOR + NewNodeId; + } + } + + public class Clipboard + { + public const string ClipboardId = "AMPLIFY_CLIPBOARD_ID"; + private readonly string[] ClipboardTagId = { "#CLIP_ITEM#" }; + private List m_clipboardStrData; + private Dictionary m_clipboardAuxData; + private Dictionary m_multiPassMasterNodeData; + + public Clipboard() + { + m_clipboardStrData = new List(); + m_clipboardAuxData = new Dictionary(); + m_multiPassMasterNodeData = new Dictionary(); + } + + public void ResetMultipassNodesData() + { + m_multiPassMasterNodeData.Clear(); + } + + public void AddMultiPassNodesToClipboard( List masterNodes, bool resetList, int lodId ) + { + if( resetList ) + m_multiPassMasterNodeData.Clear(); + + int templatesAmount = masterNodes.Count; + for( int i = 0; i < templatesAmount; i++ ) + { + if( !masterNodes[ i ].InvalidNode ) + { + string data = string.Empty; + string connection = string.Empty; + System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; + masterNodes[ i ].FullWriteToString( ref data, ref connection ); + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + ClipboardData clipboardData = new ClipboardData( data, connection, masterNodes[ i ].UniqueId ); + m_multiPassMasterNodeData.Add( masterNodes[ i ].PassUniqueName + lodId, clipboardData ); + } + } + } + + public void GetMultiPassNodesFromClipboard( List masterNodes, int lodId ) + { + int templatesAmount = masterNodes.Count; + for( int i = 0; i < templatesAmount; i++ ) + { + string clipboardDataId = masterNodes[ i ].PassUniqueName + lodId; + if( m_multiPassMasterNodeData.ContainsKey( clipboardDataId ) ) + { + ClipboardData nodeData = m_multiPassMasterNodeData[ clipboardDataId ]; + string[] nodeParams = nodeData.Data.Split( IOUtils.FIELD_SEPARATOR ); + System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; + masterNodes[ i ].FullReadFromString( ref nodeParams ); + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + } + } + + for( int i = 0; i < templatesAmount; i++ ) + { + string clipboardDataId = masterNodes[ i ].PassUniqueName + lodId; + if( m_multiPassMasterNodeData.ContainsKey( clipboardDataId ) ) + { + masterNodes[ i ].SetReadOptions(); + masterNodes[ i ].ForceOptionsRefresh(); + } + } + + } + + public void AddToClipboard( List selectedNodes , Vector3 initialPosition, ParentGraph graph ) + { + //m_clipboardStrData.Clear(); + //m_clipboardAuxData.Clear(); + + string clipboardData = IOUtils.Vector3ToString( initialPosition ) + ClipboardTagId[ 0 ]; + int masterNodeId = UIUtils.CurrentWindow.CurrentGraph.CurrentMasterNodeId; + int count = selectedNodes.Count; + for ( int i = 0; i < count; i++ ) + { + if ( UIUtils.CurrentWindow.IsShaderFunctionWindow || !graph.IsMasterNode( selectedNodes[ i ] )) + { + string nodeData = string.Empty; + string connections = string.Empty; + selectedNodes[ i ].ClipboardFullWriteToString( ref nodeData, ref connections ); + clipboardData += nodeData; + if ( !string.IsNullOrEmpty( connections ) ) + { + connections = connections.Substring( 0, connections.Length - 1 ); + clipboardData += "\n" + connections; + } + if ( i < count - 1 ) + clipboardData += ClipboardTagId[ 0 ]; + + //ClipboardData data = new ClipboardData( nodeData, connections, selectedNodes[ i ].UniqueId ); + //m_clipboardStrData.Add( data ); + //m_clipboardAuxData.Add( selectedNodes[ i ].UniqueId, data ); + } + } + + if ( !string.IsNullOrEmpty( clipboardData ) ) + { + EditorPrefs.SetString( ClipboardId, clipboardData ); + } + //for ( int i = 0; i < selectedNodes.Count; i++ ) + //{ + // if ( selectedNodes[ i ].UniqueId != masterNodeId ) + // { + // WireNode wireNode = selectedNodes[ i ] as WireNode; + // if ( wireNode != null ) + // { + // if ( !IsNodeChainValid( selectedNodes[ i ], true ) || !IsNodeChainValid( selectedNodes[ i ], false ) ) + // { + // UnityEngine.Debug.Log( "found invalid wire port" ); + // } + // } + // } + //} + } + + public Vector3 GetDataFromEditorPrefs() + { + Vector3 initialPos = Vector3.zero; + m_clipboardStrData.Clear(); + m_clipboardAuxData.Clear(); + string clipboardData = EditorPrefs.GetString( ClipboardId, string.Empty ); + if ( !string.IsNullOrEmpty( clipboardData ) ) + { + string[] clipboardDataArray = clipboardData.Split( ClipboardTagId, StringSplitOptions.None ); + initialPos = IOUtils.StringToVector3( clipboardDataArray[0] ); + for ( int i = 1; i < clipboardDataArray.Length; i++ ) + { + if ( !string.IsNullOrEmpty( clipboardDataArray[ i ] ) ) + { + int wiresIndex = clipboardDataArray[ i ].IndexOf( IOUtils.LINE_TERMINATOR ); + string nodeData = string.Empty; + string connections = string.Empty; + if ( wiresIndex < 0 ) + { + nodeData = clipboardDataArray[ i ]; + } + else + { + nodeData = clipboardDataArray[ i ].Substring( 0, wiresIndex ); + connections = clipboardDataArray[ i ].Substring( wiresIndex + 1 ); + } + string[] nodeDataArr = nodeData.Split( IOUtils.FIELD_SEPARATOR ); + if ( nodeDataArr.Length > 2 ) + { + int nodeId = Convert.ToInt32( nodeDataArr[ 2 ] ); + ClipboardData data = new ClipboardData( nodeData, connections, nodeId ); + m_clipboardStrData.Add( data ); + m_clipboardAuxData.Add( nodeId, data ); + } + + } + } + } + return initialPos; + } + + public bool IsNodeChainValid( ParentNode currentNode, bool forward ) + { + WireNode wireNode = currentNode as WireNode; + if ( wireNode == null ) + { + return m_clipboardAuxData.ContainsKey( currentNode.UniqueId ); + } + + if ( forward ) + { + if ( wireNode.InputPorts[ 0 ].ExternalReferences.Count > 0 ) + { + int nodeId = wireNode.InputPorts[ 0 ].ExternalReferences[ 0 ].NodeId; + if ( m_clipboardAuxData.ContainsKey( nodeId ) ) + { + return IsNodeChainValid( UIUtils.GetNode( nodeId ), forward ); + } + } + } + else + { + int nodeId = wireNode.OutputPorts[ 0 ].ExternalReferences[ 0 ].NodeId; + if ( m_clipboardAuxData.ContainsKey( nodeId ) ) + { + return IsNodeChainValid( UIUtils.GetNode( nodeId ), forward ); + } + } + return false; + } + + public void GenerateFullString() + { + string data = string.Empty; + for ( int i = 0; i < m_clipboardStrData.Count; i++ ) + { + data += m_clipboardStrData[ i ].ToString(); + if ( i < m_clipboardStrData.Count - 1 ) + { + data += IOUtils.LINE_TERMINATOR; + } + } + } + + public void ClearClipboard() + { + m_clipboardStrData.Clear(); + m_clipboardAuxData.Clear(); + m_multiPassMasterNodeData.Clear(); + } + + public ClipboardData GetClipboardData( int oldNodeId ) + { + if ( m_clipboardAuxData.ContainsKey( oldNodeId ) ) + return m_clipboardAuxData[ oldNodeId ]; + return null; + } + + public int GeNewNodeId( int oldNodeId ) + { + if ( m_clipboardAuxData.ContainsKey( oldNodeId ) ) + return m_clipboardAuxData[ oldNodeId ].NewNodeId; + return -1; + } + + public List CurrentClipboardStrData + { + get { return m_clipboardStrData; } + } + + public bool HasCachedMasterNodes { get { return m_multiPassMasterNodeData.Count > 0; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Clipboard.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Clipboard.cs.meta new file mode 100644 index 0000000..3e4b657 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Clipboard.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8850a8c4f3ca99f42bbf602c671ffb7f +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConfirmationWindow.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConfirmationWindow.cs new file mode 100644 index 0000000..896c432 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConfirmationWindow.cs @@ -0,0 +1,120 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public class ConfirmationWindow + { + public delegate ShaderLoadResult OnConfirmationSelected( bool value, Shader shader, Material material ); + public event OnConfirmationSelected OnConfirmationSelectedEvt; + + private const string m_yesStr = "Yes"; + private const string m_noStr = "No"; + private bool m_isActive = false; + private string m_currentMessage; + + private GUIStyle m_areaStyle; + private GUIContent m_content; + private GUIStyle m_buttonStyle; + private GUIStyle m_labelStyle; + + + private Shader m_shader; + private Material m_material; + private Rect m_area; + private bool m_autoDeactivate = true; + + + public ConfirmationWindow( float x, float y, float width, float height ) + { + m_content = new GUIContent( GUIContent.none ); + m_area = new Rect( x, y, width, height ); + } + + public void Destroy() + { + m_shader = null; + OnConfirmationSelectedEvt = null; + } + + public void ActivateConfirmation( Shader shader, Material material, string message, OnConfirmationSelected evt, bool autoDeactivate = true ) + { + OnConfirmationSelectedEvt = evt; + m_currentMessage = message; + m_shader = shader; + m_material = material; + m_autoDeactivate = autoDeactivate; + m_isActive = true; + } + + public void OnGUI() + { + if ( m_areaStyle == null ) + { + m_areaStyle = new GUIStyle( UIUtils.TextArea ); + m_areaStyle.stretchHeight = true; + m_areaStyle.stretchWidth = true; + m_areaStyle.fontSize = ( int ) Constants.DefaultTitleFontSize; + } + + if ( m_buttonStyle == null ) + { + m_buttonStyle = UIUtils.Button; + } + + if ( m_labelStyle == null ) + { + m_labelStyle = new GUIStyle( UIUtils.Label ); + m_labelStyle.alignment = TextAnchor.MiddleCenter; + m_labelStyle.wordWrap = true; + } + + m_area.x = ( int ) ( 0.5f * UIUtils.CurrentWindow.CameraInfo.width ); + m_area.y = ( int ) ( 0.5f * UIUtils.CurrentWindow.CameraInfo.height ); + + GUILayout.BeginArea( m_area, m_content, m_areaStyle ); + { + EditorGUILayout.BeginVertical(); + { + EditorGUILayout.Separator(); + EditorGUILayout.LabelField( m_currentMessage, m_labelStyle ); + + EditorGUILayout.Separator(); + EditorGUILayout.Separator(); + EditorGUILayout.BeginHorizontal(); + { + if ( GUILayout.Button( m_yesStr, m_buttonStyle ) ) + { + if ( OnConfirmationSelectedEvt != null ) + OnConfirmationSelectedEvt( true, m_shader, m_material ); + + if ( m_autoDeactivate ) + Deactivate(); + } + + if ( GUILayout.Button( m_noStr, m_buttonStyle ) ) + { + if ( OnConfirmationSelectedEvt != null ) + OnConfirmationSelectedEvt( false, m_shader, m_material ); + if ( m_autoDeactivate ) + Deactivate(); + } + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + } + GUILayout.EndArea(); + } + + public void Deactivate() + { + m_isActive = false; + OnConfirmationSelectedEvt = null; + } + public bool IsActive { get { return m_isActive; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConfirmationWindow.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConfirmationWindow.cs.meta new file mode 100644 index 0000000..7770352 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConfirmationWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 291cb40a04f835a4d89037cf3053c6a3 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConsoleLogWindow.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConsoleLogWindow.cs new file mode 100644 index 0000000..191d18d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConsoleLogWindow.cs @@ -0,0 +1,309 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [System.Serializable] + public class Toast + { + public MessageSeverity ItemType; + public string ItemMessage; + public double ItemTime; + public int ItemOwnerId; + public Toast( MessageSeverity itemType, string itemMessage, double itemTime,int itemOwnerId ) + { + ItemType = itemType; + ItemMessage = itemMessage; + ItemTime = itemTime; + ItemOwnerId = itemOwnerId; + } + } + + public class ConsoleLogWindow + { + public const int MAXWIDTH = 400; + public const float FADETIME = 7; + + private readonly GUIContent m_boxToggleContent = new GUIContent( "\u2261", "Toggle Message Box" ); + private readonly GUIContent m_clearContent = new GUIContent( "\u00D7", "Clear Messages" ); + + protected AmplifyShaderEditorWindow m_parentWindow = null; + + // needs to be serialized + private Vector2 m_currentScrollPos; + + int lastCall = -1; + + public ConsoleLogWindow( AmplifyShaderEditorWindow parentWindow ) + { + m_parentWindow = parentWindow; + } + + public void AddMessage( MessageSeverity itemType, string itemMessage , int itemOwnerId ) + { + var toast = new Toast( itemType, itemMessage, Time.realtimeSinceStartup, itemOwnerId ); + m_parentWindow.Messages.Insert( 0, toast ); + m_currentScrollPos.y = Mathf.Infinity; + + if( !m_parentWindow.MaximizeMessages ) + lastCall = Mathf.Max( (int)itemType, lastCall ); + + GUIContent gc = new GUIContent( m_parentWindow.Messages.Count + ": " + itemMessage ); + float maxWidth = m_parentWindow.MaxMsgWidth; + maxWidth = Mathf.Max( GUIStyle.none.CalcSize( gc ).x + 16, maxWidth ); + maxWidth = Mathf.Min( maxWidth, MAXWIDTH ); + m_parentWindow.MaxMsgWidth = maxWidth; + } + + public void Draw( Rect parentPosition, Vector2 mousePosition, int mouseButtonId, bool hasKeyboadFocus, float rightSide ) + { + EventType currentEventType = Event.current.type; + var messages = m_parentWindow.Messages; + var maximize = m_parentWindow.MaximizeMessages; + + Rect button = parentPosition; + button.width = 22; + button.height = 22; + button.x = parentPosition.x + parentPosition.width - button.width - rightSide - 8; + button.y = parentPosition.y + parentPosition.height - button.height - ( m_parentWindow.CurrentSelection == ASESelectionMode.Material ? 52 : 8 ); + + Rect toolbarArea = button; + toolbarArea.y -= 5; + if( maximize ) + { + toolbarArea.xMin -= m_parentWindow.MaxMsgWidth; + toolbarArea.yMin -= 66; + } + toolbarArea.x -= 6; + + bool needsRepaint = false; + if( maximize ) + { + GUIStyle labelStyle = UIUtils.ConsoleLogLabel; + toolbarArea.y -= 16 + 8; + GUILayout.BeginArea( toolbarArea, UIUtils.ConsoleLogMessage ); + EditorGUILayout.BeginVertical(); + m_currentScrollPos = EditorGUILayout.BeginScrollView( m_currentScrollPos ); + { + int count = messages.Count; + for( int i = count - 1; i >= 0; i-- ) + { + switch( messages[ i ].ItemType ) + { + case MessageSeverity.Error: + labelStyle.normal.textColor = Color.red; + break; + case MessageSeverity.Warning: + labelStyle.normal.textColor = Color.yellow; + break; + default: + case MessageSeverity.Normal: + labelStyle.normal.textColor = Color.white; + break; + } + + if( messages[ i ].ItemOwnerId < 0 ) + { + if( Event.current.control && Event.current.shift ) + { + if( GUILayout.Button( ( count - i ) + ": " + messages[ i ].ItemMessage, labelStyle ) ) + { + if( Event.current.button == 1 ) + { + EditorGUIUtility.systemCopyBuffer = messages[ i ].ItemMessage; + } + } + } + else + { + GUILayout.Label( ( count - i ) + ": " + messages[ i ].ItemMessage, labelStyle ); + } + } + else + { + if( GUILayout.Button( ( count - i ) + ": " + messages[ i ].ItemMessage, labelStyle ) ) + { + UIUtils.CurrentWindow.FocusOnNode( messages[ i ].ItemOwnerId, 1, true ); + if( Event.current.button == 1 ) + { + EditorGUIUtility.systemCopyBuffer = messages[ i ].ItemMessage; + } + } + } + } + } + EditorGUILayout.EndScrollView(); + EditorGUILayout.EndVertical(); + + GUILayout.EndArea(); + } + else + { + // draw toaster + int count = messages.Count; + Rect rect = toolbarArea; + rect.xMin -= 200; + + float startFade = FADETIME - 1; + for( int i = 0; i < count; i++ ) + { + GUIStyle msgstyle = UIUtils.ConsoleLogMessage; + float delta = (float)(Time.realtimeSinceStartup - messages[ i ].ItemTime); + if( delta > FADETIME ) + continue; + + if( delta < 0.1f ) + { + msgstyle.normal.textColor = Color.cyan; + } + else if( delta < startFade ) + { + switch( messages[ i ].ItemType ) + { + case MessageSeverity.Error: + msgstyle.normal.textColor = Color.red; + break; + case MessageSeverity.Warning: + msgstyle.normal.textColor = Color.yellow; + break; + default: + case MessageSeverity.Normal: + msgstyle.normal.textColor = Color.white; + break; + } + } + else + { + switch( messages[ i ].ItemType ) + { + case MessageSeverity.Error: + msgstyle.normal.textColor = new Color( 1, 0, 0, FADETIME - delta ); + break; + case MessageSeverity.Warning: + msgstyle.normal.textColor = new Color( 1, 1, 0, FADETIME - delta ); + break; + default: + case MessageSeverity.Normal: + msgstyle.normal.textColor = new Color( 1, 1, 1, FADETIME - delta ); + break; + } + } + + needsRepaint = true; + + GUIContent gc = new GUIContent( messages[ i ].ItemMessage ); + var sizes = msgstyle.CalcSize( gc ); + rect.xMin -= sizes.x - rect.width; + rect.height = sizes.y; + rect.y -= rect.height + 2; + if( messages[ i ].ItemOwnerId < 0 ) + { + GUI.Label( rect, gc, msgstyle ); + } + else + { + if( GUI.Button( rect, gc, msgstyle )) + { + UIUtils.CurrentWindow.FocusOnNode( messages[ i ].ItemOwnerId, 1, true ); + if( Event.current.button == 1 ) + { + EditorGUIUtility.systemCopyBuffer = messages[ i ].ItemMessage; + } + } + } + } + } + //GUI.color = cached; + + if( needsRepaint ) + m_parentWindow.MarkToRepaint(); + + GUIStyle style = UIUtils.ConsoleLogCircle; + + button.size = Vector2.one * 16; + + switch( lastCall ) + { + case 0: + style.normal.textColor = Color.cyan; + break; + case 1: + style.normal.textColor = Color.yellow; + break; + case 2: + style.normal.textColor = Color.red; + break; + default: + style.normal.textColor = new Color( 1, 1, 1, 0.5f ); + break; + } + + if( GUI.Button( button, m_boxToggleContent, style ) ) + { + maximize = !maximize; + m_parentWindow.MaximizeMessages = maximize; + m_currentScrollPos.y = Mathf.Infinity; + lastCall = -1; + } + + style.normal.textColor = new Color( 1, 1, 1, 0.5f ); + //GUI.color = cached; + button.x -= button.width + 2; + + if( maximize && GUI.Button( button, m_clearContent, style ) ) + { + if( messages.Count == 0 ) + { + maximize = false; + m_parentWindow.MaximizeMessages = maximize; + } + ClearMessages(); + } + + button.width += button.width + 2; + bool mouseOnTop = button.Contains( mousePosition ); + + if( currentEventType == EventType.MouseMove && mouseOnTop ) + m_parentWindow.MarkToRepaint(); + + if( DebugConsoleWindow.DeveloperMode ) + { + if( Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Alpha1 ) + { + UIUtils.ShowMessage( "This is an info message\nwith two lines" ); + } + + if( Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Alpha2 ) + { + UIUtils.ShowMessage( "This is a warning message", MessageSeverity.Warning ); + } + + if( Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Alpha3 ) + { + + UIUtils.ShowMessage( "THIS IS AN ERROR MESSAGE!!", MessageSeverity.Error ); + } + } + } + + public void ClearMessages() + { + m_parentWindow.Messages.Clear(); + m_parentWindow.MaxMsgWidth = 100; + } + + public void Toggle() + { + + } + + public void Destroy() + { + m_parentWindow = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConsoleLogWindow.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConsoleLogWindow.cs.meta new file mode 100644 index 0000000..617e129 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ConsoleLogWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ed706353a579cbb46b300406107108b1 +timeCreated: 1506345180 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ContextMenuItem.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ContextMenuItem.cs new file mode 100644 index 0000000..4834ee1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ContextMenuItem.cs @@ -0,0 +1,81 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public class ContextMenuItem + { + private const string PALETTE_NAME_MOD_STR = " "; + + private string m_paletteName; + private string m_name; + private string m_tags; + private string m_category; + private string m_description; + private System.Type m_type; + private GUIContent m_guiContent; + private string m_nameWithShortcut; + private AmplifyShaderFunction m_function; + private NodeAttributes m_nodeAttributes; + + public ContextMenuItem( NodeAttributes nodeAttributes, System.Type type, string name, string tags, string category, string description, AmplifyShaderFunction function, KeyCode shortcut ) + { + m_nodeAttributes = nodeAttributes; + m_name = name; + m_tags = name + ( string.IsNullOrEmpty( tags ) ? "" : " " + tags ); + m_tags = m_tags.ToLower(); + m_nameWithShortcut = shortcut != KeyCode.None ? ( name + " [ " + UIUtils.KeyCodeToString( shortcut ) + " ]" ) : name; + m_paletteName = PALETTE_NAME_MOD_STR + m_name; + m_type = type; + m_category = category; + m_description = description; + m_function = function; + m_guiContent = new GUIContent( m_nameWithShortcut, m_description ); + } + + public int CompareTo( ContextMenuItem item , bool useWeights ) + { + if ( useWeights && NodeAttributes.SortOrderPriority > -1 && item.NodeAttributes.SortOrderPriority > -1 ) + { + if ( NodeAttributes.SortOrderPriority > item.NodeAttributes.SortOrderPriority ) + { + return 1; + } + else if ( NodeAttributes.SortOrderPriority == item.NodeAttributes.SortOrderPriority ) + { + return m_name.CompareTo( item.Name ); + } + else + { + return -1; + } + } + return m_name.CompareTo( item.Name ); + } + + public string PaletteName { get { return m_paletteName; } } + public string Name { get { return m_name; } } + public string Tags { get { return m_tags; } } + public string NameWithShortcut { get { return m_nameWithShortcut; } } + public string Category { get { return m_category; } } + public string Description { get { return m_description; } } + public AmplifyShaderFunction Function { get { return m_function; } } + public System.Type NodeType { get { return m_type; } } + public GUIContent ItemUIContent { get { return m_guiContent; } } + public NodeAttributes NodeAttributes { get { return m_nodeAttributes; } } + + public override string ToString() + { + return m_name + ":" + m_category + ":" + m_description; + } + + public void Destroy() + { + m_guiContent = null; + m_nodeAttributes = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ContextMenuItem.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ContextMenuItem.cs.meta new file mode 100644 index 0000000..7b1fbe8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ContextMenuItem.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 417f409230c530b468b8ab67dd6e3b8b +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/CustomStylesContainer.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/CustomStylesContainer.cs new file mode 100644 index 0000000..0de8b80 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/CustomStylesContainer.cs @@ -0,0 +1,53 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +//using UnityEditor; +//using UnityEngine; +//namespace AmplifyShaderEditor +//{ +// //EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector) +// // this might be a bit nonsense since I could use the GetBuiltinSkin directly but this way will bea easier to change to some custom visuals on some near future +// [System.Serializable] +// public class CustomStylesContainer +// { +// public GUIStyle FoldoutStyle +// { +// get { return EditorStyles.foldout; } +// } + +// public GUIStyle Label +// { +// get { return GUI.skin.label; } +// } + +// public GUIStyle Button +// { +// get { return GUI.skin.button; } +// } + +// public GUIStyle TextArea +// { +// get { return GUI.skin.textArea; } +// } + +// public GUIStyle Toggle +// { +// get { return GUI.skin.toggle; } +// } + +// public GUIStyle Window +// { +// get { return GUI.skin.window; } +// } + +// public GUIStyle Textfield +// { +// get { return GUI.skin.textField; } +// } + +// public GUIStyle Box +// { +// get { return GUI.skin.box; } +// } +// } +//} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/CustomStylesContainer.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/CustomStylesContainer.cs.meta new file mode 100644 index 0000000..b677796 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/CustomStylesContainer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 79d0d783b532b474192b191547bee1c1 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DebugConsoleWindow.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DebugConsoleWindow.cs new file mode 100644 index 0000000..85f4604 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DebugConsoleWindow.cs @@ -0,0 +1,203 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +//#define ASE_CONSOLE_WINDOW + +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public sealed class DebugConsoleWindow : EditorWindow + { + private const float WindowSizeX = 250; + private const float WindowSizeY = 250; + private const float WindowPosX = 5; + private const float WindowPosY = 5; + private Rect m_availableArea; + + private bool m_wikiAreaFoldout = true; + private bool m_miscAreaFoldout = true; + private Vector2 m_currentScrollPos; + + private int m_minURLNode = 0; + private int m_maxURLNode = -1; + +#if ASE_CONSOLE_WINDOW + public readonly static bool DeveloperMode = true; + public static bool UseShaderPanelsInfo = true; + [MenuItem( "Window/Amplify Shader Editor/Open Debug Console" )] + static void OpenMainShaderGraph() + { + OpenWindow(); + } + [MenuItem( "Window/Amplify Shader Editor/Create Template Menu Items" )] + public static void CreateTemplateMenuItems() + { + UIUtils.CurrentWindow.TemplatesManagerInstance.CreateTemplateMenuItems(); + } + +#else + public readonly static bool DeveloperMode = false; + public static bool UseShaderPanelsInfo = false; +#endif + + public static DebugConsoleWindow OpenWindow() + { + if ( DeveloperMode ) + { + DebugConsoleWindow currentWindow = ( DebugConsoleWindow ) DebugConsoleWindow.GetWindow( typeof( DebugConsoleWindow ), false, "ASE Debug Console" ); + currentWindow.titleContent.tooltip = "Debug Options for ASE. Intented only for ASE development team"; + currentWindow.minSize = new Vector2( WindowSizeX, WindowSizeY ); + currentWindow.maxSize = new Vector2( WindowSizeX, 2 * WindowSizeY ); ; + currentWindow.wantsMouseMove = true; + return currentWindow; + } + return null; + } + + void OnGUI() + { + m_availableArea = new Rect( WindowPosX, WindowPosY, position.width - 2 * WindowPosX, position.height - 2 * WindowPosY ); + GUILayout.BeginArea( m_availableArea ); + { + m_currentScrollPos = EditorGUILayout.BeginScrollView( m_currentScrollPos, GUILayout.Width( 0 ), GUILayout.Height( 0 ) ); + { + EditorGUILayout.BeginVertical(); + { + AmplifyShaderEditorWindow window = UIUtils.CurrentWindow; + if ( window != null ) + { + EditorGUILayout.Separator(); + + NodeUtils.DrawPropertyGroup( ref m_wikiAreaFoldout, "Wiki Helper", ShowWikiHelperFunctions ); + + EditorGUILayout.Separator(); + + NodeUtils.DrawPropertyGroup( ref m_miscAreaFoldout, "Misc", ShowMiscFuntions ); + + EditorGUILayout.Separator(); + } + else + { + EditorGUILayout.LabelField( "Please open an ASE window to access debug options" ); + } + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndScrollView(); + } + GUILayout.EndArea(); + } + + void ShowWikiHelperFunctions() + { + AmplifyShaderEditorWindow window = UIUtils.CurrentWindow; + EditorGUILayout.Separator(); + + if ( GUILayout.Button( "Nodes Screen Shots" ) ) + { + window.CurrentNodeExporterUtils.ActivateAutoScreenShot( Application.dataPath + "/../NodesInfo/Shots/",0,-1 ); + } + + GUILayout.BeginHorizontal(); + if( GUILayout.Button( "Nodes URLs" ) ) + { + window.CurrentNodeExporterUtils.ActivateNodesURL( m_minURLNode, m_maxURLNode ); + } + m_minURLNode = EditorGUILayout.IntField( m_minURLNode ); + m_maxURLNode = EditorGUILayout.IntField( m_maxURLNode ); + GUILayout.EndHorizontal(); + + EditorGUILayout.Separator(); + + if( GUILayout.Button( "Nodes Undo Test" ) ) + { + window.CurrentNodeExporterUtils.ActivateAutoUndo(); + } + + EditorGUILayout.Separator(); + + if ( GUILayout.Button( "Nodes Info" ) ) + { + window.CurrentPaletteWindow.DumpAvailableNodes( false, Application.dataPath + "/../NodesInfo/" ); + window.CurrentPaletteWindow.DumpAvailableNodes( true, Application.dataPath + "/../NodesInfo/" ); + } + + EditorGUILayout.Separator(); + + if ( GUILayout.Button( "Shortcuts Info" ) ) + { + window.ShortcutManagerInstance.DumpShortcutsToDisk( Application.dataPath + "/../NodesInfo/" ); + } + } + + void ShowMiscFuntions() + { + AmplifyShaderEditorWindow window = UIUtils.CurrentWindow; + if ( GUILayout.Button( "Force Example Shader Compilation" ) ) + { + UIUtils.ForceExampleShaderCompilation(); + } + EditorGUILayout.Separator(); + + if ( GUILayout.Button( "Refresh Available Nodes" ) ) + { + window.RefreshAvaibleNodes(); + } + + EditorGUILayout.Separator(); + + if ( GUILayout.Button( "Dump Uniform Names" ) ) + { + //window.CurrentPaletteWindow.NewList() + window.DuplicatePrevBufferInstance.DumpUniformNames(); + } + + EditorGUILayout.Separator(); + + if ( GUILayout.Button( "Force Palette Update" ) ) + { + Debug.Log( UIUtils.CurrentWindow.IsShaderFunctionWindow ); + window.CurrentPaletteWindow.ForceUpdate = true; + } + + EditorGUILayout.Separator(); + + if( GUILayout.Button( "Detect Infinite Loops" ) ) + { + if( window.IsShaderFunctionWindow ) + { + Debug.Log( "Starting infinite loop detection over shader functions" ); + List nodes = window.OutsideGraph.FunctionOutputNodes.NodesList; + for( int i = 0; i < nodes.Count; i++ ) + { + UIUtils.DetectNodeLoopsFrom( nodes[ i ], new Dictionary() ); + } + } + else + { + if( window.OutsideGraph.MultiPassMasterNodes.Count > 0 ) + { + Debug.Log( "Starting infinite loop detection over shader from template" ); + List nodes = window.OutsideGraph.MultiPassMasterNodes.NodesList; + for( int i = 0; i < nodes.Count; i++ ) + { + UIUtils.DetectNodeLoopsFrom( nodes[ i ], new Dictionary() ); + } + } + else + { + Debug.Log( "Starting infinite loop detection over standard shader" ); + UIUtils.DetectNodeLoopsFrom( window.OutsideGraph.CurrentMasterNode, new Dictionary() ); + } + } + Debug.Log( "End infinite loop detection" ); + } + } + } +} + + + diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DebugConsoleWindow.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DebugConsoleWindow.cs.meta new file mode 100644 index 0000000..a9e5383 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DebugConsoleWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 52308890136cd7746a5a073c9be8f028 +timeCreated: 1487850100 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DragAndDropTool.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DragAndDropTool.cs new file mode 100644 index 0000000..2da0208 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DragAndDropTool.cs @@ -0,0 +1,47 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public class DragAndDropTool + { + public delegate void OnValidDropObject(params UnityEngine.Object[] draggedObjs ); + public event OnValidDropObject OnValidDropObjectEvt; + + public void Destroy() + { + OnValidDropObjectEvt = null; + } + + public void TestDragAndDrop( Rect dropArea ) + { + Event currentEvent = Event.current; + EventType currentEventType = currentEvent.type; + + switch (currentEventType) + { + case EventType.DragUpdated: + case EventType.DragPerform: + { + + if (!dropArea.Contains(currentEvent.mousePosition)) + return; + + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + if (currentEvent.type == EventType.DragPerform) + { + DragAndDrop.AcceptDrag(); + if (OnValidDropObjectEvt != null) + { + OnValidDropObjectEvt(DragAndDrop.objectReferences); + } + } + }break; + case EventType.DragExited:DragAndDrop.PrepareStartDrag();break; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DragAndDropTool.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DragAndDropTool.cs.meta new file mode 100644 index 0000000..3ca3a86 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DragAndDropTool.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 41c9bd09aea1377459c7e62910711c22 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DuplicatePreventionBuffer.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DuplicatePreventionBuffer.cs new file mode 100644 index 0000000..6f76333 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DuplicatePreventionBuffer.cs @@ -0,0 +1,375 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class DuplicatePreventionBuffer + { + private const string VectorNameStr = "Vector "; + private const string TextureSampleNameStr = "Texture Sample "; + private const string MatrixNameStr = "Matrix "; + private const string IntNameStr = "Int "; + private const string FloatNameStr = "Float "; + private const string ColorNameStr = "Color "; + + [SerializeField] + private int[] m_availableUVChannelsArray = { -1, -1, -1, -1 }; + private string[] m_availableUVChannelsNamesArray = { "null", + "null", + "null", + "null" }; + + private Dictionary m_availablePropertyNames = new Dictionary(); + private Dictionary m_availableUniformNames = new Dictionary(); + private Dictionary m_availableLocalVariableNames = new Dictionary(); + + public void ReleaseAllUVChannels() + { + for ( int i = 0; i < m_availableUVChannelsArray.Length; i++ ) + { + m_availableUVChannelsArray[ i ] = -1; + } + } + + public bool RegisterUVChannel( int nodeId, int channelId, string name ) + { + if ( channelId < 0 || + channelId > ( m_availableUVChannelsArray.Length - 1 ) || + m_availableUVChannelsArray[ channelId ] >= 0 ) + { + return false; + } + + m_availableUVChannelsArray[ channelId ] = nodeId; + m_availableUVChannelsNamesArray[ channelId ] = name; + return true; + } + + + public bool ReleaseUVChannel( int nodeId, int channelId ) + { + if ( channelId < 0 || + channelId > ( m_availableUVChannelsArray.Length - 1 ) ) + { + return false; + } + + if ( m_availableUVChannelsArray[ channelId ] == nodeId ) + { + m_availableUVChannelsArray[ channelId ] = -1; + return true; + } + return false; + } + + public int RegisterFirstAvailableChannel( int nodeId , string name) + { + for ( int i = 0; i < m_availableUVChannelsArray.Length; i++ ) + { + if ( m_availableUVChannelsArray[ i ] == -1 ) + { + m_availableUVChannelsArray[ i ] = nodeId; + m_availableUVChannelsNamesArray[ i ] = name; + return i; + } + } + return -1; + } + + public bool IsChannelAvailable( int channelId ) + { + if ( channelId < 0 || + channelId > ( m_availableUVChannelsArray.Length - 1 ) ) + { + return false; + } + + return ( m_availableUVChannelsArray[ channelId ] < 0 ); + } + + public int GetFirstOccupiedChannel() + { + for ( int i = 0; i < 4; i++ ) + { + if ( m_availableUVChannelsArray[ i ] > -1 ) + return i; + } + return -1; + } + + public string GetChannelName( int channelId ) + { + if ( channelId < 0 || + channelId > ( m_availableUVChannelsArray.Length - 1 ) ) + { + return string.Empty; + } + + return m_availableUVChannelsNamesArray[ channelId ] ; + } + + public void SetChannelName( int channelId , string name ) + { + if ( channelId < 0 || + channelId > ( m_availableUVChannelsArray.Length - 1 ) ) + { + return; + } + m_availableUVChannelsNamesArray[ channelId ] = name; + } + + public bool RegisterLocalVariableName( int nodeId, string name ) + { + if ( name.Length == 0 ) + return false; + + if ( m_availableLocalVariableNames.ContainsKey( name ) ) + { + if ( m_availableLocalVariableNames[ name ] > -1 ) + { + return false; + } + else + { + m_availableLocalVariableNames[ name ] = nodeId; + return true; + } + } + + m_availableLocalVariableNames.Add( name, nodeId ); + return true; + } + + public int CheckUniformNameOwner( string name ) + { + if ( name.Length == 0 ) + return -1; + + if ( m_availableUniformNames.ContainsKey( name ) ) + { + return m_availableUniformNames[ name ]; + } + + return -1; + } + + public bool RegisterUniformName( int nodeId, string name ) + { + if ( name.Length == 0 ) + return false; + + if ( m_availableUniformNames.ContainsKey( name ) ) + { + if ( m_availableUniformNames[ name ] > -1 ) + { + return false; + } + else + { + m_availableUniformNames[ name ] = nodeId; + return true; + } + } + + m_availableUniformNames.Add( name, nodeId ); + return true; + } + + public void DumpUniformNames() + { + string val = "CONTENTS\n"; + foreach ( KeyValuePair kvp in m_availableUniformNames ) + { + val += ( "key " + kvp.Key + " : value " + kvp.Value + "\n" ); + } + } + + public void DumpLocalVariableNames() + { + string val = "CONTENTS\n"; + foreach ( KeyValuePair kvp in m_availableLocalVariableNames ) + { + val += ( "key " + kvp.Key + " : value " + kvp.Value + "\n" ); + } + } + + + public bool ReleaseUniformName( int nodeId, string name ) + { + if ( !string.IsNullOrEmpty(name) && name.Length == 0 ) + return false; + + if ( m_availableUniformNames.ContainsKey( name ) ) + { + if ( m_availableUniformNames[ name ] == nodeId ) + { + m_availableUniformNames.Remove( name ); + return true; + } + } + return false; + } + + public bool ReleaseLocalVariableName( int nodeId, string name ) + { + if ( name.Length == 0 ) + return false; + + if ( m_availableLocalVariableNames.ContainsKey( name ) ) + { + if ( m_availableLocalVariableNames[ name ] == nodeId ) + { + m_availableLocalVariableNames.Remove( name ); + return true; + } + } + return false; + } + + public void ReleaseAllUniformNames() + { + m_availableUniformNames.Clear(); + } + + public void ReleaseAllLocalVariableNames() + { + m_availableLocalVariableNames.Clear(); + } + + public void GetFirstAvailableName( int nodeId, WirePortDataType type , out string outProperty , out string outInspector, bool useCustomPrefix = false, string customPrefix = null) + { + string name = string.Empty; + if ( useCustomPrefix && customPrefix != null ) + { + name = customPrefix; + } + else + { + switch ( type ) + { + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT: + { + name = FloatNameStr; + } + break; + case WirePortDataType.INT: + { + name = IntNameStr; + } + break; + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + { + name = VectorNameStr; + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + name = MatrixNameStr; + } + break; + case WirePortDataType.COLOR: + { + name = ColorNameStr; + } + break; + } + } + + int count = 0; + bool foundName = false; + while ( !foundName ) + { + string inspectorName = name + count; + string propertyName = UIUtils.GeneratePropertyName( inspectorName , PropertyType.Property ); + + if ( IsUniformNameAvailable( propertyName ) ) + { + outInspector = inspectorName; + outProperty = propertyName; + RegisterUniformName( nodeId, propertyName ); + return; + } + count += 1; + } + outProperty = string.Empty; + outInspector = string.Empty; + UIUtils.ShowMessage( "Could not find a valid name " + MessageSeverity.Warning ); + } + + public bool IsUniformNameAvailable( string name ) + { + if ( m_availableUniformNames.ContainsKey( name ) && m_availableUniformNames[ name ] > -1 ) + return false; + return true; + } + + public bool IsLocalvariableNameAvailable( string name ) + { + if ( m_availableLocalVariableNames.ContainsKey( name ) && m_availableLocalVariableNames[ name ] > -1 ) + return false; + return true; + } + + public bool GetPropertyName( int nodeId, string name ) + { + if ( m_availablePropertyNames.ContainsKey( name ) ) + { + if ( m_availablePropertyNames[ name ] > -1 ) + { + return false; + } + else + { + m_availablePropertyNames[ name ] = nodeId; + return true; + } + } + + m_availablePropertyNames.Add( name, nodeId ); + return true; + } + + + public bool ReleasePropertyName( int nodeId, string name ) + { + if ( m_availablePropertyNames.ContainsKey( name ) ) + { + if ( m_availablePropertyNames[ name ] == nodeId ) + { + m_availablePropertyNames[ name ] = -1; + return true; + } + } + return false; + } + + public void ReleaseAllPropertyNames() + { + m_availablePropertyNames.Clear(); + } + + public bool IsPropertyNameAvailable( string name ) + { + if ( m_availablePropertyNames.ContainsKey( name ) && m_availablePropertyNames[ name ] > -1 ) + return false; + return true; + } + + public void ReleaseAllData() + { + ReleaseAllUVChannels(); + ReleaseAllUniformNames(); + ReleaseAllPropertyNames(); + ReleaseAllLocalVariableNames(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DuplicatePreventionBuffer.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DuplicatePreventionBuffer.cs.meta new file mode 100644 index 0000000..fd5e661 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/DuplicatePreventionBuffer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a4cfbb4204c63ca4e8f7cec73f6b3ef8 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/GraphContextMenu.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/GraphContextMenu.cs new file mode 100644 index 0000000..b0d38f4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/GraphContextMenu.cs @@ -0,0 +1,393 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Text; +using System.Linq; +using System.Collections.Generic; +using System.Reflection; + +namespace AmplifyShaderEditor +{ + public class ShortcutKeyData + { + public bool IsPressed; + public System.Type NodeType; + public string Name; + public ShortcutKeyData( System.Type type, string name ) + { + NodeType = type; + Name = name; + IsPressed = false; + } + } + + public class GraphContextMenu + { + private List m_items; + private List m_itemFunctions; + private Dictionary m_itemsDict; + private Dictionary m_deprecatedItemsDict; + private Dictionary m_castTypes; + private Dictionary m_shortcutTypes; + + private KeyCode m_lastKeyPressed; + private ParentGraph m_currentGraph; + private bool m_correctlyLoaded = false; + + public GraphContextMenu( ParentGraph currentGraph ) + { + m_currentGraph = currentGraph; + m_correctlyLoaded = RefreshNodes( currentGraph ); + } + + private Type[] GetTypesInNamespace( Assembly assembly, string nameSpace ) + { + return assembly.GetTypes().Where( t => String.Equals( t.Namespace, nameSpace, StringComparison.Ordinal ) ).ToArray(); + } + + public bool RefreshNodes( ParentGraph currentGraph ) + { + if( m_items != null ) + { + m_items.Clear(); + m_items = null; + } + + if( m_itemFunctions != null ) + { + m_itemFunctions.Clear(); + m_itemFunctions = null; + } + + m_items = new List(); + m_itemFunctions = new List(); + + if( m_itemsDict != null ) + m_itemsDict.Clear(); + + m_itemsDict = new Dictionary(); + + if( m_deprecatedItemsDict != null ) + m_deprecatedItemsDict.Clear(); + + m_deprecatedItemsDict = new Dictionary(); + + if( m_castTypes != null ) + m_castTypes.Clear(); + + m_castTypes = new Dictionary(); + + if( m_shortcutTypes != null ) + m_shortcutTypes.Clear(); + + m_shortcutTypes = new Dictionary(); + + m_lastKeyPressed = KeyCode.None; + + // Fetch all available nodes by their attributes + try + { + //IEnumerable availableTypes = AppDomain.CurrentDomain.GetAssemblies().ToList().SelectMany( type => type.GetTypes() ); + var mainAssembly = Assembly.GetExecutingAssembly(); + Type[] availableTypes = GetTypesInNamespace( mainAssembly, "AmplifyShaderEditor" ); + +#if UNITY_2017_3_OR_NEWER + try + { + var editorAssembly = Assembly.Load( "Assembly-CSharp-Editor" ); + if( mainAssembly != editorAssembly ) + { + Type[] extraTypes = GetTypesInNamespace( editorAssembly, "AmplifyShaderEditor" ); + availableTypes = availableTypes.Concat( extraTypes ).ToArray(); + } + } + catch( Exception ) + { + // quiet catch because we don't care if it fails to find the assembly, we'll just skip it + } +#endif + + foreach( System.Type type in availableTypes ) + { + foreach( NodeAttributes attribute in Attribute.GetCustomAttributes( type ).OfType() ) + { + if( attribute.Available && !attribute.Deprecated ) + { + //if ( !UIUtils.CurrentWindow.IsShaderFunctionWindow && attribute.AvailableInFunctionsOnly ) + // continue; + + if( !UIUtils.HasColorCategory( attribute.Category ) ) + { + if( !String.IsNullOrEmpty( attribute.CustomCategoryColor ) ) + { + try + { + Color color = new Color(); + ColorUtility.TryParseHtmlString( attribute.CustomCategoryColor, out color ); + UIUtils.AddColorCategory( attribute.Category, color ); + } + catch( Exception e ) + { + Debug.LogException( e ); + UIUtils.AddColorCategory( attribute.Category, Constants.DefaultCategoryColor ); + } + } + //else + //{ + // UIUtils.AddColorCategory( attribute.Category, Constants.DefaultCategoryColor ); + //} + } + + if( attribute.CastType != null && attribute.CastType.Length > 0 && type != null ) + { + for( int i = 0; i < attribute.CastType.Length; i++ ) + { + m_castTypes.Add( attribute.CastType[ i ], type ); + } + } + + if( attribute.ShortcutKey != KeyCode.None && type != null ) + m_shortcutTypes.Add( attribute.ShortcutKey, new ShortcutKeyData( type, attribute.Name ) ); + + ContextMenuItem newItem = new ContextMenuItem( attribute, type, attribute.Name, attribute.Tags, attribute.Category, attribute.Description, null, attribute.ShortcutKey ); + if( UIUtils.GetNodeAvailabilityInBitArray( attribute.NodeAvailabilityFlags, NodeAvailability.SurfaceShader ) ) + m_items.Add( newItem ); + else if( UIUtils.GetNodeAvailabilityInBitArray( attribute.NodeAvailabilityFlags, currentGraph.ParentWindow.CurrentNodeAvailability ) ) + m_items.Add( newItem ); + else if( UIUtils.GetNodeAvailabilityInBitArray( attribute.NodeAvailabilityFlags, currentGraph.CurrentCanvasMode ) ) + m_items.Add( newItem ); + + m_itemsDict.Add( type, attribute ); + m_itemFunctions.Add( newItem ); + } + else + { + m_deprecatedItemsDict.Add( type, attribute ); + } + } + } + } + catch( ReflectionTypeLoadException exception ) + { + Debug.LogException( exception ); + return false; + } + + string[] guids = AssetDatabase.FindAssets( "t:AmplifyShaderFunction" ); + List allFunctions = new List(); + + for( int i = 0; i < guids.Length; i++ ) + { + allFunctions.Add( AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( guids[ i ] ) ) ); + } + + int functionCount = allFunctions.Count; + if( functionCount > 0 ) + { + m_castTypes.Add( typeof( AmplifyShaderFunction ), typeof( FunctionNode ) ); + } + + for( int i = 0; i < functionCount; i++ ) + { + if( !allFunctions[ i ].Hidden ) + { + NodeAttributes attribute = new NodeAttributes( allFunctions[ i ].FunctionName, allFunctions[ i ].CustomNodeCategory, allFunctions[ i ].Description, KeyCode.None, true, 0, int.MaxValue, typeof( AmplifyShaderFunction ) ); + System.Type type = typeof( FunctionNode ); + + ContextMenuItem newItem = new ContextMenuItem( attribute, type, AddSpacesToSentence( attribute.Name ), attribute.Tags, attribute.Category, attribute.Description, allFunctions[ i ], attribute.ShortcutKey ); + m_items.Add( newItem ); + m_itemFunctions.Add( newItem ); + } + } + + //Sort out the final list by name + m_items.Sort( ( x, y ) => x.Category.CompareTo( y.Category ) ); + m_itemFunctions.Sort( ( x, y ) => x.Category.CompareTo( y.Category ) ); + return true; + } + + public void Destroy() + { + for( int i = 0; i < m_items.Count; i++ ) + { + m_items[ i ].Destroy(); + } + + for( int i = 0; i < m_itemFunctions.Count; i++ ) + { + if( m_itemFunctions[ i ] != null ) + m_itemFunctions[ i ].Destroy(); + } + + m_items.Clear(); + m_items = null; + + m_itemFunctions.Clear(); + m_itemFunctions = null; + + m_itemsDict.Clear(); + m_itemsDict = null; + + m_deprecatedItemsDict.Clear(); + m_deprecatedItemsDict = null; + + m_castTypes.Clear(); + m_castTypes = null; + + m_shortcutTypes.Clear(); + m_shortcutTypes = null; + + } + + public static string AddSpacesToSentence( string text ) + { + if( string.IsNullOrEmpty( text ) ) + return string.Empty; + + bool lastIsUpper = char.IsUpper( text, 0 ); + bool lastIsLetter = char.IsLetter( text, 0 ); + StringBuilder title = new StringBuilder(); + title.Append( text[ 0 ] ); + for( int i = 1; i < text.Length; i++ ) + { + bool currIsUpper = char.IsUpper( text, i ); + bool currIsLetter = char.IsLetter( text, i ); + if( currIsUpper && !lastIsUpper && lastIsLetter ) + { + title.Append( " " ); + } + + // if current is a number and previous is a letter we space it (ie: Rotation2D = Rotation 2D) + if( lastIsLetter && char.IsNumber( text, i ) ) + { + title.Append( " " ); + } + + // if previous is upper, current is upper and the next two following are lower then we space it (ie: UVDistortion = UV Distortion) + if( i < text.Length - 1 ) + { + bool nextIsLower = char.IsLower( text, i + 1 ) && char.IsLetter( text, i + 1 ); + bool lastIsLower = i < text.Length - 2 ? char.IsLower( text, i + 2 ) && char.IsLetter( text, i + 2 ) : false; + if( lastIsUpper && currIsUpper && currIsLetter && nextIsLower && lastIsLower ) + { + title.Append( " " ); + } + } + lastIsUpper = currIsUpper; + lastIsLetter = currIsLetter; + title.Append( text[ i ] ); + } + return title.ToString(); + } + + public NodeAttributes GetNodeAttributesForType( System.Type type ) + { + if( type == null ) + { + Debug.LogError( "Invalid type detected" ); + return null; + } + + if( m_itemsDict.ContainsKey( type ) ) + return m_itemsDict[ type ]; + return null; + } + + public NodeAttributes GetDeprecatedNodeAttributesForType( System.Type type ) + { + if( m_deprecatedItemsDict.ContainsKey( type ) ) + return m_deprecatedItemsDict[ type ]; + return null; + } + + public void UpdateKeyPress( KeyCode key ) + { + if( key == KeyCode.None ) + return; + + m_lastKeyPressed = key; + if( m_shortcutTypes.ContainsKey( key ) ) + { + m_shortcutTypes[ key ].IsPressed = true; + } + } + + public void UpdateKeyReleased( KeyCode key ) + { + if( key == KeyCode.None ) + return; + + if( m_shortcutTypes.ContainsKey( key ) ) + { + m_shortcutTypes[ key ].IsPressed = false; + } + } + + public void ResetShortcutKeyStates() + { + foreach( KeyValuePair kvp in m_shortcutTypes ) + { + kvp.Value.IsPressed = false; + } + } + + public ParentNode CreateNodeFromCastType( System.Type type ) + { + if( m_castTypes.ContainsKey( type ) ) + { + ParentNode newNode = (ParentNode)ScriptableObject.CreateInstance( m_castTypes[ type ] ); + return newNode; + } + return null; + } + + + public ParentNode CreateNodeFromShortcutKey() + { + if( m_lastKeyPressed == KeyCode.None ) + return null; + + if( m_shortcutTypes.ContainsKey( m_lastKeyPressed ) && m_shortcutTypes[ m_lastKeyPressed ].IsPressed ) + { + ParentNode newNode = (ParentNode)ScriptableObject.CreateInstance( m_shortcutTypes[ m_lastKeyPressed ].NodeType ); + return newNode; + } + return null; + } + + public bool CheckShortcutKey() + { + if( m_lastKeyPressed == KeyCode.None ) + return false; + + if( m_shortcutTypes.ContainsKey( m_lastKeyPressed ) && m_shortcutTypes[ m_lastKeyPressed ].IsPressed ) + { + return true; + } + return false; + } + + public List MenuItems + { + get + { + if( m_currentGraph.ParentWindow.IsShaderFunctionWindow ) + return m_itemFunctions; + else + return m_items; + } + } + + public List ItemFunctions { get { return m_itemFunctions; } } + public KeyCode LastKeyPressed + { + get { return m_lastKeyPressed; } + } + + public Dictionary NodeShortcuts { get { return m_shortcutTypes; } } + public bool CorrectlyLoaded { get { return m_correctlyLoaded; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/GraphContextMenu.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/GraphContextMenu.cs.meta new file mode 100644 index 0000000..be8ed3c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/GraphContextMenu.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5c34fc95a1ddd7d42bc74151061035f4 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/MenuParent.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/MenuParent.cs new file mode 100644 index 0000000..3029864 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/MenuParent.cs @@ -0,0 +1,451 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public enum MenuAnchor + { + TOP_LEFT = 0, + TOP_CENTER, + TOP_RIGHT, + MIDDLE_LEFT, + MIDDLE_CENTER, + MIDDLE_RIGHT, + BOTTOM_LEFT, + BOTTOM_CENTER, + BOTTOM_RIGHT, + NONE + } + + public enum MenuAutoSize + { + MATCH_VERTICAL = 0, + MATCH_HORIZONTAL, + NONE + } + + public class MenuParent + { + protected AmplifyShaderEditorWindow m_parentWindow = null; + + protected const float MinimizeButtonXSpacing = 5; + protected const float MinimizeButtonYSpacing = 5.5f; + protected const float ResizeAreaWidth = 5; + + protected const float MinimizeCollisionAdjust = 5; + + protected GUIStyle m_style; + protected GUIContent m_content; + protected Rect m_maximizedArea; + protected Rect m_transformedArea; + protected Rect m_resizeArea; + protected MenuAnchor m_anchor; + protected MenuAutoSize m_autoSize; + protected bool m_isActive = true; + protected bool m_isMaximized = true; + + protected bool m_lockOnMinimize = false; + protected bool m_preLockState = false; + + protected Rect m_minimizedArea; + protected Rect m_minimizeButtonPos; + protected float m_realWidth; + protected GUIStyle m_empty = new GUIStyle(); + + protected float m_resizeDelta; + + protected bool m_isResizing = false; + protected bool m_resizable = false; + protected GUIStyle m_resizeAreaStyle; + protected bool m_isMouseInside = false; + protected Vector2 m_currentScrollPos; + public MenuParent( AmplifyShaderEditorWindow parentWindow, float x, float y, float width, float height, string name, MenuAnchor anchor = MenuAnchor.NONE, MenuAutoSize autoSize = MenuAutoSize.NONE ) + { + m_parentWindow = parentWindow; + m_anchor = anchor; + m_autoSize = autoSize; + m_maximizedArea = new Rect( x, y, width, height ); + m_content = new GUIContent( GUIContent.none ); + m_content.text = name; + m_transformedArea = new Rect(); + m_resizeArea = new Rect(); + m_resizeArea.width = ResizeAreaWidth; + m_resizeAreaStyle = GUIStyle.none; + m_currentScrollPos = Vector2.zero; + } + + public void SetMinimizedArea( float x, float y, float width, float height ) + { + m_minimizedArea = new Rect( x, y, width, height ); + } + + protected void InitDraw( Rect parentPosition, Vector2 mousePosition, int mouseButtonId ) + { + if ( m_style == null ) + { + m_style = new GUIStyle( UIUtils.TextArea ); + +#if UNITY_2019_3_OR_NEWER + m_style.normal.background = m_style.normal.scaledBackgrounds[ 0 ]; + m_style.normal.scaledBackgrounds = null; + m_style.border = new RectOffset( 4, 4, 4, 4 ); +#endif + m_style.stretchHeight = true; + m_style.stretchWidth = true; + m_style.fontSize = ( int ) Constants.DefaultTitleFontSize; + m_style.fontStyle = FontStyle.Normal; + Texture minimizeTex = UIUtils.GetCustomStyle( CustomStyle.MaximizeButton ).normal.background; + m_minimizeButtonPos = new Rect( 0, 0, minimizeTex.width, minimizeTex.height ); + } + + Rect currentArea = m_isMaximized ? m_maximizedArea : m_minimizedArea; + + if ( m_isMaximized ) + { + if ( m_resizable ) + { + if ( m_isResizing ) + { + if ( m_anchor == MenuAnchor.TOP_LEFT ) + m_resizeDelta = ( ParentWindow.CurrentEvent.mousePosition.x - m_maximizedArea.width ); + else if ( m_anchor == MenuAnchor.TOP_RIGHT ) + m_resizeDelta = ParentWindow.CurrentEvent.mousePosition.x - ( parentPosition.width - m_maximizedArea.width); + } + } + + m_realWidth = m_maximizedArea.width; + if ( m_resizable ) + { + if ( m_anchor == MenuAnchor.TOP_LEFT ) + { + currentArea.width += m_resizeDelta; + m_realWidth += m_resizeDelta; + } + else if ( m_anchor == MenuAnchor.TOP_RIGHT ) + { + currentArea.width -= m_resizeDelta; + m_realWidth -= m_resizeDelta; + } + } + } + else + { + if ( currentArea.x < 0 ) + { + m_realWidth = currentArea.width + currentArea.x; + } + else if ( ( currentArea.x + currentArea.width ) > parentPosition.width ) + { + m_realWidth = parentPosition.width - currentArea.x; + } + if ( m_realWidth < 0 ) + m_realWidth = 0; + } + + switch ( m_anchor ) + { + case MenuAnchor.TOP_LEFT: + { + m_transformedArea.x = currentArea.x; + m_transformedArea.y = currentArea.y; + if ( m_isMaximized ) + { + m_minimizeButtonPos.x = m_transformedArea.x + m_transformedArea.width - m_minimizeButtonPos.width - MinimizeButtonXSpacing; + m_minimizeButtonPos.y = m_transformedArea.y + MinimizeButtonYSpacing; + + m_resizeArea.x = m_transformedArea.x + m_transformedArea.width; + m_resizeArea.y = m_minimizeButtonPos.y; + m_resizeArea.height = m_transformedArea.height; + } + else + { + float width = ( m_transformedArea.width - m_transformedArea.x ); + m_minimizeButtonPos.x = m_transformedArea.x + width * 0.5f - m_minimizeButtonPos.width * 0.5f; + m_minimizeButtonPos.y = m_transformedArea.height * 0.5f - m_minimizeButtonPos.height * 0.5f; + } + } + break; + case MenuAnchor.TOP_CENTER: + { + m_transformedArea.x = parentPosition.width * 0.5f + currentArea.x; + m_transformedArea.y = currentArea.y; + } + break; + case MenuAnchor.TOP_RIGHT: + { + m_transformedArea.x = parentPosition.width - currentArea.x - currentArea.width; + m_transformedArea.y = currentArea.y; + if ( m_isMaximized ) + { + m_minimizeButtonPos.x = m_transformedArea.x + MinimizeButtonXSpacing; + m_minimizeButtonPos.y = m_transformedArea.y + MinimizeButtonYSpacing; + + m_resizeArea.x = m_transformedArea.x - ResizeAreaWidth; + m_resizeArea.y = m_minimizeButtonPos.y; + m_resizeArea.height = m_transformedArea.height; + } + else + { + float width = ( parentPosition.width - m_transformedArea.x ); + m_minimizeButtonPos.x = m_transformedArea.x + width * 0.5f - m_minimizeButtonPos.width * 0.5f; + m_minimizeButtonPos.y = m_transformedArea.height * 0.5f - m_minimizeButtonPos.height * 0.5f; + } + } + break; + case MenuAnchor.MIDDLE_LEFT: + { + m_transformedArea.x = currentArea.x; + m_transformedArea.y = parentPosition.height * 0.5f + currentArea.y; + } + break; + case MenuAnchor.MIDDLE_CENTER: + { + m_transformedArea.x = parentPosition.width * 0.5f + currentArea.x; + m_transformedArea.y = parentPosition.height * 0.5f + currentArea.y; + } + break; + case MenuAnchor.MIDDLE_RIGHT: + { + m_transformedArea.x = parentPosition.width - currentArea.x - currentArea.width; + m_transformedArea.y = parentPosition.height * 0.5f + currentArea.y; + } + break; + case MenuAnchor.BOTTOM_LEFT: + { + m_transformedArea.x = currentArea.x; + m_transformedArea.y = parentPosition.height - currentArea.y - currentArea.height; + } + break; + case MenuAnchor.BOTTOM_CENTER: + { + m_transformedArea.x = parentPosition.width * 0.5f + currentArea.x; + m_transformedArea.y = parentPosition.height - currentArea.y - currentArea.height; + } + break; + case MenuAnchor.BOTTOM_RIGHT: + { + m_transformedArea.x = parentPosition.width - currentArea.x - currentArea.width; + m_transformedArea.y = parentPosition.height - currentArea.y - currentArea.height; + } + break; + + case MenuAnchor.NONE: + { + m_transformedArea.x = currentArea.x; + m_transformedArea.y = currentArea.y; + } + break; + } + + switch ( m_autoSize ) + { + case MenuAutoSize.MATCH_HORIZONTAL: + { + m_transformedArea.width = parentPosition.width - m_transformedArea.x; + m_transformedArea.height = currentArea.height; + } + break; + + case MenuAutoSize.MATCH_VERTICAL: + { + m_transformedArea.width = currentArea.width; + m_transformedArea.height = parentPosition.height - m_transformedArea.y; + } + break; + case MenuAutoSize.NONE: + { + m_transformedArea.width = currentArea.width; + m_transformedArea.height = currentArea.height; + } + break; + } + + } + public virtual void Draw( Rect parentPosition, Vector2 mousePosition, int mouseButtonId, bool hasKeyboadFocus ) + { + InitDraw( parentPosition, mousePosition, mouseButtonId ); + if ( ParentWindow.CurrentEvent.type == EventType.MouseDrag && ParentWindow.CurrentEvent.button > 0 /*catches both middle and right mouse button*/ ) + { + m_isMouseInside = IsInside( mousePosition ); + if ( m_isMouseInside ) + { + m_currentScrollPos.x += Constants.MenuDragSpeed * ParentWindow.CurrentEvent.delta.x; + if ( m_currentScrollPos.x < 0 ) + m_currentScrollPos.x = 0; + m_currentScrollPos.y += Constants.MenuDragSpeed * ParentWindow.CurrentEvent.delta.y; + if ( m_currentScrollPos.y < 0 ) + m_currentScrollPos.y = 0; + + } + } + } + + public void PostDraw() + { + if ( !m_isMaximized ) + { + m_transformedArea.height = 35; + GUI.Label( m_transformedArea, m_content, m_style ); + } + + Color colorBuffer = GUI.color; + GUI.color = EditorGUIUtility.isProSkin ? Color.white : Color.black; + bool guiEnabledBuffer = GUI.enabled; + GUI.enabled = !m_lockOnMinimize; + Rect buttonArea = m_minimizeButtonPos; + + buttonArea.x -= MinimizeCollisionAdjust; + buttonArea.width += 2 * MinimizeCollisionAdjust; + + buttonArea.y -= MinimizeCollisionAdjust; + buttonArea.height += 2 * MinimizeCollisionAdjust; + + if ( m_parentWindow.CameraDrawInfo.CurrentEventType == EventType.Repaint ) + GUI.Label( m_minimizeButtonPos, string.Empty, UIUtils.GetCustomStyle( m_isMaximized ? CustomStyle.MinimizeButton : CustomStyle.MaximizeButton ) ); + + if( m_parentWindow.CameraDrawInfo.CurrentEventType == EventType.MouseDown && buttonArea.Contains( m_parentWindow.CameraDrawInfo.MousePosition ) ) + //if ( GUI.Button( buttonArea, string.Empty, m_empty ) ) + { + m_isMaximized = !m_isMaximized; + m_resizeDelta = 0; + } + + if ( m_resizable && m_isMaximized ) + { + EditorGUIUtility.AddCursorRect( m_resizeArea, MouseCursor.ResizeHorizontal ); + if ( !m_isResizing && GUI.RepeatButton( m_resizeArea, string.Empty, m_resizeAreaStyle ) ) + { + m_isResizing = true; + } + else + { + if ( m_isResizing ) + { + if ( ParentWindow.CurrentEvent.isMouse && ParentWindow.CurrentEvent.type != EventType.MouseDrag ) + { + m_isResizing = false; + } + } + } + + if ( m_realWidth < buttonArea.width ) + { + // Auto-minimize + m_isMaximized = false; + m_resizeDelta = 0; + m_isResizing = false; + } + else + { + float halfSizeWindow = 0.5f * ParentWindow.position.width; + if ( m_realWidth > halfSizeWindow ) + { + m_realWidth = 0.5f * ParentWindow.position.width; + if ( m_resizeDelta > 0 ) + { + m_resizeDelta = m_realWidth - m_maximizedArea.width; + } + else + { + m_resizeDelta = m_maximizedArea.width - m_realWidth; + } + } + } + } + + GUI.enabled = guiEnabledBuffer; + GUI.color = colorBuffer; + + } + + public void OnLostFocus() + { + if ( m_isResizing ) + { + m_isResizing = false; + } + } + + virtual public void Destroy() + { + m_empty = null; + m_resizeAreaStyle = null; + } + + public float InitialX + { + get { return m_maximizedArea.x; } + set { m_maximizedArea.x = value; } + } + + public float Width + { + get { return m_maximizedArea.width; } + set { m_maximizedArea.width = value; } + } + + public float RealWidth + { + get { return m_realWidth; } + } + public float Height + { + get { return m_maximizedArea.height; } + set { m_maximizedArea.height = value; } + } + + public Rect Size + { + get { return m_maximizedArea; } + } + + public virtual bool IsInside( Vector2 position ) + { + if ( !m_isActive ) + return false; + + return m_transformedArea.Contains( position ); + } + + public bool IsMaximized + { + get { return m_isMaximized; } + set { m_isMaximized = value; } + } + + public Rect TransformedArea + { + get { return m_transformedArea; } + } + + public bool Resizable { set { m_resizable = value; } } + public bool IsResizing { get { return m_isResizing; } } + public bool LockOnMinimize + { + set + { + if ( m_lockOnMinimize == value ) + return; + + m_lockOnMinimize = value; + if ( value ) + { + m_preLockState = m_isMaximized; + m_isMaximized = false; + } + else + { + m_isMaximized = m_preLockState; + } + } + } + public bool IsActive + { + get { return m_isActive; } + } + public AmplifyShaderEditorWindow ParentWindow { get { return m_parentWindow; } set { m_parentWindow = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/MenuParent.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/MenuParent.cs.meta new file mode 100644 index 0000000..2c0ba16 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/MenuParent.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5d535d3799a3ef547aea607fdc8b947b +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeParametersWindow.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeParametersWindow.cs new file mode 100644 index 0000000..8b8ed9c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeParametersWindow.cs @@ -0,0 +1,557 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using UnityEditorInternal; + +namespace AmplifyShaderEditor +{ + public sealed class NodeParametersWindow : MenuParent + { + private int m_lastSelectedNode = -1; + private const string TitleStr = "Node Properties"; + private GUIStyle m_nodePropertiesStyle; + private GUIContent m_dummyContent = new GUIContent(); + private GUIStyle m_propertyAdjustment; + + private ReorderableList m_functionInputsReordableList = null; + private int m_functionInputsLastCount = 0; + + private ReorderableList m_functionSwitchesReordableList = null; + private int m_functionSwitchesLastCount = 0; + + private ReorderableList m_functionOutputsReordableList = null; + private int m_functionOutputsLastCount = 0; + + private ReorderableList m_propertyReordableList = null; + private int m_lastCount = 0; + + private bool m_forceUpdate = false; + + [SerializeField] + private List m_propertyReordableNodes = new List(); + + // width and height are between [0,1] and represent a percentage of the total screen area + public NodeParametersWindow( AmplifyShaderEditorWindow parentWindow ) : base( parentWindow, 0, 0, 285, 0, string.Empty, MenuAnchor.TOP_LEFT, MenuAutoSize.MATCH_VERTICAL ) + { + SetMinimizedArea( -225, 0, 260, 0 ); + } + + public void OnShaderFunctionLoad() + { + m_functionInputsReordableList = null; + m_functionSwitchesReordableList = null; + m_functionOutputsReordableList = null; + } + + public bool Draw( Rect parentPosition, ParentNode selectedNode, Vector2 mousePosition, int mouseButtonId, bool hasKeyboardFocus ) + { + bool changeCheck = false; + base.Draw( parentPosition, mousePosition, mouseButtonId, hasKeyboardFocus ); + if ( m_nodePropertiesStyle == null ) + { + m_nodePropertiesStyle = UIUtils.GetCustomStyle( CustomStyle.NodePropertiesTitle ); + m_nodePropertiesStyle.normal.textColor = m_nodePropertiesStyle.active.textColor = EditorGUIUtility.isProSkin ? new Color( 1f, 1f, 1f ) : new Color( 0f, 0f, 0f ); + } + + if ( m_isMaximized ) + { + KeyCode key = Event.current.keyCode; + if ( m_isMouseInside || hasKeyboardFocus ) + { + if ( key == ShortcutsManager.ScrollUpKey ) + { + m_currentScrollPos.y -= 10; + if ( m_currentScrollPos.y < 0 ) + { + m_currentScrollPos.y = 0; + } + Event.current.Use(); + } + + if ( key == ShortcutsManager.ScrollDownKey ) + { + m_currentScrollPos.y += 10; + Event.current.Use(); + } + } + + if( m_forceUpdate ) + { + if( m_propertyReordableList != null ) + m_propertyReordableList.ReleaseKeyboardFocus(); + m_propertyReordableList = null; + + if ( m_functionInputsReordableList != null ) + m_functionInputsReordableList.ReleaseKeyboardFocus(); + m_functionInputsReordableList = null; + + if( m_functionSwitchesReordableList != null ) + m_functionSwitchesReordableList.ReleaseKeyboardFocus(); + m_functionSwitchesReordableList = null; + + if ( m_functionOutputsReordableList != null ) + m_functionOutputsReordableList.ReleaseKeyboardFocus(); + m_functionOutputsReordableList = null; + m_forceUpdate = false; + } + + GUILayout.BeginArea( m_transformedArea, m_content, m_style ); + { + //Draw selected node parameters + if ( selectedNode != null ) + { + // this hack is need because without it the several FloatFields/Textfields/... would show wrong values ( different from the ones they were assigned to show ) + if ( m_lastSelectedNode != selectedNode.UniqueId ) + { + m_lastSelectedNode = selectedNode.UniqueId; + GUI.FocusControl( "" ); + } + + EditorGUILayout.BeginVertical(); + { + EditorGUILayout.Separator(); + if ( selectedNode.UniqueId == ParentWindow.CurrentGraph.CurrentMasterNodeId ) + { + m_dummyContent.text = "Output Node"; + } + else + { + if ( selectedNode.Attributes != null ) + { + + m_dummyContent.text = selectedNode.Attributes.Name; + } + else if ( selectedNode is CommentaryNode ) + { + m_dummyContent.text = "Commentary"; + } + else + { + m_dummyContent.text = TitleStr; + } + } + + EditorGUILayout.LabelField( m_dummyContent, m_nodePropertiesStyle ); + + EditorGUILayout.Separator(); + //UIUtils.RecordObject( selectedNode , "Changing properties on node " + selectedNode.UniqueId); + m_currentScrollPos = EditorGUILayout.BeginScrollView( m_currentScrollPos, GUILayout.Width( 0 ), GUILayout.Height( 0 ) ); + float labelWidth = EditorGUIUtility.labelWidth; + //if( selectedNode.TextLabelWidth > 0 ) + // EditorGUIUtility.labelWidth = selectedNode.TextLabelWidth; + //else + EditorGUIUtility.labelWidth = TransformedArea.width * 0.42f; + + changeCheck = selectedNode.SafeDrawProperties(); + EditorGUIUtility.labelWidth = labelWidth; + EditorGUILayout.EndScrollView(); + } + EditorGUILayout.EndVertical(); + + if ( changeCheck ) + { + if ( selectedNode.ConnStatus == NodeConnectionStatus.Connected ) + ParentWindow.SetSaveIsDirty(); + } + } + else + { + //Draw Graph Params + EditorGUILayout.BeginVertical(); + { + EditorGUILayout.Separator(); + EditorGUILayout.LabelField( "Graph Properties", m_nodePropertiesStyle ); + EditorGUILayout.Separator(); + + m_currentScrollPos = EditorGUILayout.BeginScrollView( m_currentScrollPos, GUILayout.Width( 0 ), GUILayout.Height( 0 ) ); + float labelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 90; + + bool generalIsVisible = m_parentWindow.InnerWindowVariables.ExpandedGeneralShaderOptions; + NodeUtils.DrawPropertyGroup( ref generalIsVisible, " General", DrawGeneralFunction ); + m_parentWindow.InnerWindowVariables.ExpandedGeneralShaderOptions = generalIsVisible; + AmplifyShaderFunction function = ParentWindow.CurrentGraph.CurrentShaderFunction; + if( function != null ) + { + //function.AdditionalIncludes.Draw( ParentWindow.CurrentGraph.CurrentOutputNode ); + //function.AdditionalPragmas.Draw( ParentWindow.CurrentGraph.CurrentOutputNode ); + function.AdditionalDirectives.Draw( ParentWindow.CurrentGraph.CurrentOutputNode ); + } + + bool inputIsVisible = m_parentWindow.InnerWindowVariables.ExpandedFunctionInputs; + NodeUtils.DrawPropertyGroup( ref inputIsVisible, " Function Inputs", DrawFunctionInputs ); + m_parentWindow.InnerWindowVariables.ExpandedFunctionInputs = inputIsVisible; + + bool swicthIsVisible = m_parentWindow.InnerWindowVariables.ExpandedFunctionSwitches; + NodeUtils.DrawPropertyGroup( ref swicthIsVisible, " Function Switches", DrawFunctionSwitches ); + m_parentWindow.InnerWindowVariables.ExpandedFunctionSwitches = swicthIsVisible; + + bool outputIsVisible = m_parentWindow.InnerWindowVariables.ExpandedFunctionOutputs; + NodeUtils.DrawPropertyGroup( ref outputIsVisible, " Function Outputs", DrawFunctionOutputs ); + m_parentWindow.InnerWindowVariables.ExpandedFunctionOutputs = outputIsVisible; + + bool properties = ParentWindow.InnerWindowVariables.ExpandedProperties; + NodeUtils.DrawPropertyGroup( ref properties, " Material Properties", DrawFunctionProperties ); + ParentWindow.InnerWindowVariables.ExpandedProperties = properties; + + EditorGUIUtility.labelWidth = labelWidth; + EditorGUILayout.EndScrollView(); + } + EditorGUILayout.EndVertical(); + } + } + // Close window area + GUILayout.EndArea(); + } + + PostDraw(); + return changeCheck; + } + + public void DrawGeneralFunction() + { + AmplifyShaderFunction function = ParentWindow.CurrentGraph.CurrentShaderFunction; + if ( function == null ) + return; + + float cacheWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 115; + + SerializedObject serializedObject = new UnityEditor.SerializedObject( function ); + + if ( serializedObject != null ) + { + SerializedProperty temo = serializedObject.FindProperty( "m_description" ); + EditorGUILayout.PropertyField( temo, new GUIContent( " Description" ) ); + + SerializedProperty cat = serializedObject.FindProperty( "m_nodeCategory" ); + SerializedProperty ppos = serializedObject.FindProperty( "m_previewPosition" ); + + EditorGUILayout.PropertyField( ppos, new GUIContent( "Preview Position" ) ); + cat.intValue = ParentWindow.CurrentGraph.CurrentOutputNode.EditorGUILayoutPopup( "Category", cat.intValue, UIUtils.CategoryPresets ); + + if( cat.enumValueIndex == 0 ) + { + SerializedProperty custCat = serializedObject.FindProperty( "m_customNodeCategory" ); + EditorGUILayout.PropertyField( custCat, new GUIContent( "Custom" ) ); + } + SerializedProperty hidden = serializedObject.FindProperty( "m_hidden" ); + EditorGUILayout.PropertyField( hidden, new GUIContent( "Hidden" ) ); + serializedObject.ApplyModifiedProperties(); + } + EditorGUIUtility.labelWidth = cacheWidth; + } + + + public void DrawFunctionInputs() + { + List functionInputNodes = UIUtils.FunctionInputList(); + + if ( m_functionInputsReordableList == null || functionInputNodes.Count != m_functionInputsLastCount ) + { + functionInputNodes.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + + m_functionInputsReordableList = new ReorderableList( functionInputNodes, typeof( FunctionInput ), true, false, false, false ); + m_functionInputsReordableList.headerHeight = 0; + m_functionInputsReordableList.footerHeight = 0; + m_functionInputsReordableList.showDefaultBackground = false; + + m_functionInputsReordableList.drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) => + { + EditorGUI.LabelField( rect, functionInputNodes[ index ].InputName ); + }; + + m_functionInputsReordableList.onChangedCallback = ( list ) => + { + //for ( int i = 0; i < functionInputNodes.Count; i++ ) + //{ + // functionInputNodes[ i ].OrderIndex = i; + //} + ForceInputReorder( ref functionInputNodes ); + }; + + m_functionInputsLastCount = m_functionInputsReordableList.count; + } + + if ( m_functionInputsReordableList != null ) + { + if ( m_propertyAdjustment == null ) + { + m_propertyAdjustment = new GUIStyle(); + m_propertyAdjustment.padding.left = 17; + } + EditorGUILayout.BeginVertical( m_propertyAdjustment ); + m_functionInputsReordableList.DoLayoutList(); + EditorGUILayout.EndVertical(); + } + } + + public void ForceInputReorder( ref List functionInputNodes ) + { + for( int i = 0; i < functionInputNodes.Count; i++ ) + { + functionInputNodes[ i ].OrderIndex = i; + } + } + + public void DrawFunctionSwitches() + { + List functionSwitchNodes = UIUtils.FunctionSwitchList(); + + if( m_functionSwitchesReordableList == null || functionSwitchNodes.Count != m_functionSwitchesLastCount ) + { + functionSwitchNodes.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + + UIUtils.UpdateFunctionSwitchArr(); + + m_functionSwitchesReordableList = new ReorderableList( functionSwitchNodes, typeof( FunctionSwitch ), true, false, false, false ); + m_functionSwitchesReordableList.headerHeight = 0; + m_functionSwitchesReordableList.footerHeight = 0; + m_functionSwitchesReordableList.showDefaultBackground = false; + + m_functionSwitchesReordableList.drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) => + { + EditorGUI.LabelField( rect, functionSwitchNodes[ index ].OptionLabel ); + }; + + m_functionSwitchesReordableList.onChangedCallback = ( list ) => + { + ForceSwitchesReorder(ref functionSwitchNodes ); + }; + + m_functionSwitchesLastCount = m_functionSwitchesReordableList.count; + } + + if( m_functionSwitchesReordableList != null ) + { + if( m_propertyAdjustment == null ) + { + m_propertyAdjustment = new GUIStyle(); + m_propertyAdjustment.padding.left = 17; + } + EditorGUILayout.BeginVertical( m_propertyAdjustment ); + m_functionSwitchesReordableList.DoLayoutList(); + EditorGUILayout.EndVertical(); + } + } + + public void ForceSwitchesReorder( ref List functionSwitchNodes ) + { + for( int i = 0; i < functionSwitchNodes.Count; i++ ) + { + functionSwitchNodes[ i ].OrderIndex = i; + } + + UIUtils.UpdateFunctionSwitchArr(); + } + + public void DrawFunctionOutputs() + { + List functionOutputNodes = UIUtils.FunctionOutputList(); + + if ( m_functionOutputsReordableList == null || functionOutputNodes.Count != m_functionOutputsLastCount ) + { + functionOutputNodes.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + + m_functionOutputsReordableList = new ReorderableList( functionOutputNodes, typeof( FunctionOutput ), true, false, false, false ); + m_functionOutputsReordableList.headerHeight = 0; + m_functionOutputsReordableList.footerHeight = 0; + m_functionOutputsReordableList.showDefaultBackground = false; + + m_functionOutputsReordableList.drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) => + { + EditorGUI.LabelField( rect, functionOutputNodes[ index ].OutputName ); + }; + + m_functionOutputsReordableList.onChangedCallback = ( list ) => + { + for ( int i = 0; i < functionOutputNodes.Count; i++ ) + { + functionOutputNodes[ i ].OrderIndex = i; + } + }; + + m_functionOutputsLastCount = m_functionOutputsReordableList.count; + } + + if ( m_functionOutputsReordableList != null ) + { + if ( m_propertyAdjustment == null ) + { + m_propertyAdjustment = new GUIStyle(); + m_propertyAdjustment.padding.left = 17; + } + EditorGUILayout.BeginVertical( m_propertyAdjustment ); + m_functionOutputsReordableList.DoLayoutList(); + EditorGUILayout.EndVertical(); + } + } + + private void RefreshVisibleList( ref List allNodes ) + { + // temp reference for lambda expression + List nodes = allNodes; + m_propertyReordableNodes.Clear(); + + for( int i = 0; i < nodes.Count; i++ ) + { + ReordenatorNode rnode = nodes[ i ] as ReordenatorNode; + if( ( rnode == null || !rnode.IsInside ) && ( !m_propertyReordableNodes.Exists( x => x.PropertyName.Equals( nodes[ i ].PropertyName ) ) ) ) + m_propertyReordableNodes.Add( nodes[ i ] ); + } + + m_propertyReordableNodes.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + } + + public void DrawFunctionProperties() + { + List nodes = UIUtils.PropertyNodesList(); + + if( nodes.Count != m_lastCount ) + { + RefreshVisibleList( ref nodes ); + m_lastCount = nodes.Count; + } + + if( m_propertyReordableList == null ) + { + m_propertyReordableList = new ReorderableList( m_propertyReordableNodes, typeof( PropertyNode ), true, false, false, false ) + { + headerHeight = 0, + footerHeight = 0, + showDefaultBackground = false, + + drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) => + { + var first = rect; + first.width *= 0.60f; + EditorGUI.LabelField( first, m_propertyReordableNodes[ index ].PropertyInspectorName ); + var second = rect; + second.width *= 0.4f; + second.x += first.width; + if( GUI.Button( second, m_propertyReordableNodes[ index ].PropertyName, new GUIStyle( "AssetLabel Partial" ) ) ) + { + UIUtils.FocusOnNode( m_propertyReordableNodes[ index ], 1, false ); + } + }, + + onReorderCallback = ( list ) => + { + ReorderList( ref nodes ); + } + }; + ReorderList( ref nodes ); + } + + if( m_propertyReordableList != null ) + { + if( m_propertyAdjustment == null ) + { + m_propertyAdjustment = new GUIStyle(); + m_propertyAdjustment.padding.left = 17; + } + EditorGUILayout.BeginVertical( m_propertyAdjustment ); + m_propertyReordableList.DoLayoutList(); + EditorGUILayout.EndVertical(); + } + } + + public void ForceReordering() + { + List nodes = UIUtils.PropertyNodesList(); + ReorderList( ref nodes ); + + List functionInputNodes = UIUtils.FunctionInputList(); + ForceInputReorder( ref functionInputNodes ); + + List functionSwitchNodes = UIUtils.FunctionSwitchList(); + ForceSwitchesReorder( ref functionSwitchNodes ); + //RecursiveLog(); + } + + private void RecursiveLog() + { + List nodes = UIUtils.PropertyNodesList(); + nodes.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + for( int i = 0; i < nodes.Count; i++ ) + { + if( ( nodes[ i ] is ReordenatorNode ) ) + ( nodes[ i ] as ReordenatorNode ).RecursiveLog(); + else + Debug.Log( nodes[ i ].OrderIndex + " " + nodes[ i ].PropertyName ); + } + } + + + private void ReorderList( ref List nodes ) + { + // clear lock list before reordering because of multiple sf being used + for( int i = 0; i < nodes.Count; i++ ) + { + ReordenatorNode rnode = nodes[ i ] as ReordenatorNode; + if ( rnode != null ) + rnode.RecursiveClear(); + } + + int propoffset = 0; + int count = 0; + for ( int i = 0; i < m_propertyReordableNodes.Count; i++ ) + { + ReordenatorNode renode = m_propertyReordableNodes[ i ] as ReordenatorNode; + if ( renode != null ) + { + if ( !renode.IsInside ) + { + m_propertyReordableNodes[ i ].OrderIndex = count + propoffset; + + if ( renode.PropertyListCount > 0 ) + { + propoffset += renode.RecursiveCount(); + + // the same reordenator can exist multiple times, apply ordering to all of them + for( int j = 0; j < nodes.Count; j++ ) + { + ReordenatorNode pnode = ( nodes[ j ] as ReordenatorNode ); + if ( pnode != null && pnode.PropertyName.Equals( renode.PropertyName ) ) + { + pnode.OrderIndex = renode.RawOrderIndex; + pnode.RecursiveSetOrderOffset( renode.RawOrderIndex, true ); + } + } + } + else + { + count++; + } + } + else + { + m_propertyReordableNodes[ i ].OrderIndex = 0; + } + } + else + { + m_propertyReordableNodes[ i ].OrderIndex = count + propoffset; + count++; + } + } + } + + public override void Destroy() + { + base.Destroy(); + m_functionInputsReordableList = null; + m_functionOutputsReordableList = null; + m_propertyReordableList = null; + } + + public bool ForceUpdate + { + get { return m_forceUpdate; } + set { m_forceUpdate = value; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeParametersWindow.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeParametersWindow.cs.meta new file mode 100644 index 0000000..c49545c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeParametersWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d09f21096aa7c9f438e91a6e7f2621fb +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeWireReferencesUtils.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeWireReferencesUtils.cs new file mode 100644 index 0000000..f1793a2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeWireReferencesUtils.cs @@ -0,0 +1,56 @@ +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public class NodeWireReferencesUtils + { + public WireReference InputPortReference = new WireReference(); + public WireReference SwitchPortReference = new WireReference(); + public WireReference OutputPortReference = new WireReference(); + + public Vector2 SnapPosition = Vector2.zero; + public bool SnapEnabled = false; + public WireReference SnapPort = new WireReference(); + + public bool ValidReferences() + { + return ( InputPortReference.IsValid || OutputPortReference.IsValid ); + } + + public void InvalidateReferences() + { + InputPortReference.Invalidate(); + OutputPortReference.Invalidate(); + SnapPort.Invalidate(); + SnapEnabled = false; + } + + + public void SetOutputReference( int nodeId, int portId, WirePortDataType dataType, bool typeLocked ) + { + if( InputPortReference.IsValid ) + InputPortReference.Invalidate(); + OutputPortReference.SetReference( nodeId, portId, dataType, typeLocked ); + } + + public void SetInputReference( int nodeId, int portId, WirePortDataType dataType, bool typeLocked ) + { + if( OutputPortReference.IsValid ) + OutputPortReference.Invalidate(); + InputPortReference.SetReference( nodeId, portId, dataType, typeLocked ); + } + + public void ActivateSnap( Vector2 position, WirePort port ) + { + SnapPort.SetReference( port ); + SnapEnabled = true; + SnapPosition = position; + } + + public void DeactivateSnap() + { + SnapEnabled = false; + SnapPort.Invalidate(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeWireReferencesUtils.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeWireReferencesUtils.cs.meta new file mode 100644 index 0000000..6cc9bbe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/NodeWireReferencesUtils.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bfbc736093c900c418a7668e3003663a +timeCreated: 1500289690 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette.meta new file mode 100644 index 0000000..71c4251 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a89b03eb735b82a4da19a8381846935f +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/ContextPalette.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/ContextPalette.cs new file mode 100644 index 0000000..ae87061 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/ContextPalette.cs @@ -0,0 +1,101 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System.Collections.Generic; +using System; + +namespace AmplifyShaderEditor +{ + public sealed class ContextPalette : PaletteParent + { + private Vector3 m_position; + private Vector2 m_startDropPosition; + public ContextPalette( AmplifyShaderEditorWindow parentWindow ) : base( parentWindow, 0, 0, 250, 250, string.Empty, MenuAnchor.NONE, MenuAutoSize.NONE ) + { + m_isActive = false; + OnPaletteNodeCreateEvt += OnOptionSelected; + m_searchFilterControl += "CONTEXTPALETTE"; + } + + public override void OnEnterPressed(int index = 0) + { + if ( m_searchFilter.Length > 0 && m_currentItems.Count > 0 ) + { + FireNodeCreateEvent( m_currentItems[ index ].NodeType, m_currentItems[ index ].Name, m_currentItems[ index ].Function ); + } + else + { + Disable(); + } + } + + public override void OnEscapePressed() + { + Disable(); + if ( m_parentWindow.WireReferenceUtils.ValidReferences() ) + { + m_parentWindow.WireReferenceUtils.InvalidateReferences(); + } + } + + public override void Draw( Rect parentPosition, Vector2 mousePosition, int mouseButtonId, bool hasKeyboadFocus ) + { + //if ( !_isActive ) + // return; + + if ( Event.current.type == EventType.MouseDown && !IsInside( Event.current.mousePosition ) ) + { + Disable(); + return; + } + base.Draw( parentPosition, mousePosition, mouseButtonId, hasKeyboadFocus ); + } + + + public void Show( Vector2 position, Rect cameraInfo ) + { + m_startDropPosition = position; + m_maximizedArea.x = ( position.x + m_maximizedArea.width ) > cameraInfo.width ? ( cameraInfo.width - 1.1f * m_maximizedArea.width ) : position.x; + m_maximizedArea.y = ( position.y + m_maximizedArea.height ) > cameraInfo.height ? ( cameraInfo.height - 1.1f * m_maximizedArea.height ) : position.y; + m_position = new Vector3( m_maximizedArea.x, m_maximizedArea.y, 0f ); + m_isActive = true; + m_focusOnSearch = true; + } + + + // This override is removing focus from our window ... need to figure out a workaround before re-using it + //public override bool CheckButton( GUIContent content, GUIStyle style, int buttonId ) + //{ + // if ( buttonId != m_validButtonId ) + // return false; + + // return GUILayout.Button( content, style ); + //} + + void OnOptionSelected( System.Type type, string name, AmplifyShaderFunction function ) + { + Disable(); + } + + public void Disable() + { + m_isActive = false; + } + + public Vector2 StartDropPosition + { + get { return m_startDropPosition; } + } + + public Vector3 CurrentPosition + { + get { return m_position; } + } + + public Vector2 CurrentPosition2D + { + get { return new Vector2( m_position.x, m_position.y ); } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/ContextPalette.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/ContextPalette.cs.meta new file mode 100644 index 0000000..59f3f89 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/ContextPalette.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 15597b146a1fc154abd63ac75cffb73f +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteParent.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteParent.cs new file mode 100644 index 0000000..67ce6e1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteParent.cs @@ -0,0 +1,573 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System.Collections.Generic; +using UnityEditor; +using System; +using System.Text.RegularExpressions; + +namespace AmplifyShaderEditor +{ + public class PaletteFilterData + { + public bool Visible; + public bool HasCommunityData; + public List Contents; + public PaletteFilterData( bool visible ) + { + Visible = visible; + Contents = new List(); + } + } + + public class PaletteParent : MenuParent + { + private const float ItemSize = 18; + public delegate void OnPaletteNodeCreate( System.Type type, string name, AmplifyShaderFunction function ); + public event OnPaletteNodeCreate OnPaletteNodeCreateEvt; + + private string m_searchFilterStr = "Search"; + protected string m_searchFilterControl = "SHADERNAMETEXTFIELDCONTROLNAME"; + protected bool m_focusOnSearch = false; + protected bool m_defaultCategoryVisible = false; + + //protected List m_allItems; + protected List m_currentItems; + protected Dictionary m_currentCategories; + private bool m_forceUpdate = true; + + + protected string m_searchFilter = string.Empty; + + private float m_searchLabelSize = -1; + private GUIStyle m_buttonStyle; + private GUIStyle m_foldoutStyle; + + protected bool m_previousWindowIsFunction = false; + + protected int m_validButtonId = 0; + protected int m_initialSeparatorAmount = 1; + + private Vector2 m_currScrollBarDims = new Vector2( 1, 1 ); + + public PaletteParent( AmplifyShaderEditorWindow parentWindow, float x, float y, float width, float height, string name, MenuAnchor anchor = MenuAnchor.NONE, MenuAutoSize autoSize = MenuAutoSize.NONE ) : base( parentWindow, x, y, width, height, name, anchor, autoSize ) + { + m_searchFilter = string.Empty; + m_currentCategories = new Dictionary(); + //m_allItems = items; + m_currentItems = new List(); + } + + public virtual void OnEnterPressed( int index = 0 ) { } + public virtual void OnEscapePressed() { } + + public void FireNodeCreateEvent( System.Type type, string name, AmplifyShaderFunction function ) + { + OnPaletteNodeCreateEvt( type, name, function ); + } + + public override void Draw( Rect parentPosition, Vector2 mousePosition, int mouseButtonId, bool hasKeyboadFocus ) + { + base.Draw( parentPosition, mousePosition, mouseButtonId, hasKeyboadFocus ); + if( m_previousWindowIsFunction != ParentWindow.IsShaderFunctionWindow ) + { + m_forceUpdate = true; + } + + m_previousWindowIsFunction = ParentWindow.IsShaderFunctionWindow; + + List allItems = ParentWindow.ContextMenuInstance.MenuItems; + + if( m_searchLabelSize < 0 ) + { + m_searchLabelSize = GUI.skin.label.CalcSize( new GUIContent( m_searchFilterStr ) ).x; + } + + if( m_foldoutStyle == null ) + { + m_foldoutStyle = new GUIStyle( GUI.skin.GetStyle( "foldout" ) ); + m_foldoutStyle.fontStyle = FontStyle.Bold; + } + + if( m_buttonStyle == null ) + { + m_buttonStyle = UIUtils.Label; + } + + Event currenEvent = Event.current; + + GUILayout.BeginArea( m_transformedArea, m_content, m_style ); + { + for( int i = 0; i < m_initialSeparatorAmount; i++ ) + { + EditorGUILayout.Separator(); + } + + if( currenEvent.type == EventType.KeyDown ) + { + KeyCode key = currenEvent.keyCode; + //if ( key == KeyCode.Return || key == KeyCode.KeypadEnter ) + // OnEnterPressed(); + + if( ( currenEvent.keyCode == KeyCode.KeypadEnter || currenEvent.keyCode == KeyCode.Return ) && currenEvent.type == EventType.KeyDown ) + { + int index = m_currentItems.FindIndex( x => GUI.GetNameOfFocusedControl().Equals( x.ItemUIContent.text + m_resizable ) ); + if( index > -1 ) + OnEnterPressed( index ); + else + OnEnterPressed(); + } + + if( key == KeyCode.Escape ) + OnEscapePressed(); + + if( m_isMouseInside || hasKeyboadFocus ) + { + if( key == ShortcutsManager.ScrollUpKey ) + { + m_currentScrollPos.y -= 10; + if( m_currentScrollPos.y < 0 ) + { + m_currentScrollPos.y = 0; + } + currenEvent.Use(); + } + + if( key == ShortcutsManager.ScrollDownKey ) + { + m_currentScrollPos.y += 10; + currenEvent.Use(); + } + } + + } + + float width = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = m_searchLabelSize; + EditorGUI.BeginChangeCheck(); + { + GUI.SetNextControlName( m_searchFilterControl + m_resizable ); + m_searchFilter = EditorGUILayout.TextField( m_searchFilterStr, m_searchFilter ); + if( m_focusOnSearch ) + { + m_focusOnSearch = false; + EditorGUI.FocusTextInControl( m_searchFilterControl + m_resizable ); + } + } + if( EditorGUI.EndChangeCheck() ) + m_forceUpdate = true; + + EditorGUIUtility.labelWidth = width; + bool usingSearchFilter = ( m_searchFilter.Length == 0 ); + m_currScrollBarDims.x = m_transformedArea.width; + m_currScrollBarDims.y = m_transformedArea.height - 2 - 16 - 2 - 7 * m_initialSeparatorAmount - 2; + m_currentScrollPos = EditorGUILayout.BeginScrollView( m_currentScrollPos/*, GUILayout.Width( 242 ), GUILayout.Height( 250 - 2 - 16 - 2 - 7 - 2) */); + { + if( m_forceUpdate ) + { + m_forceUpdate = false; + + //m_currentItems.Clear(); + m_currentCategories.Clear(); + + if( usingSearchFilter ) + { + for( int i = 0; i < allItems.Count; i++ ) + { + //m_currentItems.Add( allItems[ i ] ); + if( !m_currentCategories.ContainsKey( allItems[ i ].Category ) ) + { + m_currentCategories.Add( allItems[ i ].Category, new PaletteFilterData( m_defaultCategoryVisible ) ); + //m_currentCategories[ allItems[ i ].Category ].HasCommunityData = allItems[ i ].NodeAttributes.FromCommunity || m_currentCategories[ allItems[ i ].Category ].HasCommunityData; + } + m_currentCategories[ allItems[ i ].Category ].Contents.Add( allItems[ i ] ); + } + } + else + { + for( int i = 0; i < allItems.Count; i++ ) + { + var searchList = m_searchFilter.Trim( ' ' ).ToLower().Split(' '); + + int matchesFound = 0; + for( int k = 0; k < searchList.Length; k++ ) + { + MatchCollection wordmatch = Regex.Matches( allItems[ i ].Tags, "\\b"+searchList[ k ] ); + if( wordmatch.Count > 0 ) + matchesFound++; + else + break; + } + + if( searchList.Length == matchesFound ) + { + //m_currentItems.Add( allItems[ i ] ); + if( !m_currentCategories.ContainsKey( allItems[ i ].Category ) ) + { + m_currentCategories.Add( allItems[ i ].Category, new PaletteFilterData( m_defaultCategoryVisible ) ); + //m_currentCategories[ allItems[ i ].Category ].HasCommunityData = allItems[ i ].NodeAttributes.FromCommunity || m_currentCategories[ allItems[ i ].Category ].HasCommunityData; + } + m_currentCategories[ allItems[ i ].Category ].Contents.Add( allItems[ i ] ); + } + } + } + var categoryEnumerator = m_currentCategories.GetEnumerator(); + while( categoryEnumerator.MoveNext() ) + { + categoryEnumerator.Current.Value.Contents.Sort( ( x, y ) => x.CompareTo( y, usingSearchFilter ) ); + } + + //sort current list respecting categories + m_currentItems.Clear(); + foreach( var item in m_currentCategories ) + { + for( int i = 0; i < item.Value.Contents.Count; i++ ) + { + m_currentItems.Add( item.Value.Contents[ i ] ); + } + } + } + + string watching = string.Empty; + + // unselect the main search field so it can focus list elements next + if( ( currenEvent.keyCode == KeyCode.DownArrow || currenEvent.keyCode == KeyCode.UpArrow ) && m_searchFilter.Length > 0 ) + { + if( GUI.GetNameOfFocusedControl().Equals( m_searchFilterControl + m_resizable ) ) + { + EditorGUI.FocusTextInControl( null ); + } + } + + if( currenEvent.keyCode == KeyCode.DownArrow && currenEvent.type == EventType.KeyDown ) + { + currenEvent.Use(); + + int nextIndex = m_currentItems.FindIndex( x => GUI.GetNameOfFocusedControl().Equals( x.ItemUIContent.text + m_resizable ) ) + 1; + if( nextIndex == m_currentItems.Count ) + nextIndex = 0; + + watching = m_currentItems[ nextIndex ].ItemUIContent.text + m_resizable; + GUI.FocusControl( watching ); + + } + + if( currenEvent.keyCode == KeyCode.UpArrow && currenEvent.type == EventType.KeyDown ) + { + currenEvent.Use(); + + int nextIndex = m_currentItems.FindIndex( x => GUI.GetNameOfFocusedControl().Equals( x.ItemUIContent.text + m_resizable ) ) - 1; + if( nextIndex < 0 ) + nextIndex = m_currentItems.Count - 1; + + watching = m_currentItems[ nextIndex ].ItemUIContent.text + m_resizable; + GUI.FocusControl( watching ); + } + + if( currenEvent.keyCode == KeyCode.Tab ) + { + ContextMenuItem item = m_currentItems.Find( x => GUI.GetNameOfFocusedControl().Equals( x.ItemUIContent.text + m_resizable ) ); + if( item != null ) + { + watching = item.ItemUIContent.text + m_resizable; + } + } + + float currPos = 0; + var enumerator = m_currentCategories.GetEnumerator(); + + float cache = EditorGUIUtility.labelWidth; + while( enumerator.MoveNext() ) + { + var current = enumerator.Current; + bool visible = GUILayout.Toggle( current.Value.Visible, current.Key, m_foldoutStyle ); + if( m_validButtonId == mouseButtonId ) + { + current.Value.Visible = visible; + } + + currPos += ItemSize; + if( m_searchFilter.Length > 0 || current.Value.Visible ) + { + for( int i = 0; i < current.Value.Contents.Count; i++ ) + { + //if ( !IsItemVisible( currPos ) ) + //{ + // // Invisible + // GUILayout.Space( ItemSize ); + //} + //else + { + currPos += ItemSize; + // Visible + EditorGUILayout.BeginHorizontal(); + GUILayout.Space( 16 ); + //if ( m_isMouseInside ) + //{ + // //GUI.SetNextControlName( current.Value.Contents[ i ].ItemUIContent.text ); + // if ( CheckButton( current.Value.Contents[ i ].ItemUIContent, m_buttonStyle, mouseButtonId ) ) + // { + // int controlID = GUIUtility.GetControlID( FocusType.Passive ); + // GUIUtility.hotControl = controlID; + // OnPaletteNodeCreateEvt( current.Value.Contents[ i ].NodeType, current.Value.Contents[ i ].Name, current.Value.Contents[ i ].Function ); + // } + //} + //else + { + Rect thisRect = EditorGUILayout.GetControlRect( false, 16f, EditorStyles.label ); + //if ( m_resizable ) + { + if( GUI.RepeatButton( thisRect, string.Empty, EditorStyles.label ) ) + { + int controlID = GUIUtility.GetControlID( FocusType.Passive ); + GUIUtility.hotControl = controlID; + OnPaletteNodeCreateEvt( current.Value.Contents[ i ].NodeType, current.Value.Contents[ i ].Name, current.Value.Contents[ i ].Function ); + //unfocus to make it focus the next text field correctly + GUI.FocusControl( null ); + } + } + GUI.SetNextControlName( current.Value.Contents[ i ].ItemUIContent.text + m_resizable ); + //EditorGUI.SelectableLabel( thisRect, current.Value.Contents[ i ].ItemUIContent.text, EditorStyles.label ); + //float cache = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = thisRect.width; + EditorGUI.Toggle( thisRect, current.Value.Contents[ i ].ItemUIContent.text, false, EditorStyles.label ); + EditorGUIUtility.labelWidth = cache; + if( watching == current.Value.Contents[ i ].ItemUIContent.text + m_resizable ) + { + bool boundBottom = currPos - m_currentScrollPos.y > m_currScrollBarDims.y; + bool boundTop = currPos - m_currentScrollPos.y - 4 <= 0; + + if( boundBottom ) + m_currentScrollPos.y = currPos - m_currScrollBarDims.y + 2; + else if( boundTop ) + m_currentScrollPos.y = currPos - 18; + //else if ( boundBottom && !downDirection ) + // m_currentScrollPos.y = currPos - m_currScrollBarDims.y + 2; + //else if ( boundTop && downDirection ) + // m_currentScrollPos.y = currPos - 18; + } + } + EditorGUILayout.EndHorizontal(); + } + //currPos += ItemSize; + } + } + } + EditorGUIUtility.labelWidth = cache; + } + EditorGUILayout.EndScrollView(); + } + GUILayout.EndArea(); + + } + public void CheckCommunityNodes() + { + var enumerator = m_currentCategories.GetEnumerator(); + while( enumerator.MoveNext() ) + { + var current = enumerator.Current; + current.Value.HasCommunityData = false; + int count = current.Value.Contents.Count; + for( int i = 0; i < count; i++ ) + { + if( current.Value.Contents[ i ].NodeAttributes.FromCommunity ) + { + current.Value.HasCommunityData = true; + break; + } + } + } + } + + public void DumpAvailableNodes( bool fromCommunity, string pathname ) + { + string noTOCHeader = "__NOTOC__\n"; + string nodesHeader = "== Available Node Categories ==\n"; + string InitialCategoriesFormat = "[[#{0}|{0}]]
\n"; + string InitialCategories = string.Empty; + string CurrentCategoryFormat = "\n== {0} ==\n\n"; + //string NodesFootFormat = "[[Unity Products:Amplify Shader Editor/{0} | Learn More]] -\n[[#Top|Back to Categories]]\n"; + string NodesFootFormatSep = "[[#Top|Back to Top]]\n----\n"; + string OverallFoot = "[[Category:Nodes]]"; + + string NodeInfoBeginFormat = "
\n"; + string nodeInfoBodyFormat = "{{| id=\"{2}\" class=\"wikitable\" |\n" + + "|- \n" + + "|
[[Unity Products:Amplify Shader Editor/{1}|]]
\n" + + "
\n" + + "{{| style=\"width: 100%; height: 150px;\"\n" + + "|-\n" + + "| [[Unity Products:Amplify Shader Editor/{1}|'''{2}''']]\n" + + "|- style=\"vertical-align:top; height: 100%;\" |\n" + + "|

{3}

\n" + + "|- style=\"text-align:right;\" |\n" + + "|{4}[[Unity Products:Amplify Shader Editor/{1} | Learn More]]\n" + + "|}}
\n" + + "|}}\n"; + string NodeInfoEndFormat = "
\n"; + + //string NodeInfoBeginFormat = "This page is under construction!\n\n"; + //string nodeInfoBodyFormat = "\n[[Unity Products:Amplify Shader Editor/{1}|'''{2}''']]\n\n{3}"; + //string NodeInfoEndFormat = "\n\n[[Unity_Products:Amplify_Shader_Editor/Nodes | Back to Node List ]]\n[[Category:Nodes]][[Category:{0}]]\n\n\n"; + + //string NodeInfoBeginFormat = "{| cellpadding=\"10\"\n"; + //string nodeInfoBodyFormat = "|- style=\"vertical-align:top;\"\n| http://amplify.pt/Nodes/{0}.jpg\n| [[Unity Products:Amplify Shader Editor/{1} | '''{2}''' ]]
{3}\n"; + //string NodeInfoEndFormat = "|}\n"; + + string nodesInfo = string.Empty; + BuildFullList( true ); + CheckCommunityNodes(); + var enumerator = m_currentCategories.GetEnumerator(); + while( enumerator.MoveNext() ) + { + var current = enumerator.Current; + if( fromCommunity && current.Value.HasCommunityData || !fromCommunity ) + { + InitialCategories += string.Format( InitialCategoriesFormat, current.Key ); + nodesInfo += string.Format( CurrentCategoryFormat, current.Key ); + int count = current.Value.Contents.Count; + for( int i = 0; i < count; i++ ) + { + if( ( fromCommunity && current.Value.Contents[ i ].NodeAttributes.FromCommunity ) + || !fromCommunity + //|| ( !fromCommunity && !current.Value.Contents[ i ].NodeAttributes.FromCommunity ) + ) + { + string nodeFullName = current.Value.Contents[ i ].Name; + string pictureFilename = UIUtils.ReplaceInvalidStrings( nodeFullName ); + + string pageFilename = UIUtils.RemoveWikiInvalidCharacters( pictureFilename ); + + pictureFilename = UIUtils.RemoveInvalidCharacters( pictureFilename ); + + string nodeDescription = current.Value.Contents[ i ].ItemUIContent.tooltip; + string communityText = string.Empty; + if( current.Value.Contents[ i ].NodeAttributes.FromCommunity ) + communityText = "( originally by "+ current.Value.Contents[ i ].NodeAttributes.Community + " ) "; + + string nodeInfoBody = string.Format( nodeInfoBodyFormat, pictureFilename, pageFilename, nodeFullName, nodeDescription, communityText ); + //string nodeInfoFoot = string.Format( NodesFootFormat, pageFilename ); + + nodesInfo += ( NodeInfoBeginFormat + nodeInfoBody + NodeInfoEndFormat ); + //nodesInfo += ( NodeInfoBeginFormat + nodeInfoBody + string.Format( NodeInfoEndFormat, current.Key ) ); + //if ( i != ( count - 1 ) ) + //{ + // nodesInfo += NodesFootFormatSep; + //} + } + } + nodesInfo += NodesFootFormatSep; + } + } + + string finalText = noTOCHeader + nodesHeader + InitialCategories + nodesInfo + OverallFoot; + + if( !System.IO.Directory.Exists( pathname ) ) + { + System.IO.Directory.CreateDirectory( pathname ); + } + // Save file + string nodesPathname = pathname + ( fromCommunity ? "AvailableNodesFromCommunity.txt" : "AvailableNodes.txt" ); + Debug.Log( " Creating nodes file at " + nodesPathname ); + IOUtils.SaveTextfileToDisk( finalText, nodesPathname, false ); + BuildFullList( false ); + } + + public virtual bool CheckButton( GUIContent content, GUIStyle style, int buttonId ) + { + if( buttonId != m_validButtonId ) + { + GUILayout.Label( content, style ); + return false; + } + + return GUILayout.RepeatButton( content, style ); + } + + public void FillList( ref List list, bool forceAllItems ) + { + List allList = forceAllItems ? ParentWindow.ContextMenuInstance.ItemFunctions : ParentWindow.ContextMenuInstance.MenuItems; + + list.Clear(); + int count = allList.Count; + for( int i = 0; i < count; i++ ) + { + list.Add( allList[ i ] ); + } + } + + public Dictionary BuildFullList( bool forceAllNodes = false ) + { + //Only need to build if search filter is active and list is set according to it + if( m_searchFilter.Length > 0 || !m_isActive || m_currentCategories.Count == 0 ) + { + m_currentItems.Clear(); + m_currentCategories.Clear(); + + List allItems = forceAllNodes ? ParentWindow.ContextMenuInstance.ItemFunctions : ParentWindow.ContextMenuInstance.MenuItems; + + for( int i = 0; i < allItems.Count; i++ ) + { + if( allItems[ i ].Name.IndexOf( m_searchFilter, StringComparison.InvariantCultureIgnoreCase ) >= 0 || + allItems[ i ].Category.IndexOf( m_searchFilter, StringComparison.InvariantCultureIgnoreCase ) >= 0 + ) + { + m_currentItems.Add( allItems[ i ] ); + if( !m_currentCategories.ContainsKey( allItems[ i ].Category ) ) + { + m_currentCategories.Add( allItems[ i ].Category, new PaletteFilterData( m_defaultCategoryVisible ) ); + //m_currentCategories[ allItems[ i ].Category ].HasCommunityData = allItems[ i ].NodeAttributes.FromCommunity || m_currentCategories[ allItems[ i ].Category ].HasCommunityData; + } + m_currentCategories[ allItems[ i ].Category ].Contents.Add( allItems[ i ] ); + } + } + + var categoryEnumerator = m_currentCategories.GetEnumerator(); + while( categoryEnumerator.MoveNext() ) + { + categoryEnumerator.Current.Value.Contents.Sort( ( x, y ) => x.CompareTo( y, false ) ); + } + + //mark to force update and take search filter into account + m_forceUpdate = true; + } + return m_currentCategories; + } + + private bool IsItemVisible( float currPos ) + { + if( ( currPos < m_currentScrollPos.y && ( currPos + ItemSize ) < m_currentScrollPos.y ) || + ( currPos > ( m_currentScrollPos.y + m_currScrollBarDims.y ) && + ( currPos + ItemSize ) > ( m_currentScrollPos.y + m_currScrollBarDims.y ) ) ) + { + return false; + } + return true; + } + + public override void Destroy() + { + base.Destroy(); + + //m_allItems = null; + + m_currentItems.Clear(); + m_currentItems = null; + + m_currentCategories.Clear(); + m_currentCategories = null; + + OnPaletteNodeCreateEvt = null; + m_buttonStyle = null; + m_foldoutStyle = null; + } + + //public void Clear() { + // m_allItems.Clear(); + // m_allItems = new List(); + //} + + public bool ForceUpdate { get { return m_forceUpdate; } set { m_forceUpdate = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteParent.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteParent.cs.meta new file mode 100644 index 0000000..b9d921f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteParent.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: df4c2f840dca60a4cb118325ce2febfa +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PalettePopUp.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PalettePopUp.cs new file mode 100644 index 0000000..84cfbc4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PalettePopUp.cs @@ -0,0 +1,73 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public class PalettePopUp + { + private const int DeltaX = 5; + private Rect m_areaSettings; + private Vector2 m_mouseDeltaPos = new Vector2( 10, -10 ); + private bool m_isActive = false; + private GUIContent m_content; + private GUIStyle m_style; + private GUIStyle m_fontStyle; + private GUIContent m_labelContent; + + public PalettePopUp() + { + m_content = new GUIContent( GUIContent.none ); + m_areaSettings = new Rect( 0, 0, 100, 30 ); + m_labelContent = new GUIContent( "Test Label" ); + } + + public void Activate( string label ) + { + m_labelContent.text = label; + m_areaSettings.width = -1; + m_isActive = true; + } + + public void Deactivate() + { + m_isActive = false; + } + + public void Draw( Vector2 mousePos ) + { + if ( m_style == null ) + { + m_style = UIUtils.TextArea; + } + + if ( m_fontStyle == null ) + { + m_fontStyle = new GUIStyle( UIUtils.Label ); + m_fontStyle.fontSize = 15; + } + + if ( m_areaSettings.width < 0 ) + { + m_areaSettings.width = m_fontStyle.CalcSize( m_labelContent ).x + 2 * DeltaX; + } + + m_areaSettings.position = mousePos + m_mouseDeltaPos; + GUI.Label( m_areaSettings, m_content, m_style ); + m_areaSettings.position += new Vector2( DeltaX,DeltaX); + GUI.Label( m_areaSettings, m_labelContent, m_fontStyle ); + } + + public void Destroy() + { + m_content = null; + m_style = null; + } + + public bool IsActive + { + get { return m_isActive; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PalettePopUp.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PalettePopUp.cs.meta new file mode 100644 index 0000000..f0f84d4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PalettePopUp.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bc4f137f15efe1d42b7bcbf984ec1545 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteWindow.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteWindow.cs new file mode 100644 index 0000000..f0b6960 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteWindow.cs @@ -0,0 +1,33 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System.Collections.Generic; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public sealed class PaletteWindow : PaletteParent + { + public PaletteWindow( AmplifyShaderEditorWindow parentWindow ) : base( parentWindow, 0, 0, 250, 0, string.Empty, MenuAnchor.TOP_RIGHT, MenuAutoSize.MATCH_VERTICAL ) + { + m_searchFilterControl += "PALETTEWINDOW"; + m_initialSeparatorAmount = 4; + SetMinimizedArea( -225, 0, 260, 0 ); + } + + public override void Draw( Rect parentPosition, Vector2 mousePosition, int mouseButtonId, bool hasKeyboadFocus ) + { + if ( m_isMaximized ) + { + base.Draw( parentPosition, mousePosition, mouseButtonId, hasKeyboadFocus ); + } + else + { + InitDraw( parentPosition, mousePosition, mouseButtonId ); + } + PostDraw(); + } + } +} + + diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteWindow.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteWindow.cs.meta new file mode 100644 index 0000000..521f776 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Palette/PaletteWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 63408b264ef8cb346a5ce9e559a5ed22 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/PortLegendInfo.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/PortLegendInfo.cs new file mode 100644 index 0000000..9f76a51 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/PortLegendInfo.cs @@ -0,0 +1,469 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + class NodeDescriptionInfo + { + public bool FoldoutValue; + public string Category; + public string[,] Contents; + } + + public sealed class PortLegendInfo : EditorWindow + { + private const string NoASEWindowWarning = "Please Open the ASE to get access to shortcut info"; + private const float PixelSeparator = 5; + private const string EditorShortcutsTitle = "Editor Shortcuts"; + private const string MenuShortcutsTitle = "Menu Shortcuts"; + private const string NodesShortcutsTitle = "Nodes Shortcuts"; + private const string PortShortcutsTitle = "Port Shortcuts"; + private const string PortLegendTitle = "Port Legend"; + private const string NodesDescTitle = "Node Info"; + private const string CompatibleAssetsTitle = "Compatible Assets"; + + private const string KeyboardUsageTemplate = "[{0}] - {1}"; + private const string m_lockedStr = "Locked Port"; + + private const float WindowSizeX = 350; + private const float WindowSizeY = 300; + private const float WindowPosX = 5; + private const float WindowPosY = 5; + + private int TitleLabelWidth = 150; + private Rect m_availableArea; + + private bool m_portAreaFoldout = true; + private bool m_editorShortcutAreaFoldout = true; + private bool m_menuShortcutAreaFoldout = true; + private bool m_nodesShortcutAreaFoldout = true; + private bool m_nodesDescriptionAreaFoldout = true; + private bool m_compatibleAssetsFoldout = true; + + private Vector2 m_currentScrollPos; + + private GUIStyle m_portStyle; + private GUIStyle m_labelStyleBold; + private GUIStyle m_labelStyle; + + private GUIStyle m_nodeInfoLabelStyleBold; + private GUIStyle m_nodeInfoLabelStyle; + + private GUIStyle m_nodeInfoFoldoutStyle; + + private GUIContent m_content = new GUIContent( "Helper", "Shows helper info for ASE users" ); + private bool m_init = true; + + private List m_editorShortcuts = null; + private List m_nodesShortcuts = null; + private List m_nodeDescriptionsInfo = null; + private List m_compatibleAssetsInfo = null; + + public static PortLegendInfo OpenWindow() + { + PortLegendInfo currentWindow = ( PortLegendInfo ) PortLegendInfo.GetWindow( typeof( PortLegendInfo ), false ); + currentWindow.minSize = new Vector2( WindowSizeX, WindowSizeY ); + currentWindow.maxSize = new Vector2( WindowSizeX * 2, 2 * WindowSizeY ); ; + currentWindow.wantsMouseMove = true; + return currentWindow; + } + + public void Init() + { + m_init = false; + wantsMouseMove = false; + titleContent = m_content; + m_portStyle = new GUIStyle( UIUtils.GetCustomStyle( CustomStyle.PortEmptyIcon ) ); + m_portStyle.alignment = TextAnchor.MiddleLeft; + m_portStyle.imagePosition = ImagePosition.ImageOnly; + m_portStyle.margin = new RectOffset( 5, 0, 5, 0 ); + + m_labelStyleBold = new GUIStyle( UIUtils.InputPortLabel ); + m_labelStyleBold.fontStyle = FontStyle.Bold; + m_labelStyleBold.fontSize = ( int ) ( Constants.TextFieldFontSize ); + + + m_labelStyle = new GUIStyle( UIUtils.InputPortLabel ); + m_labelStyle.clipping = TextClipping.Overflow; + m_labelStyle.imagePosition = ImagePosition.TextOnly; + m_labelStyle.contentOffset = new Vector2( -10, 0 ); + m_labelStyle.fontSize = ( int ) ( Constants.TextFieldFontSize ); + + m_nodeInfoLabelStyleBold = new GUIStyle( UIUtils.InputPortLabel ); + m_nodeInfoLabelStyleBold.fontStyle = FontStyle.Bold; + m_nodeInfoLabelStyleBold.fontSize = ( int ) ( Constants.TextFieldFontSize ); + + m_nodeInfoLabelStyle = new GUIStyle( UIUtils.InputPortLabel ); + m_nodeInfoLabelStyle.clipping = TextClipping.Clip; + m_nodeInfoLabelStyle.imagePosition = ImagePosition.TextOnly; + m_nodeInfoLabelStyle.fontSize = ( int ) ( Constants.TextFieldFontSize ); + + + m_nodeInfoFoldoutStyle = new GUIStyle( ( GUIStyle ) "foldout" ); + m_nodeInfoFoldoutStyle.fontStyle = FontStyle.Bold; + + if ( !EditorGUIUtility.isProSkin ) + { + m_labelStyleBold.normal.textColor = m_labelStyle.normal.textColor = Color.black; + m_nodeInfoLabelStyleBold.normal.textColor = m_labelStyle.normal.textColor = Color.black; + m_nodeInfoLabelStyle.normal.textColor = m_labelStyle.normal.textColor = Color.black; + } + + m_availableArea = new Rect( WindowPosX, WindowPosY, WindowSizeX - 2 * WindowPosX, WindowSizeY - 2 * WindowPosY ); + } + + void DrawPort( WirePortDataType type ) + { + EditorGUILayout.BeginHorizontal(); + { + GUI.color = UIUtils.GetColorForDataType( type, false ); + GUILayout.Box( string.Empty, m_portStyle, GUILayout.Width( UIUtils.PortsSize.x ), GUILayout.Height( UIUtils.PortsSize.y ) ); + GUI.color = Color.white; + EditorGUILayout.LabelField( UIUtils.GetNameForDataType( type ), m_labelStyle ); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.Separator(); + } + + void OnGUI() + { + if ( !UIUtils.Initialized || UIUtils.CurrentWindow == null ) + { + EditorGUILayout.LabelField( NoASEWindowWarning ); + return; + } + + if ( m_init ) + { + Init(); + } + + TitleLabelWidth = (int)(this.position.width * 0.42f); + + KeyCode key = Event.current.keyCode; + if ( key == ShortcutsManager.ScrollUpKey ) + { + m_currentScrollPos.y -= 10; + if ( m_currentScrollPos.y < 0 ) + { + m_currentScrollPos.y = 0; + } + Event.current.Use(); + } + + if ( key == ShortcutsManager.ScrollDownKey ) + { + m_currentScrollPos.y += 10; + Event.current.Use(); + } + + if ( Event.current.type == EventType.MouseDrag && Event.current.button > 0 ) + { + m_currentScrollPos.x += Constants.MenuDragSpeed * Event.current.delta.x; + if ( m_currentScrollPos.x < 0 ) + { + m_currentScrollPos.x = 0; + } + + m_currentScrollPos.y += Constants.MenuDragSpeed * Event.current.delta.y; + if ( m_currentScrollPos.y < 0 ) + { + m_currentScrollPos.y = 0; + } + } + + m_availableArea = new Rect( WindowPosX, WindowPosY, position.width - 2 * WindowPosX, position.height - 2 * WindowPosY ); + GUILayout.BeginArea( m_availableArea ); + { + if ( GUILayout.Button( "Wiki Page" ) ) + { + Application.OpenURL( Constants.HelpURL ); + } + + m_currentScrollPos = GUILayout.BeginScrollView( m_currentScrollPos ); + { + EditorGUILayout.BeginVertical(); + { + NodeUtils.DrawPropertyGroup( ref m_portAreaFoldout, PortLegendTitle, DrawPortInfo ); + float currLabelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 1; + NodeUtils.DrawPropertyGroup( ref m_editorShortcutAreaFoldout, EditorShortcutsTitle, DrawEditorShortcuts ); + NodeUtils.DrawPropertyGroup( ref m_menuShortcutAreaFoldout, MenuShortcutsTitle, DrawMenuShortcuts ); + NodeUtils.DrawPropertyGroup( ref m_nodesShortcutAreaFoldout, NodesShortcutsTitle, DrawNodesShortcuts ); + NodeUtils.DrawPropertyGroup( ref m_compatibleAssetsFoldout, CompatibleAssetsTitle, DrawCompatibleAssets ); + NodeUtils.DrawPropertyGroup( ref m_nodesDescriptionAreaFoldout, NodesDescTitle, DrawNodeDescriptions ); + EditorGUIUtility.labelWidth = currLabelWidth; + } + EditorGUILayout.EndVertical(); + } + GUILayout.EndScrollView(); + } + GUILayout.EndArea(); + + } + + void DrawPortInfo() + { + Color originalColor = GUI.color; + + DrawPort( WirePortDataType.OBJECT ); + DrawPort( WirePortDataType.INT ); + DrawPort( WirePortDataType.FLOAT ); + DrawPort( WirePortDataType.FLOAT2 ); + DrawPort( WirePortDataType.FLOAT3 ); + DrawPort( WirePortDataType.FLOAT4 ); + DrawPort( WirePortDataType.COLOR ); + DrawPort( WirePortDataType.SAMPLER2D ); + DrawPort( WirePortDataType.FLOAT3x3 ); + DrawPort( WirePortDataType.FLOAT4x4 ); + + EditorGUILayout.BeginHorizontal(); + { + GUI.color = Constants.LockedPortColor; + GUILayout.Box( string.Empty, m_portStyle, GUILayout.Width( UIUtils.PortsSize.x ), GUILayout.Height( UIUtils.PortsSize.y ) ); + GUI.color = Color.white; + EditorGUILayout.LabelField( m_lockedStr, m_labelStyle ); + } + EditorGUILayout.EndHorizontal(); + + GUI.color = originalColor; + } + + public void DrawEditorShortcuts() + { + AmplifyShaderEditorWindow window = UIUtils.CurrentWindow; + if ( window != null ) + { + if ( m_editorShortcuts == null ) + { + m_editorShortcuts = window.ShortcutManagerInstance.AvailableEditorShortcutsList; + } + + EditorGUI.indentLevel--; + int count = m_editorShortcuts.Count; + for ( int i = 0; i < count; i++ ) + { + DrawItem( m_editorShortcuts[ i ].Name, m_editorShortcuts[ i ].Description ); + } + DrawItem( "Q", "Alternative Pan modifier" ); + DrawItem( "Ctrl + F", "Find nodes" ); + DrawItem( "LMB Drag", "Box selection" ); + DrawItem( "MMB/RMB Drag", "Camera pan" ); + DrawItem( "Alt + MMB/RMB Drag", "Zoom graph" ); + DrawItem( "Shift/Ctrl + Node Select", "Add/Remove from selection" ); + DrawItem( "Shift + Node Drag", "Node move with offset" ); + DrawItem( "Ctrl + Node Drag", "Node move with snap" ); + DrawItem( "MMB/RMB + Drag Panel", "Scroll panel" ); + DrawItem( "Alt + LMB Drag", "Additive box selection" ); + DrawItem( "Alt + Shift + Drag", "Subtractive box selection" ); + DrawItem( "Alt + Node Drag", "Auto-(Dis)Connect node on existing wire connection" ); + EditorGUI.indentLevel++; + + } + else + { + EditorGUILayout.LabelField( NoASEWindowWarning ); + } + } + + public void DrawMenuShortcuts() + { + AmplifyShaderEditorWindow window = UIUtils.CurrentWindow; + if ( window != null ) + { + EditorGUI.indentLevel--; + DrawItem( ShortcutsManager.ScrollUpKey.ToString(), "Scroll Up Menu" ); + DrawItem( ShortcutsManager.ScrollDownKey.ToString(), "Scroll Down Menu" ); + DrawItem( "RMB Drag", "Scroll Menu" ); + EditorGUI.indentLevel++; + } + else + { + EditorGUILayout.LabelField( NoASEWindowWarning ); + } + } + + void DrawItem( string name, string description ) + { + GUILayout.BeginHorizontal(); + GUILayout.Label( name, m_labelStyleBold , GUILayout.Width( TitleLabelWidth ) ); + GUILayout.Label( description, m_labelStyle ); + GUILayout.EndHorizontal(); + GUILayout.Space( PixelSeparator ); + } + + public void DrawNodesShortcuts() + { + AmplifyShaderEditorWindow window = UIUtils.CurrentWindow; + if ( window != null ) + { + if ( m_nodesShortcuts == null || m_nodesShortcuts.Count == 0 ) + { + m_nodesShortcuts = window.ShortcutManagerInstance.AvailableNodesShortcutsList; + } + + EditorGUI.indentLevel--; + int count = m_nodesShortcuts.Count; + for ( int i = 0; i < count; i++ ) + { + DrawItem( m_nodesShortcuts[ i ].Name, m_nodesShortcuts[ i ].Description ); + } + EditorGUI.indentLevel++; + } + else + { + EditorGUILayout.LabelField( NoASEWindowWarning ); + } + } + string CreateCompatibilityString( string source ) + { + string[] split = source.Split( '.' ); + if ( split != null && split.Length > 1 ) + { + return split[ 1 ]; + } + else + { + return source; + } + } + public void DrawCompatibleAssets() + { + AmplifyShaderEditorWindow window = UIUtils.CurrentWindow; + if ( window != null ) + { + if ( m_compatibleAssetsInfo == null ) + { + m_compatibleAssetsInfo = new List(); + List items = window.ContextMenuInstance.MenuItems; + int count = items.Count; + for ( int i = 0; i < count; i++ ) + { + if ( items[ i ].NodeAttributes != null && items[ i ].NodeAttributes.CastType != null ) + { + string types = string.Empty; + if ( items[ i ].NodeAttributes.CastType.Length > 1 ) + { + for ( int j = 0; j < items[ i ].NodeAttributes.CastType.Length; j++ ) + { + types += CreateCompatibilityString( items[ i ].NodeAttributes.CastType[ j ].ToString() ); + + + if ( j < items[ i ].NodeAttributes.CastType.Length - 1 ) + { + types += ", "; + } + } + } + else + { + types = CreateCompatibilityString( items[ i ].NodeAttributes.CastType[ 0 ].ToString() ); + } + m_compatibleAssetsInfo.Add( new string[] { items[ i ].NodeAttributes.Name + ": ", types } ); + } + } + } + EditorGUI.indentLevel--; + int nodeCount = m_compatibleAssetsInfo.Count; + for ( int j = 0; j < nodeCount; j++ ) + { + DrawItem( m_compatibleAssetsInfo[ j ][ 0 ], m_compatibleAssetsInfo[ j ][ 1 ] ); + } + EditorGUI.indentLevel++; + } + else + { + EditorGUILayout.LabelField( NoASEWindowWarning ); + } + } + + public void DrawNodeDescriptions() + { + AmplifyShaderEditorWindow window = UIUtils.CurrentWindow; + if ( window != null ) + { + if ( m_nodeDescriptionsInfo == null ) + { + //fetch node info + m_nodeDescriptionsInfo = new List(); + Dictionary nodeData = window.CurrentPaletteWindow.BuildFullList(); + var enumerator = nodeData.GetEnumerator(); + while ( enumerator.MoveNext() ) + { + List nodes = enumerator.Current.Value.Contents; + int count = nodes.Count; + + NodeDescriptionInfo currInfo = new NodeDescriptionInfo(); + currInfo.Contents = new string[ count, 2 ]; + currInfo.Category = enumerator.Current.Key; + + for ( int i = 0; i < count; i++ ) + { + currInfo.Contents[ i, 0 ] = nodes[ i ].Name + ':'; + currInfo.Contents[ i, 1 ] = nodes[ i ].Description; + } + m_nodeDescriptionsInfo.Add( currInfo ); + } + } + + //draw + { + GUILayout.Space( 5 ); + int count = m_nodeDescriptionsInfo.Count; + EditorGUI.indentLevel--; + for ( int i = 0; i < count; i++ ) + { + m_nodeDescriptionsInfo[ i ].FoldoutValue = EditorGUILayout.Foldout( m_nodeDescriptionsInfo[ i ].FoldoutValue, m_nodeDescriptionsInfo[ i ].Category, m_nodeInfoFoldoutStyle ); + if ( m_nodeDescriptionsInfo[ i ].FoldoutValue ) + { + EditorGUI.indentLevel++; + int nodeCount = m_nodeDescriptionsInfo[ i ].Contents.GetLength( 0 ); + for ( int j = 0; j < nodeCount; j++ ) + { + GUILayout.Label( m_nodeDescriptionsInfo[ i ].Contents[ j, 0 ], m_nodeInfoLabelStyleBold ); + GUILayout.Label( m_nodeDescriptionsInfo[ i ].Contents[ j, 1 ], m_nodeInfoLabelStyle ); + GUILayout.Space( PixelSeparator ); + } + EditorGUI.indentLevel--; + } + GUILayout.Space( PixelSeparator ); + } + EditorGUI.indentLevel++; + } + } + else + { + EditorGUILayout.LabelField( NoASEWindowWarning ); + } + } + + private void OnDestroy() + { + m_nodesShortcuts = null; + m_editorShortcuts = null; + m_portStyle = null; + m_labelStyle = null; + m_labelStyleBold = null; + m_nodeInfoLabelStyle = null; + m_nodeInfoLabelStyleBold = null; + m_nodeInfoFoldoutStyle = null; + m_init = false; + + if ( m_nodeDescriptionsInfo != null ) + { + m_nodeDescriptionsInfo.Clear(); + m_nodeDescriptionsInfo = null; + } + + if( m_compatibleAssetsInfo != null ) + { + m_compatibleAssetsInfo.Clear(); + m_compatibleAssetsInfo = null; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/PortLegendInfo.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/PortLegendInfo.cs.meta new file mode 100644 index 0000000..42646fc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/PortLegendInfo.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 20dad8f4196f0e643a9c56d1202e74dc +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/SceneSaveCallback.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/SceneSaveCallback.cs new file mode 100644 index 0000000..7b4e51d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/SceneSaveCallback.cs @@ -0,0 +1,40 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + // Catch when scene is saved (Ctr+S) and also save ase shader + public class SceneSaveCallback : UnityEditor.AssetModificationProcessor + { + private const string UnityStr = ".unity"; + + static string[] OnWillSaveAssets( string[] paths ) + { + if( !Preferences.GlobalUpdateOnSceneSave ) + return paths; + + bool canSave = false; + + if ( paths.Length == 0 ) + { + canSave = true; + } + else + { + for ( int i = 0; i < paths.Length; i++ ) + { + // Only save shader when saving scenes + if ( !string.IsNullOrEmpty( paths[ i ] ) && paths[ i ].Contains( UnityStr ) ) + { + canSave = true; + break; + } + } + } + if ( canSave && UIUtils.CurrentWindow ) + UIUtils.CurrentWindow.SetCtrlSCallback( false ); + + return paths; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/SceneSaveCallback.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/SceneSaveCallback.cs.meta new file mode 100644 index 0000000..a91c39b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/SceneSaveCallback.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 708e90c98affcb04aa2fcfedf4329a7c +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderEditorModeWindow.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderEditorModeWindow.cs new file mode 100644 index 0000000..6a987d4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderEditorModeWindow.cs @@ -0,0 +1,192 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public sealed class ShaderEditorModeWindow : MenuParent + { + private static readonly Color OverallColorOn = new Color( 1f, 1f, 1f, 0.9f ); + private static readonly Color OverallColorOff = new Color( 1f, 1f, 1f, 0.3f ); + private static readonly Color FontColorOff = new Color( 1f, 1f, 1f, 0.4f ); + private const float DeltaY = 15; + private const float DeltaX = 10; + + private const float CollSizeX = 180; + private const float CollSizeY = 70; + + //private static string MatFormat = "MATERIAL\n{0}"; + //private static string ShaderFormat = "SHADER\n{0}"; + //private const string CurrMatStr = "MATERIAL"; + //private const string CurrShaderStr = "SHADER"; + + private const string NoMaterialStr = "No Material"; + private const string NoShaderStr = "No Shader"; + + private bool m_init = true; + private string m_previousShaderName = string.Empty; + private string m_previousMaterialName = string.Empty; + private string m_previousShaderFunctionName = string.Empty; + + private Vector2 m_auxVector2; + private GUIContent m_leftAuxContent = new GUIContent(); + private GUIContent m_rightAuxContent = new GUIContent(); + private GUIStyle m_leftButtonStyle = null; + private GUIStyle m_rightButtonStyle = null; + private Rect m_leftButtonRect; + private Rect m_rightButtonRect; + + public ShaderEditorModeWindow( AmplifyShaderEditorWindow parentWindow ) : base( parentWindow, 0, 0, 0, 0, "ShaderEditorModeWindow", MenuAnchor.BOTTOM_CENTER, MenuAutoSize.NONE ) { } + + public void ConfigStyle( GUIStyle style ) + { + style.normal.textColor = FontColorOff; + style.hover.textColor = FontColorOff; + style.active.textColor = FontColorOff; + style.focused.textColor = FontColorOff; + + style.onNormal.textColor = FontColorOff; + style.onHover.textColor = FontColorOff; + style.onActive.textColor = FontColorOff; + style.onFocused.textColor = FontColorOff; + } + + + public void Draw( Rect graphArea, Vector2 mousePos, Shader currentShader, Material currentMaterial, float usableArea, float leftPos, float rightPos /*, bool showLastSelection*/ ) + { + EventType currentEventType = Event.current.type; + + if( !( currentEventType == EventType.Repaint || currentEventType == EventType.MouseDown || currentEventType == EventType.MouseMove ) ) + return; + + if ( m_init ) + { + m_init = false; + GUIStyle shaderModeTitle = UIUtils.GetCustomStyle( CustomStyle.ShaderModeTitle ); + GUIStyle shaderModeNoShader = UIUtils.GetCustomStyle( CustomStyle.ShaderModeNoShader ); + GUIStyle materialModeTitle = UIUtils.GetCustomStyle( CustomStyle.MaterialModeTitle ); + GUIStyle shaderNoMaterialModeTitle = UIUtils.GetCustomStyle( CustomStyle.ShaderNoMaterialModeTitle ); + + ConfigStyle( shaderModeTitle ); + ConfigStyle( shaderModeNoShader ); + ConfigStyle( materialModeTitle ); + ConfigStyle( shaderNoMaterialModeTitle ); + } + Color buffereredColor = GUI.color; + + MasterNode currentMasterNode = ParentWindow.CurrentGraph.CurrentMasterNode; + // Shader Mode + if ( currentMasterNode != null ) + { + m_leftButtonStyle = UIUtils.GetCustomStyle( currentShader == null ? CustomStyle.ShaderModeNoShader : CustomStyle.ShaderModeTitle ); + m_leftButtonRect = graphArea; + m_leftButtonRect.x = 10 + leftPos; + m_leftButtonRect.y += m_leftButtonRect.height - 38 - 15; + string shaderName = ( currentShader != null ) ? ( currentShader.name ) : NoShaderStr; + + if ( m_previousShaderName != shaderName ) + { + m_previousShaderName = shaderName; + m_leftAuxContent.text = "SHADER\n" + shaderName; + } + + m_auxVector2 = m_leftButtonStyle.CalcSize( m_leftAuxContent ); + m_leftButtonRect.width = m_auxVector2.x + 30 + 4; + m_leftButtonRect.height = 38; + + bool mouseOnTop = m_leftButtonRect.Contains( mousePos ); + GUI.color = mouseOnTop ? OverallColorOn : OverallColorOff; + GUI.Label( m_leftButtonRect, m_leftAuxContent, m_leftButtonStyle ); + + if( currentEventType == EventType.MouseMove && mouseOnTop ) + m_parentWindow.MarkToRepaint(); + + if ( currentEventType == EventType.MouseDown && mouseOnTop && currentShader != null ) + { + Event.current.Use(); + Selection.activeObject = currentShader; + EditorGUIUtility.PingObject( Selection.activeObject ); + } + + // Material Mode + if ( currentMaterial != null ) + { + m_rightButtonStyle = UIUtils.GetCustomStyle( CustomStyle.MaterialModeTitle ); + m_rightButtonRect = graphArea; + string matName = ( currentMaterial != null ) ? ( currentMaterial.name ) : NoMaterialStr; + + if ( m_previousMaterialName != matName ) + { + m_previousMaterialName = matName; + m_rightAuxContent.text = "MATERIAL\n" + matName; + } + + m_auxVector2 = m_rightButtonStyle.CalcSize( m_rightAuxContent ); + m_rightButtonRect.width = m_auxVector2.x + 30 + 4; + m_rightButtonRect.height = 38; + + m_rightButtonRect.x = graphArea.xMax - m_rightButtonRect.width - rightPos - 10; + m_rightButtonRect.y = graphArea.yMax - 38 - 15; + + bool mouseOnTopRight = m_rightButtonRect.Contains( mousePos ); + GUI.color = mouseOnTopRight ? OverallColorOn : OverallColorOff; + GUI.Label( m_rightButtonRect, m_rightAuxContent, m_rightButtonStyle ); + + if( currentEventType == EventType.MouseMove && mouseOnTopRight ) + m_parentWindow.MarkToRepaint(); + + if ( currentEventType == EventType.MouseDown && mouseOnTopRight ) + { + Event.current.Use(); + Selection.activeObject = currentMaterial; + EditorGUIUtility.PingObject( Selection.activeObject ); + } + } + } + + // Shader Function + else if ( currentMasterNode == null && ParentWindow.CurrentGraph.CurrentOutputNode != null ) + { + m_leftButtonStyle = UIUtils.GetCustomStyle( CustomStyle.ShaderFunctionMode ); + m_leftButtonRect = graphArea; + m_leftButtonRect.x = 10 + leftPos; + m_leftButtonRect.y += m_leftButtonRect.height - 38 - 15; + string functionName = ( ParentWindow.CurrentGraph.CurrentShaderFunction != null ) ? ( ParentWindow.CurrentGraph.CurrentShaderFunction.name ) : "No Shader Function"; + + if ( m_previousShaderFunctionName != functionName ) + { + m_previousShaderFunctionName = functionName; + m_leftAuxContent.text = "SHADER FUNCTION\n" + functionName; + } + + m_auxVector2 = m_leftButtonStyle.CalcSize( m_leftAuxContent ); + m_leftButtonRect.width = m_auxVector2.x + 30 + 4; + m_leftButtonRect.height = 38; + + bool mouseOnTop = m_leftButtonRect.Contains( mousePos ); + GUI.color = mouseOnTop ? OverallColorOn : OverallColorOff; + GUI.Label( m_leftButtonRect, m_leftAuxContent, m_leftButtonStyle ); + + if ( currentEventType == EventType.MouseDown && mouseOnTop && ParentWindow.CurrentGraph.CurrentShaderFunction != null ) + { + Event.current.Use(); + Selection.activeObject = ParentWindow.CurrentGraph.CurrentShaderFunction; + EditorGUIUtility.PingObject( Selection.activeObject ); + } + } + + GUI.color = buffereredColor; + } + + public override void Destroy() + { + base.Destroy(); + m_leftAuxContent = null; + m_rightAuxContent = null; + m_leftButtonStyle = null; + m_rightButtonStyle = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderEditorModeWindow.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderEditorModeWindow.cs.meta new file mode 100644 index 0000000..5f0a8f6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderEditorModeWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 672d96e3a4f68d44f9456d2fc53d4d73 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderLibrary.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderLibrary.cs new file mode 100644 index 0000000..e405e2e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderLibrary.cs @@ -0,0 +1,91 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEditor; +using System.Collections.Generic; +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class ShaderLibrary : EditorWindow + { + private const string SHADER_LIB_FILE = "/AmplifyShaderEditor/Resources/ShaderLibrary/ShaderLibrary.txt"; + private bool m_init = false; + private Vector2 m_scrollPos = new Vector2(); + [SerializeField] + private List m_shaders = new List(); + void Init() + { + m_init = true; + string list = IOUtils.LoadTextFileFromDisk( Application.dataPath + SHADER_LIB_FILE ); + if ( String.IsNullOrEmpty( list ) ) + return; + + string[] listArr = list.Split( IOUtils.FIELD_SEPARATOR ); + for ( int i = 0; i < listArr.Length; i++ ) + { + m_shaders.Add( listArr[ i ] ); + } + + UIUtils.MainSkin.customStyles[ 10 ].active.background = Texture2D.whiteTexture; + + UIUtils.MainSkin.customStyles[ 6 ].fixedHeight = UIUtils.MainSkin.customStyles[ 6 ].normal.background.height; + UIUtils.MainSkin.customStyles[ 6 ].fixedWidth = UIUtils.MainSkin.customStyles[ 6 ].normal.background.width; + + UIUtils.MainSkin.customStyles[ 7 ].fixedHeight = UIUtils.MainSkin.customStyles[ 7 ].normal.background.height; + UIUtils.MainSkin.customStyles[ 7 ].fixedWidth = UIUtils.MainSkin.customStyles[ 7 ].normal.background.width; + + UIUtils.MainSkin.customStyles[ 8 ].fixedHeight = UIUtils.MainSkin.customStyles[ 8 ].normal.background.height; + UIUtils.MainSkin.customStyles[ 8 ].fixedWidth = UIUtils.MainSkin.customStyles[ 8 ].normal.background.width; + + UIUtils.MainSkin.customStyles[ 9 ].fixedHeight = UIUtils.MainSkin.customStyles[ 9 ].normal.background.height; + UIUtils.MainSkin.customStyles[ 9 ].fixedWidth = UIUtils.MainSkin.customStyles[ 9 ].normal.background.width; + + } + + void OnGUI() + { + if ( !m_init ) + { + Init(); + } + + Rect availableArea = position; + + availableArea.y = 100f; + availableArea.x = 0.05f * availableArea.width; + availableArea.height *= 0.5f; + availableArea.width *= 0.9f; + EditorGUILayout.BeginVertical(); + { + EditorGUILayout.LabelField( "Shader Library", UIUtils.MainSkin.customStyles[ 5 ] ); + GUILayout.Space( 10 ); + EditorGUILayout.BeginHorizontal(); + { + GUILayout.Space( 0.05f * position.width ); + GUILayout.Button( string.Empty, UIUtils.MainSkin.customStyles[ 8 ] ); + GUILayout.Button( string.Empty, UIUtils.MainSkin.customStyles[ 9 ] ); + GUILayout.Space( 0.8f*position.width ); + GUILayout.Button( string.Empty, UIUtils.MainSkin.customStyles[ 7 ] ); + GUILayout.Button( string.Empty, UIUtils.MainSkin.customStyles[ 6 ] ); + } + EditorGUILayout.EndHorizontal(); + + GUILayout.BeginArea( availableArea ); + m_scrollPos = EditorGUILayout.BeginScrollView( m_scrollPos, UIUtils.MainSkin.box ); + { + for ( int i = 0; i < m_shaders.Count; i++ ) + { + GUILayout.Button( m_shaders[ i ], UIUtils.MainSkin.customStyles[ 10 ] ); + } + } + EditorGUILayout.EndScrollView(); + GUILayout.EndArea(); + } + EditorGUILayout.EndVertical(); + + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderLibrary.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderLibrary.cs.meta new file mode 100644 index 0000000..9a6c519 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/ShaderLibrary.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cbdd03f297692584391b9dc0625a80ed +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools.meta new file mode 100644 index 0000000..4f19188 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3857a2f02c659104fa6f0fe94cfe00dd +folderAsset: yes +timeCreated: 1481126945 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButton.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButton.cs new file mode 100644 index 0000000..a199463 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButton.cs @@ -0,0 +1,249 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public sealed class ToolsMenuButton : ToolsMenuButtonParent + { + public delegate void ToolButtonPressed( ToolButtonType type ); + public event ToolButtonPressed ToolButtonPressedEvt; + + private Rect m_buttonArea; + private List m_buttonTexture; + private string m_buttonTexturePath; + private ToolButtonType m_buttonType; + private GUIStyle m_style; + private bool m_enabled = true; + private bool m_drawOnFunction = true; + + private List m_cachedStates; + private int m_bufferedState = -1; + private string m_bufferedTooltip = string.Empty; + + public ToolsMenuButton( AmplifyShaderEditorWindow parentWindow, ToolButtonType type, float x, float y, float width, float height, string texturePath, string text, string tooltip, float buttonSpacing = -1, bool drawOnFunction = true ) : base( parentWindow, text, tooltip, buttonSpacing ) + { + m_buttonArea = new Rect( x, y, width, height ); + m_buttonType = type; + + m_buttonTexturePath = texturePath; + m_cachedStates = new List(); + m_drawOnFunction = drawOnFunction; + } + + public void AddState( string state ) + { + m_cachedStates.Add( state ); + } + + public override void Destroy() + { + ToolButtonPressedEvt = null; + if ( m_buttonTexture != null ) + { + for ( int i = 0; i < m_buttonTexture.Count; i++ ) + { + Resources.UnloadAsset( m_buttonTexture[ i ] ); + } + m_buttonTexture.Clear(); + } + m_buttonTexture = null; + } + protected override void Init() + { + base.Init(); + if ( m_buttonTexture == null ) + { + m_buttonTexturePath = AssetDatabase.GUIDToAssetPath( m_buttonTexturePath ); + m_buttonTexture = new List(); + m_buttonTexture.Add( AssetDatabase.LoadAssetAtPath( m_buttonTexturePath, typeof( Texture2D ) ) as Texture2D ); + } + + if ( m_cachedStates.Count > 0 ) + { + for ( int i = 0; i < m_cachedStates.Count; i++ ) + { + m_cachedStates[ i ] = AssetDatabase.GUIDToAssetPath( m_cachedStates[ i ] ); + m_buttonTexture.Add( AssetDatabase.LoadAssetAtPath( m_cachedStates[ i ], typeof( Texture2D ) ) as Texture2D ); + } + m_cachedStates.Clear(); + } + + if ( m_style == null ) + { + m_style = new GUIStyle( /*UIUtils.Button*/ GUIStyle.none ); + m_style.normal.background = m_buttonTexture[ 0 ]; + + m_style.hover.background = m_buttonTexture[ 0 ]; + m_style.hover.textColor = m_style.normal.textColor; + + m_style.active.background = m_buttonTexture[ 0 ]; + m_style.active.textColor = m_style.normal.textColor; + + m_style.onNormal.background = m_buttonTexture[ 0 ]; + m_style.onNormal.textColor = m_style.normal.textColor; + + m_style.onHover.background = m_buttonTexture[ 0 ]; + m_style.onHover.textColor = m_style.normal.textColor; + + m_style.onActive.background = m_buttonTexture[ 0 ]; + m_style.onActive.textColor = m_style.normal.textColor; + + m_style.clipping = TextClipping.Overflow; + m_style.fontStyle = FontStyle.Bold; + m_style.alignment = TextAnchor.LowerCenter; + m_style.contentOffset = new Vector2( 0, 15 ); + m_style.fontSize = 10; + bool resizeFromTexture = false; + if ( m_buttonArea.width > 0 ) + { + m_style.fixedWidth = m_buttonArea.width; + } + else + { + resizeFromTexture = true; + } + + if ( m_buttonArea.height > 0 ) + { + m_style.fixedHeight = m_buttonArea.height; + } + else + { + resizeFromTexture = true; + } + + if ( resizeFromTexture ) + { + m_buttonArea.width = m_style.fixedWidth = m_buttonTexture[ 0 ].width; + m_buttonArea.height = m_style.fixedHeight = m_buttonTexture[ 0 ].height; + } + } + + } + public override void Draw() + { + base.Draw(); + bool guiEnabledBuffer = GUI.enabled; + GUI.enabled = m_enabled; + + if ( GUILayout.Button( m_content, m_style ) && ToolButtonPressedEvt != null ) + { + ToolButtonPressedEvt( m_buttonType ); + } + GUI.enabled = guiEnabledBuffer; + } + + public override void Draw( float x, float y ) + { + if ( !(m_parentWindow.CameraDrawInfo.CurrentEventType == EventType.MouseDown || m_parentWindow.CameraDrawInfo.CurrentEventType == EventType.Repaint ) ) + return; + + if ( m_parentWindow.CurrentGraph.CurrentMasterNode == null && !m_drawOnFunction) + return; + + + base.Draw( x, y ); + + if ( m_bufferedState > -1 ) + { + if ( string.IsNullOrEmpty( m_bufferedTooltip ) ) + { + SetStateOnButton( m_bufferedState ); + } + else + { + SetStateOnButton( m_bufferedState, m_bufferedTooltip ); + } + + m_bufferedState = -1; + m_bufferedTooltip = string.Empty; + } + + + m_buttonArea.x = x; + m_buttonArea.y = y; + + if ( m_parentWindow.CameraDrawInfo.CurrentEventType == EventType.MouseDown && m_buttonArea.Contains( m_parentWindow.CameraDrawInfo.MousePosition ) && ToolButtonPressedEvt != null ) + { + ToolButtonPressedEvt( m_buttonType ); + Event.current.Use(); + m_parentWindow.CameraDrawInfo.CurrentEventType = EventType.Used; + } + else if ( m_parentWindow.CameraDrawInfo.CurrentEventType == EventType.Repaint ) + { + GUI.Label( m_buttonArea, m_content, m_style ); + } + + //if ( GUI.Button( m_buttonArea, m_content, m_style ) && ToolButtonPressedEvt != null ) + //{ + // ToolButtonPressedEvt( m_buttonType ); + //} + } + + public override void Draw( Vector2 pos ) + { + Draw( pos.x, pos.y ); + } + + public override void SetStateOnButton( int state, string tooltip ) + { + + if ( m_buttonTexture == null || m_style == null ) + { + m_bufferedState = state; + m_bufferedTooltip = tooltip; + return; + } + + + if ( state < 0 || state >= m_buttonTexture.Count ) + { + return; + } + + base.SetStateOnButton( state, tooltip ); + m_style.normal.background = m_buttonTexture[ state ]; + m_style.hover.background = m_buttonTexture[ state ]; + m_style.active.background = m_buttonTexture[ state ]; + m_style.onNormal.background = m_buttonTexture[ state ]; + m_style.onHover.background = m_buttonTexture[ state ]; + m_style.onActive.background = m_buttonTexture[ state ]; + } + + public override void SetStateOnButton( int state ) + { + if ( m_buttonTexture == null || m_style == null ) + { + m_bufferedState = state; + return; + } + + if ( state < 0 || state >= m_buttonTexture.Count ) + { + return; + } + base.SetStateOnButton( state ); + m_style.normal.background = m_buttonTexture[ state ]; + m_style.hover.background = m_buttonTexture[ state ]; + m_style.active.background = m_buttonTexture[ state ]; + m_style.onNormal.background = m_buttonTexture[ state ]; + m_style.onHover.background = m_buttonTexture[ state ]; + m_style.onActive.background = m_buttonTexture[ state ]; + } + + public bool IsInside( Vector2 pos ) + { + return m_buttonArea.Contains( pos ); + } + + public bool Enabled + { + get { return m_enabled; } + set { m_enabled = value; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButton.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButton.cs.meta new file mode 100644 index 0000000..11180c8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButton.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 890f4ed5c9f62af43bda6584705fa0be +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonParent.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonParent.cs new file mode 100644 index 0000000..b3136b4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonParent.cs @@ -0,0 +1,75 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public class ToolsMenuButtonParent + { + protected AmplifyShaderEditorWindow m_parentWindow = null; + private float m_buttonSpacing = 10; + private int m_currentState = 0; + private bool m_isInitialized = false; + protected GUIContent m_content; + public ToolsMenuButtonParent( AmplifyShaderEditorWindow parentWindow, string text, string tooltip, float buttonSpacing ) + { + m_parentWindow = parentWindow; + m_content = new GUIContent( text, tooltip ); + + if ( buttonSpacing > 0 ) + m_buttonSpacing = buttonSpacing; + } + + public virtual void Draw() + { + if ( !m_isInitialized ) + { + Init(); + } + + //GUILayout.Space( m_buttonSpacing ); + } + + public virtual void Draw( Vector2 pos ) + { + Draw( pos.x, pos.y ); + } + + public virtual void Draw( float x ,float y ) + { + if ( !m_isInitialized ) + { + Init(); + } + } + + protected virtual void Init() + { + m_isInitialized = false; + } + + public virtual void SetStateOnButton( int state, string tooltip ) + { + m_currentState = state; + m_content.tooltip = tooltip; + } + + public virtual void SetStateOnButton( int state ) + { + m_currentState = state; + } + + public virtual void Destroy() { } + + public float ButtonSpacing + { + get { return m_buttonSpacing; } + } + + public int CurrentState + { + get { return m_currentState; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonParent.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonParent.cs.meta new file mode 100644 index 0000000..b14de18 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonParent.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a3bf3644c2c2fbb4fa0dd8b86effc6e1 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonSep.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonSep.cs new file mode 100644 index 0000000..69d11eb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonSep.cs @@ -0,0 +1,41 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public sealed class ToolsMenuButtonSep : ToolsMenuButtonParent + { + private Color m_splitterColor = EditorGUIUtility.isProSkin ? new Color( 0.157f, 0.157f, 0.157f ) : new Color( 0.5f, 0.5f, 0.5f ); + [SerializeField] + private GUIStyle m_sepStyle; + public ToolsMenuButtonSep( AmplifyShaderEditorWindow parentWindow = null, string text = null, string tooltip = null, float buttonSpacing = -1 ) : base( parentWindow, text, tooltip, buttonSpacing ) { } + + public override void Draw() + { + base.Draw(); + if ( m_sepStyle == null ) + { + m_sepStyle = new GUIStyle(); + m_sepStyle.normal.background = Texture2D.whiteTexture; + m_sepStyle.hover.background = Texture2D.whiteTexture; + m_sepStyle.active.background = Texture2D.whiteTexture; + m_sepStyle.onNormal.background = Texture2D.whiteTexture; + m_sepStyle.onHover.background = Texture2D.whiteTexture; + m_sepStyle.onActive.background = Texture2D.whiteTexture; + m_sepStyle.stretchHeight = true; + } + Color originalColor = GUI.color; + GUI.color = m_splitterColor; + GUILayout.Box( string.Empty, m_sepStyle, GUILayout.MaxWidth( 2 ), GUILayout.ExpandHeight( true ) ); + GUI.color = originalColor; + } + + public override void Destroy() + { + m_sepStyle = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonSep.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonSep.cs.meta new file mode 100644 index 0000000..5567293 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsMenuButtonSep.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b4c65a9d96791c34eb587cea9662161f +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsWindow.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsWindow.cs new file mode 100644 index 0000000..ccb0f4b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsWindow.cs @@ -0,0 +1,632 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public enum ToolButtonType + { + Update = 0, + Live, + OpenSourceCode, + CleanUnusedNodes, + //SelectShader, + New, + Open, + Save, + Library, + Options, + Help, + MasterNode, + FocusOnMasterNode, + FocusOnSelection, + ShowInfoWindow, + ShowTipsWindow, + ShowConsole, + TakeScreenshot, + Share + } + + public enum ToolbarType + { + File, + Help + } + + public class ToolbarMenuTab + { + private Rect m_tabArea; + private GenericMenu m_tabMenu; + public ToolbarMenuTab( float x, float y, float width, float height ) + { + m_tabMenu = new GenericMenu(); + m_tabArea = new Rect( x, y, width, height ); + } + + public void ShowMenu() + { + m_tabMenu.DropDown( m_tabArea ); + } + + public void AddItem( string itemName, GenericMenu.MenuFunction callback ) + { + m_tabMenu.AddItem( new GUIContent( itemName ), false, callback ); + } + } + + [Serializable] + public sealed class ToolsWindow : MenuParent + { + private static readonly Color RightIconsColorOff = new Color( 1f, 1f, 1f, 0.8f ); + private static readonly Color LeftIconsColorOff = new Color( 1f, 1f, 1f, 0.5f ); + + private static readonly Color RightIconsColorOn = new Color( 1f, 1f, 1f, 1.0f ); + private static readonly Color LeftIconsColorOn = new Color( 1f, 1f, 1f, 0.8f ); + + private const float TabY = 9; + private const float TabX = 5; + private const string ShaderFileTitleStr = "Current Shader"; + private const string FileToolbarStr = "File"; + private const string HelpToolbarStr = "Help"; + private const string LiveShaderStr = "Live Shader"; + private const string LoadOnSelectionStr = "Load on selection"; + private const string CurrentObjectStr = "Current Object: "; + + + public ToolsMenuButton.ToolButtonPressed ToolButtonPressedEvt; + //private GUIStyle m_toolbarButtonStyle; + private GUIStyle m_toggleStyle; + private GUIStyle m_borderStyle; + + // left + private ToolsMenuButton m_updateButton; + private ToolsMenuButton m_liveButton; + private ToolsMenuButton m_openSourceCodeButton; + + //middle right + private ToolsMenuButton m_cleanUnusedNodesButton; + private ToolsMenuButton m_focusOnMasterNodeButton; + private ToolsMenuButton m_focusOnSelectionButton; + + // right + private ToolsMenuButton m_shareButton; + private ToolsMenuButton m_takeScreenshotButton; + private ToolsMenuButton m_showInfoWindowButton; + + // hidden + private ToolsMenuButton m_showTipsWindowButton; + private ToolsMenuButton m_showConsoleWindowButton; + + //Used for collision detection to invalidate inputs on graph area + private Rect m_areaLeft = new Rect( 0, 0, 140, 40 ); + private Rect m_areaRight = new Rect( 0, 0, 75, 40 ); + private Rect m_boxRect; + private Rect m_borderRect; + + public const double InactivityRefreshTime = 0.25; + private int m_currentSelected = 0; + + //Search Bar + private const string SearchBarId = "ASE_SEARCH_BAR"; + private bool m_searchBarVisible = false; + private bool m_selectSearchBarTextfield = false; + private bool m_refreshSearchResultList = false; + + private Rect m_searchBarSize; + private string m_searchBarValue = string.Empty; + private List m_searchResultNodes = new List(); + + // width and height are between [0,1] and represent a percentage of the total screen area + public ToolsWindow( AmplifyShaderEditorWindow parentWindow ) : base( parentWindow, 0, 0, 0, 64, "Tools", MenuAnchor.TOP_LEFT, MenuAutoSize.NONE ) + { + m_updateButton = new ToolsMenuButton( m_parentWindow, ToolButtonType.Update, 0, 0, -1, -1, IOUtils.UpdateOutdatedGUID, string.Empty, "Create and apply shader to material.", 5 ); + m_updateButton.ToolButtonPressedEvt += OnButtonPressedEvent; + m_updateButton.AddState( IOUtils.UpdateOFFGUID ); + m_updateButton.AddState( IOUtils.UpdateUpToDatedGUID ); + + m_liveButton = new ToolsMenuButton( m_parentWindow, ToolButtonType.Live, 0, 0, -1, -1, IOUtils.LiveOffGUID, string.Empty, "Automatically saves shader when canvas is changed.", 50 ); + m_liveButton.ToolButtonPressedEvt += OnButtonPressedEvent; + m_liveButton.AddState( IOUtils.LiveOnGUID ); + m_liveButton.AddState( IOUtils.LivePendingGUID ); + + //ToolsMenuButton cleanUnusedNodesButton = new ToolsMenuButton( m_parentWindow, ToolButtonType.CleanUnusedNodes, 0, 0, -1, -1, IOUtils.CleanupOFFGUID, string.Empty, "Remove all nodes not connected to the master node.", 77 ); + //cleanUnusedNodesButton.ToolButtonPressedEvt += OnButtonPressedEvent; + //cleanUnusedNodesButton.AddState( IOUtils.CleanUpOnGUID ); + //m_list[ ( int ) ToolButtonType.CleanUnusedNodes ] = cleanUnusedNodesButton; + + m_openSourceCodeButton = new ToolsMenuButton( m_parentWindow, ToolButtonType.OpenSourceCode, 0, 0, -1, -1, IOUtils.OpenSourceCodeOFFGUID, string.Empty, "Open shader file in your default shader editor.", 80, false ); + m_openSourceCodeButton.ToolButtonPressedEvt += OnButtonPressedEvent; + m_openSourceCodeButton.AddState( IOUtils.OpenSourceCodeONGUID ); + + + // middle right + m_cleanUnusedNodesButton = new ToolsMenuButton( m_parentWindow, ToolButtonType.CleanUnusedNodes, 0, 0, -1, -1, IOUtils.CleanupOFFGUID, string.Empty, "Remove all nodes not connected to the master node.", 77 ); + m_cleanUnusedNodesButton.ToolButtonPressedEvt += OnButtonPressedEvent; + m_cleanUnusedNodesButton.AddState( IOUtils.CleanUpOnGUID ); + + m_focusOnMasterNodeButton = new ToolsMenuButton( m_parentWindow, ToolButtonType.FocusOnMasterNode, 0, 0, -1, -1, IOUtils.FocusNodeGUID, string.Empty, "Focus on active master node.", -1, false ); + m_focusOnMasterNodeButton.ToolButtonPressedEvt += OnButtonPressedEvent; + + m_focusOnSelectionButton = new ToolsMenuButton( m_parentWindow, ToolButtonType.FocusOnSelection, 0, 0, -1, -1, IOUtils.FitViewGUID, string.Empty, "Focus on selection or fit to screen if none selected." ); + m_focusOnSelectionButton.ToolButtonPressedEvt += OnButtonPressedEvent; + + + // right + m_shareButton = new ToolsMenuButton( m_parentWindow, ToolButtonType.Share, 0, 0, -1, -1, IOUtils.ShareOFFGUID, string.Empty, "Share selection", 100 ); + m_shareButton.ToolButtonPressedEvt += OnButtonPressedEvent; + m_shareButton.AddState( IOUtils.ShareONGUID ); + + m_takeScreenshotButton = new ToolsMenuButton( m_parentWindow, ToolButtonType.TakeScreenshot, 0, 0, -1, -1, IOUtils.TakeScreenshotOFFGUID, string.Empty, "Take ScreenShot (WINDOWS ONLY).", 100 ); + m_takeScreenshotButton.ToolButtonPressedEvt += OnButtonPressedEvent; + m_takeScreenshotButton.AddState( IOUtils.TakeScreenshotONGUID ); + + m_showInfoWindowButton = new ToolsMenuButton( m_parentWindow, ToolButtonType.ShowInfoWindow, 0, 0, -1, -1, IOUtils.ShowInfoWindowGUID, string.Empty, "Open Helper Window." ); + m_showInfoWindowButton.ToolButtonPressedEvt += OnButtonPressedEvent; + + + // hidden + m_showTipsWindowButton = new ToolsMenuButton( m_parentWindow, ToolButtonType.ShowTipsWindow, 0, 0, -1, -1, IOUtils.ShowTipsWindowGUID, string.Empty, "Open Quick Tips!" ); + m_showTipsWindowButton.ToolButtonPressedEvt += OnButtonPressedEvent; + + m_showConsoleWindowButton = new ToolsMenuButton( m_parentWindow, ToolButtonType.ShowConsole, 0, 0, -1, -1, IOUtils.ShowConsoleWindowGUID, string.Empty, "Show internal console", 74 ); + m_showConsoleWindowButton.ToolButtonPressedEvt += OnButtonPressedEvent; + m_showConsoleWindowButton.AddState( IOUtils.ShowConsoleWindowGUID ); + + m_searchBarSize = new Rect( 0, TabY + 4, 110, 60 ); + } + + void OnShowPortLegend() + { + ParentWindow.ShowPortInfo(); + } + + override public void Destroy() + { + base.Destroy(); + //for ( int i = 0; i < m_list.Length; i++ ) + //{ + // m_list[ i ].Destroy(); + //} + //m_list = null; + + m_searchResultNodes.Clear(); + m_searchResultNodes = null; + + m_updateButton.Destroy(); + m_updateButton = null; + + m_liveButton.Destroy(); + m_liveButton = null; + + m_openSourceCodeButton.Destroy(); + m_openSourceCodeButton = null; + + m_focusOnMasterNodeButton.Destroy(); + m_focusOnMasterNodeButton = null; + + m_focusOnSelectionButton.Destroy(); + m_focusOnSelectionButton = null; + + m_showInfoWindowButton.Destroy(); + m_showInfoWindowButton = null; + + m_takeScreenshotButton.Destroy(); + m_takeScreenshotButton = null; + + m_shareButton.Destroy(); + m_shareButton = null; + + m_showTipsWindowButton.Destroy(); + m_showTipsWindowButton = null; + + m_cleanUnusedNodesButton.Destroy(); + m_cleanUnusedNodesButton = null; + + m_showConsoleWindowButton.Destroy(); + m_showConsoleWindowButton = null; + } + + void OnButtonPressedEvent( ToolButtonType type ) + { + if ( ToolButtonPressedEvt != null ) + ToolButtonPressedEvt( type ); + } + + public override void Draw( Rect parentPosition, Vector2 mousePosition, int mouseButtonId, bool hasKeyboadFocus ) + { + base.Draw( parentPosition, mousePosition, mouseButtonId, hasKeyboadFocus ); + + Color bufferedColor = GUI.color; + m_areaLeft.x = m_transformedArea.x + TabX; + m_areaRight.x = m_transformedArea.x + m_transformedArea.width - 75 - TabX; + + //if ( m_toolbarButtonStyle == null ) + //{ + // m_toolbarButtonStyle = new GUIStyle( UIUtils.Button ); + // m_toolbarButtonStyle.fixedWidth = 100; + //} + + if ( m_toggleStyle == null ) + { + m_toggleStyle = UIUtils.Toggle; + } + + //for ( int i = 0; i < m_list.Length; i++ ) + //{ + // GUI.color = m_list[ i ].IsInside( mousePosition ) ? LeftIconsColorOn : LeftIconsColorOff; + // m_list[ i ].Draw( TabX + m_transformedArea.x + m_list[ i ].ButtonSpacing, TabY ); + //} + GUI.color = m_updateButton.IsInside( mousePosition ) ? LeftIconsColorOn : LeftIconsColorOff; + m_updateButton.Draw( TabX + m_transformedArea.x + m_updateButton.ButtonSpacing, TabY ); + + GUI.color = m_liveButton.IsInside( mousePosition ) ? LeftIconsColorOn : LeftIconsColorOff; + m_liveButton.Draw( TabX + m_transformedArea.x + m_liveButton.ButtonSpacing, TabY ); + + GUI.color = m_openSourceCodeButton.IsInside( mousePosition ) ? LeftIconsColorOn : LeftIconsColorOff; + m_openSourceCodeButton.Draw( TabX + m_transformedArea.x + m_openSourceCodeButton.ButtonSpacing, TabY ); + + if ( m_searchBarVisible ) + { + m_searchBarSize.x = m_transformedArea.x + m_transformedArea.width - 320 - TabX; + string currentFocus = GUI.GetNameOfFocusedControl(); + + if ( Event.current.type == EventType.KeyDown ) + { + KeyCode keyCode = Event.current.keyCode; + if ( Event.current.shift ) + { + if ( keyCode == KeyCode.F3 || + ( ( keyCode == KeyCode.KeypadEnter || keyCode == KeyCode.Return ) && + ( currentFocus.Equals( SearchBarId ) || string.IsNullOrEmpty( currentFocus ) ) ) ) + SelectPrevious(); + } + else + { + if ( keyCode == KeyCode.F3 || + ( ( keyCode == KeyCode.KeypadEnter || keyCode == KeyCode.Return ) && + ( currentFocus.Equals( SearchBarId ) || string.IsNullOrEmpty( currentFocus ) ) ) ) + SelectNext(); + } + } + + if( currentFocus.Equals( SearchBarId ) || ( m_parentWindow.CameraDrawInfo.CurrentEventType == EventType.MouseDown && m_searchBarSize.Contains( m_parentWindow.CameraDrawInfo.MousePosition ) ) || m_selectSearchBarTextfield ) + { + EditorGUI.BeginChangeCheck(); + { + GUI.SetNextControlName( SearchBarId ); + m_searchBarValue = EditorGUI.TextField( m_searchBarSize, m_searchBarValue, UIUtils.ToolbarSearchTextfield ); + } + if ( EditorGUI.EndChangeCheck() ) + { + m_refreshSearchResultList = true; + } + } else + { + GUI.Label( m_searchBarSize, m_searchBarValue, UIUtils.ToolbarSearchTextfield ); + } + + m_searchBarSize.x += m_searchBarSize.width; + if ( m_parentWindow.CameraDrawInfo.CurrentEventType == EventType.MouseDown && m_searchBarSize.Contains( m_parentWindow.CameraDrawInfo.MousePosition ) ) + { + if ( string.IsNullOrEmpty( m_searchBarValue ) ) + { + m_searchBarVisible = false; + m_refreshSearchResultList = false; + } + else + { + m_searchBarValue = string.Empty; + m_searchResultNodes.Clear(); + m_currentSelected = -1; + } + } + + GUI.Label( m_searchBarSize, string.Empty, UIUtils.ToolbarSearchCancelButton ); + + + + if ( Event.current.isKey && Event.current.keyCode == KeyCode.Escape ) + { + m_searchBarVisible = false; + m_refreshSearchResultList = false; + GUI.FocusControl( null ); + m_selectSearchBarTextfield = false; + } + + if ( m_refreshSearchResultList && ( m_parentWindow.CurrentInactiveTime > InactivityRefreshTime ) ) + { + RefreshList(); + } + } + + if ( m_selectSearchBarTextfield ) + { + m_selectSearchBarTextfield = false; + EditorGUI.FocusTextInControl( SearchBarId ); + //GUI.FocusControl( SearchBarId ); + } + + //if ( Event.current.control && Event.current.isKey && Event.current.keyCode == KeyCode.F && Event.current.type == EventType.KeyDown ) + if( m_parentWindow.CurrentCommandName.Equals("Find") ) + { + if ( !m_searchBarVisible ) + { + m_searchBarVisible = true; + m_refreshSearchResultList = false; + } + m_selectSearchBarTextfield = true; + } + + GUI.color = m_shareButton.IsInside( mousePosition ) ? RightIconsColorOn : RightIconsColorOff; + m_shareButton.Draw( m_transformedArea.x + m_transformedArea.width - 195 - TabX, TabY ); + + GUI.color = m_takeScreenshotButton.IsInside( mousePosition ) ? RightIconsColorOn : RightIconsColorOff; + m_takeScreenshotButton.Draw( m_transformedArea.x + m_transformedArea.width - 165 - TabX, TabY ); + + + + GUI.color = m_focusOnSelectionButton.IsInside( mousePosition ) ? RightIconsColorOn : RightIconsColorOff; + m_focusOnSelectionButton.Draw( m_transformedArea.x + m_transformedArea.width - 120 - TabX, TabY ); + + GUI.color = m_focusOnMasterNodeButton.IsInside( mousePosition ) ? RightIconsColorOn : RightIconsColorOff; + m_focusOnMasterNodeButton.Draw( m_transformedArea.x + m_transformedArea.width - 85 - TabX, TabY ); + + GUI.color = m_cleanUnusedNodesButton.IsInside( mousePosition ) ? RightIconsColorOn : RightIconsColorOff; + m_cleanUnusedNodesButton.Draw( m_transformedArea.x + m_transformedArea.width - 50 - TabX, TabY ); + + GUI.color = m_showInfoWindowButton.IsInside( mousePosition ) ? RightIconsColorOn : RightIconsColorOff; + m_showInfoWindowButton.Draw( m_transformedArea.x + m_transformedArea.width - 25 - TabX, TabY ); + + + //GUI.color = m_showTipsWindowButton.IsInside( mousePosition ) ? RightIconsColorOn : RightIconsColorOff; + //m_showTipsWindowButton.Draw( m_transformedArea.x + m_transformedArea.width - 190 - TabX, TabY ); + + //GUI.color = m_showConsoleWindowButton.IsInside( mousePosition ) ? RightIconsColorOn : RightIconsColorOff; + //m_showConsoleWindowButton.Draw( m_transformedArea.x + m_transformedArea.width - 195 - TabX, TabY ); + + GUI.color = bufferedColor; + + } + + public void OnNodeRemovedFromGraph( ParentNode node ) + { + m_searchResultNodes.Remove( node ); + } + + int m_previousNodeCount = 0; + + void RefreshList() + { + m_refreshSearchResultList = false; + m_currentSelected = -1; + m_searchResultNodes.Clear(); + if ( !string.IsNullOrEmpty( m_searchBarValue ) ) + { + List nodes = m_parentWindow.CurrentGraph.AllNodes; + int count = nodes.Count; + m_previousNodeCount = count; + for ( int i = 0; i < count; i++ ) + { + if ( nodes[ i ].CheckFindText( m_searchBarValue ) ) + { + m_searchResultNodes.Add( nodes[ i ] ); + } + } + } + } + + void SelectNext() + { + if ( m_refreshSearchResultList || m_parentWindow.CurrentGraph.AllNodes.Count != m_previousNodeCount ) + { + RefreshList(); + } + + if ( m_searchResultNodes.Count > 0 ) + { + m_currentSelected = ( m_currentSelected + 1 ) % m_searchResultNodes.Count; + m_parentWindow.FocusOnNode( m_searchResultNodes[ m_currentSelected ], 1, true ,true); + } + } + + void SelectPrevious() + { + if ( m_refreshSearchResultList || m_parentWindow.CurrentGraph.AllNodes.Count != m_previousNodeCount ) + { + RefreshList(); + } + + if ( m_searchResultNodes.Count > 0 ) + { + m_currentSelected = ( m_currentSelected > 1 ) ? ( m_currentSelected - 1 ) : ( m_searchResultNodes.Count - 1 ); + m_parentWindow.FocusOnNode( m_searchResultNodes[ m_currentSelected ], 1, true ); + } + } + + + public void SetStateOnButton( ToolButtonType button, int state, string tooltip ) + { + switch ( button ) + { + case ToolButtonType.New: + case ToolButtonType.Open: + case ToolButtonType.Save: + case ToolButtonType.Library: + case ToolButtonType.Options: + case ToolButtonType.Help: + case ToolButtonType.MasterNode: break; + case ToolButtonType.OpenSourceCode: + { + m_openSourceCodeButton.SetStateOnButton( state, tooltip ); + } + break; + case ToolButtonType.Update: + { + m_updateButton.SetStateOnButton( state, tooltip ); + } + break; + case ToolButtonType.Live: + { + m_liveButton.SetStateOnButton( state, tooltip ); + } + break; + case ToolButtonType.TakeScreenshot: + { + m_takeScreenshotButton.SetStateOnButton( state, tooltip ); + } + break; + case ToolButtonType.CleanUnusedNodes: + //case eToolButtonType.SelectShader: + { + m_cleanUnusedNodesButton.SetStateOnButton( state, tooltip ); + } + break; + case ToolButtonType.FocusOnMasterNode: + { + m_focusOnMasterNodeButton.SetStateOnButton( state, tooltip ); + } + break; + case ToolButtonType.FocusOnSelection: + { + m_focusOnSelectionButton.SetStateOnButton( state, tooltip ); + } + break; + case ToolButtonType.Share: + { + m_shareButton.SetStateOnButton( state, tooltip ); + } + break; + case ToolButtonType.ShowInfoWindow: + { + m_showInfoWindowButton.SetStateOnButton( state, tooltip ); + } + break; + case ToolButtonType.ShowTipsWindow: + { + m_showTipsWindowButton.SetStateOnButton( state, tooltip ); + } + break; + case ToolButtonType.ShowConsole: + { + m_showConsoleWindowButton.SetStateOnButton( state, tooltip ); + } + break; + } + } + + public void SetStateOnButton( ToolButtonType button, int state ) + { + switch ( button ) + { + case ToolButtonType.New: + case ToolButtonType.Open: + case ToolButtonType.Save: + case ToolButtonType.Library: + case ToolButtonType.Options: + case ToolButtonType.Help: + case ToolButtonType.MasterNode: break; + case ToolButtonType.OpenSourceCode: + { + m_openSourceCodeButton.SetStateOnButton( state ); + } + break; + case ToolButtonType.Update: + { + m_updateButton.SetStateOnButton( state ); + } + break; + case ToolButtonType.Live: + { + m_liveButton.SetStateOnButton( state ); + } + break; + case ToolButtonType.TakeScreenshot: + { + m_takeScreenshotButton.SetStateOnButton( state ); + } + break; + case ToolButtonType.CleanUnusedNodes: + //case eToolButtonType.SelectShader: + { + m_cleanUnusedNodesButton.SetStateOnButton( state ); + } + break; + case ToolButtonType.FocusOnMasterNode: + { + m_focusOnMasterNodeButton.SetStateOnButton( state ); + } + break; + case ToolButtonType.FocusOnSelection: + { + m_focusOnSelectionButton.SetStateOnButton( state ); + } + break; + case ToolButtonType.Share: + { + m_shareButton.SetStateOnButton( state ); + } + break; + case ToolButtonType.ShowInfoWindow: + { + m_showInfoWindowButton.SetStateOnButton( state ); + } + break; + case ToolButtonType.ShowTipsWindow: + { + m_showTipsWindowButton.SetStateOnButton( state ); + }break; + case ToolButtonType.ShowConsole: + { + m_showConsoleWindowButton.SetStateOnButton( state ); + } + break; + } + } + + public void DrawShaderTitle( MenuParent nodeParametersWindow, MenuParent paletteWindow, float availableCanvasWidth, float graphAreaHeight, string shaderName ) + { + float leftAdjust = nodeParametersWindow.IsMaximized ? nodeParametersWindow.RealWidth : 0; + float rightAdjust = paletteWindow.IsMaximized ? 0 : paletteWindow.RealWidth; + + m_boxRect = new Rect( leftAdjust + rightAdjust, 0, availableCanvasWidth, 35 ); + m_boxRect.x += paletteWindow.IsMaximized ? 0 : -paletteWindow.RealWidth; + m_boxRect.width += nodeParametersWindow.IsMaximized ? 0 : nodeParametersWindow.RealWidth; + m_boxRect.width += paletteWindow.IsMaximized ? 0 : paletteWindow.RealWidth; + m_borderRect = new Rect( m_boxRect ); + m_borderRect.height = graphAreaHeight; + + int extra = m_searchBarVisible ? (int)m_searchBarSize.width + 20: 0; + //m_boxRect.xMax -= ( paletteWindow.IsMaximized ? 195 : 230 ) + extra; + //m_boxRect.xMin += nodeParametersWindow.IsMaximized ? 95 : 145; + + UIUtils.ToolbarMainTitle.padding.right = ( paletteWindow.IsMaximized ? 195 : 230 ) + extra; + UIUtils.ToolbarMainTitle.padding.left = nodeParametersWindow.IsMaximized ? 110 : 145; + + if ( m_borderStyle == null ) + { + m_borderStyle = ( ParentWindow.CurrentGraph.CurrentMasterNode == null ) ? UIUtils.GetCustomStyle( CustomStyle.ShaderFunctionBorder ) : UIUtils.GetCustomStyle( CustomStyle.ShaderBorder ); + } + + GUI.Label( m_borderRect, shaderName, m_borderStyle ); + GUI.Label( m_boxRect, shaderName, UIUtils.ToolbarMainTitle ); + } + + public override bool IsInside( Vector2 position ) + { + if ( !m_isActive ) + return false; + + return m_boxRect.Contains( position ) || m_areaLeft.Contains( position ) || m_areaRight.Contains( position ); + } + + public GUIStyle BorderStyle + { + get { return m_borderStyle; } + set { m_borderStyle = value; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsWindow.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsWindow.cs.meta new file mode 100644 index 0000000..3bd8f54 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Menu/Tools/ToolsWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b1c1f3bedf849cb41a1648bf895bc0f7 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Native.meta new file mode 100644 index 0000000..c3ec23a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 08d94054f82fc06498060596f83da0ba +folderAsset: yes +timeCreated: 1481126943 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackColor.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackColor.cs new file mode 100644 index 0000000..aeafb2a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackColor.cs @@ -0,0 +1,55 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class FallbackColor : IFallbackVars + { + [SerializeField] + private Color m_current; + [SerializeField] + private Color m_previous; + + public FallbackColor() + { + m_current = new Color(0, 0, 0, 0); + m_previous = new Color(0, 0, 0, 0); + } + + public FallbackColor(Color data) + { + m_current = data; + m_previous = data; + } + + public void Revert() + { + Color aux = m_current; + m_current = m_previous; + m_previous = aux; + } + + public Color Current + { + get + { + return m_current; + } + + set + { + m_previous = m_current; + m_current = value; + } + } + + public override string ToString() + { + return m_current.ToString(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackColor.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackColor.cs.meta new file mode 100644 index 0000000..004e9ae --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackColor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8c6dccc523e2ad440a82edd582b84a45 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackFloat.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackFloat.cs new file mode 100644 index 0000000..69d6f39 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackFloat.cs @@ -0,0 +1,56 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class FallbackFloat : IFallbackVars + { + [SerializeField] + private float m_current; + [SerializeField] + private float m_previous; + + public FallbackFloat() + { + m_current = 0; + m_previous = 0; + } + + public FallbackFloat( float data ) + { + m_current = data; + m_previous = data; + } + + public void Revert() + { + float aux = m_current; + m_current = m_previous; + m_previous = aux; + } + + + public float Current + { + get + { + return m_current; + } + + set + { + m_previous = m_current; + m_current = value; + } + } + + public override string ToString() + { + return m_current.ToString(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackFloat.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackFloat.cs.meta new file mode 100644 index 0000000..c7f6c88 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackFloat.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a957e66c7a41d6848966d526c9687347 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackInt.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackInt.cs new file mode 100644 index 0000000..bd9b8a7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackInt.cs @@ -0,0 +1,56 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class FallbackInt : IFallbackVars + { + [SerializeField] + private int m_current; + [SerializeField] + private int m_previous; + + public FallbackInt() + { + m_current = 0; + m_previous = 0; + } + + public FallbackInt( int data ) + { + m_current = data; + m_previous = data; + } + + public void Revert() + { + int aux = m_current; + m_current = m_previous; + m_previous = aux; + } + + + public int Current + { + get + { + return m_current; + } + + set + { + m_previous = m_current; + m_current = value; + } + } + + public override string ToString() + { + return m_current.ToString(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackInt.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackInt.cs.meta new file mode 100644 index 0000000..d75cf8d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackInt.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 09c28ab321caf3b47839606e37d3cdd2 +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackMatrix4x4.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackMatrix4x4.cs new file mode 100644 index 0000000..8405790 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackMatrix4x4.cs @@ -0,0 +1,55 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class FallbackMatrix4x4 : IFallbackVars + { + [SerializeField] + private Matrix4x4 m_current; + [SerializeField] + private Matrix4x4 m_previous; + + public FallbackMatrix4x4() + { + m_current = new Matrix4x4(); + m_previous = new Matrix4x4(); + } + + public FallbackMatrix4x4( Matrix4x4 data ) + { + m_current = data; + m_previous = data; + } + + public void Revert() + { + Matrix4x4 aux = m_current; + m_current = m_previous; + m_previous = aux; + } + + public Matrix4x4 Current + { + get + { + return m_current; + } + + set + { + m_previous = m_current; + m_current = value; + } + } + + public override string ToString() + { + return m_current.ToString(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackMatrix4x4.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackMatrix4x4.cs.meta new file mode 100644 index 0000000..e6208e2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackMatrix4x4.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 48af68670bdba9147b4ed55138e4edf6 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackString.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackString.cs new file mode 100644 index 0000000..e33e096 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackString.cs @@ -0,0 +1,56 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class FallbackString : IFallbackVars + { + [SerializeField] + private string m_current; + [SerializeField] + private string m_previous; + + public FallbackString() + { + m_current = string.Empty; + m_previous = string.Empty; + } + + public FallbackString( string data ) + { + m_current = data; + m_previous = data; + } + + public void Revert() + { + string aux = m_current; + m_current = m_previous; + m_previous = aux; + } + + + public string Current + { + get + { + return m_current; + } + + set + { + m_previous = m_current; + m_current = value; + } + } + + public override string ToString() + { + return m_current; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackString.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackString.cs.meta new file mode 100644 index 0000000..82d80d5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackString.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cc2e25b7c55e9284699ccad75e79a075 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackTexture.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackTexture.cs new file mode 100644 index 0000000..afee1e7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackTexture.cs @@ -0,0 +1,55 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class FallbackTexture : IFallbackVars + { + [SerializeField] + private Texture m_current; + [SerializeField] + private Texture m_previous; + + public FallbackTexture() + { + m_current = null; + m_previous = null; + } + + public FallbackTexture( Texture data ) + { + m_current = data; + m_previous = data; + } + + public void Revert() + { + Texture aux = m_current; + m_current = m_previous; + m_previous = aux; + } + + public Texture Current + { + get + { + return m_current; + } + + set + { + m_previous = m_current; + m_current = value; + } + } + + public override string ToString() + { + return m_current.ToString(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackTexture.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackTexture.cs.meta new file mode 100644 index 0000000..21258f2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackTexture.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 309e413cfa89510429c67fa82c557da7 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVariable.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVariable.cs new file mode 100644 index 0000000..c6d3eaf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVariable.cs @@ -0,0 +1,36 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + //GENERICS DON'T WORK WITH HOT CODE RELOAD + [Serializable] + public class FallbackVariable + { + [SerializeField] + private T m_current; + [SerializeField] + private T m_last; + + public void Revert() + { + m_current = m_last; + } + + public T Current + { + get + { + return m_current; + } + set + { + m_last = m_current; + m_current = value; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVariable.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVariable.cs.meta new file mode 100644 index 0000000..2af70ab --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVariable.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ec850a4093c249d449f22e0483040b9c +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector2.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector2.cs new file mode 100644 index 0000000..adad9d0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector2.cs @@ -0,0 +1,56 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class FallbackVector2 : IFallbackVars + { + [SerializeField] + private Vector2 m_current; + [SerializeField] + private Vector2 m_previous; + + public FallbackVector2() + { + m_current = new Vector2( 0, 0 ); + m_previous = new Vector2( 0, 0 ); + } + + public FallbackVector2( Vector2 data ) + { + m_current = data; + m_previous = data; + } + + public void Revert() + { + Vector2 aux = m_current; + m_current = m_previous; + m_previous = aux; + } + + + public Vector2 Current + { + get + { + return m_current; + } + + set + { + m_previous = m_current; + m_current = value; + } + } + + public override string ToString() + { + return m_current.ToString(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector2.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector2.cs.meta new file mode 100644 index 0000000..c04cca1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector2.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ab3a976b3cb79ad41986d2f7d4439642 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector3.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector3.cs new file mode 100644 index 0000000..f2fe132 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector3.cs @@ -0,0 +1,56 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class FallbackVector3 : IFallbackVars + { + [SerializeField] + private Vector3 m_current; + [SerializeField] + private Vector3 m_previous; + + public FallbackVector3() + { + m_current = new Vector3( 0, 0, 0 ); + m_previous = new Vector3( 0, 0, 0 ); + } + + public FallbackVector3( Vector3 data ) + { + m_current = data; + m_previous = data; + } + + public void Revert() + { + Vector3 aux = m_current; + m_current = m_previous; + m_previous = aux; + } + + + public Vector3 Current + { + get + { + return m_current; + } + + set + { + m_previous = m_current; + m_current = value; + } + } + + public override string ToString() + { + return m_current.ToString(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector3.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector3.cs.meta new file mode 100644 index 0000000..d22ae5b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector3.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0e681455d27d2264fbc2683a1510df2c +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector4.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector4.cs new file mode 100644 index 0000000..63be658 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector4.cs @@ -0,0 +1,48 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class FallbackVector4 : IFallbackVars + { + [SerializeField] + private Vector4 m_current; + [SerializeField] + private Vector4 m_previous; + + public FallbackVector4() + { + m_current = new Vector4( 0, 0, 0, 0 ); + m_previous = new Vector4( 0, 0, 0, 0 ); + } + + public FallbackVector4( Vector4 data ) + { + m_current = data; + m_previous = data; + } + + public void Revert() + { + Vector4 aux = m_current; + m_current = m_previous; + m_previous = aux; + } + + public Vector4 Current + { + get { return m_current; } + set + { + m_previous = m_current; + m_current = value; + } + } + + public override string ToString() { return m_current.ToString(); } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector4.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector4.cs.meta new file mode 100644 index 0000000..704deb7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/FallbackVector4.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4e23c25f035ba604ea999f214c0a7833 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/IFallbackVars.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/IFallbackVars.cs new file mode 100644 index 0000000..17f7fcf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/IFallbackVars.cs @@ -0,0 +1,10 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + interface IFallbackVars + { + void Revert(); + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Native/IFallbackVars.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/IFallbackVars.cs.meta new file mode 100644 index 0000000..f558f54 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Native/IFallbackVars.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8b0dda023474c6e41a39c36e48af72b2 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes.meta new file mode 100644 index 0000000..1847e2b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: dd2ad7a1ab86e9344b83b2a88cc030cf +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CommentaryNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CommentaryNode.cs new file mode 100644 index 0000000..141fea0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CommentaryNode.cs @@ -0,0 +1,692 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using System.Collections.Generic; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public enum eResizeAxis + { + X_AXIS, + Y_AXIS, + ALL + } + + [Serializable] + public sealed class CommentaryNode : ParentNode, ISerializationCallbackReceiver + { + private const string InfoText = "Press Alt + Left Mouse Click/Drag to make all Comment node area interactable.\nDouble click on the Comment at the node body to modify it directly from there."; + + private const string CommentaryTitle = "Comment"; + private const float BORDER_SIZE_X = 50; + private const float BORDER_SIZE_Y = 50; + private const float MIN_SIZE_X = 100; + private const float MIN_SIZE_Y = 100; + private const float COMMENTARY_BOX_HEIGHT = 30; + + private readonly Vector2 ResizeButtonPos = new Vector2( 1, 1 ); + + [SerializeField] + private string m_commentText = "Comment"; + + [SerializeField] + private string m_titleText = string.Empty; + + [SerializeField] + private eResizeAxis m_resizeAxis = eResizeAxis.ALL; + + [SerializeField] + private List m_nodesOnCommentary = new List(); + private Dictionary m_nodesOnCommentaryDict = new Dictionary(); + private bool m_reRegisterNodes = false; + + [SerializeField] + private Rect m_resizeLeftIconCoords; + + [SerializeField] + private Rect m_resizeRightIconCoords; + + [SerializeField] + private Rect m_auxHeaderPos; + + [SerializeField] + private Rect m_commentArea; + + private Texture2D m_resizeIconTex; + + private bool m_isResizingRight = false; + private bool m_isResizingLeft = false; + + private Vector2 m_resizeStartPoint = Vector2.zero; + + private string m_focusName = "CommentaryNode"; + private bool m_focusOnTitle = false; + private bool m_graphDepthAnalized = false; + + private bool m_checkCommentText = true; + private bool m_checkTitleText = true; + + public Color m_frameColor = Color.white; + + private List m_nodesIds = new List(); + private bool m_checkContents = false; + + private bool m_isEditing; + private bool m_stopEditing; + private bool m_startEditing; + private double m_clickTime; + private double m_doubleClickTime = 0.3; + + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_reorderLocked = true; + m_rmbIgnore = true; + m_defaultInteractionMode = InteractionMode.Both; + m_headerColor = UIUtils.GetColorFromCategory( "Commentary" ); + m_connStatus = NodeConnectionStatus.Island; + m_textLabelWidth = 90; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_focusName = CommentaryTitle + OutputId; + } + + public void CreateFromSelectedNodes( Vector2 mousePosOnCanvasCoords, ParentNode[] selectedNodes ) + { + if ( selectedNodes.Length == 0 ) + { + m_position = new Rect( mousePosOnCanvasCoords, new Vector2( 100, 100 ) ); + return; + } + + Vector2 minPos = new Vector2( float.MaxValue, float.MaxValue ); + Vector2 maxPos = new Vector2( float.MinValue, float.MinValue ); + + for ( int i = 0; i < selectedNodes.Length; i++ ) + { + //Check min + if ( selectedNodes[ i ].Position.x < minPos.x ) + minPos.x = selectedNodes[ i ].Position.x; + + if ( selectedNodes[ i ].Position.y < minPos.y ) + minPos.y = selectedNodes[ i ].Position.y; + + //check max + float nodeXMax = selectedNodes[ i ].Position.x + selectedNodes[ i ].Position.width; + if ( nodeXMax > maxPos.x ) + { + maxPos.x = nodeXMax; + } + + float nodeYMax = selectedNodes[ i ].Position.y + selectedNodes[ i ].Position.height; + if ( nodeYMax > maxPos.y ) + { + maxPos.y = nodeYMax; + } + + //_nodesOnCommentary.Add( selectedNodes[ i ] ); + //selectedNodes[ i ].OnNodeStoppedMovingEvent += NodeStoppedMoving; + AddNodeToCommentary( selectedNodes[ i ] ); + } + + Vector2 dims = maxPos - minPos + new Vector2( 2 * BORDER_SIZE_X, 2 * BORDER_SIZE_Y ); + m_position = new Rect( minPos.x - BORDER_SIZE_X, minPos.y - BORDER_SIZE_Y, dims.x, dims.y ); + } + + public override void Move( Vector2 delta, bool snap ) + { + if ( m_isResizingRight || m_isResizingLeft ) + return; + + base.Move( delta, snap ); + for ( int i = 0; i < m_nodesOnCommentary.Count; i++ ) + { + if ( !m_nodesOnCommentary[ i ].Selected ) + { + m_nodesOnCommentary[ i ].RecordObject( Constants.UndoMoveNodesId ); + m_nodesOnCommentary[ i ].Move( delta, snap ); + } + } + } + + public void NodeStoppedMoving( ParentNode node, bool testOnlySelected, InteractionMode useTargetInteraction ) + { + if ( !m_position.Contains( node.Vec2Position ) && !m_position.Contains( node.Corner ) ) + { + RemoveNode( node ); + } + } + + public void NodeDestroyed( ParentNode node ) + { + RemoveNode( node ); + } + + public void RemoveNode( ParentNode node ) + { + if ( m_nodesOnCommentaryDict.ContainsKey( node.UniqueId ) ) + { + UIUtils.MarkUndoAction(); + RecordObject( Constants.UndoRemoveNodeFromCommentaryId ); + node.RecordObject( Constants.UndoRemoveNodeFromCommentaryId ); + m_nodesOnCommentary.Remove( node ); + m_nodesOnCommentaryDict.Remove( node.UniqueId ); + node.OnNodeStoppedMovingEvent -= NodeStoppedMoving; + node.OnNodeDestroyedEvent -= NodeDestroyed; + node.CommentaryParent = -1; + } + } + + public void RemoveAllNodes() + { + UIUtils.MarkUndoAction(); + for ( int i = 0; i < m_nodesOnCommentary.Count; i++ ) + { + RecordObject( Constants.UndoRemoveNodeFromCommentaryId ); + m_nodesOnCommentary[ i ].RecordObject( Constants.UndoRemoveNodeFromCommentaryId ); + m_nodesOnCommentary[ i ].OnNodeStoppedMovingEvent -= NodeStoppedMoving; + m_nodesOnCommentary[ i ].OnNodeDestroyedEvent -= NodeDestroyed; + m_nodesOnCommentary[ i ].CommentaryParent = -1; + } + m_nodesOnCommentary.Clear(); + m_nodesOnCommentaryDict.Clear(); + } + + public override void Destroy() + { + base.Destroy(); + RemoveAllNodes(); + } + + public void AddNodeToCommentary( ParentNode node ) + { + if( node.UniqueId == UniqueId ) + return; + + if ( !m_nodesOnCommentaryDict.ContainsKey( node.UniqueId ) ) + { + bool addToNode = false; + + if ( node.CommentaryParent < 0 ) + { + addToNode = true; + if ( node.Depth <= m_depth ) + { + ActivateNodeReordering( node.Depth ); + } + } + else + { + CommentaryNode other = UIUtils.GetNode( node.CommentaryParent ) as CommentaryNode; + if ( other != null ) + { + if ( other.Depth < Depth ) + { + other.RemoveNode( node ); + addToNode = true; + } + + } + } + + if ( addToNode ) + { + UIUtils.MarkUndoAction(); + RecordObject( Constants.UndoAddNodeToCommentaryId ); + node.RecordObject( Constants.UndoAddNodeToCommentaryId ); + + m_nodesOnCommentary.Add( node ); + m_nodesOnCommentaryDict.Add( node.UniqueId, node ); + node.OnNodeStoppedMovingEvent += NodeStoppedMoving; + node.OnNodeDestroyedEvent += NodeDestroyed; + node.CommentaryParent = UniqueId; + } + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr,()=> + { + EditorGUI.BeginChangeCheck(); + m_titleText = EditorGUILayoutTextField( "Frame Title", m_titleText ); + if ( EditorGUI.EndChangeCheck() ) + { + m_checkTitleText = true; + } + EditorGUI.BeginChangeCheck(); + m_commentText = EditorGUILayoutTextField( CommentaryTitle, m_commentText ); + if ( EditorGUI.EndChangeCheck() ) + { + m_checkCommentText = true; + } + + m_frameColor = EditorGUILayoutColorField( "Frame Color", m_frameColor ); + } ); + EditorGUILayout.HelpBox( InfoText, MessageType.Info ); + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + if ( m_nodesIds.Count > 0 ) + { + for ( int i = 0; i < m_nodesIds.Count; i++ ) + { + ParentNode node = ContainerGraph.GetNode( m_nodesIds[ i ] ); + if ( node ) + { + AddNodeToCommentary( node ); + } + } + m_nodesIds.Clear(); + } + + if ( m_reRegisterNodes ) + { + m_reRegisterNodes = false; + m_nodesOnCommentaryDict.Clear(); + for ( int i = 0; i < m_nodesOnCommentary.Count; i++ ) + { + if ( m_nodesOnCommentary[ i ] != null ) + { + m_nodesOnCommentary[ i ].OnNodeStoppedMovingEvent += NodeStoppedMoving; + m_nodesOnCommentary[ i ].OnNodeDestroyedEvent += NodeDestroyed; + m_nodesOnCommentaryDict.Add( m_nodesOnCommentary[ i ].UniqueId, m_nodesOnCommentary[ i ] ); + } + } + } + + //base.OnLayout( drawInfo ); + CalculatePositionAndVisibility( drawInfo ); + + m_headerPosition = m_globalPosition; + m_headerPosition.height = UIUtils.CurrentHeaderHeight; + + m_auxHeaderPos = m_position; + m_auxHeaderPos.height = UIUtils.HeaderMaxHeight; + + m_commentArea = m_globalPosition; + m_commentArea.height = COMMENTARY_BOX_HEIGHT * drawInfo.InvertedZoom; + m_commentArea.xMin += 10 * drawInfo.InvertedZoom; + m_commentArea.xMax -= 10 * drawInfo.InvertedZoom; + + if ( m_resizeIconTex == null ) + { + m_resizeIconTex = UIUtils.GetCustomStyle( CustomStyle.CommentaryResizeButton ).normal.background; + } + + // LEFT RESIZE BUTTON + m_resizeLeftIconCoords = m_globalPosition; + m_resizeLeftIconCoords.x = m_globalPosition.x + 2; + m_resizeLeftIconCoords.y = m_globalPosition.y + m_globalPosition.height - 2 - ( m_resizeIconTex.height + ResizeButtonPos.y ) * drawInfo.InvertedZoom; + m_resizeLeftIconCoords.width = m_resizeIconTex.width * drawInfo.InvertedZoom; + m_resizeLeftIconCoords.height = m_resizeIconTex.height * drawInfo.InvertedZoom; + + // RIGHT RESIZE BUTTON + m_resizeRightIconCoords = m_globalPosition; + m_resizeRightIconCoords.x = m_globalPosition.x + m_globalPosition.width - 1 - ( m_resizeIconTex.width + ResizeButtonPos.x ) * drawInfo.InvertedZoom; + m_resizeRightIconCoords.y = m_globalPosition.y + m_globalPosition.height - 2 - ( m_resizeIconTex.height + ResizeButtonPos.y ) * drawInfo.InvertedZoom; + m_resizeRightIconCoords.width = m_resizeIconTex.width * drawInfo.InvertedZoom; + m_resizeRightIconCoords.height = m_resizeIconTex.height * drawInfo.InvertedZoom; + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + if ( !m_isVisible ) + return; + + m_colorBuffer = GUI.color; + // Background + GUI.color = Constants.NodeBodyColor * m_frameColor; + GUI.Label( m_globalPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.CommentaryBackground ) ); + + // Header + GUI.color = m_headerColor * m_headerColorModifier * m_frameColor; + GUI.Label( m_headerPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeHeader ) ); + GUI.color = m_colorBuffer; + + // Fixed Title ( only renders when not editing ) + if ( !m_isEditing && !m_startEditing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + GUI.Label( m_commentArea, m_commentText, UIUtils.CommentaryTitle ); + } + + // Buttons + GUI.Label( m_resizeLeftIconCoords, string.Empty, UIUtils.GetCustomStyle( CustomStyle.CommentaryResizeButtonInv ) ); + GUI.Label( m_resizeRightIconCoords, string.Empty, UIUtils.GetCustomStyle( CustomStyle.CommentaryResizeButton ) ); + + // Selection Box + if ( m_selected ) + { + GUI.color = Constants.NodeSelectedColor; + RectOffset cache = UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ).border; + UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ).border = UIUtils.RectOffsetSix; + GUI.Label( m_globalPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ) ); + UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ).border = cache; + GUI.color = m_colorBuffer; + } + + if ( !string.IsNullOrEmpty( m_titleText ) ) + { + Rect titleRect = m_globalPosition; + titleRect.y -= 24; + titleRect.height = 24; + GUI.Label( titleRect, m_titleText, UIUtils.GetCustomStyle( CustomStyle.CommentarySuperTitle ) ); + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + // Custom Editable Title + if ( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + if ( !m_isEditing && ( ( !ContainerGraph.ParentWindow.MouseInteracted && drawInfo.CurrentEventType == EventType.MouseDown && m_commentArea.Contains( drawInfo.MousePosition ) ) ) ) + { + if ( ( EditorApplication.timeSinceStartup - m_clickTime ) < m_doubleClickTime ) + m_startEditing = true; + else + GUI.FocusControl( null ); + m_clickTime = EditorApplication.timeSinceStartup; + } + else if ( m_isEditing && ( ( drawInfo.CurrentEventType == EventType.MouseDown && !m_commentArea.Contains( drawInfo.MousePosition ) ) || !EditorGUIUtility.editingTextField ) ) + { + m_stopEditing = true; + } + + if ( m_isEditing || m_startEditing ) + { + EditorGUI.BeginChangeCheck(); + GUI.SetNextControlName( m_focusName ); + m_commentText = EditorGUITextField( m_commentArea, string.Empty, m_commentText, UIUtils.CommentaryTitle ); + if ( EditorGUI.EndChangeCheck() ) + { + m_checkCommentText = true; + } + + if ( m_startEditing ) + EditorGUI.FocusTextInControl( m_focusName ); + } + + if ( drawInfo.CurrentEventType == EventType.Repaint ) + { + if ( m_startEditing ) + { + m_startEditing = false; + m_isEditing = true; + } + + if ( m_stopEditing ) + { + m_stopEditing = false; + m_isEditing = false; + GUI.FocusControl( null ); + } + } + } + + if ( drawInfo.CurrentEventType == EventType.MouseDown && drawInfo.LeftMouseButtonPressed ) + { + // Left Button + if( m_resizeLeftIconCoords.Contains( drawInfo.MousePosition ) && ContainerGraph.ParentWindow.CurrentEvent.modifiers != EventModifiers.Shift ) + { + if ( !m_isResizingLeft ) + { + m_isResizingLeft = true; + ContainerGraph.ParentWindow.ForceAutoPanDir = true; + m_resizeStartPoint = drawInfo.TransformedMousePos; + } + } + + // Right Button + if ( m_resizeRightIconCoords.Contains( drawInfo.MousePosition ) && ContainerGraph.ParentWindow.CurrentEvent.modifiers != EventModifiers.Shift ) + { + if ( !m_isResizingRight ) + { + m_isResizingRight = true; + ContainerGraph.ParentWindow.ForceAutoPanDir = true; + m_resizeStartPoint = drawInfo.TransformedMousePos; + } + } + } + + if ( drawInfo.CurrentEventType == EventType.Repaint || drawInfo.CurrentEventType == EventType.MouseUp ) + { + // Left Button + EditorGUIUtility.AddCursorRect( m_resizeLeftIconCoords, MouseCursor.ResizeUpRight ); + if ( m_isResizingLeft ) + { + if ( drawInfo.CurrentEventType == EventType.MouseUp ) + { + m_isResizingLeft = false; + ContainerGraph.ParentWindow.ForceAutoPanDir = false; + RemoveAllNodes(); + FireStoppedMovingEvent( false, InteractionMode.Target ); + } + else + { + Vector2 currSize = ( drawInfo.TransformedMousePos - m_resizeStartPoint ) /*/ drawInfo.InvertedZoom*/; + m_resizeStartPoint = drawInfo.TransformedMousePos; + if ( m_resizeAxis != eResizeAxis.Y_AXIS ) + { + m_position.x += currSize.x; + m_position.width -= currSize.x; + if ( m_position.width < MIN_SIZE_X ) + { + m_position.x -= ( MIN_SIZE_X - m_position.width ); + m_position.width = MIN_SIZE_X; + } + } + + if ( m_resizeAxis != eResizeAxis.X_AXIS ) + { + m_position.height += currSize.y; + if ( m_position.height < MIN_SIZE_Y ) + { + m_position.height = MIN_SIZE_Y; + } + } + } + } + + // Right Button + EditorGUIUtility.AddCursorRect( m_resizeRightIconCoords, MouseCursor.ResizeUpLeft ); + if ( m_isResizingRight ) + { + if ( drawInfo.CurrentEventType == EventType.MouseUp ) + { + m_isResizingRight = false; + ContainerGraph.ParentWindow.ForceAutoPanDir = false; + RemoveAllNodes(); + FireStoppedMovingEvent( false, InteractionMode.Target ); + } + else + { + Vector2 currSize = ( drawInfo.TransformedMousePos - m_resizeStartPoint ) /*/ drawInfo.InvertedZoom*/; + m_resizeStartPoint = drawInfo.TransformedMousePos; + if ( m_resizeAxis != eResizeAxis.Y_AXIS ) + { + m_position.width += currSize.x; + if ( m_position.width < MIN_SIZE_X ) + { + m_position.width = MIN_SIZE_X; + } + } + + if ( m_resizeAxis != eResizeAxis.X_AXIS ) + { + m_position.height += currSize.y; + if ( m_position.height < MIN_SIZE_Y ) + { + m_position.height = MIN_SIZE_Y; + } + } + } + } + } + + if ( m_checkCommentText ) + { + m_checkCommentText = false; + m_commentText = m_commentText.Replace( IOUtils.FIELD_SEPARATOR, ' ' ); + } + + if ( m_checkTitleText ) + { + m_checkTitleText = false; + m_titleText = m_titleText.Replace( IOUtils.FIELD_SEPARATOR, ' ' ); + } + + if ( m_focusOnTitle && drawInfo.CurrentEventType == EventType.KeyUp ) + { + m_focusOnTitle = false; + m_startEditing = true; + } + } + + public void Focus() + { + m_focusOnTitle = true; + } + + public override void OnAfterDeserialize() + { + base.OnAfterDeserialize(); + m_reRegisterNodes = true; + } + + public override bool OnNodeInteraction( ParentNode node ) + { + if ( node == null || UniqueId == node.UniqueId ) + return false; + + for( int i = 0; i < m_nodesOnCommentary.Count; i++ ) + { + if( m_nodesOnCommentary[ i ] && m_nodesOnCommentary[ i ] != this && m_nodesOnCommentary[ i ].OnNodeInteraction( node ) ) + { + return false; + } + } + + if( m_position.Contains( node.Vec2Position ) && m_position.Contains( node.Corner ) ) + { + AddNodeToCommentary( node ); + return true; + } + return false; + } + + public override void OnSelfStoppedMovingEvent() + { + FireStoppedMovingEvent( false, InteractionMode.Both ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_position.width = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + m_position.height = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + m_commentText = GetCurrentParam( ref nodeParams ); + int count = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + for ( int i = 0; i < count; i++ ) + { + m_nodesIds.Add( Convert.ToInt32( GetCurrentParam( ref nodeParams ) ) ); + } + + if ( UIUtils.CurrentShaderVersion() > 5004 ) + m_titleText = GetCurrentParam( ref nodeParams ); + + if ( UIUtils.CurrentShaderVersion() > 12002 ) + { + string[] colorChannels = GetCurrentParam( ref nodeParams ).Split( IOUtils.VECTOR_SEPARATOR ); + if ( colorChannels.Length == 4 ) + { + m_frameColor.r = Convert.ToSingle( colorChannels[ 0 ] ); + m_frameColor.g = Convert.ToSingle( colorChannels[ 1 ] ); + m_frameColor.b = Convert.ToSingle( colorChannels[ 2 ] ); + m_frameColor.a = Convert.ToSingle( colorChannels[ 3 ] ); + } + else + { + UIUtils.ShowMessage( UniqueId, "Incorrect number of color values", MessageSeverity.Error ); + } + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_position.width ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_position.height ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_commentText ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_nodesOnCommentary.Count ); + for ( int i = 0; i < m_nodesOnCommentary.Count; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_nodesOnCommentary[ i ].UniqueId ); + } + + IOUtils.AddFieldValueToString( ref nodeInfo, m_titleText ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_frameColor.r.ToString() + IOUtils.VECTOR_SEPARATOR + m_frameColor.g.ToString() + IOUtils.VECTOR_SEPARATOR + m_frameColor.b.ToString() + IOUtils.VECTOR_SEPARATOR + m_frameColor.a.ToString() ); + } + + public override void ResetNodeData() + { + base.ResetNodeData(); + m_graphDepthAnalized = false; + } + + public override void ReadAdditionalClipboardData( ref string[] nodeParams ) + { + base.ReadAdditionalClipboardData( ref nodeParams ); + m_nodesIds.Clear(); + m_checkContents = true; + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( m_checkContents ) + { + m_checkContents = false; + OnSelfStoppedMovingEvent(); + } + } + + public override void CalculateCustomGraphDepth() + { + if ( m_graphDepthAnalized ) + return; + + m_graphDepth = int.MinValue; + int count = m_nodesOnCommentary.Count; + for ( int i = 0; i < count; i++ ) + { + if ( m_nodesOnCommentary[ i ].ConnStatus == NodeConnectionStatus.Island ) + { + m_nodesOnCommentary[ i ].CalculateCustomGraphDepth(); + } + + if ( m_nodesOnCommentary[ i ].GraphDepth >= m_graphDepth ) + { + m_graphDepth = m_nodesOnCommentary[ i ].GraphDepth + 1; + } + } + m_graphDepthAnalized = true; + } + + public override Rect Position { get { return Event.current.alt ? m_position : m_auxHeaderPos; } } + public override bool Contains( Vector3 pos ) + { + return Event.current.alt ? m_globalPosition.Contains( pos ) : ( m_headerPosition.Contains( pos ) || m_resizeRightIconCoords.Contains( pos ) || m_resizeLeftIconCoords.Contains( pos ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CommentaryNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CommentaryNode.cs.meta new file mode 100644 index 0000000..34eb425 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CommentaryNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 08f1d9c1d8cbe5841a6429d565096eab +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants.meta new file mode 100644 index 0000000..8706d1a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e7354e1a2beece044944bc1cba85aebc +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ColorNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ColorNode.cs new file mode 100644 index 0000000..e1f21b8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ColorNode.cs @@ -0,0 +1,507 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Color", "Constants And Properties", "Color property", null, KeyCode.Alpha5 )] + public sealed class ColorNode : PropertyNode + { + private const string ColorSpaceStr = "Color Space"; + + [SerializeField] +#if UNITY_2018_1_OR_NEWER + [ColorUsage( true, true )] +#else + [ColorUsage( true, true, float.MinValue, float.MinValue, float.MinValue, float.MaxValue )] +#endif + private Color m_defaultValue = new Color( 0, 0, 0, 0 ); + + [SerializeField] +#if UNITY_2018_1_OR_NEWER + [ColorUsage( true, true )] +#else + [ColorUsage( true, true, float.MinValue, float.MinValue, float.MinValue, float.MaxValue )] +#endif + private Color m_materialValue = new Color( 0, 0, 0, 0 ); + + [SerializeField] + private bool m_isHDR = false; + + //[SerializeField] + //private ASEColorSpace m_colorSpace = ASEColorSpace.Auto; +#if !UNITY_2018_1_OR_NEWER + private ColorPickerHDRConfig m_hdrConfig = new ColorPickerHDRConfig( 0, float.MaxValue, 0, float.MaxValue ); +#endif + private GUIContent m_dummyContent; + + private int m_cachedPropertyId = -1; + + private bool m_isEditingFields; + + [SerializeField] + private bool m_autoGammaToLinearConversion = true; + + private const string AutoGammaToLinearConversion = "IsGammaSpace() ? {0} : {1}"; + private const string AutoGammaToLinearStr = "Auto Gamma To Linear"; + + public ColorNode() : base() { } + public ColorNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + GlobalTypeWarningText = string.Format( GlobalTypeWarningText, "Color" ); + m_insideSize.Set( 100, 50 ); + m_dummyContent = new GUIContent(); + AddOutputColorPorts( "RGBA" ); + m_drawPreview = false; + m_drawPreviewExpander = false; + m_canExpand = false; + m_showHybridInstancedUI = true; + m_selectedLocation = PreviewLocation.BottomCenter; + m_previewShaderGUID = "6cf365ccc7ae776488ae8960d6d134c3"; + m_srpBatcherCompatible = true; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_InputColor" ); + + if( m_materialMode && m_currentParameterType != PropertyType.Constant ) + PreviewMaterial.SetColor( m_cachedPropertyId, m_materialValue ); + else + PreviewMaterial.SetColor( m_cachedPropertyId, m_defaultValue ); + } + + public override void CopyDefaultsToMaterial() + { + m_materialValue = m_defaultValue; + } + + public override void DrawSubProperties() + { + m_textLabelWidth = ( m_currentParameterType == PropertyType.Constant ) ? 152 : 105; + +#if UNITY_2018_1_OR_NEWER + m_defaultValue = EditorGUILayoutColorField( Constants.DefaultValueLabelContent, m_defaultValue, false, true, m_isHDR ); +#else + m_defaultValue = EditorGUILayoutColorField( Constants.DefaultValueLabelContent, m_defaultValue, false, true, m_isHDR, m_hdrConfig ); +#endif + if( m_currentParameterType == PropertyType.Constant ) + { + + m_autoGammaToLinearConversion = EditorGUILayoutToggle( AutoGammaToLinearStr, m_autoGammaToLinearConversion ); + } + } + + //public override void DrawMainPropertyBlock() + //{ + // EditorGUILayout.BeginVertical(); + // { + + // PropertyType parameterType = (PropertyType)EditorGUILayoutEnumPopup( ParameterTypeStr, m_currentParameterType ); + // if( parameterType != m_currentParameterType ) + // { + // ChangeParameterType( parameterType ); + // BeginPropertyFromInspectorCheck(); + // } + + // switch( m_currentParameterType ) + // { + // case PropertyType.Property: + // case PropertyType.InstancedProperty: + // { + // ShowPropertyInspectorNameGUI(); + // ShowPropertyNameGUI( true ); + // ShowVariableMode(); + // ShowPrecision(); + // ShowToolbar(); + // } + // break; + // case PropertyType.Global: + // { + // ShowPropertyInspectorNameGUI(); + // ShowPropertyNameGUI( false ); + // ShowVariableMode(); + // ShowPrecision(); + // ShowDefaults(); + // } + // break; + // case PropertyType.Constant: + // { + // ShowPropertyInspectorNameGUI(); + // ShowPrecision(); + // m_colorSpace = (ASEColorSpace)EditorGUILayoutEnumPopup( ColorSpaceStr, m_colorSpace ); + // ShowDefaults(); + // } + // break; + // } + // } + // EditorGUILayout.EndVertical(); + //} + + public override void DrawMaterialProperties() + { + if( m_materialMode ) + EditorGUI.BeginChangeCheck(); +#if UNITY_2018_1_OR_NEWER + m_materialValue = EditorGUILayoutColorField( Constants.MaterialValueLabelContent, m_materialValue, false, true, m_isHDR ); +#else + m_materialValue = EditorGUILayoutColorField( Constants.MaterialValueLabelContent, m_materialValue, false, true, m_isHDR, m_hdrConfig ); +#endif + if( m_materialMode && EditorGUI.EndChangeCheck() ) + m_requireMaterialUpdate = true; + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_propertyDrawPos = m_globalPosition; + m_propertyDrawPos.x = m_remainingBox.x; + m_propertyDrawPos.y = m_remainingBox.y; + m_propertyDrawPos.width = 80 * drawInfo.InvertedZoom; + m_propertyDrawPos.height = m_remainingBox.height; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if( drawInfo.CurrentEventType != EventType.MouseDown ) + return; + + Rect hitBox = m_remainingBox; + //hitBox.xMin -= LabelWidth * drawInfo.InvertedZoom; + bool insideBox = hitBox.Contains( drawInfo.MousePosition ); + + if( insideBox ) + { + m_isEditingFields = true; + } + else if( m_isEditingFields && !insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = false; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( !m_isVisible ) + return; + + if( m_isEditingFields && m_currentParameterType != PropertyType.Global ) + { + if( m_materialMode && m_currentParameterType != PropertyType.Constant ) + { + EditorGUI.BeginChangeCheck(); +#if UNITY_2018_1_OR_NEWER + m_materialValue = EditorGUIColorField( m_propertyDrawPos, m_dummyContent, m_materialValue, false, true, m_isHDR ); +#else + m_materialValue = EditorGUIColorField( m_propertyDrawPos, m_dummyContent, m_materialValue, false, true, m_isHDR, m_hdrConfig ); +#endif + if( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + m_requireMaterialUpdate = true; + if( m_currentParameterType != PropertyType.Constant ) + { + BeginDelayedDirtyProperty(); + } + } + } + else + { + EditorGUI.BeginChangeCheck(); +#if UNITY_2018_1_OR_NEWER + m_defaultValue = EditorGUIColorField( m_propertyDrawPos, m_dummyContent, m_defaultValue, false, true, m_isHDR ); +#else + m_defaultValue = EditorGUIColorField( m_propertyDrawPos, m_dummyContent, m_defaultValue, false, true, m_isHDR, m_hdrConfig ); +#endif + if( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + BeginDelayedDirtyProperty(); + } + } + } + else if( drawInfo.CurrentEventType == EventType.Repaint ) + { + if( m_materialMode && m_currentParameterType != PropertyType.Constant ) + EditorGUIUtility.DrawColorSwatch( m_propertyDrawPos, m_materialValue ); + else + EditorGUIUtility.DrawColorSwatch( m_propertyDrawPos, m_defaultValue ); + + GUI.Label( m_propertyDrawPos, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + } + } + + public override void ConfigureLocalVariable( ref MasterNodeDataCollector dataCollector ) + { + Color color = m_defaultValue; + //switch( m_colorSpace ) + //{ + // default: + // case ASEColorSpace.Auto: color = m_defaultValue; break; + // case ASEColorSpace.Gamma: color = m_defaultValue.gamma; break; + // case ASEColorSpace.Linear: color = m_defaultValue.linear; break; + //} + + dataCollector.AddLocalVariable( UniqueId, CreateLocalVarDec( color.r + "," + color.g + "," + color.b + "," + color.a ) ); + + m_outputPorts[ 0 ].SetLocalValue( m_propertyName , dataCollector.PortCategory); + m_outputPorts[ 1 ].SetLocalValue( m_propertyName + ".r", dataCollector.PortCategory ); + m_outputPorts[ 2 ].SetLocalValue( m_propertyName + ".g", dataCollector.PortCategory ); + m_outputPorts[ 3 ].SetLocalValue( m_propertyName + ".b", dataCollector.PortCategory ); + m_outputPorts[ 4 ].SetLocalValue( m_propertyName + ".a", dataCollector.PortCategory ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + m_precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ); + + if( m_currentParameterType != PropertyType.Constant ) + return GetOutputVectorItem( 0, outputId, PropertyData( dataCollector.PortCategory ) ); + + // Constant Only Code + + if( m_outputPorts[ outputId ].IsLocalValue(dataCollector.PortCategory) ) + { + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + if( m_autoGammaToLinearConversion ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputColorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue(dataCollector.PortCategory) ); + + Color linear = m_defaultValue.linear; + + string colorGamma = m_precisionString + "(" + m_defaultValue.r + "," + m_defaultValue.g + "," + m_defaultValue.b + "," + m_defaultValue.a + ")"; + string colorLinear = m_precisionString + "(" + linear.r + "," + linear.g + "," + linear.b + "," + m_defaultValue.a + ")"; + + string result = string.Format( AutoGammaToLinearConversion, colorGamma, colorLinear ); + RegisterLocalVariable( 0, result, ref dataCollector, "color" + OutputId ); + return GetOutputColorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + else + { + if( CheckLocalVariable( ref dataCollector ) ) + { + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + Color color = m_defaultValue; + //switch( m_colorSpace ) + //{ + // default: + // case ASEColorSpace.Auto: color = m_defaultValue; break; + // case ASEColorSpace.Gamma: color = m_defaultValue.gamma; break; + // case ASEColorSpace.Linear: color = m_defaultValue.linear; break; + //} + string result = string.Empty; + + switch( outputId ) + { + case 0: + { + result = m_precisionString + "(" + color.r + "," + color.g + "," + color.b + "," + color.a + ")"; + } + break; + + case 1: + { + result = color.r.ToString(); + } + break; + case 2: + { + result = color.g.ToString(); + } + break; + case 3: + { + result = color.b.ToString(); + } + break; + case 4: + { + result = color.a.ToString(); + } + break; + } + return result; + } + } + + protected override void OnAtrributesChanged() + { + CheckIfHDR(); + CheckHeaderAttribute(); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + CheckIfHDR(); + } + + void CheckIfHDR() + { + int count = m_selectedAttribs.Count; + bool hdrBuffer = m_isHDR; + m_isHDR = false; + for( int i = 0; i < count; i++ ) + { + if( m_selectedAttribs[ i ] == 1 /*HDR Property ID*/) + { + m_isHDR = true; + break; + } + } + + if( hdrBuffer && !m_isHDR ) + { + bool fireDirtyProperty = false; + + if( m_defaultValue.r > 1 || m_defaultValue.g > 1 || m_defaultValue.b > 1 ) + { + float defaultColorLength = Mathf.Sqrt( m_defaultValue.r * m_defaultValue.r + m_defaultValue.g * m_defaultValue.g + m_defaultValue.b * m_defaultValue.b ); + m_defaultValue.r /= defaultColorLength; + m_defaultValue.g /= defaultColorLength; + m_defaultValue.b /= defaultColorLength; + fireDirtyProperty = true; + } + + if( m_materialValue.r > 1 || m_materialValue.g > 1 || m_materialValue.b > 1 ) + { + float materialColorLength = Mathf.Sqrt( m_materialValue.r * m_materialValue.r + m_materialValue.g * m_materialValue.g + m_materialValue.b * m_materialValue.b ); + m_materialValue.r /= materialColorLength; + m_materialValue.g /= materialColorLength; + m_materialValue.b /= materialColorLength; + fireDirtyProperty = true; + } + + if( fireDirtyProperty ) + BeginDelayedDirtyProperty(); + } + } + + public override string GetPropertyValue() + { + return PropertyAttributes + m_propertyName + "(\"" + m_propertyInspectorName + "\", Color) = (" + m_defaultValue.r + "," + m_defaultValue.g + "," + m_defaultValue.b + "," + m_defaultValue.a + ")"; + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + + if( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction ) + { + mat.SetColor( m_propertyName, m_materialValue ); + } + } + + public override void SetMaterialMode( Material mat, bool fetchMaterialValues ) + { + base.SetMaterialMode( mat, fetchMaterialValues ); + if( m_materialMode && fetchMaterialValues ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && mat.HasProperty( m_propertyName ) ) + MaterialValue = mat.GetColor( m_propertyName ); + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( m_propertyName ) ) + { + MaterialValue = material.GetColor( m_propertyName ); + PreviewIsDirty = true; + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_defaultValue = IOUtils.StringToColor( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 14101 ) + { + m_materialValue = IOUtils.StringToColor( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 15900 ) + { + m_autoGammaToLinearConversion = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + else + { + m_autoGammaToLinearConversion = false; + } + //if( UIUtils.CurrentShaderVersion() > 14202 ) + //{ + // m_colorSpace = (ASEColorSpace)Enum.Parse( typeof( ASEColorSpace ), GetCurrentParam( ref nodeParams ) ); + //} + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.ColorToString( m_defaultValue ) ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.ColorToString( m_materialValue ) ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_autoGammaToLinearConversion ); + //IOUtils.AddFieldValueToString( ref nodeInfo, m_colorSpace ); + } + + public override void SetGlobalValue() { Shader.SetGlobalColor( m_propertyName, m_defaultValue ); } + public override void FetchGlobalValue() { m_materialValue = Shader.GetGlobalColor( m_propertyName ); } + + public override string GetPropertyValStr() + { + return ( m_materialMode && m_currentParameterType != PropertyType.Constant ) ? m_materialValue.r.ToString( Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_materialValue.g.ToString( Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_materialValue.b.ToString( Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_materialValue.a.ToString( Constants.PropertyVectorFormatLabel ) : + m_defaultValue.r.ToString( Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_defaultValue.g.ToString( Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_defaultValue.b.ToString( Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_defaultValue.a.ToString( Constants.PropertyVectorFormatLabel ); + } + + private Color MaterialValue + { + set + { + if( !m_isHDR && ( value.r > 1 || value.g > 1 || value.r > 1 ) ) + { + float materialColorLength = Mathf.Sqrt( value.r * value.r + value.g * value.g + value.b * value.b ); + m_materialValue.r = value.r / materialColorLength; + m_materialValue.g = value.g / materialColorLength; + m_materialValue.b = value.b / materialColorLength; + m_materialValue.a = value.a; + } + else + { + m_materialValue = value; + } + } + } + + public Color Value + { + get { return m_defaultValue; } + set { m_defaultValue = value; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ColorNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ColorNode.cs.meta new file mode 100644 index 0000000..1a21bb5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ColorNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4b99bcf4cd965c648bbbc1de0d1b152a +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GlobalArrayNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GlobalArrayNode.cs new file mode 100644 index 0000000..1e6b924 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GlobalArrayNode.cs @@ -0,0 +1,489 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Global Array +// Donated by Johann van Berkel + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Global Array" , "Constants And Properties" , "The node returns a value from a global array, which you can configure by entering the name of the array in the node's settings." , null , KeyCode.None , true , false , null , null , "Johann van Berkel" )] + public sealed class GlobalArrayNode : ParentNode + { + private const string DefaultArrayName = "MyGlobalArray"; + private const string TypeStr = "Type"; + private const string AutoRangeCheckStr = "Range Check"; + private const string ArrayFormatStr = "{0}[{1}]"; + private const string JaggedArrayFormatStr = "{0}[{1}][{2}]"; + private const string IsJaggedStr = "Is Jagged"; + private const string AutoRegisterStr = "Auto-Register"; + + private readonly string[] AvailableTypesLabel = { "Float" , "Color" , "Vector4" , "Matrix4x4" }; + private readonly WirePortDataType[] AvailableTypesValues = { WirePortDataType.FLOAT , WirePortDataType.COLOR , WirePortDataType.FLOAT4 , WirePortDataType.FLOAT4x4 }; + + [SerializeField] + private string m_name = DefaultArrayName; + + [SerializeField] + private int m_indexX = 0; + + [SerializeField] + private int m_indexY = 0; + + [SerializeField] + private int m_arrayLengthX = 1; + + [SerializeField] + private int m_arrayLengthY = 1; + + [SerializeField] + private int m_type = 0; + + [SerializeField] + private bool m_autoRangeCheck = false; + + [SerializeField] + private bool m_isJagged = false; + + [SerializeField] + private bool m_autoRegister = false; + + ////////////////////////////////////////////////////////////////// + private readonly Color ReferenceHeaderColor = new Color( 0.6f , 3.0f , 1.25f , 1.0f ); + + [SerializeField] + private TexReferenceType m_referenceType = TexReferenceType.Object; + + [SerializeField] + private int m_referenceArrayId = -1; + + [SerializeField] + private int m_referenceNodeId = -1; + + private GlobalArrayNode m_referenceNode = null; + + private bool m_updated = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + + AddInputPort( WirePortDataType.INT , false , "Index" , -1 , MasterNodePortCategory.Fragment , 0 ); + AddInputPort( WirePortDataType.INT , false , "Index Y" , -1 , MasterNodePortCategory.Fragment , 2 ); + AddInputPort( WirePortDataType.INT , false , "Array Length" , -1 , MasterNodePortCategory.Fragment , 1 ); + AddInputPort( WirePortDataType.INT , false , "Array Length Y" , -1 , MasterNodePortCategory.Fragment , 3 ); + + AddOutputPort( WirePortDataType.FLOAT , "Out" ); + + m_textLabelWidth = 95; + m_autoWrapProperties = true; + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr , m_name ) ); + UpdatePorts(); + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + UIUtils.CurrentWindow.OutsideGraph.GlobalArrayNodes.AddNode( this ); + } + + public override void Destroy() + { + base.Destroy(); + UIUtils.CurrentWindow.OutsideGraph.GlobalArrayNodes.RemoveNode( this ); + } + + void UpdatePorts() + { + InputPort indexXPort = GetInputPortByUniqueId( 0 ); + InputPort arrayLengthPortX = GetInputPortByUniqueId( 1 ); + InputPort indexYPort = GetInputPortByUniqueId( 2 ); + InputPort arrayLengthPortY = GetInputPortByUniqueId( 3 ); + if( m_referenceType == TexReferenceType.Object ) + { + m_headerColorModifier = Color.white; + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr , m_name ) ); + arrayLengthPortX.Visible = true; + if( m_isJagged ) + { + indexXPort.Name = "Index X"; + arrayLengthPortX.Name = "Array Length X"; + indexYPort.Visible = true; + arrayLengthPortY.Visible = true; + } + else + { + indexXPort.Name = "Index"; + arrayLengthPortX.Name = "Array Length"; + indexYPort.Visible = false; + arrayLengthPortY.Visible = false; + } + } + else if( m_referenceNodeId > -1 ) + { + m_headerColorModifier = ReferenceHeaderColor; + if( m_referenceNode == null ) + m_referenceNode = UIUtils.GetNode( m_referenceNodeId ) as GlobalArrayNode; + + if( m_referenceNode != null ) + { + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr , m_referenceNode.DataToArray ) ); + arrayLengthPortX.Visible = false; + arrayLengthPortY.Visible = false; + if( m_referenceNode.IsJagged ) + { + indexXPort.Name = "Index X"; + indexYPort.Visible = true; + } + else + { + indexXPort.Name = "Index"; + indexYPort.Visible = false; + } + } + } + m_sizeIsDirty = true; + } + + void DrawObjectProperties() + { + EditorGUI.BeginChangeCheck(); + m_name = EditorGUILayoutStringField( "Name" , m_name ); + if( EditorGUI.EndChangeCheck() ) + { + m_updated = true; + m_name = UIUtils.RemoveInvalidCharacters( m_name ); + if( string.IsNullOrEmpty( m_name ) ) + m_name = DefaultArrayName; + UIUtils.UpdateGlobalArrayDataNode( UniqueId , m_name ); + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr , m_name ) ); + } + + + m_autoRegister = EditorGUILayoutToggle( AutoRegisterStr , m_autoRegister ); + + EditorGUI.BeginChangeCheck(); + m_isJagged = EditorGUILayoutToggle( IsJaggedStr , m_isJagged ); + if( EditorGUI.EndChangeCheck() ) + { + m_updated = true; + UpdatePorts(); + } + + InputPort indexXPort = GetInputPortByUniqueId( 0 ); + if( !indexXPort.IsConnected ) + { + EditorGUI.BeginChangeCheck(); + m_indexX = EditorGUILayoutIntField( indexXPort.Name , m_indexX ); + if( EditorGUI.EndChangeCheck() ) + { + m_indexX = Mathf.Clamp( m_indexX , 0 , ( ArrayLengthX - 1 ) ); + } + } + + if( m_isJagged ) + { + InputPort indexYPort = GetInputPortByUniqueId( 2 ); + if( !indexYPort.IsConnected ) + { + EditorGUI.BeginChangeCheck(); + m_indexY = EditorGUILayoutIntField( indexYPort.Name , m_indexY ); + if( EditorGUI.EndChangeCheck() ) + { + m_indexY = Mathf.Clamp( m_indexY , 0 , ( ArrayLengthY - 1 ) ); + } + } + } + + InputPort arrayLengthXPort = GetInputPortByUniqueId( 1 ); + if( !arrayLengthXPort.IsConnected ) + { + EditorGUI.BeginChangeCheck(); + m_arrayLengthX = EditorGUILayoutIntField( arrayLengthXPort.Name , m_arrayLengthX ); + if( EditorGUI.EndChangeCheck() ) + { + m_arrayLengthX = Mathf.Max( 1 , m_arrayLengthX ); + } + } + + if( m_isJagged ) + { + InputPort arrayLengthYPort = GetInputPortByUniqueId( 3 ); + if( !arrayLengthYPort.IsConnected ) + { + EditorGUI.BeginChangeCheck(); + m_arrayLengthY = EditorGUILayoutIntField( arrayLengthYPort.Name , m_arrayLengthY ); + if( EditorGUI.EndChangeCheck() ) + { + m_arrayLengthY = Mathf.Max( 1 , m_arrayLengthY ); + } + } + } + + EditorGUI.BeginChangeCheck(); + m_type = EditorGUILayoutPopup( TypeStr , m_type , AvailableTypesLabel ); + if( EditorGUI.EndChangeCheck() ) + { + m_outputPorts[ 0 ].ChangeType( (WirePortDataType)AvailableTypesValues[ m_type ] , false ); + } + + m_autoRangeCheck = EditorGUILayoutToggle( AutoRangeCheckStr , m_autoRangeCheck ); + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + m_updated = false; + if( m_referenceType == TexReferenceType.Instance ) + { + if( m_referenceNodeId > -1 && m_referenceNode == null ) + { + m_referenceNode = UIUtils.GetNode( m_referenceNodeId ) as GlobalArrayNode; + if( m_referenceNode == null ) + { + m_referenceNodeId = -1; + } + } + if( m_referenceNode != null && m_referenceNode.Updated ) + { + UpdatePorts(); + } + } + } + + void DrawInstancedProperties() + { + string[] arr = UIUtils.GlobalArrayNodeArr(); + bool guiEnabledBuffer = GUI.enabled; + if( arr != null && arr.Length > 0 ) + { + GUI.enabled = true; + } + else + { + m_referenceArrayId = -1; + m_referenceNodeId = -1; + m_referenceNode = null; + GUI.enabled = false; + } + EditorGUI.BeginChangeCheck(); + m_referenceArrayId = EditorGUILayoutPopup( Constants.AvailableReferenceStr , m_referenceArrayId , arr ); + if( EditorGUI.EndChangeCheck() ) + { + m_referenceNode = UIUtils.GetGlobalArrayNode( m_referenceArrayId ); + if( m_referenceNode != null ) + { + m_referenceNodeId = m_referenceNode.UniqueId; + } + UpdatePorts(); + } + + GUI.enabled = guiEnabledBuffer; + + InputPort indexXPort = GetInputPortByUniqueId( 0 ); + if( !indexXPort.IsConnected ) + { + EditorGUI.BeginChangeCheck(); + m_indexX = EditorGUILayoutIntField( indexXPort.Name , m_indexX ); + if( EditorGUI.EndChangeCheck() ) + { + m_indexX = Mathf.Clamp( m_indexX , 0 , ( ArrayLengthX - 1 ) ); + } + } + + if( m_isJagged ) + { + InputPort indexYPort = GetInputPortByUniqueId( 2 ); + if( !indexYPort.IsConnected ) + { + EditorGUI.BeginChangeCheck(); + m_indexY = EditorGUILayoutIntField( indexYPort.Name , m_indexY ); + if( EditorGUI.EndChangeCheck() ) + { + m_indexY = Mathf.Clamp( m_indexY , 0 , ( ArrayLengthY - 1 ) ); + } + } + } + } + + public override void DrawProperties() + { + EditorGUI.BeginChangeCheck(); + m_referenceType = (TexReferenceType)EditorGUILayoutPopup( Constants.ReferenceTypeStr , (int)m_referenceType , Constants.ReferenceArrayLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePorts(); + } + + if( m_referenceType == TexReferenceType.Object ) + DrawObjectProperties(); + else + DrawInstancedProperties(); + } + + public string GetArrayValue( string indexX , string indexY = null ) + { + if( m_isJagged ) + return string.Format( JaggedArrayFormatStr , m_name , indexX , indexY ); + + return string.Format( ArrayFormatStr , m_name , indexX ); + } + + public string GenerateInstancedShaderForOutput( int outputId , ref MasterNodeDataCollector dataCollector , bool ignoreLocalvar ) + { + string result = string.Empty; + if( m_referenceNode != null ) + { + InputPort indexXPort = GetInputPortByUniqueId( 0 ); + if( m_referenceNode.IsJagged ) + { + InputPort indexYPort = GetInputPortByUniqueId( 2 ); + string arrayIndexX = indexXPort.IsConnected ? indexXPort.GeneratePortInstructions( ref dataCollector ) : m_indexX.ToString(); + string arrayIndexY = indexYPort.IsConnected ? indexYPort.GeneratePortInstructions( ref dataCollector ) : m_indexY.ToString(); + result = m_referenceNode.GetArrayValue( arrayIndexX , arrayIndexY ); + } + else + { + string arrayIndexX = indexXPort.IsConnected ? indexXPort.GeneratePortInstructions( ref dataCollector ) : m_indexX.ToString(); + result = m_referenceNode.GetArrayValue( arrayIndexX ); + } + } + m_outputPorts[ 0 ].SetLocalValue( result , dataCollector.PortCategory ); + return result; + } + + public override string GenerateShaderForOutput( int outputId , ref MasterNodeDataCollector dataCollector , bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + if( m_referenceType == TexReferenceType.Instance ) + return GenerateInstancedShaderForOutput( outputId , ref dataCollector , ignoreLocalvar ); + + string dataType = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType , AvailableTypesValues[ m_type ] ); + + InputPort indexXPort = GetInputPortByUniqueId( 0 ); + InputPort arrayLengthXPort = GetInputPortByUniqueId( 1 ); + string result = string.Empty; + + if( m_isJagged ) + { + InputPort indexYPort = GetInputPortByUniqueId( 2 ); + InputPort arrayLengthYPort = GetInputPortByUniqueId( 3 ); + + string arrayIndexX = indexXPort.IsConnected ? indexXPort.GeneratePortInstructions( ref dataCollector ) : m_indexX.ToString(); + string arrayLengthX = arrayLengthXPort.IsConnected ? arrayLengthXPort.GeneratePortInstructions( ref dataCollector ) : ArrayLengthX.ToString(); + + string arrayIndexY = indexYPort.IsConnected ? indexYPort.GeneratePortInstructions( ref dataCollector ) : m_indexY.ToString(); + string arrayLengthY = arrayLengthYPort.IsConnected ? arrayLengthYPort.GeneratePortInstructions( ref dataCollector ) : ArrayLengthY.ToString(); + + dataCollector.AddToUniforms( UniqueId , dataType , string.Format( JaggedArrayFormatStr , m_name , arrayLengthX , arrayLengthY ) ); + if( m_autoRangeCheck ) + { + arrayIndexX = string.Format( "clamp({0},0,({1} - 1))" , arrayIndexX , arrayLengthX ); + arrayIndexY = string.Format( "clamp({0},0,({1} - 1))" , arrayIndexY , arrayLengthY ); + } + result = string.Format( JaggedArrayFormatStr , m_name , arrayIndexX , arrayIndexY ); + } + else + { + + string arrayIndex = indexXPort.IsConnected ? indexXPort.GeneratePortInstructions( ref dataCollector ) : m_indexX.ToString(); + string arrayLength = arrayLengthXPort.IsConnected ? arrayLengthXPort.GeneratePortInstructions( ref dataCollector ) : ArrayLengthX.ToString(); + + + dataCollector.AddToUniforms( UniqueId , dataType , string.Format( ArrayFormatStr , m_name , arrayLength ) ); + + if( m_autoRangeCheck ) + arrayIndex = string.Format( "clamp({0},0,({1} - 1))" , arrayIndex , arrayLength ); + + result = string.Format( ArrayFormatStr , m_name , arrayIndex ); + } + + m_outputPorts[ 0 ].SetLocalValue( result , dataCollector.PortCategory ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public void CheckIfAutoRegister( ref MasterNodeDataCollector dataCollector ) + { + if( m_referenceType == TexReferenceType.Object && m_autoRegister && m_connStatus != NodeConnectionStatus.Connected ) + { + string dataType = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType , AvailableTypesValues[ m_type ] ); + if( m_isJagged ) + { + dataCollector.AddToUniforms( UniqueId , dataType , string.Format( JaggedArrayFormatStr , m_name , ArrayLengthX , ArrayLengthY ) ); + } + else + { + dataCollector.AddToUniforms( UniqueId , dataType , string.Format( ArrayFormatStr , m_name , ArrayLengthX ) ); + } + } + } + + public override void WriteToString( ref string nodeInfo , ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo , ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_name ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_indexX ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_arrayLengthX ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_type ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_autoRangeCheck ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_isJagged ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_indexY ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_arrayLengthY ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_autoRegister ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_referenceType ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_referenceNodeId ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_name = GetCurrentParam( ref nodeParams ); + m_indexX = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_arrayLengthX = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_type = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_autoRangeCheck = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 15801 ) + { + m_isJagged = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_indexY = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_arrayLengthY = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_autoRegister = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_referenceType = (TexReferenceType)Enum.Parse( typeof( TexReferenceType ) , GetCurrentParam( ref nodeParams ) ); + m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr , m_name ) ); + UpdatePorts(); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( m_referenceType == TexReferenceType.Instance && m_referenceNodeId > -1 ) + { + m_referenceNode = UIUtils.GetNode( m_referenceNodeId ) as GlobalArrayNode; + if( m_referenceNode != null ) + { + m_referenceArrayId = UIUtils.GetGlobalArrayNodeRegisterId( m_referenceNodeId ); + UpdatePorts(); + } + else + { + m_referenceNodeId = -1; + } + } + } + public int ArrayLengthX { get { return ( m_referenceNode != null ) ? m_referenceNode.ArrayLengthX : m_arrayLengthX; } } + public int ArrayLengthY { get { return ( m_referenceNode != null ) ? m_referenceNode.ArrayLengthY : m_arrayLengthY; } } + + public bool AutoRegister { get { return m_autoRegister; } } + public bool IsJagged { get { return m_isJagged; } } + public bool Updated { get { return m_updated; } } + public override string DataToArray { get { return m_name; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GlobalArrayNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GlobalArrayNode.cs.meta new file mode 100644 index 0000000..c017121 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GlobalArrayNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 833b18e1479dbd24c80c5b990e16e2bb +timeCreated: 1499769855 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GradientNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GradientNode.cs new file mode 100644 index 0000000..ca7aff0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GradientNode.cs @@ -0,0 +1,230 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Reflection; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Gradient", "Constants And Properties", "Gradient property" )] + public sealed class GradientNode : ParentNode + { + [SerializeField] + private Gradient m_gradient = new Gradient(); + + private string m_functionHeader = "NewGradient( {0}, {1}, {2}," + + " {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}," + + " {11}, {12}, {13}, {14}, {15}, {16}, {17}, {18} )"; + private string m_functionBody = string.Empty; + + private string m_functionHeaderStruct = "Gradient( {0} )"; + private string m_functionBodyStruct = string.Empty; + + public Gradient Gradient { get { return m_gradient; } } + + public GradientNode() : base() { } + public GradientNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_insideSize.Set( 128, m_insideSize.y ); + AddOutputPort( WirePortDataType.OBJECT, Constants.EmptyPortValue ); + m_autoWrapProperties = true; + m_textLabelWidth = 100; + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_gradient = EditorGUILayoutEx.GradientField( "Gradient", m_gradient ); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( !m_isVisible ) + return; + + m_gradient = EditorGUIEx.GradientField( m_remainingBox, m_gradient ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + m_functionBodyStruct = string.Empty; + m_functionBody = string.Empty; + if( !dataCollector.IsSRP ) + { + GenerateGradientStruct( ref m_functionBodyStruct ); + dataCollector.AddFunctions( m_functionHeaderStruct, m_functionBodyStruct, "0" ); + GenerateGradient( ref m_functionBody ); + } + else + { + dataCollector.AddToIncludes( UniqueId, "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" ); + } + + string[] colors = new string[ 8 ]; + for( int i = 0; i < 8; i++ ) + { + if( i < m_gradient.colorKeys.Length ) + { + colors[ i ] = "float4( " + m_gradient.colorKeys[ i ].color.r + ", " + m_gradient.colorKeys[ i ].color.g + ", " + m_gradient.colorKeys[ i ].color.b + ", " + m_gradient.colorKeys[ i ].time + " )"; + } + else + { + colors[ i ] = "0"; + } + } + + string[] alphas = new string[ 8 ]; + for( int i = 0; i < 8; i++ ) + { + if( i < m_gradient.alphaKeys.Length ) + { + alphas[ i ] = "float2( " + m_gradient.alphaKeys[ i ].alpha + ", " + m_gradient.alphaKeys[ i ].time + " )"; + } + else + { + alphas[ i ] = "0"; + } + } + + string functionResult = dataCollector.AddFunctions( m_functionHeader, m_functionBody, (int)m_gradient.mode, m_gradient.colorKeys.Length, m_gradient.alphaKeys.Length + , colors[ 0 ], colors[ 1 ], colors[ 2 ], colors[ 3 ], colors[ 4 ], colors[ 5 ], colors[ 6 ], colors[ 7 ] + , alphas[ 0 ], alphas[ 1 ], alphas[ 2 ], alphas[ 3 ], alphas[ 4 ], alphas[ 5 ], alphas[ 6 ], alphas[ 7 ] ); + + dataCollector.AddLocalVariable( UniqueId, "Gradient gradient" + OutputId + " = " + functionResult + ";" ); + + return "gradient" + OutputId; + } + + public static void GenerateGradientStruct( ref string body ) + { + body = string.Empty; + IOUtils.AddFunctionHeader( ref body, "struct Gradient" ); + IOUtils.AddFunctionLine( ref body, "int type;" ); + IOUtils.AddFunctionLine( ref body, "int colorsLength;" ); + IOUtils.AddFunctionLine( ref body, "int alphasLength;" ); + IOUtils.AddFunctionLine( ref body, "float4 colors[8];" ); + IOUtils.AddFunctionLine( ref body, "float2 alphas[8];" ); + IOUtils.AddSingleLineFunction( ref body, "};\n" ); + } + + public static void GenerateGradient( ref string body ) + { + body = string.Empty; + IOUtils.AddFunctionHeader( ref body, "Gradient NewGradient(int type, int colorsLength, int alphasLength, \n\t\tfloat4 colors0, float4 colors1, float4 colors2, float4 colors3, float4 colors4, float4 colors5, float4 colors6, float4 colors7,\n\t\tfloat2 alphas0, float2 alphas1, float2 alphas2, float2 alphas3, float2 alphas4, float2 alphas5, float2 alphas6, float2 alphas7)" ); + IOUtils.AddFunctionLine( ref body, "Gradient g;" ); + IOUtils.AddFunctionLine( ref body, "g.type = type;" ); + IOUtils.AddFunctionLine( ref body, "g.colorsLength = colorsLength;" ); + IOUtils.AddFunctionLine( ref body, "g.alphasLength = alphasLength;" ); + IOUtils.AddFunctionLine( ref body, "g.colors[ 0 ] = colors0;" ); + IOUtils.AddFunctionLine( ref body, "g.colors[ 1 ] = colors1;" ); + IOUtils.AddFunctionLine( ref body, "g.colors[ 2 ] = colors2;" ); + IOUtils.AddFunctionLine( ref body, "g.colors[ 3 ] = colors3;" ); + IOUtils.AddFunctionLine( ref body, "g.colors[ 4 ] = colors4;" ); + IOUtils.AddFunctionLine( ref body, "g.colors[ 5 ] = colors5;" ); + IOUtils.AddFunctionLine( ref body, "g.colors[ 6 ] = colors6;" ); + IOUtils.AddFunctionLine( ref body, "g.colors[ 7 ] = colors7;" ); + IOUtils.AddFunctionLine( ref body, "g.alphas[ 0 ] = alphas0;" ); + IOUtils.AddFunctionLine( ref body, "g.alphas[ 1 ] = alphas1;" ); + IOUtils.AddFunctionLine( ref body, "g.alphas[ 2 ] = alphas2;" ); + IOUtils.AddFunctionLine( ref body, "g.alphas[ 3 ] = alphas3;" ); + IOUtils.AddFunctionLine( ref body, "g.alphas[ 4 ] = alphas4;" ); + IOUtils.AddFunctionLine( ref body, "g.alphas[ 5 ] = alphas5;" ); + IOUtils.AddFunctionLine( ref body, "g.alphas[ 6 ] = alphas6;" ); + IOUtils.AddFunctionLine( ref body, "g.alphas[ 7 ] = alphas7;" ); + IOUtils.AddFunctionLine( ref body, "return g;" ); + IOUtils.CloseFunctionBody( ref body ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_gradient.mode = (GradientMode)Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + int colorCount = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + int alphaCount = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + + var colorKeys = new GradientColorKey[ colorCount ]; + for( int i = 0; i < colorCount; i++ ) + { + Vector4 colorKey = IOUtils.StringToVector4( GetCurrentParam( ref nodeParams ) ); + colorKeys[ i ].color = colorKey; + colorKeys[ i ].time = colorKey.w; + } + m_gradient.colorKeys = colorKeys; + + var alphaKeys = new GradientAlphaKey[ alphaCount ]; + for( int i = 0; i < alphaCount; i++ ) + { + Vector2 alphaKey = IOUtils.StringToVector2( GetCurrentParam( ref nodeParams ) ); + alphaKeys[ i ].alpha = alphaKey.x; + alphaKeys[ i ].time = alphaKey.y; + } + m_gradient.alphaKeys = alphaKeys; + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, (int)m_gradient.mode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_gradient.colorKeys.Length ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_gradient.alphaKeys.Length ); + + for( int i = 0; i < m_gradient.colorKeys.Length; i++ ) + { + Vector4 colorKey = new Vector4( m_gradient.colorKeys[ i ].color.r, m_gradient.colorKeys[ i ].color.g, m_gradient.colorKeys[ i ].color.b, m_gradient.colorKeys[ i ].time ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Vector4ToString( colorKey ) ); + } + + for( int i = 0; i < m_gradient.alphaKeys.Length; i++ ) + { + Vector2 alphaKey = new Vector4( m_gradient.alphaKeys[ i ].alpha, m_gradient.alphaKeys[ i ].time ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Vector2ToString( alphaKey ) ); + } + } + } + + internal static class EditorGUILayoutEx + { + public static System.Type Type = typeof( EditorGUILayout ); + public static Gradient GradientField( Gradient value, params GUILayoutOption[] options ) + { +#if UNITY_2018_3_OR_NEWER + return EditorGUILayout.GradientField( value, options ); +#else + MethodInfo method = EditorGUILayoutEx.Type.GetMethod( "GradientField", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof( Gradient ), typeof( GUILayoutOption[] ) }, null ); + return (Gradient)method.Invoke( Type, new object[] { value, options } ); +#endif + } + + public static Gradient GradientField( string label, Gradient value, params GUILayoutOption[] options ) + { +#if UNITY_2018_3_OR_NEWER + return EditorGUILayout.GradientField( label, value, options ); +#else + MethodInfo method = EditorGUILayoutEx.Type.GetMethod( "GradientField", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof( string ), typeof( Gradient ), typeof( GUILayoutOption[] ) }, null ); + return (Gradient)method.Invoke( Type, new object[] { label, value, options } ); +#endif + } + } + + internal static class EditorGUIEx + { + public static System.Type Type = typeof( EditorGUI ); + + public static Gradient GradientField( Rect position, Gradient gradient ) + { +#if UNITY_2018_3_OR_NEWER + return EditorGUI.GradientField( position, gradient ); +#else + return (Gradient)EditorGUIEx.Type.InvokeMember( "GradientField", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { position, gradient } ); +#endif + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GradientNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GradientNode.cs.meta new file mode 100644 index 0000000..cb9b560 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/GradientNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 98100a8a545b8ce42bc5657fd40a24a5 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/IntNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/IntNode.cs new file mode 100644 index 0000000..f90df63 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/IntNode.cs @@ -0,0 +1,300 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Int", "Constants And Properties", "Int property", null, KeyCode.Alpha0 )] + public sealed class IntNode : PropertyNode + { + [SerializeField] + private int m_defaultValue; + + [SerializeField] + private int m_materialValue; + + [SerializeField] + private bool m_setAsUINT = false; + + private const float LabelWidth = 8; + + private int m_cachedPropertyId = -1; + + private bool m_isEditingFields; + private int m_previousValue; + private string m_fieldText = "0"; + + public IntNode() : base() { } + public IntNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + GlobalTypeWarningText = string.Format( GlobalTypeWarningText, "Int" ); + AddOutputPort( WirePortDataType.INT, Constants.EmptyPortValue ); + m_insideSize.Set( 50, 10 ); + m_selectedLocation = PreviewLocation.BottomCenter; + m_drawPrecisionUI = false; + m_showHybridInstancedUI = true; + m_availableAttribs.Add( new PropertyAttributes( "Enum", "[Enum]" ) ); + m_previewShaderGUID = "0f64d695b6ffacc469f2dd31432a232a"; + m_srpBatcherCompatible = true; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + UIUtils.RegisterFloatIntNode( this ); + } + + public override void Destroy() + { + base.Destroy(); + UIUtils.UnregisterFloatIntNode( this ); + } + + public override void OnDirtyProperty() + { + UIUtils.UpdateFloatIntDataNode( UniqueId, PropertyInspectorName ); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + OnPropertyNameChanged(); + OnDirtyProperty(); + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_InputInt" ); + + if( m_materialMode && m_currentParameterType != PropertyType.Constant ) + PreviewMaterial.SetInt( m_cachedPropertyId, m_materialValue ); + else + PreviewMaterial.SetInt( m_cachedPropertyId, m_defaultValue ); + } + + + public override void CopyDefaultsToMaterial() + { + m_materialValue = m_defaultValue; + DrawSetAsUINT(); + } + + public override void DrawSubProperties() + { + m_defaultValue = EditorGUILayoutIntField( Constants.DefaultValueLabel, m_defaultValue ); + DrawSetAsUINT(); + } + + private void DrawSetAsUINT() + { + EditorGUI.BeginChangeCheck(); + m_setAsUINT = EditorGUILayoutToggle( "Set as UINT", m_setAsUINT ); + if( EditorGUI.EndChangeCheck() ) + { + WirePortDataType portType = m_setAsUINT ? WirePortDataType.UINT : WirePortDataType.INT; + m_outputPorts[ 0 ].ChangeType( portType, false ); + } + } + + public override void DrawMaterialProperties() + { + if( m_materialMode ) + EditorGUI.BeginChangeCheck(); + + m_materialValue = EditorGUILayoutIntField( Constants.MaterialValueLabel, m_materialValue ); + + if( m_materialMode && EditorGUI.EndChangeCheck() ) + { + m_requireMaterialUpdate = true; + } + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_propertyDrawPos = m_remainingBox; + m_propertyDrawPos.x = m_remainingBox.x - LabelWidth * drawInfo.InvertedZoom; + m_propertyDrawPos.width = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_WIDTH_FIELD_SIZE; + m_propertyDrawPos.height = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if( drawInfo.CurrentEventType != EventType.MouseDown ) + return; + + Rect hitBox = m_remainingBox; + hitBox.xMin -= LabelWidth * drawInfo.InvertedZoom; + bool insideBox = hitBox.Contains( drawInfo.MousePosition ); + + if( insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = true; + } + else if( m_isEditingFields && !insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = false; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( !m_isVisible ) + return; + + if( m_isEditingFields && m_currentParameterType != PropertyType.Global ) + { + float labelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = LabelWidth * drawInfo.InvertedZoom; + + if( m_materialMode && m_currentParameterType != PropertyType.Constant ) + { + EditorGUI.BeginChangeCheck(); + m_materialValue = EditorGUIIntField( m_propertyDrawPos, " ", m_materialValue, UIUtils.MainSkin.textField ); + if( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + m_requireMaterialUpdate = true; + if( m_currentParameterType != PropertyType.Constant ) + BeginDelayedDirtyProperty(); + } + } + else + { + EditorGUI.BeginChangeCheck(); + + m_defaultValue = EditorGUIIntField( m_propertyDrawPos, " ", m_defaultValue, UIUtils.MainSkin.textField ); + + if( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + BeginDelayedDirtyProperty(); + } + } + EditorGUIUtility.labelWidth = labelWidth; + } + else if( drawInfo.CurrentEventType == EventType.Repaint ) + { + bool guiEnabled = GUI.enabled; + GUI.enabled = m_currentParameterType != PropertyType.Global; + Rect fakeField = m_propertyDrawPos; + fakeField.xMin += LabelWidth * drawInfo.InvertedZoom; + if( GUI.enabled ) + { + Rect fakeLabel = m_propertyDrawPos; + fakeLabel.xMax = fakeField.xMin; + EditorGUIUtility.AddCursorRect( fakeLabel, MouseCursor.SlideArrow ); + EditorGUIUtility.AddCursorRect( fakeField, MouseCursor.Text ); + } + bool currMode = m_materialMode && m_currentParameterType != PropertyType.Constant; + int value = currMode ? m_materialValue : m_defaultValue; + + if( m_previousValue != value ) + { + m_previousValue = value; + m_fieldText = value.ToString(); + } + + GUI.Label( fakeField, m_fieldText, UIUtils.MainSkin.textField ); + GUI.enabled = guiEnabled; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + + if( m_currentParameterType != PropertyType.Constant ) + return PropertyData( dataCollector.PortCategory ); + + return m_defaultValue.ToString(); + } + + public override string GetPropertyValue() + { + return PropertyAttributes + m_propertyName + "(\"" + m_propertyInspectorName + "\", Int) = " + m_defaultValue; + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction ) + { + mat.SetInt( m_propertyName, m_materialValue ); + } + } + + public override void SetMaterialMode( Material mat, bool fetchMaterialValues ) + { + base.SetMaterialMode( mat, fetchMaterialValues ); + if( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) && mat.HasProperty( m_propertyName ) ) + { + m_materialValue = mat.GetInt( m_propertyName ); + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( m_propertyName ) ) + { + m_materialValue = material.GetInt( m_propertyName ); + PreviewIsDirty = true; + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_defaultValue = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 14101 ) + m_materialValue = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 18500 ) + m_setAsUINT = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_materialValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_setAsUINT ); + } + + public override string GetPropertyValStr() + { + return ( m_materialMode && m_currentParameterType != PropertyType.Constant ) ? + m_materialValue.ToString( Mathf.Abs( m_materialValue ) > 1000 ? Constants.PropertyBigIntFormatLabel : Constants.PropertyIntFormatLabel ) : + m_defaultValue.ToString( Mathf.Abs( m_defaultValue ) > 1000 ? Constants.PropertyBigIntFormatLabel : Constants.PropertyIntFormatLabel ); + } + + public override void SetGlobalValue() { Shader.SetGlobalInt( m_propertyName, m_defaultValue ); } + public override void FetchGlobalValue() { m_materialValue = Shader.GetGlobalInt( m_propertyName ); } + public int Value + { + get { return m_defaultValue; } + set { m_defaultValue = value; } + } + + public void SetMaterialValueFromInline( int val ) + { + m_materialValue = val; + m_requireMaterialUpdate = true; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/IntNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/IntNode.cs.meta new file mode 100644 index 0000000..0bbac6f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/IntNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 86df2da3da3b1eb4493b968b47030b17 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix3X3Node.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix3X3Node.cs new file mode 100644 index 0000000..02266c8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix3X3Node.cs @@ -0,0 +1,261 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Matrix3X3", "Constants And Properties", "Matrix3X3 property" )] + public sealed class Matrix3X3Node : MatrixParentNode + { + private string[,] m_fieldText = new string[ 3, 3 ] { { "0", "0", "0" }, { "0", "0", "0" }, { "0", "0", "0" } }; + public Matrix3X3Node() : base() { } + public Matrix3X3Node( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + GlobalTypeWarningText = string.Format( GlobalTypeWarningText, "Matrix" ); + AddOutputPort( WirePortDataType.FLOAT3x3, Constants.EmptyPortValue ); + m_insideSize.Set( Constants.FLOAT_DRAW_WIDTH_FIELD_SIZE * 3 + Constants.FLOAT_WIDTH_SPACING * 2, Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE * 3 + Constants.FLOAT_WIDTH_SPACING * 2 + Constants.OUTSIDE_WIRE_MARGIN ); + //m_defaultValue = new Matrix4x4(); + //m_materialValue = new Matrix4x4(); + m_drawPreview = false; + } + + public override void CopyDefaultsToMaterial() + { + m_materialValue = m_defaultValue; + } + + public override void DrawSubProperties() + { + EditorGUILayout.LabelField( Constants.DefaultValueLabel ); + for( int row = 0; row < 3; row++ ) + { + EditorGUILayout.BeginHorizontal(); + for( int column = 0; column < 3; column++ ) + { + m_defaultValue[ row, column ] = EditorGUILayoutFloatField( string.Empty, m_defaultValue[ row, column ], GUILayout.MaxWidth( 76 ) ); + } + EditorGUILayout.EndHorizontal(); + } + } + + public override void DrawMaterialProperties() + { + if( m_materialMode ) + EditorGUI.BeginChangeCheck(); + + EditorGUILayout.LabelField( Constants.MaterialValueLabel ); + for( int row = 0; row < 3; row++ ) + { + EditorGUILayout.BeginHorizontal(); + for( int column = 0; column < 3; column++ ) + { + m_materialValue[ row, column ] = EditorGUILayoutFloatField( string.Empty, m_materialValue[ row, column ], GUILayout.MaxWidth( 76 ) ); + } + EditorGUILayout.EndHorizontal(); + } + + if( m_materialMode && EditorGUI.EndChangeCheck() ) + m_requireMaterialUpdate = true; + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_propertyDrawPos.position = m_remainingBox.position; + m_propertyDrawPos.width = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_WIDTH_FIELD_SIZE; + m_propertyDrawPos.height = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if( drawInfo.CurrentEventType != EventType.MouseDown ) + return; + + Rect hitBox = m_remainingBox; + hitBox.height = m_insideSize.y * drawInfo.InvertedZoom; + bool insideBox = hitBox.Contains( drawInfo.MousePosition ); + + if( insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = true; + } + else if( m_isEditingFields && !insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = false; + } + } + + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( !m_isVisible ) + return; + + if( m_isEditingFields && m_currentParameterType != PropertyType.Global ) + { + bool currMode = m_materialMode && m_currentParameterType != PropertyType.Constant; + Matrix4x4 value = currMode ? m_materialValue : m_defaultValue; + + EditorGUI.BeginChangeCheck(); + for( int row = 0; row < 3; row++ ) + { + for( int column = 0; column < 3; column++ ) + { + m_propertyDrawPos.position = m_remainingBox.position + Vector2.Scale( m_propertyDrawPos.size, new Vector2( column, row ) ) + new Vector2( Constants.FLOAT_WIDTH_SPACING * drawInfo.InvertedZoom * column, Constants.FLOAT_WIDTH_SPACING * drawInfo.InvertedZoom * row ); + value[ row, column ] = EditorGUIFloatField( m_propertyDrawPos, string.Empty, value[ row, column ], UIUtils.MainSkin.textField ); + } + } + + if( currMode ) + { + m_materialValue = value; + } + else + { + m_defaultValue = value; + } + + if( EditorGUI.EndChangeCheck() ) + { + m_requireMaterialUpdate = m_materialMode; + BeginDelayedDirtyProperty(); + } + } + else if( drawInfo.CurrentEventType == EventType.Repaint ) + { + bool guiEnabled = GUI.enabled; + GUI.enabled = m_currentParameterType != PropertyType.Global; + + bool currMode = m_materialMode && m_currentParameterType != PropertyType.Constant; + Matrix4x4 value = currMode ? m_materialValue : m_defaultValue; + for( int row = 0; row < 3; row++ ) + { + for( int column = 0; column < 3; column++ ) + { + Rect fakeField = m_propertyDrawPos; + fakeField.position = m_remainingBox.position + Vector2.Scale( m_propertyDrawPos.size, new Vector2( column, row ) ) + new Vector2( Constants.FLOAT_WIDTH_SPACING * drawInfo.InvertedZoom * column, Constants.FLOAT_WIDTH_SPACING * drawInfo.InvertedZoom * row ); + if( GUI.enabled ) + EditorGUIUtility.AddCursorRect( fakeField, MouseCursor.Text ); + + if( m_previousValue[ row, column ] != value[ row, column ] ) + { + m_previousValue[ row, column ] = value[ row, column ]; + m_fieldText[ row, column ] = value[ row, column ].ToString(); + } + + GUI.Label( fakeField, m_fieldText[ row, column ], UIUtils.MainSkin.textField ); + } + } + GUI.enabled = guiEnabled; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + m_precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ); + if( m_currentParameterType != PropertyType.Constant ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + string localVarName = PropertyData( dataCollector.PortCategory ) + "Local3x3"; + string localVarValue = string.Format( "float3x3({0}._m00,{0}._m01,{0}._m02,{0}._m10,{0}._m11,{0}._m12,{0}._m20,{0}._m21,{0}._m22 )", PropertyData( dataCollector.PortCategory ) ); + RegisterLocalVariable( 0, localVarValue, ref dataCollector, localVarName ); + return localVarName; + } + + Matrix4x4 value = m_defaultValue; + + return m_precisionString + "(" + value[ 0, 0 ] + "," + value[ 0, 1 ] + "," + value[ 0, 2 ] + "," + + +value[ 1, 0 ] + "," + value[ 1, 1 ] + "," + value[ 1, 2 ] + "," + + +value[ 2, 0 ] + "," + value[ 2, 1 ] + "," + value[ 2, 2 ] + ")"; + + } + + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction ) + { + Shader.SetGlobalMatrix( m_propertyName, m_materialValue ); + //mat.SetMatrix( m_propertyName, m_materialValue ); + } + } + + public override bool GetUniformData( out string dataType, out string dataName, ref bool fullValue ) + { + dataType = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, WirePortDataType.FLOAT4x4 ); + dataName = m_propertyName; + return true; + } + + public override void SetMaterialMode( Material mat, bool fetchMaterialValues ) + { + base.SetMaterialMode( mat, fetchMaterialValues ); + if( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) && mat.HasProperty( m_propertyName ) ) + { + m_materialValue = mat.GetMatrix( m_propertyName ); + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( m_propertyName ) ) + { + m_materialValue = material.GetMatrix( m_propertyName ); + PreviewIsDirty = true; + } + } + + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_defaultValue = IOUtils.StringToMatrix3x3( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Matrix3x3ToString( m_defaultValue ) ); + } + + public override void ReadAdditionalClipboardData( ref string[] nodeParams ) + { + base.ReadAdditionalClipboardData( ref nodeParams ); + m_materialValue = IOUtils.StringToMatrix3x3( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteAdditionalClipboardData( ref string nodeInfo ) + { + base.WriteAdditionalClipboardData( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Matrix3x3ToString( m_materialValue ) ); + } + + public override string GetPropertyValStr() + { + return ( m_materialMode && m_currentParameterType != PropertyType.Constant ) ? m_materialValue[ 0, 0 ].ToString( Mathf.Abs( m_materialValue[ 0, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 0, 1 ].ToString( Mathf.Abs( m_materialValue[ 0, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 0, 2 ].ToString( Mathf.Abs( m_materialValue[ 0, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.MATRIX_DATA_SEPARATOR + + m_materialValue[ 1, 0 ].ToString( Mathf.Abs( m_materialValue[ 1, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 1, 1 ].ToString( Mathf.Abs( m_materialValue[ 1, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 1, 2 ].ToString( Mathf.Abs( m_materialValue[ 1, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.MATRIX_DATA_SEPARATOR + + m_materialValue[ 2, 0 ].ToString( Mathf.Abs( m_materialValue[ 2, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 2, 1 ].ToString( Mathf.Abs( m_materialValue[ 2, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 2, 2 ].ToString( Mathf.Abs( m_materialValue[ 2, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) : + + m_defaultValue[ 0, 0 ].ToString( Mathf.Abs( m_defaultValue[ 0, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 0, 1 ].ToString( Mathf.Abs( m_defaultValue[ 0, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 0, 2 ].ToString( Mathf.Abs( m_defaultValue[ 0, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.MATRIX_DATA_SEPARATOR + + m_defaultValue[ 1, 0 ].ToString( Mathf.Abs( m_defaultValue[ 1, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 1, 1 ].ToString( Mathf.Abs( m_defaultValue[ 1, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 1, 2 ].ToString( Mathf.Abs( m_defaultValue[ 1, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.MATRIX_DATA_SEPARATOR + + m_defaultValue[ 2, 0 ].ToString( Mathf.Abs( m_defaultValue[ 2, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 2, 1 ].ToString( Mathf.Abs( m_defaultValue[ 2, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 2, 2 ].ToString( Mathf.Abs( m_defaultValue[ 2, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ); + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix3X3Node.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix3X3Node.cs.meta new file mode 100644 index 0000000..4c852d9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix3X3Node.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 01e5a5829caac674fa819ed229de31b6 +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix4X4Node.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix4X4Node.cs new file mode 100644 index 0000000..44b9970 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix4X4Node.cs @@ -0,0 +1,248 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Matrix4X4", "Constants And Properties", "Matrix4X4 property" )] + public sealed class Matrix4X4Node : MatrixParentNode + { + private string[,] m_fieldText = new string[ 4, 4 ] { { "0", "0", "0", "0" }, { "0", "0", "0", "0" }, { "0", "0", "0", "0" }, { "0", "0", "0", "0" } }; + public Matrix4X4Node() : base() { } + public Matrix4X4Node( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + GlobalTypeWarningText = string.Format( GlobalTypeWarningText, "Matrix" ); + AddOutputPort( WirePortDataType.FLOAT4x4, Constants.EmptyPortValue ); + m_insideSize.Set( Constants.FLOAT_DRAW_WIDTH_FIELD_SIZE * 4 + Constants.FLOAT_WIDTH_SPACING * 3, Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE * 4 + Constants.FLOAT_WIDTH_SPACING * 3 + Constants.OUTSIDE_WIRE_MARGIN ); + //m_defaultValue = new Matrix4x4(); + //m_materialValue = new Matrix4x4(); + m_drawPreview = false; + } + + public override void CopyDefaultsToMaterial() + { + m_materialValue = m_defaultValue; + } + + public override void DrawSubProperties() + { + EditorGUILayout.LabelField( Constants.DefaultValueLabel ); + for ( int row = 0; row < 4; row++ ) + { + EditorGUILayout.BeginHorizontal(); + for ( int column = 0; column < 4; column++ ) + { + m_defaultValue[ row, column ] = EditorGUILayoutFloatField( string.Empty, m_defaultValue[ row, column ], GUILayout.MaxWidth( 55 ) ); + } + EditorGUILayout.EndHorizontal(); + } + } + + public override void DrawMaterialProperties() + { + if ( m_materialMode ) + EditorGUI.BeginChangeCheck(); + + EditorGUILayout.LabelField( Constants.MaterialValueLabel ); + for ( int row = 0; row < 4; row++ ) + { + EditorGUILayout.BeginHorizontal(); + for ( int column = 0; column < 4; column++ ) + { + m_materialValue[ row, column ] = EditorGUILayoutFloatField( string.Empty, m_materialValue[ row, column ], GUILayout.MaxWidth( 55 ) ); + } + EditorGUILayout.EndHorizontal(); + } + + if ( m_materialMode && EditorGUI.EndChangeCheck() ) + m_requireMaterialUpdate = true; + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_propertyDrawPos.position = m_remainingBox.position; + m_propertyDrawPos.width = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_WIDTH_FIELD_SIZE; + m_propertyDrawPos.height = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if ( drawInfo.CurrentEventType != EventType.MouseDown ) + return; + + Rect hitBox = m_remainingBox; + hitBox.height = m_insideSize.y * drawInfo.InvertedZoom; + bool insideBox = hitBox.Contains( drawInfo.MousePosition ); + + if ( insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = true; + } + else if ( m_isEditingFields && !insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = false; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if ( !m_isVisible ) + return; + + if ( m_isEditingFields && m_currentParameterType != PropertyType.Global ) + { + bool currMode = m_materialMode && m_currentParameterType != PropertyType.Constant; + Matrix4x4 value = currMode ? m_materialValue : m_defaultValue; + + EditorGUI.BeginChangeCheck(); + for ( int row = 0; row < 4; row++ ) + { + for ( int column = 0; column < 4; column++ ) + { + m_propertyDrawPos.position = m_remainingBox.position + Vector2.Scale( m_propertyDrawPos.size, new Vector2( column, row ) ) + new Vector2( Constants.FLOAT_WIDTH_SPACING * drawInfo.InvertedZoom * column, Constants.FLOAT_WIDTH_SPACING * drawInfo.InvertedZoom * row ); + value[ row, column ] = EditorGUIFloatField( m_propertyDrawPos, string.Empty, value[ row, column ], UIUtils.MainSkin.textField ); + } + } + + if ( currMode ) + { + m_materialValue = value; + } + else + { + m_defaultValue = value; + } + + if ( EditorGUI.EndChangeCheck() ) + { + m_requireMaterialUpdate = m_materialMode; + BeginDelayedDirtyProperty(); + } + } + else if ( drawInfo.CurrentEventType == EventType.Repaint ) + { + bool guiEnabled = GUI.enabled; + GUI.enabled = m_currentParameterType != PropertyType.Global; + + bool currMode = m_materialMode && m_currentParameterType != PropertyType.Constant; + Matrix4x4 value = currMode ? m_materialValue : m_defaultValue; + for ( int row = 0; row < 4; row++ ) + { + for ( int column = 0; column < 4; column++ ) + { + Rect fakeField = m_propertyDrawPos; + fakeField.position = m_remainingBox.position + Vector2.Scale( m_propertyDrawPos.size, new Vector2( column, row ) ) + new Vector2( Constants.FLOAT_WIDTH_SPACING * drawInfo.InvertedZoom * column, Constants.FLOAT_WIDTH_SPACING * drawInfo.InvertedZoom * row ); + if( GUI.enabled ) + EditorGUIUtility.AddCursorRect( fakeField, MouseCursor.Text ); + + if ( m_previousValue[ row, column ] != value[ row, column ] ) + { + m_previousValue[ row, column ] = value[ row, column ]; + m_fieldText[ row, column ] = value[ row, column ].ToString(); + } + + GUI.Label( fakeField, m_fieldText[ row, column ], UIUtils.MainSkin.textField ); + } + } + GUI.enabled = guiEnabled; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + m_precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ); + if ( m_currentParameterType != PropertyType.Constant ) + return PropertyData( dataCollector.PortCategory ); + + Matrix4x4 value = m_defaultValue; + + return m_precisionString+"(" + value[ 0, 0 ] + "," + value[ 0, 1 ] + "," + value[ 0, 2 ] + "," + value[ 0, 3 ] + "," + + +value[ 1, 0 ] + "," + value[ 1, 1 ] + "," + value[ 1, 2 ] + "," + value[ 1, 3 ] + "," + + +value[ 2, 0 ] + "," + value[ 2, 1 ] + "," + value[ 2, 2 ] + "," + value[ 2, 3 ] + "," + + +value[ 3, 0 ] + "," + value[ 3, 1 ] + "," + value[ 3, 2 ] + "," + value[ 3, 3 ] + ")"; + + } + + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if ( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction ) + { + mat.SetMatrix( m_propertyName, m_materialValue ); + } + } + + public override void SetMaterialMode( Material mat , bool fetchMaterialValues ) + { + base.SetMaterialMode( mat , fetchMaterialValues ); + if ( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) && mat.HasProperty( m_propertyName ) ) + { + m_materialValue = mat.GetMatrix( m_propertyName ); + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( m_propertyName ) ) + { + m_materialValue = material.GetMatrix( m_propertyName ); + PreviewIsDirty = true; + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_defaultValue = IOUtils.StringToMatrix4x4( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Matrix4x4ToString( m_defaultValue ) ); + } + + public override void ReadAdditionalClipboardData( ref string[] nodeParams ) + { + base.ReadAdditionalClipboardData( ref nodeParams ); + m_materialValue = IOUtils.StringToMatrix4x4( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteAdditionalClipboardData( ref string nodeInfo ) + { + base.WriteAdditionalClipboardData( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Matrix4x4ToString( m_materialValue ) ); + } + + + public override string GetPropertyValStr() + { + return ( m_materialMode && m_currentParameterType != PropertyType.Constant ) ? m_materialValue[ 0, 0 ].ToString( Mathf.Abs( m_materialValue[ 0, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 0, 1 ].ToString( Mathf.Abs( m_materialValue[ 0, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 0, 2 ].ToString( Mathf.Abs( m_materialValue[ 0, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 0, 3 ].ToString( Mathf.Abs( m_materialValue[ 0, 3 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.MATRIX_DATA_SEPARATOR + + m_materialValue[ 1, 0 ].ToString( Mathf.Abs( m_materialValue[ 1, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 1, 1 ].ToString( Mathf.Abs( m_materialValue[ 1, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 1, 2 ].ToString( Mathf.Abs( m_materialValue[ 1, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 1, 3 ].ToString( Mathf.Abs( m_materialValue[ 1, 3 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.MATRIX_DATA_SEPARATOR + + m_materialValue[ 2, 0 ].ToString( Mathf.Abs( m_materialValue[ 2, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 2, 1 ].ToString( Mathf.Abs( m_materialValue[ 2, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 2, 2 ].ToString( Mathf.Abs( m_materialValue[ 2, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 2, 3 ].ToString( Mathf.Abs( m_materialValue[ 2, 3 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.MATRIX_DATA_SEPARATOR + + m_materialValue[ 3, 0 ].ToString( Mathf.Abs( m_materialValue[ 3, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 3, 1 ].ToString( Mathf.Abs( m_materialValue[ 3, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 3, 2 ].ToString( Mathf.Abs( m_materialValue[ 3, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_materialValue[ 3, 3 ].ToString( Mathf.Abs( m_materialValue[ 3, 3 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) : + + m_defaultValue[ 0, 0 ].ToString( Mathf.Abs( m_defaultValue[ 0, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 0, 1 ].ToString( Mathf.Abs( m_defaultValue[ 0, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 0, 2 ].ToString( Mathf.Abs( m_defaultValue[ 0, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 0, 3 ].ToString( Mathf.Abs( m_defaultValue[ 0, 3 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.MATRIX_DATA_SEPARATOR + + m_defaultValue[ 1, 0 ].ToString( Mathf.Abs( m_defaultValue[ 1, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 1, 1 ].ToString( Mathf.Abs( m_defaultValue[ 1, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 1, 2 ].ToString( Mathf.Abs( m_defaultValue[ 1, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 1, 3 ].ToString( Mathf.Abs( m_defaultValue[ 1, 3 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.MATRIX_DATA_SEPARATOR + + m_defaultValue[ 2, 0 ].ToString( Mathf.Abs( m_defaultValue[ 2, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 2, 1 ].ToString( Mathf.Abs( m_defaultValue[ 2, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 2, 2 ].ToString( Mathf.Abs( m_defaultValue[ 2, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 2, 3 ].ToString( Mathf.Abs( m_defaultValue[ 2, 3 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.MATRIX_DATA_SEPARATOR + + m_defaultValue[ 3, 0 ].ToString( Mathf.Abs( m_defaultValue[ 3, 0 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 3, 1 ].ToString( Mathf.Abs( m_defaultValue[ 3, 1 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 3, 2 ].ToString( Mathf.Abs( m_defaultValue[ 3, 2 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ) + IOUtils.VECTOR_SEPARATOR + m_defaultValue[ 3, 3 ].ToString( Mathf.Abs( m_defaultValue[ 3, 3 ] ) > 1000 ? Constants.PropertyBigMatrixFormatLabel : Constants.PropertyMatrixFormatLabel ); + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix4X4Node.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix4X4Node.cs.meta new file mode 100644 index 0000000..10ec1a2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Matrix4X4Node.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4fa5db614b9379b4da27edafa0a8f4e9 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/MatrixParentNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/MatrixParentNode.cs new file mode 100644 index 0000000..85e0504 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/MatrixParentNode.cs @@ -0,0 +1,86 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class MatrixParentNode : PropertyNode + { + private readonly string[] AvailablePropertyTypeLabels = { PropertyType.Constant.ToString(), PropertyType.Global.ToString(), "Instanced" }; + private readonly int[] AvailablePropertyTypeValues = { (int)PropertyType.Constant, (int)PropertyType.Global , (int)PropertyType.InstancedProperty }; + + protected bool m_isEditingFields; + + [SerializeField] + protected Matrix4x4 m_defaultValue = Matrix4x4.identity; + + [SerializeField] + protected Matrix4x4 m_materialValue = Matrix4x4.identity; + + [NonSerialized] + protected Matrix4x4 m_previousValue; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + public MatrixParentNode() : base() { } + public MatrixParentNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_freeType = false; + m_showVariableMode = true; + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + m_hasLeftDropdown = true; + m_drawAttributes = false; + m_availableAttribs.Clear(); + + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + protected void DrawParameterType() + { + PropertyType parameterType = (PropertyType)EditorGUILayoutIntPopup( ParameterTypeStr, (int)m_currentParameterType, AvailablePropertyTypeLabels, AvailablePropertyTypeValues ); + if( parameterType != m_currentParameterType ) + { + ChangeParameterType( parameterType ); + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + PropertyType parameterType = (PropertyType)m_upperLeftWidget.DrawWidget( this, (int)m_currentParameterType, AvailablePropertyTypeLabels, AvailablePropertyTypeValues ); + if( parameterType != m_currentParameterType ) + { + ChangeParameterType( parameterType ); + } + } + + public override void DrawMainPropertyBlock() + { + DrawParameterType(); + base.DrawMainPropertyBlock(); + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void SetGlobalValue() { Shader.SetGlobalMatrix( m_propertyName, m_defaultValue ); } + public override void FetchGlobalValue() { m_materialValue = Shader.GetGlobalMatrix( m_propertyName ); } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/MatrixParentNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/MatrixParentNode.cs.meta new file mode 100644 index 0000000..ed87f49 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/MatrixParentNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d31dc25864c509a4f967e32079a27d6f +timeCreated: 1507902748 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PiNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PiNode.cs new file mode 100644 index 0000000..659a128 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PiNode.cs @@ -0,0 +1,63 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "PI", "Constants And Properties", "PI constant : 3.14159265359" )] + public sealed class PiNode : ParentNode + { + public PiNode() : base() { } + public PiNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, true, "Multiplier" ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_textLabelWidth = 70; + InputPorts[ 0 ].FloatInternalData = 1; + m_useInternalPortData = true; + m_previewShaderGUID = "bf4a65726dab3d445a69fb1d0945c33e"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + string finalValue = string.Empty; + string piString = dataCollector.IsSRP ? "PI" : "UNITY_PI"; + if( !InputPorts[ 0 ].IsConnected && InputPorts[ 0 ].FloatInternalData == 1 ) + { + finalValue = piString; + } else + { + string multiplier = InputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + finalValue = "( " + multiplier + " * " + piString + " )"; + } + + + if ( finalValue.Equals( string.Empty ) ) + { + UIUtils.ShowMessage( UniqueId, "PINode generating empty code", MessageSeverity.Warning ); + } + return finalValue; + } + + //public override void ReadFromString( ref string[] nodeParams ) + //{ + // base.ReadFromString( ref nodeParams ); + + // Removed on version 5004 + //m_value = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + //} + + //public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + //{ + // base.WriteToString( ref nodeInfo, ref connectionsInfo ); + //} + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PiNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PiNode.cs.meta new file mode 100644 index 0000000..64327b8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PiNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7a8a03953b97a594b81b2fb71d4a57ec +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PropertyNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PropertyNode.cs new file mode 100644 index 0000000..451035b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PropertyNode.cs @@ -0,0 +1,1926 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public enum PropertyType + { + Constant = 0, + Property, + InstancedProperty, + Global + } + + public enum VariableMode + { + Create = 0, + Fetch + } + + [Serializable] + public class PropertyAttributes + { + public string Name; + public string Attribute; + public bool HasDeprecatedValue; + public string DeprecatedValue; + public PropertyAttributes( string name, string attribute , string deprecated = null ) + { + Name = name; + Attribute = attribute; + DeprecatedValue = deprecated; + HasDeprecatedValue = deprecated != null; + } + } + + [Serializable] + public class PropertyNode : ParentNode + { + private const string LongNameEnder = "... )"; + protected int m_longNameSize = 200; + //private const string InstancedPropertyWarning = "Instanced Property option shouldn't be used on official SRP templates as all property variables are already declared as instanced inside a CBuffer.\nPlease consider changing to Property option."; + private const string TooltipFormatter = "{0}\n\nName: {1}\nValue: {2}"; + private const string InvalidAttributeFormatter = "Attribute {0} not found on node {1}. Please click on this message to select node and review its attributes section"; + protected string GlobalTypeWarningText = "Global variables must be set via a C# script using the Shader.SetGlobal{0}(...) method.\nPlease note that setting a global variable will affect all shaders which are using it."; + private const string HybridInstancedStr = "Hybrid Instanced"; + private const string AutoRegisterStr = "Auto-Register"; + private const string IgnoreVarDeclarationStr = "Variable Mode"; + private const string IsPropertyStr = "Is Property"; + private const string PropertyNameStr = "Property Name"; + private const string PropertyInspectorStr = "Name"; + protected const string EnumsStr = "Enums"; + protected const string CustomAttrStr = "Custom Attributes"; + protected const string HeaderAttrStr = "Headers"; + protected const string ParameterTypeStr = "Type"; + private const string PropertyTextfieldControlName = "PropertyName"; + private const string PropertyInspTextfieldControlName = "PropertyInspectorName"; + private const string OrderIndexStr = "Order Index"; + protected const double MaxTimestamp = 2; + private const double MaxPropertyTimestamp = 2; + private const double MaxGlobalFetchTimestamp = 2; + protected readonly string[] LabelToolbarTitle = { "Material", "Default" }; + protected readonly string[] EnumModesStr = { "Create Enums", "Use Engine Enum Class" }; + protected readonly int[] EnumModeIntValues = { 0, 1 }; + private const string FetchToCreateDuplicatesMsg = "Reverting property name from '{0}' to '{1}' as it is registered to another property node."; + private const string FetchToCreateOnDuplicateNodeMsg = "Setting new property name '{0}' as '{1}' is registered to another property node."; + private const string HeaderId = "Header"; + private const string EnumId = "Enum"; + + [SerializeField] + protected PropertyType m_currentParameterType; + + [SerializeField] + private PropertyType m_lastParameterType; + + [SerializeField] + protected string m_propertyName = string.Empty; + + [SerializeField] + protected string m_propertyInspectorName = string.Empty; + + [SerializeField] + protected string m_precisionString; + protected bool m_drawPrecisionUI = true; + + [SerializeField] + private int m_orderIndex = -1; + + [SerializeField] + protected VariableMode m_variableMode = VariableMode.Create; + + [SerializeField] + protected bool m_autoGlobalName = true; + + [SerializeField] + protected bool m_hybridInstanced = false; + + [SerializeField] + protected bool m_autoRegister = false; + + [SerializeField] + protected bool m_registerPropertyOnInstancing = true; + + [SerializeField] + private List m_enumNames = new List(); + + [SerializeField] + private List m_enumValues = new List(); + + [SerializeField] + private int m_enumCount = 0; + + [SerializeField] + private int m_enumModeInt = 0; + + [SerializeField] + private int m_customAttrCount = 0; + + [SerializeField] + private List m_customAttr = new List(); + + [SerializeField] + private bool m_hasHeaders = false; + + [SerializeField] + private List m_headerAttributeValues = new List(); + + + [SerializeField] + private string m_enumClassName = string.Empty; + + private bool m_hasEnum = false; + + protected bool m_showTitleWhenNotEditing = true; + + private int m_orderIndexOffset = 0; + + protected bool m_drawAttributes = true; + + protected bool m_underscoredGlobal = false; + protected bool m_globalDefaultBehavior = true; + + protected bool m_freeName; + protected bool m_freeType; + protected bool m_showVariableMode = false; + protected bool m_propertyNameIsDirty; + + protected bool m_showAutoRegisterUI = true; + + protected bool m_showHybridInstancedUI = false; + + protected bool m_useVarSubtitle = false; + + protected bool m_propertyFromInspector; + protected double m_propertyFromInspectorTimestamp; + + protected bool m_checkDuplicateProperty; + protected double m_checkDuplicatePropertyTimestamp; + + protected double m_globalFetchTimestamp; + + protected bool m_delayedDirtyProperty; + protected double m_delayedDirtyPropertyTimestamp; + + protected string m_defaultPropertyName; + protected string m_oldName = string.Empty; + + private bool m_reRegisterName = false; + protected bool m_allowPropertyDuplicates = false; + //protected bool m_useCustomPrefix = false; + protected string m_customPrefix = null; + + protected int m_propertyTab = 0; + + [SerializeField] + private string m_uniqueName; + + // Property Attributes + private const float ButtonLayoutWidth = 15; + + protected bool m_visibleAttribsFoldout; + protected bool m_visibleEnumsFoldout; + protected bool m_visibleCustomAttrFoldout; + protected bool m_visibleHeaderAttrFoldout; + protected List m_availableAttribs = new List(); + private string[] m_availableAttribsArr; + + [SerializeField] + private bool[] m_selectedAttribsArr; + + [SerializeField] + protected List m_selectedAttribs = new List(); + + //Title editing + protected bool m_isEditing; + protected bool m_stopEditing; + protected bool m_startEditing; + protected double m_clickTime; + protected double m_doubleClickTime = 0.3; + private Rect m_titleClickArea; + + protected bool m_srpBatcherCompatible = false; + protected bool m_excludeUniform = false; + + [SerializeField] + private bool m_addGlobalToSRPBatcher = false; + + public PropertyNode() : base() { } + public PropertyNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_textLabelWidth = 105; + if( UIUtils.CurrentWindow != null && UIUtils.CurrentWindow.CurrentGraph != null ) + m_orderIndex = UIUtils.GetPropertyNodeAmount(); + m_currentParameterType = PropertyType.Constant; + m_freeType = true; + m_freeName = true; + m_propertyNameIsDirty = true; + m_customPrecision = true; + m_availableAttribs.Add( new PropertyAttributes( "Hide in Inspector", "[HideInInspector]" ) ); + m_availableAttribs.Add( new PropertyAttributes( "HDR", "[HDR]" ) ); + m_availableAttribs.Add( new PropertyAttributes( "Gamma", "[Gamma]" ) ); + m_availableAttribs.Add( new PropertyAttributes( "Per Renderer Data", "[PerRendererData]" ) ); + m_availableAttribs.Add( new PropertyAttributes( "Header", "[Header]" ) ); + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + + if( PaddingTitleLeft == 0 && m_freeType ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + + m_hasLeftDropdown = m_freeType; + } + + protected void BeginDelayedDirtyProperty() + { + m_delayedDirtyProperty = true; + m_delayedDirtyPropertyTimestamp = EditorApplication.timeSinceStartup; + } + + public void CheckDelayedDirtyProperty() + { + if( m_delayedDirtyProperty ) + { + if( ( EditorApplication.timeSinceStartup - m_delayedDirtyPropertyTimestamp ) > MaxPropertyTimestamp ) + { + m_delayedDirtyProperty = false; + m_propertyNameIsDirty = true; + m_sizeIsDirty = true; + } + } + } + + public void BeginPropertyFromInspectorCheck() + { + m_propertyFromInspector = true; + m_propertyFromInspectorTimestamp = EditorApplication.timeSinceStartup; + } + + public virtual void CheckPropertyFromInspector( bool forceUpdate = false ) + { + if( m_propertyFromInspector ) + { + if( forceUpdate || ( EditorApplication.timeSinceStartup - m_propertyFromInspectorTimestamp ) > MaxTimestamp ) + { + m_propertyFromInspector = false; + bool autoGlobal = m_autoGlobalName || m_currentParameterType == PropertyType.Global; + RegisterPropertyName( true, m_propertyInspectorName, autoGlobal, m_underscoredGlobal ); + m_propertyNameIsDirty = true; + } + } + } + + public void CheckDuplicateProperty() + { + if( m_checkDuplicateProperty && + ( EditorApplication.timeSinceStartup - m_checkDuplicatePropertyTimestamp ) > MaxTimestamp ) + { + m_checkDuplicateProperty = false; + m_propertyName = UIUtils.GeneratePropertyName( m_propertyName, PropertyType.Global, false ); + + if( UIUtils.IsNumericName( m_propertyName ) ) + { + UIUtils.ShowMessage( UniqueId, string.Format( "Invalid property name '{0}' as it cannot start with numbers. Reverting to previous name.", m_propertyName ), MessageSeverity.Warning ); + m_propertyName = m_oldName; + GUI.FocusControl( string.Empty ); + return; + } + + if( !m_propertyName.Equals( m_oldName ) ) + { + if( UIUtils.IsUniformNameAvailable( m_propertyName ) || m_allowPropertyDuplicates ) + { + UIUtils.ReleaseUniformName( UniqueId, m_oldName ); + + m_oldName = m_propertyName; + m_propertyNameIsDirty = true; + m_reRegisterName = false; + UIUtils.RegisterUniformName( UniqueId, m_propertyName ); + OnPropertyNameChanged(); + } + else + { + GUI.FocusControl( string.Empty ); + RegisterFirstAvailablePropertyName( true, true ); + UIUtils.ShowMessage( UniqueId, string.Format( "Duplicate property name found on edited node.\nAssigning first valid one {0}", m_propertyName ) ); + } + } + } + } + + protected override void OnUniqueIDAssigned() + { + if( m_variableMode == VariableMode.Create ) + RegisterFirstAvailablePropertyName( false ); + + if( m_nodeAttribs != null ) + m_uniqueName = m_nodeAttribs.Name + UniqueId; + + UIUtils.RegisterRawPropertyNode( this ); + } + + public bool CheckLocalVariable( ref MasterNodeDataCollector dataCollector ) + { + bool addToLocalValue = false; + int count = 0; + for( int i = 0; i < m_outputPorts.Count; i++ ) + { + if( m_outputPorts[ i ].IsConnected ) + { + if( m_outputPorts[ i ].ConnectionCount > 1 ) + { + addToLocalValue = true; + break; + } + count += 1; + if( count > 1 ) + { + addToLocalValue = true; + break; + } + } + } + + if( addToLocalValue ) + { + ConfigureLocalVariable( ref dataCollector ); + } + + return addToLocalValue; + } + + public virtual void ConfigureLocalVariable( ref MasterNodeDataCollector dataCollector ) { } + public virtual void CopyDefaultsToMaterial() { } + + public override void SetupFromCastObject( UnityEngine.Object obj ) + { + RegisterPropertyName( true, obj.name, true, m_underscoredGlobal ); + } + + public void ChangeParameterType( PropertyType parameterType ) + { + Undo.RegisterCompleteObjectUndo( m_containerGraph.ParentWindow, Constants.UndoChangePropertyTypeNodesId ); + Undo.RegisterCompleteObjectUndo( m_containerGraph, Constants.UndoChangePropertyTypeNodesId ); + Undo.RecordObject( this, Constants.UndoChangePropertyTypeNodesId ); + + if( m_currentParameterType == PropertyType.Constant || m_currentParameterType == PropertyType.Global ) + { + CopyDefaultsToMaterial(); + } + + if( parameterType == PropertyType.InstancedProperty ) + { + //if( m_containerGraph.IsSRP ) + //{ + // UIUtils.ShowMessage( InstancedPropertyWarning,MessageSeverity.Warning ); + //} + + UIUtils.CurrentWindow.OutsideGraph.AddInstancePropertyCount(); + } + else if( m_currentParameterType == PropertyType.InstancedProperty ) + { + UIUtils.CurrentWindow.OutsideGraph.RemoveInstancePropertyCount(); + } + + if( ( parameterType == PropertyType.Property || parameterType == PropertyType.InstancedProperty ) + && m_currentParameterType != PropertyType.Property && m_currentParameterType != PropertyType.InstancedProperty ) + { + UIUtils.RegisterPropertyNode( this ); + } + + if( ( parameterType != PropertyType.Property && parameterType != PropertyType.InstancedProperty ) + && ( m_currentParameterType == PropertyType.Property || m_currentParameterType == PropertyType.InstancedProperty ) ) + { + UIUtils.UnregisterPropertyNode( this ); + } + + m_currentParameterType = parameterType; + if( parameterType == PropertyType.Constant ) + { + CurrentVariableMode = VariableMode.Create; + } + + } + + void InitializeAttribsArray() + { + m_availableAttribsArr = new string[ m_availableAttribs.Count ]; + m_selectedAttribsArr = new bool[ m_availableAttribs.Count ]; + for( int i = 0; i < m_availableAttribsArr.Length; i++ ) + { + m_availableAttribsArr[ i ] = m_availableAttribs[ i ].Name; + m_selectedAttribsArr[ i ] = false; + + if( m_selectedAttribs.FindIndex( x => x == i ) > -1 ) + { + m_selectedAttribsArr[ i ] = true; + m_visibleAttribsFoldout = true; + } + } + } + + protected virtual void OnAtrributesChanged() { CheckEnumAttribute(); CheckHeaderAttribute(); } + void DrawAttributesAddRemoveButtons() + { + if( m_availableAttribsArr == null ) + { + InitializeAttribsArray(); + } + + int attribCount = m_selectedAttribs.Count; + // Add new port + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ButtonLayoutWidth ) ) ) + { + m_visibleAttribsFoldout = true; + m_selectedAttribs.Add( 0 ); + OnAtrributesChanged(); + } + + //Remove port + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ButtonLayoutWidth ) ) ) + { + if( attribCount > 0 ) + { + m_selectedAttribs.RemoveAt( attribCount - 1 ); + OnAtrributesChanged(); + } + } + } + + void CheckEnumAttribute() + { + m_hasEnum = false; + foreach( var item in m_selectedAttribs ) + { + if( m_availableAttribsArr[ item ].Equals( "Enum" ) ) + m_hasEnum = true; + } + } + + + + protected void CheckHeaderAttribute() + { + m_hasHeaders = false; + foreach( var item in m_selectedAttribs ) + { + if( m_availableAttribsArr[ item ].Equals( HeaderId ) ) + { + m_hasHeaders = true; + } + } + } + + void DrawEnumAddRemoveButtons() + { + // Add new port + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ButtonLayoutWidth ) ) && m_enumModeInt == 0 ) + { + m_enumNames.Add( "Option" + ( m_enumValues.Count + 1 ) ); + m_enumValues.Add( m_enumValues.Count ); + m_enumCount++; + m_visibleEnumsFoldout = true; + } + + //Remove port + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ButtonLayoutWidth ) ) && m_enumModeInt == 0 ) + { + if( m_enumNames.Count - 1 > -1 ) + { + m_enumNames.RemoveAt( m_enumNames.Count - 1 ); + m_enumValues.RemoveAt( m_enumValues.Count - 1 ); + m_enumCount--; + } + } + } + + protected void DrawEnums() + { + m_enumModeInt = EditorGUILayout.IntPopup( "Mode", m_enumModeInt, EnumModesStr, EnumModeIntValues ); + + if( m_enumModeInt == 0 ) + { + if( m_enumNames.Count == 0 ) + EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add more.", MessageType.Info ); + + float cacheLabelSize = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 50; + + for( int i = 0; i < m_enumNames.Count; i++ ) + { + EditorGUI.BeginChangeCheck(); + EditorGUILayout.BeginHorizontal(); + m_enumNames[ i ] = EditorGUILayoutTextField( "Name", m_enumNames[ i ] ); + m_enumValues[ i ] = EditorGUILayoutIntField( "Value", m_enumValues[ i ], GUILayout.Width( 100 ) ); + EditorGUILayout.EndHorizontal(); + if( EditorGUI.EndChangeCheck() ) + { + m_enumNames[ i ] = UIUtils.RemoveInvalidEnumCharacters( m_enumNames[ i ] ); + if( string.IsNullOrEmpty( m_enumNames[ i ] ) ) + { + m_enumNames[ i ] = "Option" + ( i + 1 ); + } + } + } + + EditorGUIUtility.labelWidth = cacheLabelSize; + if( m_enumNames.Count > 0 ) + { + EditorGUILayout.BeginHorizontal(); + GUILayout.Label( " " ); + DrawEnumAddRemoveButtons(); + EditorGUILayout.EndHorizontal(); + } + } + else + { + EditorGUILayout.BeginHorizontal(); + m_enumClassName = EditorGUILayoutTextField( "Class Name", m_enumClassName ); + + if( GUILayout.Button( string.Empty, UIUtils.InspectorPopdropdownFallback, GUILayout.Width( 17 ), GUILayout.Height( 19 ) ) ) + { + GenericMenu menu = new GenericMenu(); + AddMenuItem( menu, "UnityEngine.Rendering.CullMode" ); + AddMenuItem( menu, "UnityEngine.Rendering.ColorWriteMask" ); + AddMenuItem( menu, "UnityEngine.Rendering.CompareFunction" ); + AddMenuItem( menu, "UnityEngine.Rendering.StencilOp" ); + AddMenuItem( menu, "UnityEngine.Rendering.BlendMode" ); + AddMenuItem( menu, "UnityEngine.Rendering.BlendOp" ); + menu.ShowAsContext(); + } + EditorGUILayout.EndHorizontal(); + } + } + + private void AddMenuItem( GenericMenu menu, string newClass ) + { + menu.AddItem( new GUIContent( newClass ), m_enumClassName.Equals( newClass ), OnSelection, newClass ); + } + + private void OnSelection( object newClass ) + { + m_enumClassName = (string)newClass; + } + + protected void DrawCustomAttrAddRemoveButtons() + { + // Add new port + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ButtonLayoutWidth ) ) ) + { + m_customAttr.Add( "" ); + m_customAttrCount++; + //m_enumCount++; + m_visibleCustomAttrFoldout = true; + } + + //Remove port + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ButtonLayoutWidth ) ) ) + { + if( m_customAttr.Count - 1 > -1 ) + { + m_customAttr.RemoveAt( m_customAttr.Count - 1 ); + m_customAttrCount--; + } + } + } + + protected void DrawCustomAttributes() + { + for( int i = 0; i < m_customAttrCount; i++ ) + { + EditorGUI.BeginChangeCheck(); + m_customAttr[ i ] = EditorGUILayoutTextField( "Attribute " + i, m_customAttr[ i ] ); + if( EditorGUI.EndChangeCheck() ) + { + m_customAttr[ i ] = UIUtils.RemoveInvalidAttrCharacters( m_customAttr[ i ] ); + } + } + + if( m_customAttrCount <= 0 ) + { + EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add more.", MessageType.Info ); + return; + } + + EditorGUILayout.BeginHorizontal(); + GUILayout.Label( " " ); + DrawCustomAttrAddRemoveButtons(); + EditorGUILayout.EndHorizontal(); + } + + protected void DrawHeaderAttrAddRemoveButtons() + { + // Add new port + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ButtonLayoutWidth ) ) ) + { + m_headerAttributeValues.Add( "" ); + m_visibleHeaderAttrFoldout = true; + } + + //Remove port + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ButtonLayoutWidth ) ) ) + { + if( m_headerAttributeValues.Count > 0 ) + { + m_headerAttributeValues.RemoveAt( m_headerAttributeValues.Count - 1 ); + } + } + } + + protected void DrawHeaderAttributes() + { + int count = m_headerAttributeValues.Count; + for( int i = 0; i < count; i++ ) + { + EditorGUI.BeginChangeCheck(); + m_headerAttributeValues[ i ] = EditorGUILayoutTextField( "Header " + i, m_headerAttributeValues[ i ] ); + if( EditorGUI.EndChangeCheck() ) + { + m_headerAttributeValues[ i ] = UIUtils.RemoveHeaderAttrCharacters( m_headerAttributeValues[ i ] ); + } + } + + + + + if( count <= 0 ) + { + EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add more.", MessageType.Info ); + return; + } + + EditorGUILayout.BeginHorizontal(); + GUILayout.Label( " " ); + DrawHeaderAttrAddRemoveButtons(); + EditorGUILayout.EndHorizontal(); + } + + + public virtual void DrawAttributes() + { + int attribCount = m_selectedAttribs.Count; + EditorGUI.BeginChangeCheck(); + if( m_availableAttribsArr == null ) + { + InitializeAttribsArray(); + } + for( int i = 0; i < m_availableAttribsArr.Length; i++ ) + { + m_selectedAttribsArr[ i ] = EditorGUILayoutToggleLeft( m_availableAttribsArr[ i ], m_selectedAttribsArr[ i ] ); + } + if( EditorGUI.EndChangeCheck() ) + { + m_selectedAttribs.Clear(); + for( int i = 0; i < m_selectedAttribsArr.Length; i++ ) + { + if( m_selectedAttribsArr[ i ] ) + m_selectedAttribs.Add( i ); + } + + OnAtrributesChanged(); + } + + bool customAttr = EditorGUILayoutToggleLeft( "Custom", m_customAttrCount == 0 ? false : true ); + if( !customAttr ) + { + m_customAttrCount = 0; + } + else if( customAttr && m_customAttrCount < 1 ) + { + if( m_customAttr.Count == 0 ) + m_customAttr.Add( "" ); + + m_customAttrCount = m_customAttr.Count; + } + //m_customAttrCount = EditorGUILayoutToggleLeft( "Custom Attribute", m_customAttrCount == 0 ? false : true ) == 0 ? false : true; + + //if( attribCount == 0 ) + //{ + // EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add more.", MessageType.Info ); + //} + + //bool actionAllowed = true; + //int deleteItem = -1; + + //for ( int i = 0; i < attribCount; i++ ) + //{ + // EditorGUI.BeginChangeCheck(); + // { + // m_selectedAttribs[ i ] = EditorGUILayoutPopup( m_selectedAttribs[ i ], m_availableAttribsArr ); + // } + // if ( EditorGUI.EndChangeCheck() ) + // { + // OnAtrributesChanged(); + // } + + // EditorGUILayout.BeginHorizontal(); + // GUILayout.Label( " " ); + // // Add After + // if ( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ButtonLayoutWidth ) ) ) + // { + // if ( actionAllowed ) + // { + // m_selectedAttribs.Insert( i, m_selectedAttribs[ i ] ); + // actionAllowed = false; + // OnAtrributesChanged(); + // } + // } + + // // Remove Current + // if ( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ButtonLayoutWidth ) ) ) + // { + // if ( actionAllowed ) + // { + // actionAllowed = false; + // deleteItem = i; + // } + // } + // EditorGUILayout.EndHorizontal(); + //} + //if ( deleteItem > -1 ) + //{ + // m_selectedAttribs.RemoveAt( deleteItem ); + // OnAtrributesChanged(); + //} + } + public virtual void DrawMainPropertyBlock() + { + EditorGUILayout.BeginVertical(); + { + if( m_freeType ) + { + PropertyType parameterType = (PropertyType)EditorGUILayoutEnumPopup( ParameterTypeStr, m_currentParameterType ); + if( parameterType != m_currentParameterType ) + { + ChangeParameterType( parameterType ); + BeginPropertyFromInspectorCheck(); + } + } + + if( m_freeName ) + { + switch( m_currentParameterType ) + { + case PropertyType.Property: + case PropertyType.InstancedProperty: + { + ShowPropertyInspectorNameGUI(); + ShowPropertyNameGUI( true ); + ShowVariableMode(); + ShowHybridInstanced(); + ShowAutoRegister(); + ShowPrecision(); + ShowToolbar(); + } + break; + case PropertyType.Global: + { + ShowPropertyInspectorNameGUI(); + ShowPropertyNameGUI( false ); + ShowVariableMode(); + ShowAutoRegister(); + ShowPrecision(); + ShowDefaults(); + } + break; + case PropertyType.Constant: + { + ShowPropertyInspectorNameGUI(); + ShowPrecision(); + ShowDefaults(); + } + break; + } + } + } + EditorGUILayout.EndVertical(); + } + + public void DrawMainPropertyBlockNoPrecision() + { + EditorGUILayout.BeginVertical(); + { + if( m_freeType ) + { + PropertyType parameterType = (PropertyType)EditorGUILayoutEnumPopup( ParameterTypeStr, m_currentParameterType ); + if( parameterType != m_currentParameterType ) + { + ChangeParameterType( parameterType ); + BeginPropertyFromInspectorCheck(); + } + } + + if( m_freeName ) + { + switch( m_currentParameterType ) + { + case PropertyType.Property: + case PropertyType.InstancedProperty: + { + ShowPropertyInspectorNameGUI(); + ShowPropertyNameGUI( true ); + ShowToolbar(); + } + break; + case PropertyType.Global: + { + ShowPropertyInspectorNameGUI(); + ShowPropertyNameGUI( false ); + ShowDefaults(); + } + break; + case PropertyType.Constant: + { + ShowPropertyInspectorNameGUI(); + ShowDefaults(); + } + break; + } + } + } + EditorGUILayout.EndVertical(); + } + + public override void DrawProperties() + { + base.DrawProperties(); + if( m_freeType || m_freeName ) + { + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr, DrawMainPropertyBlock ); + if( m_drawAttributes ) + NodeUtils.DrawPropertyGroup( ref m_visibleAttribsFoldout, Constants.AttributesLaberStr, DrawAttributes ); + + if( m_hasEnum ) + { + if( m_enumModeInt == 0 ) + NodeUtils.DrawPropertyGroup( ref m_visibleEnumsFoldout, EnumsStr, DrawEnums, DrawEnumAddRemoveButtons ); + else + NodeUtils.DrawPropertyGroup( ref m_visibleEnumsFoldout, EnumsStr, DrawEnums ); + } + + if( m_drawAttributes ) + { + if( m_hasHeaders ) + NodeUtils.DrawPropertyGroup( ref m_visibleHeaderAttrFoldout, HeaderAttrStr, DrawHeaderAttributes, DrawHeaderAttrAddRemoveButtons ); + + if( m_customAttrCount > 0 ) + NodeUtils.DrawPropertyGroup( ref m_visibleCustomAttrFoldout, CustomAttrStr, DrawCustomAttributes, DrawCustomAttrAddRemoveButtons ); + } + + CheckPropertyFromInspector(); + } + } + + public void ShowPrecision() + { + if( m_drawPrecisionUI ) + { + bool guiEnabled = GUI.enabled; + GUI.enabled = m_currentParameterType == PropertyType.Constant || m_variableMode == VariableMode.Create; + EditorGUI.BeginChangeCheck(); + DrawPrecisionProperty(); + if( EditorGUI.EndChangeCheck() ) + m_precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ); + + GUI.enabled = guiEnabled; + + } + } + + public void ShowToolbar() + { + //if ( !CanDrawMaterial ) + //{ + // ShowDefaults(); + // return; + //} + + EditorGUILayout.BeginHorizontal(); + GUILayout.Space( 20 ); + m_propertyTab = GUILayout.Toolbar( m_propertyTab, LabelToolbarTitle ); + EditorGUILayout.EndHorizontal(); + switch( m_propertyTab ) + { + default: + case 0: + { + EditorGUI.BeginChangeCheck(); + DrawMaterialProperties(); + if( EditorGUI.EndChangeCheck() ) + { + BeginDelayedDirtyProperty(); + } + } + break; + case 1: + { + ShowDefaults(); + } + break; + } + } + + public void ShowDefaults() + { + EditorGUI.BeginChangeCheck(); + DrawSubProperties(); + if( EditorGUI.EndChangeCheck() ) + { + BeginDelayedDirtyProperty(); + } + if( m_currentParameterType == PropertyType.Global && m_globalDefaultBehavior ) + { + if( DebugConsoleWindow.DeveloperMode ) + { + ShowGlobalValueButton(); + } + EditorGUILayout.HelpBox( GlobalTypeWarningText, MessageType.Warning ); + } + } + + public void ShowPropertyInspectorNameGUI() + { + EditorGUI.BeginChangeCheck(); + m_propertyInspectorName = EditorGUILayoutTextField( PropertyInspectorStr, m_propertyInspectorName ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_propertyInspectorName.Length > 0 ) + { + BeginPropertyFromInspectorCheck(); + } + } + } + + public void ShowPropertyNameGUI( bool isProperty ) + { + bool guiEnabledBuffer = GUI.enabled; + if( isProperty ) + { + EditorGUILayout.BeginHorizontal(); + GUI.enabled = !m_autoGlobalName; + EditorGUI.BeginChangeCheck(); + m_propertyName = EditorGUILayoutTextField( PropertyNameStr, m_propertyName ); + if( EditorGUI.EndChangeCheck() ) + { + //BeginPropertyFromInspectorCheck(); + m_checkDuplicateProperty = true; + m_checkDuplicatePropertyTimestamp = EditorApplication.timeSinceStartup; + } + GUI.enabled = guiEnabledBuffer; + EditorGUI.BeginChangeCheck(); + m_autoGlobalName = GUILayout.Toggle( m_autoGlobalName, ( m_autoGlobalName ? UIUtils.LockIconOpen : UIUtils.LockIconClosed ), "minibutton", GUILayout.Width( 22 ) ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_autoGlobalName ) + BeginPropertyFromInspectorCheck(); + } + EditorGUILayout.EndHorizontal(); + } + else + { + GUI.enabled = false; + m_propertyName = EditorGUILayoutTextField( PropertyNameStr, m_propertyName ); + GUI.enabled = guiEnabledBuffer; + } + } + + public void ShowVariableMode() + { + if( m_showVariableMode || m_freeType ) + CurrentVariableMode = (VariableMode)EditorGUILayoutEnumPopup( IgnoreVarDeclarationStr, m_variableMode ); + } + + public void ShowHybridInstanced() + { + if( m_showHybridInstancedUI && CurrentParameterType == PropertyType.Property && ( m_containerGraph.IsSRP || m_containerGraph.CurrentShaderFunction != null ) ) + { + m_hybridInstanced = EditorGUILayoutToggle( HybridInstancedStr, m_hybridInstanced ); + } + } + + public void ShowAutoRegister() + { + if( m_showAutoRegisterUI && CurrentParameterType != PropertyType.Constant ) + { + m_autoRegister = EditorGUILayoutToggle( AutoRegisterStr, m_autoRegister ); + } + } + + public virtual string GetPropertyValStr() { return string.Empty; } + + public override bool OnClick( Vector2 currentMousePos2D ) + { + bool singleClick = base.OnClick( currentMousePos2D ); + m_propertyTab = m_materialMode ? 0 : 1; + return singleClick; + } + + public override void OnNodeDoubleClicked( Vector2 currentMousePos2D ) + { + if( currentMousePos2D.y - m_globalPosition.y > ( Constants.NODE_HEADER_HEIGHT + Constants.NODE_HEADER_EXTRA_HEIGHT ) * ContainerGraph.ParentWindow.CameraDrawInfo.InvertedZoom ) + { + ContainerGraph.ParentWindow.ParametersWindow.IsMaximized = !ContainerGraph.ParentWindow.ParametersWindow.IsMaximized; + } + } + + public override void DrawTitle( Rect titlePos ) + { + //base.DrawTitle( titlePos ); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + // Custom Editable Title + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + if( !m_isEditing && ( ( !ContainerGraph.ParentWindow.MouseInteracted && drawInfo.CurrentEventType == EventType.MouseDown && m_titleClickArea.Contains( drawInfo.MousePosition ) ) ) ) + { + if( ( EditorApplication.timeSinceStartup - m_clickTime ) < m_doubleClickTime ) + m_startEditing = true; + else + GUI.FocusControl( null ); + m_clickTime = EditorApplication.timeSinceStartup; + } + else if( m_isEditing && ( ( drawInfo.CurrentEventType == EventType.MouseDown && !m_titleClickArea.Contains( drawInfo.MousePosition ) ) || !EditorGUIUtility.editingTextField ) ) + { + m_stopEditing = true; + } + + if( m_isEditing || m_startEditing ) + { + EditorGUI.BeginChangeCheck(); + GUI.SetNextControlName( m_uniqueName ); + m_propertyInspectorName = EditorGUITextField( m_titleClickArea, string.Empty, m_propertyInspectorName, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + if( EditorGUI.EndChangeCheck() ) + { + SetClippedTitle( m_propertyInspectorName, m_longNameSize ); + m_sizeIsDirty = true; + m_isDirty = true; + if( m_propertyInspectorName.Length > 0 ) + { + BeginPropertyFromInspectorCheck(); + } + } + + if( m_startEditing ) + EditorGUI.FocusTextInControl( m_uniqueName ); + //if( m_stopEditing ) + // GUI.FocusControl( null ); + } + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + if( m_startEditing ) + { + m_startEditing = false; + m_isEditing = true; + } + + if( m_stopEditing ) + { + m_stopEditing = false; + m_isEditing = false; + GUI.FocusControl( null ); + } + } + + + if( m_freeType ) + { + if( m_dropdownEditing ) + { + PropertyType parameterType = (PropertyType)EditorGUIEnumPopup( m_dropdownRect, m_currentParameterType, UIUtils.PropertyPopUp ); + if( parameterType != m_currentParameterType ) + { + ChangeParameterType( parameterType ); + BeginPropertyFromInspectorCheck(); + DropdownEditing = false; + } + } + } + } + + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + //base.OnNodeLayout( drawInfo ); + if( m_reRegisterName ) + { + m_reRegisterName = false; + UIUtils.RegisterUniformName( UniqueId, m_propertyName ); + } + + CheckDelayedDirtyProperty(); + + if( m_currentParameterType != m_lastParameterType || m_propertyNameIsDirty ) + { + m_lastParameterType = m_currentParameterType; + m_propertyNameIsDirty = false; + OnDirtyProperty(); + if( m_currentParameterType != PropertyType.Constant ) + { + SetClippedTitle( m_propertyInspectorName, m_longNameSize ); + //bool globalHandler = false; + //if( globalHandler ) + //{ + string currValue = ( m_currentParameterType == PropertyType.Global && m_globalDefaultBehavior ) ? "" : GetPropertyValStr(); + SetClippedAdditionalTitle( string.Format( m_useVarSubtitle ? Constants.SubTitleVarNameFormatStr : Constants.SubTitleValueFormatStr, currValue ), m_longNameSize, LongNameEnder ); + //} + //else + //{ + // if( m_currentParameterType == PropertyType.Global ) + // { + // SetAdditonalTitleText( "Global" ); + // } + // else + // { + // SetAdditonalTitleText( string.Format( m_useVarSubtitle ? Constants.SubTitleVarNameFormatStr : Constants.SubTitleValueFormatStr, GetPropertyValStr() ) ); + // } + //} + } + else + { + SetClippedTitle( m_propertyInspectorName, m_longNameSize ); + SetClippedAdditionalTitle( string.Format( Constants.SubTitleConstFormatStr, GetPropertyValStr() ), m_longNameSize, LongNameEnder ); + } + } + + CheckPropertyFromInspector(); + CheckDuplicateProperty(); + // RUN LAYOUT CHANGES AFTER TITLES CHANGE + base.OnNodeLayout( drawInfo ); + + m_titleClickArea = m_titlePos; + m_titleClickArea.height = Constants.NODE_HEADER_HEIGHT; + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + + if( !m_isVisible ) + return; + + // Fixed Title ( only renders when not editing ) + if( m_showTitleWhenNotEditing && !m_isEditing && !m_startEditing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + GUI.Label( m_titleClickArea, m_content, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + } + } + + public void RegisterFirstAvailablePropertyName( bool releaseOldOne, bool appendIndexToCurrOne = false ) + { + if( releaseOldOne ) + UIUtils.ReleaseUniformName( UniqueId, m_oldName ); + + if( m_isNodeBeingCopied || appendIndexToCurrOne ) + { + if( string.IsNullOrEmpty( m_propertyName ) ) + return; + + string newPropertyName = UIUtils.GetUniqueUniformName( m_propertyName ); + if( newPropertyName != m_propertyName ) + { + UIUtils.RegisterUniformName( UniqueId, newPropertyName ); + m_propertyName = newPropertyName; + } + else + { + if( UIUtils.IsUniformNameAvailable( m_propertyName ) ) + UIUtils.RegisterUniformName( UniqueId, m_propertyName ); + else + UIUtils.GetFirstAvailableName( UniqueId, m_outputPorts[ 0 ].DataType, out m_propertyName, out m_propertyInspectorName, !string.IsNullOrEmpty( m_customPrefix ), m_customPrefix ); + } + + } + else + { + UIUtils.GetFirstAvailableName( UniqueId, m_outputPorts[ 0 ].DataType, out m_propertyName, out m_propertyInspectorName, !string.IsNullOrEmpty( m_customPrefix ), m_customPrefix ); + } + m_oldName = m_propertyName; + m_propertyNameIsDirty = true; + m_reRegisterName = false; + OnPropertyNameChanged(); + } + + public void SetRawPropertyName( string name ) + { + m_propertyName = name; + } + + public void RegisterPropertyName( bool releaseOldOne, string newName, bool autoGlobal = true, bool forceUnderscore = false ) + { + if( m_currentParameterType != PropertyType.Constant && m_variableMode == VariableMode.Fetch ) + { + string localPropertyName = string.Empty; + if( autoGlobal ) + localPropertyName = UIUtils.GeneratePropertyName( newName, m_currentParameterType, forceUnderscore ); + else + { + localPropertyName = UIUtils.GeneratePropertyName( m_propertyName, PropertyType.Global, forceUnderscore ); + if( UIUtils.IsNumericName( localPropertyName ) ) + { + m_propertyName = m_oldName; + } + + } + + m_propertyName = localPropertyName; + m_propertyInspectorName = newName; + m_propertyNameIsDirty = true; + m_reRegisterName = false; + OnPropertyNameChanged(); + return; + } + + string propertyName = string.Empty; + if( autoGlobal ) + propertyName = UIUtils.GeneratePropertyName( newName, m_currentParameterType, forceUnderscore ); + else + { + propertyName = UIUtils.GeneratePropertyName( m_propertyName, PropertyType.Global, forceUnderscore ); + if( UIUtils.IsNumericName( propertyName ) ) + { + m_propertyName = m_oldName; + } + } + + if( m_propertyName.Equals( propertyName ) ) + return; + + if( UIUtils.IsUniformNameAvailable( propertyName ) || m_allowPropertyDuplicates ) + { + if( releaseOldOne ) + UIUtils.ReleaseUniformName( UniqueId, m_oldName ); + + m_oldName = propertyName; + m_propertyName = propertyName; + if( autoGlobal ) + m_propertyInspectorName = newName; + m_propertyNameIsDirty = true; + m_reRegisterName = false; + UIUtils.RegisterUniformName( UniqueId, propertyName ); + OnPropertyNameChanged(); + } + else + { + GUI.FocusControl( string.Empty ); + RegisterFirstAvailablePropertyName( releaseOldOne ); + UIUtils.ShowMessage( UniqueId, string.Format( "Duplicate name found on edited node.\nAssigning first valid one {0}", m_propertyInspectorName ) ); + } + } + + protected string CreateLocalVarDec( string value ) + { + return string.Format( Constants.PropertyLocalVarDec, UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ), m_propertyName, value ); + } + + public virtual void CheckIfAutoRegister( ref MasterNodeDataCollector dataCollector ) + { + // Also testing inside shader function because node can be used indirectly over a custom expression and directly over a Function Output node + // That isn't being used externaly making it to not be registered ( since m_connStatus it set to Connected by being connected to an output node + if( CurrentParameterType != PropertyType.Constant && m_autoRegister && ( m_connStatus != NodeConnectionStatus.Connected || InsideShaderFunction ) ) + { + RegisterProperty( ref dataCollector ); + } + } + + virtual protected void RegisterProperty( ref MasterNodeDataCollector dataCollector ) + { + CheckPropertyFromInspector( true ); + if( m_propertyName.Length == 0 ) + { + RegisterFirstAvailablePropertyName( false ); + } + + switch( CurrentParameterType ) + { + case PropertyType.Property: + { + //Debug.Log( this.GetInstanceID()+" "+ OrderIndex+" "+GetPropertyValue() ); + dataCollector.AddToProperties( UniqueId, GetPropertyValue(), OrderIndex ); + string dataType = string.Empty; + string dataName = string.Empty; + bool fullValue = false; + if( m_variableMode == VariableMode.Create && GetUniformData( out dataType, out dataName, ref fullValue ) ) + { + if( fullValue ) + { + dataCollector.AddToUniforms( UniqueId, dataName, m_srpBatcherCompatible ); + } + else + { + dataCollector.AddToUniforms( UniqueId, dataType, dataName, m_srpBatcherCompatible, m_excludeUniform ); + } + } + + if( m_hybridInstanced && dataCollector.IsTemplate && dataCollector.IsSRP ) + { + dataCollector.AddToDotsProperties( m_outputPorts[ 0 ].DataType, UniqueId, m_propertyName, OrderIndex, CurrentPrecisionType ); + } + //dataCollector.AddToUniforms( m_uniqueId, GetUniformValue() ); + } + break; + case PropertyType.InstancedProperty: + { + dataCollector.AddToPragmas( UniqueId, IOUtils.InstancedPropertiesHeader ); + + if( m_registerPropertyOnInstancing ) + dataCollector.AddToProperties( UniqueId, GetPropertyValue(), OrderIndex ); + + dataCollector.AddToInstancedProperties( m_outputPorts[ 0 ].DataType, UniqueId, GetInstancedUniformValue( dataCollector.IsTemplate, dataCollector.IsSRP ), OrderIndex ); + } + break; + case PropertyType.Global: + { + string dataType = string.Empty; + string dataName = string.Empty; + bool fullValue = false; + if( m_variableMode == VariableMode.Create && GetUniformData( out dataType, out dataName, ref fullValue ) ) + { + if( fullValue ) + { + dataCollector.AddToUniforms( UniqueId, dataName, m_addGlobalToSRPBatcher ); + } + else + { + dataCollector.AddToUniforms( UniqueId, dataType, dataName, m_addGlobalToSRPBatcher, m_excludeUniform ); + } + } + //dataCollector.AddToUniforms( m_uniqueId, GetUniformValue() ); + } + break; + case PropertyType.Constant: break; + } + dataCollector.AddPropertyNode( this ); + if( m_currentParameterType == PropertyType.InstancedProperty && !m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + { + string instancedVar = dataCollector.IsSRP ? + //m_propertyName : + string.Format( IOUtils.LWSRPInstancedPropertiesData, dataCollector.InstanceBlockName, m_propertyName ) : + string.Format( IOUtils.InstancedPropertiesData, m_propertyName ); + + bool insideSF = InsideShaderFunction; + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + if( insideSF ) + ContainerGraph.ParentWindow.CustomGraph = this.ContainerGraph; + + RegisterLocalVariable( 0, instancedVar, ref dataCollector, m_propertyName + "_Instance" ); + + if( insideSF ) + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + RegisterProperty( ref dataCollector ); + return string.Empty; + } + + public override void Destroy() + { + base.Destroy(); + UIUtils.UnregisterRawPropertyNode( this ); + if( !string.IsNullOrEmpty( m_propertyName ) && UniqueId >= 0 ) + UIUtils.ReleaseUniformName( UniqueId, m_propertyName ); + + if( m_currentParameterType == PropertyType.InstancedProperty ) + { + UIUtils.CurrentWindow.OutsideGraph.RemoveInstancePropertyCount(); + UIUtils.UnregisterPropertyNode( this ); + } + + if( m_currentParameterType == PropertyType.Property ) + { + UIUtils.UnregisterPropertyNode( this ); + } + + if( m_availableAttribs != null ) + m_availableAttribs.Clear(); + + m_availableAttribs = null; + } + private const string HeaderFormatStr = "[Header({0})]"; + string BuildHeader() + { + string result = string.Empty; + for( int i = 0; i < m_headerAttributeValues.Count; i++ ) + { + result += string.Format( HeaderFormatStr, m_headerAttributeValues[ i ] ); + } + return result; + } + + string BuildEnum() + { + string result = "[Enum("; + if( m_enumModeInt == 0 ) + { + for( int i = 0; i < m_enumNames.Count; i++ ) + { + result += m_enumNames[ i ] + "," + m_enumValues[ i ]; + if( i + 1 < m_enumNames.Count ) + result += ","; + } + } + else + { + result += m_enumClassName; + } + result += ")]"; + return result; + } + + public string PropertyAttributes + { + get + { + int attribCount = m_selectedAttribs.Count; + + if( m_selectedAttribs.Count == 0 && m_customAttrCount == 0 ) + return string.Empty; + + string attribs = string.Empty; + for( int i = 0; i < attribCount; i++ ) + { + if( m_availableAttribs[ m_selectedAttribs[ i ] ].Name.Equals( "Enum" ) ) + attribs += BuildEnum(); + else if( m_availableAttribs[ m_selectedAttribs[ i ] ].Name.Equals( HeaderId ) ) + attribs += BuildHeader(); + else + attribs += m_availableAttribs[ m_selectedAttribs[ i ] ].Attribute; + } + + for( int i = 0; i < m_customAttrCount; i++ ) + { + if( !string.IsNullOrEmpty( m_customAttr[ i ] ) ) + attribs += "[" + m_customAttr[ i ] + "]"; + } + return attribs; + } + } + public virtual void OnDirtyProperty() { } + public virtual void OnPropertyNameChanged() { UIUtils.UpdatePropertyDataNode( UniqueId, PropertyInspectorName ); } + public virtual void DrawSubProperties() { } + public virtual void DrawMaterialProperties() { } + + public virtual string GetPropertyValue() { return string.Empty; } + + public string GetInstancedUniformValue( bool isTemplate, bool isSRP ) + { + if( isTemplate ) + { + if( isSRP ) + { + return string.Format( IOUtils.LWSRPInstancedPropertiesElement, UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ), m_propertyName ); + //return GetUniformValue(); + } + else + { + return string.Format( IOUtils.InstancedPropertiesElement, UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ), m_propertyName ); + } + } + else + return string.Format( IOUtils.InstancedPropertiesElementTabs, UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ), m_propertyName ); + } + + public string GetInstancedUniformValue( bool isTemplate, bool isSRP, WirePortDataType dataType, string value ) + { + if( isTemplate ) + { + if( isSRP ) + { + //return GetUniformValue( dataType, value ); + return string.Format( IOUtils.LWSRPInstancedPropertiesElement, UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, dataType ), value ); + } + else + { + return string.Format( IOUtils.InstancedPropertiesElement, UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, dataType ), value ); + } + } + else + return string.Format( IOUtils.InstancedPropertiesElementTabs, UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, dataType ), value ); + } + + public virtual string GetUniformValue() + { + bool excludeUniformKeyword = ( m_currentParameterType == PropertyType.InstancedProperty ) || + m_containerGraph.IsSRP; + int index = excludeUniformKeyword ? 1 : 0; + return string.Format( Constants.UniformDec[ index ], UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ), m_propertyName ); + } + + public string GetUniformValue( WirePortDataType dataType, string value ) + { + bool excludeUniformKeyword = ( m_currentParameterType == PropertyType.InstancedProperty ) || + m_containerGraph.IsSRP; + int index = excludeUniformKeyword ? 1 : 0; + return string.Format( Constants.UniformDec[ index ], UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, dataType ), value ); + } + + public virtual bool GetUniformData( out string dataType, out string dataName, ref bool fullValue ) + { + dataType = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ); + dataName = m_propertyName; + fullValue = false; + return true; + } + + public PropertyType CurrentParameterType + { + get { return m_currentParameterType; } + set { m_currentParameterType = value; } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentParameterType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_propertyName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_propertyInspectorName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_orderIndex ); + int attribCount = m_selectedAttribs.Count; + IOUtils.AddFieldValueToString( ref nodeInfo, attribCount ); + if( attribCount > 0 ) + { + for( int i = 0; i < attribCount; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_availableAttribs[ m_selectedAttribs[ i ] ].Attribute ); + } + } + IOUtils.AddFieldValueToString( ref nodeInfo, m_variableMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_autoGlobalName ); + + int headerCount = m_headerAttributeValues.Count; + IOUtils.AddFieldValueToString( ref nodeInfo, headerCount ); + for( int i = 0; i < headerCount; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_headerAttributeValues[ i ] ); + } + + IOUtils.AddFieldValueToString( ref nodeInfo, m_enumCount ); + for( int i = 0; i < m_enumCount; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_enumNames[ i ] ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_enumValues[ i ] ); + } + IOUtils.AddFieldValueToString( ref nodeInfo, m_enumModeInt ); + if( m_enumModeInt == 1 ) + IOUtils.AddFieldValueToString( ref nodeInfo, m_enumClassName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_autoRegister ); + + IOUtils.AddFieldValueToString( ref nodeInfo, m_customAttrCount ); + if( m_customAttrCount > 0 ) + { + for( int i = 0; i < m_customAttrCount; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_customAttr[ i ] ); + } + } + + IOUtils.AddFieldValueToString( ref nodeInfo, m_hybridInstanced ); + } + + int IdForAttrib( string name ) + { + int attribCount = m_availableAttribs.Count; + for( int i = 0; i < attribCount; i++ ) + { + if( m_availableAttribs[ i ].Attribute.Equals( name ) || + (m_availableAttribs[ i ].HasDeprecatedValue && m_availableAttribs[ i ].DeprecatedValue.Equals( name ) ) ) + return i; + } + return -1; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() < 2505 ) + { + string property = GetCurrentParam( ref nodeParams ); + m_currentParameterType = property.Equals( "Uniform" ) ? PropertyType.Global : (PropertyType)Enum.Parse( typeof( PropertyType ), property ); + } + else + { + m_currentParameterType = (PropertyType)Enum.Parse( typeof( PropertyType ), GetCurrentParam( ref nodeParams ) ); + } + + if( m_currentParameterType == PropertyType.InstancedProperty ) + { + UIUtils.CurrentWindow.OutsideGraph.AddInstancePropertyCount(); + UIUtils.RegisterPropertyNode( this ); + } + + if( m_currentParameterType == PropertyType.Property ) + { + UIUtils.RegisterPropertyNode( this ); + } + + m_propertyName = GetCurrentParam( ref nodeParams ); + m_propertyInspectorName = GetCurrentParam( ref nodeParams ); + + if( UIUtils.CurrentShaderVersion() > 13 ) + { + m_orderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 4102 ) + { + int attribAmount = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( attribAmount > 0 ) + { + for( int i = 0; i < attribAmount; i++ ) + { + string attribute = GetCurrentParam( ref nodeParams ); + int idForAttribute = IdForAttrib( attribute ); + if( idForAttribute >= 0 ) + { + m_selectedAttribs.Add( idForAttribute ); + } + else + { + UIUtils.ShowMessage( UniqueId, string.Format( InvalidAttributeFormatter, attribute,m_propertyInspectorName ) , MessageSeverity.Warning ); + } + } + + m_visibleAttribsFoldout = true; + } + InitializeAttribsArray(); + } + + + if( UIUtils.CurrentShaderVersion() > 14003 ) + { + m_variableMode = (VariableMode)Enum.Parse( typeof( VariableMode ), GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 14201 ) + { + m_autoGlobalName = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 18707 ) + { + if( UIUtils.CurrentShaderVersion() == 18708 ) + { + m_headerAttributeValues.Add( GetCurrentParam( ref nodeParams ) ); + } + else + { + int headerCount = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + for( int i = 0; i < headerCount; i++ ) + { + m_headerAttributeValues.Add( GetCurrentParam( ref nodeParams ) ); + } + } + } + + if( UIUtils.CurrentShaderVersion() > 14403 ) + { + m_enumCount = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + for( int i = 0; i < m_enumCount; i++ ) + { + m_enumNames.Add( GetCurrentParam( ref nodeParams ) ); + m_enumValues.Add( Convert.ToInt32( GetCurrentParam( ref nodeParams ) ) ); + } + } + + if( UIUtils.CurrentShaderVersion() > 14501 ) + { + m_enumModeInt = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( m_enumModeInt == 1 ) + m_enumClassName = GetCurrentParam( ref nodeParams ); + m_autoRegister = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + + m_customAttrCount = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + for( int i = 0; i < m_customAttrCount; i++ ) + { + m_customAttr.Add( GetCurrentParam( ref nodeParams ) ); + } + if( m_customAttrCount > 0 ) + { + m_visibleCustomAttrFoldout = true; + m_visibleAttribsFoldout = true; + } + } + + if( UIUtils.CurrentShaderVersion() > 18003 ) + { + m_hybridInstanced = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + CheckEnumAttribute(); + CheckHeaderAttribute(); + if( m_enumCount > 0 ) + m_visibleEnumsFoldout = true; + + m_propertyNameIsDirty = true; + m_reRegisterName = false; + + if( !m_isNodeBeingCopied ) + { + if( m_variableMode != VariableMode.Fetch || m_currentParameterType == PropertyType.Constant ) + { + UIUtils.ReleaseUniformName( UniqueId, m_oldName ); + UIUtils.RegisterUniformName( UniqueId, m_propertyName ); + m_oldName = m_propertyName; + } + } + else + { + m_oldName = m_propertyName; + } + + ReleaseRansomedProperty(); + + } + + public virtual void ReleaseRansomedProperty() + { + if( m_variableMode == VariableMode.Fetch/* && m_autoGlobalName */) + { + //Fooling setter to have a different value + m_variableMode = VariableMode.Create; + CurrentVariableMode = VariableMode.Fetch; + } + } + + void UpdateTooltip() + { + string currValue = string.Empty; + if( m_currentParameterType != PropertyType.Constant ) + { + currValue = ( m_currentParameterType == PropertyType.Global && m_globalDefaultBehavior ) ? "" : GetPropertyValStr(); + } + else + { + currValue = GetPropertyValStr(); + } + + m_tooltipText = string.Format( TooltipFormatter, m_nodeAttribs.Description, m_propertyInspectorName, currValue ); + } + + public override void SetClippedTitle( string newText, int maxSize = 170, string endString = "..." ) + { + base.SetClippedTitle( newText, maxSize, endString ); + UpdateTooltip(); + } + + public override void SetClippedAdditionalTitle( string newText, int maxSize = 170, string endString = "..." ) + { + base.SetClippedAdditionalTitle( newText, maxSize, endString ); + UpdateTooltip(); + } + + public override void OnEnable() + { + base.OnEnable(); + m_reRegisterName = true; + } + + public bool CanDrawMaterial { get { return m_materialMode && m_currentParameterType != PropertyType.Constant; } } + public int RawOrderIndex + { + get { return m_orderIndex; } + } + + public int OrderIndex + { + get { return m_orderIndex + m_orderIndexOffset; } + set { m_orderIndex = value; } + } + + public int OrderIndexOffset + { + get { return m_orderIndexOffset; } + set { m_orderIndexOffset = value; } + } + + public VariableMode CurrentVariableMode + { + get { return m_variableMode; } + set + { + if( value != m_variableMode ) + { + m_variableMode = value; + if( value == VariableMode.Fetch ) + { + // Release ownership on name + if( UIUtils.CheckUniformNameOwner( m_oldName ) == UniqueId ) + { + UIUtils.ReleaseUniformName( UniqueId , m_oldName ); + } + m_oldName = m_propertyName; + } + else + { + if( !m_propertyName.Equals( m_oldName ) ) + { + if( UIUtils.IsUniformNameAvailable( m_propertyName ) ) + { + UIUtils.ReleaseUniformName( UniqueId, m_oldName ); + UIUtils.RegisterUniformName( UniqueId, m_propertyName ); + } + else + { + UIUtils.ShowMessage( UniqueId, string.Format( FetchToCreateDuplicatesMsg, m_propertyName, m_oldName ), MessageSeverity.Warning ); + m_propertyName = m_oldName; + } + m_propertyNameIsDirty = true; + OnPropertyNameChanged(); + } + else + { + if( UIUtils.IsUniformNameAvailable( m_propertyName ) ) + { + UIUtils.RegisterUniformName( UniqueId , m_propertyName ); + } + else if( UIUtils.CheckUniformNameOwner( m_propertyName ) != UniqueId ) + { + string oldProperty = m_propertyName; + RegisterFirstAvailablePropertyName( false ); + UIUtils.ShowMessage( UniqueId, string.Format( FetchToCreateOnDuplicateNodeMsg, m_propertyName, oldProperty ), MessageSeverity.Warning ); + } + } + } + } + } + } + + public string PropertyData( MasterNodePortCategory portCategory ) + { + return ( m_currentParameterType == PropertyType.InstancedProperty ) ? m_outputPorts[ 0 ].LocalValue( portCategory ) : m_propertyName; + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + if( m_currentParameterType == PropertyType.Global && m_globalDefaultBehavior && ( EditorApplication.timeSinceStartup - m_globalFetchTimestamp ) > MaxGlobalFetchTimestamp ) + { + FetchGlobalValue(); + m_globalFetchTimestamp = EditorApplication.timeSinceStartup; + } + } + + public void ShowGlobalValueButton() + { + if( GUILayout.Button( "Set Global Value" ) ) + { + SetGlobalValue(); + } + } + + public override bool CheckFindText( string text ) + { + return base.CheckFindText( text ) || + m_propertyName.IndexOf( text, StringComparison.CurrentCultureIgnoreCase ) >= 0 || + m_propertyInspectorName.IndexOf( text, StringComparison.CurrentCultureIgnoreCase ) >= 0; + } + + //This should only be used on template internal properties + public void PropertyNameFromTemplate( TemplateShaderPropertyData data ) + { + m_propertyName = data.PropertyName; + m_propertyInspectorName = data.PropertyInspectorName; + } + public virtual void GeneratePPSInfo( ref string propertyDeclaration, ref string propertySet ) { } + public virtual void SetGlobalValue() { } + public virtual void FetchGlobalValue() { } + + public virtual string PropertyName { get { return m_propertyName; } } + public virtual string PropertyInspectorName { get { return m_propertyInspectorName; } } + public bool FreeType { get { return m_freeType; } set { m_freeType = value; } } + public bool ReRegisterName { get { return m_reRegisterName; } set { m_reRegisterName = value; } } + public string CustomPrefix { get { return m_customPrefix; } set { m_customPrefix = value; } } + public override void RefreshOnUndo() + { + base.RefreshOnUndo(); + BeginPropertyFromInspectorCheck(); + } + public override string DataToArray { get { return PropertyInspectorName; } } + public bool RegisterPropertyOnInstancing { get { return m_registerPropertyOnInstancing; } set { m_registerPropertyOnInstancing = value; } } + public bool SrpBatcherCompatible { get { return m_srpBatcherCompatible; } } + public bool AddGlobalToSRPBatcher { get { return m_addGlobalToSRPBatcher; } set { m_addGlobalToSRPBatcher = value; } } + public bool AutoRegister { get { return m_autoRegister; } set { m_autoRegister = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PropertyNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PropertyNode.cs.meta new file mode 100644 index 0000000..704a244 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/PropertyNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5bbfd66571b12f84983b398231271694 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/RangedFloatNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/RangedFloatNode.cs new file mode 100644 index 0000000..1b52b60 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/RangedFloatNode.cs @@ -0,0 +1,535 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Float", "Constants And Properties", "Float property", null, KeyCode.Alpha1 )] + public sealed class RangedFloatNode : PropertyNode + { + private const int OriginalFontSize = 11; + + private const string MinValueStr = "Min"; + private const string MaxValueStr = "Max"; + + private const float LabelWidth = 8; + + [SerializeField] + private float m_defaultValue = 0; + + [SerializeField] + private float m_materialValue = 0; + + [SerializeField] + private float m_min = 0; + + [SerializeField] + private float m_max = 0; + + [SerializeField] + private bool m_floatMode = true; + + private int m_cachedPropertyId = -1; + + private bool m_isEditingFields; + private Vector3 m_previousValue = Vector3.zero; + private string[] m_fieldText = new string[] { "0", "0", "0" }; + + public RangedFloatNode() : base() { } + public RangedFloatNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + GlobalTypeWarningText = string.Format( GlobalTypeWarningText, "Float" ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_insideSize.Set( 50, 0 ); + m_showPreview = false; + m_showHybridInstancedUI = true; + m_selectedLocation = PreviewLocation.BottomCenter; + m_availableAttribs.Add( new PropertyAttributes( "Toggle", "[Toggle]" ) ); +#if UNITY_2018_1_OR_NEWER + m_availableAttribs.Add( new PropertyAttributes( "No Keyword Toggle", "[ToggleUI]","[NoKeywordToggle]" ) ); +#else + m_availableAttribs.Add( new PropertyAttributes( "No Keyword Toggle", "[NoKeywordToggle]" ) ); +#endif + m_availableAttribs.Add( new PropertyAttributes( "Int Range", "[IntRange]" ) ); + m_availableAttribs.Add( new PropertyAttributes( "Enum", "[Enum]" ) ); + m_previewShaderGUID = "d9ca47581ac157145bff6f72ac5dd73e"; + m_srpBatcherCompatible = true; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + UIUtils.RegisterFloatIntNode( this ); + } + + public override void Destroy() + { + base.Destroy(); + UIUtils.UnregisterFloatIntNode( this ); + } + + public override void OnDirtyProperty() + { + UIUtils.UpdateFloatIntDataNode( UniqueId, PropertyInspectorName ); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + OnPropertyNameChanged(); + OnDirtyProperty(); + } + + public void SetFloatMode( bool value ) + { + if ( m_floatMode == value ) + return; + + m_floatMode = value; + if ( value ) + { + m_insideSize.x = 50;// + ( m_showPreview ? 50 : 0 ); + //m_firstPreviewDraw = true; + } + else + { + m_insideSize.x = 200;// + ( m_showPreview ? 0 : 0 ); + //m_firstPreviewDraw = true; + } + m_sizeIsDirty = true; + } + + public override void CopyDefaultsToMaterial() + { + m_materialValue = m_defaultValue; + } + + void DrawMinMaxUI() + { + EditorGUI.BeginChangeCheck(); + m_min = EditorGUILayoutFloatField( MinValueStr, m_min ); + m_max = EditorGUILayoutFloatField( MaxValueStr, m_max ); + if ( m_min > m_max ) + m_min = m_max; + + if ( m_max < m_min ) + m_max = m_min; + + if ( EditorGUI.EndChangeCheck() ) + { + SetFloatMode( m_min == m_max ); + } + } + public override void DrawSubProperties() + { + DrawMinMaxUI(); + + if ( m_floatMode ) + { + m_defaultValue = EditorGUILayoutFloatField( Constants.DefaultValueLabel, m_defaultValue ); + } + else + { + m_defaultValue = EditorGUILayoutSlider( Constants.DefaultValueLabel, m_defaultValue, m_min, m_max ); + } + } + + public override void DrawMaterialProperties() + { + DrawMinMaxUI(); + + EditorGUI.BeginChangeCheck(); + + if ( m_floatMode ) + { + m_materialValue = EditorGUILayoutFloatField( Constants.MaterialValueLabel, m_materialValue ); + } + else + { + m_materialValue = EditorGUILayoutSlider( Constants.MaterialValueLabel, m_materialValue, m_min, m_max ); + } + if ( EditorGUI.EndChangeCheck() ) + { + //MarkForPreviewUpdate(); + if ( m_materialMode ) + m_requireMaterialUpdate = true; + } + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if ( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_InputFloat" ); + + if ( m_materialMode && m_currentParameterType != PropertyType.Constant ) + PreviewMaterial.SetFloat( m_cachedPropertyId, m_materialValue ); + else + PreviewMaterial.SetFloat( m_cachedPropertyId, m_defaultValue ); + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + if ( m_floatMode ) + { + m_propertyDrawPos = m_remainingBox; + m_propertyDrawPos.x = m_remainingBox.x - LabelWidth * drawInfo.InvertedZoom; + m_propertyDrawPos.width = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_WIDTH_FIELD_SIZE; + m_propertyDrawPos.height = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE; + } + else + { + m_propertyDrawPos = m_remainingBox; + m_propertyDrawPos.width = m_outputPorts[ 0 ].Position.x - m_propertyDrawPos.x - (m_outputPorts[ 0 ].LabelSize.x + (Constants.PORT_TO_LABEL_SPACE_X + 3) * drawInfo.InvertedZoom + 2); + m_propertyDrawPos.height = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE; + } + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if ( drawInfo.CurrentEventType != EventType.MouseDown ) + return; + + Rect hitBox = m_remainingBox; + hitBox.xMin -= LabelWidth * drawInfo.InvertedZoom; + bool insideBox = hitBox.Contains( drawInfo.MousePosition ); + + if ( insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = true; + } + else if ( m_isEditingFields && !insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = false; + } + } + void DrawFakeFloatMaterial( DrawInfo drawInfo ) + { + if( m_floatMode ) + { + //UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref m_materialValue, LabelWidth * drawInfo.InvertedZoom ); + Rect fakeField = m_propertyDrawPos; + fakeField.xMin += LabelWidth * drawInfo.InvertedZoom; + if( GUI.enabled ) + { + Rect fakeLabel = m_propertyDrawPos; + fakeLabel.xMax = fakeField.xMin; + EditorGUIUtility.AddCursorRect( fakeLabel, MouseCursor.SlideArrow ); + EditorGUIUtility.AddCursorRect( fakeField, MouseCursor.Text ); + } + if( m_previousValue[ 0 ] != m_materialValue ) + { + m_previousValue[ 0 ] = m_materialValue; + m_fieldText[ 0 ] = m_materialValue.ToString(); + } + + GUI.Label( fakeField, m_fieldText[ 0 ], UIUtils.MainSkin.textField ); + } + else + { + DrawFakeSlider( ref m_materialValue, drawInfo ); + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if ( !m_isVisible ) + return; + + if ( m_isEditingFields && m_currentParameterType != PropertyType.Global ) + { + if ( m_materialMode && m_currentParameterType != PropertyType.Constant ) + { + EditorGUI.BeginChangeCheck(); + if ( m_floatMode ) + { + UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref m_materialValue, LabelWidth * drawInfo.InvertedZoom ); + } + else + { + DrawSlider( ref m_materialValue, drawInfo ); + } + if ( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + m_requireMaterialUpdate = true; + if ( m_currentParameterType != PropertyType.Constant ) + { + BeginDelayedDirtyProperty(); + } + } + } + else + { + EditorGUI.BeginChangeCheck(); + + if ( m_floatMode ) + { + UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref m_defaultValue, LabelWidth * drawInfo.InvertedZoom ); + } + else + { + DrawSlider( ref m_defaultValue, drawInfo ); + } + if ( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + BeginDelayedDirtyProperty(); + } + + } + } + else if ( drawInfo.CurrentEventType == EventType.Repaint && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + { + if( m_currentParameterType == PropertyType.Global ) + { + bool guiEnabled = GUI.enabled; + GUI.enabled = false; + DrawFakeFloatMaterial( drawInfo ); + GUI.enabled = guiEnabled; + } + else if ( m_materialMode && m_currentParameterType != PropertyType.Constant ) + { + DrawFakeFloatMaterial( drawInfo ); + } + else + { + if ( m_floatMode ) + { + //UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref m_defaultValue, LabelWidth * drawInfo.InvertedZoom ); + Rect fakeField = m_propertyDrawPos; + fakeField.xMin += LabelWidth * drawInfo.InvertedZoom; + Rect fakeLabel = m_propertyDrawPos; + fakeLabel.xMax = fakeField.xMin; + EditorGUIUtility.AddCursorRect( fakeLabel, MouseCursor.SlideArrow ); + EditorGUIUtility.AddCursorRect( fakeField, MouseCursor.Text ); + + if ( m_previousValue[ 0 ] != m_defaultValue ) + { + m_previousValue[ 0 ] = m_defaultValue; + m_fieldText[ 0 ] = m_defaultValue.ToString(); + } + + GUI.Label( fakeField, m_fieldText[ 0 ], UIUtils.MainSkin.textField ); + } + else + { + DrawFakeSlider( ref m_defaultValue, drawInfo ); + } + } + } + } + + void DrawFakeSlider( ref float value, DrawInfo drawInfo ) + { + float rangeWidth = 30 * drawInfo.InvertedZoom; + float rangeSpacing = 5 * drawInfo.InvertedZoom; + + //Min + Rect minRect = m_propertyDrawPos; + minRect.width = rangeWidth; + EditorGUIUtility.AddCursorRect( minRect, MouseCursor.Text ); + if ( m_previousValue[ 1 ] != m_min ) + { + m_previousValue[ 1 ] = m_min; + m_fieldText[ 1 ] = m_min.ToString(); + } + GUI.Label( minRect, m_fieldText[ 1 ], UIUtils.MainSkin.textField ); + + //Value Area + Rect valRect = m_propertyDrawPos; + valRect.width = rangeWidth; + valRect.x = m_propertyDrawPos.xMax - rangeWidth - rangeWidth - rangeSpacing; + EditorGUIUtility.AddCursorRect( valRect, MouseCursor.Text ); + if ( m_previousValue[ 0 ] != value ) + { + m_previousValue[ 0 ] = value; + m_fieldText[ 0 ] = value.ToString(); + } + GUI.Label( valRect, m_fieldText[ 0 ], UIUtils.MainSkin.textField ); + + //Max + Rect maxRect = m_propertyDrawPos; + maxRect.width = rangeWidth; + maxRect.x = m_propertyDrawPos.xMax - rangeWidth; + EditorGUIUtility.AddCursorRect( maxRect, MouseCursor.Text ); + if ( m_previousValue[ 2 ] != m_max ) + { + m_previousValue[ 2 ] = m_max; + m_fieldText[ 2 ] = m_max.ToString(); + } + GUI.Label( maxRect, m_fieldText[ 2 ], UIUtils.MainSkin.textField ); + + Rect sliderValRect = m_propertyDrawPos; + sliderValRect.x = minRect.xMax + rangeSpacing; + sliderValRect.xMax = valRect.xMin - rangeSpacing; + Rect sliderBackRect = sliderValRect; + sliderBackRect.height = 5 * drawInfo.InvertedZoom; + sliderBackRect.center = new Vector2( sliderValRect.center.x, Mathf.Round( sliderValRect.center.y ) ); + + + GUI.Label( sliderBackRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SliderStyle ) ); + + sliderValRect.width = 10; + float percent = ( value - m_min) / ( m_max-m_min ); + percent = Mathf.Clamp01( percent ); + sliderValRect.x += percent * (sliderBackRect.width - 10 * drawInfo.InvertedZoom ); + GUI.Label( sliderValRect, string.Empty, UIUtils.RangedFloatSliderThumbStyle ); + } + + void DrawSlider( ref float value, DrawInfo drawInfo ) + { + float rangeWidth = 30 * drawInfo.InvertedZoom; + float rangeSpacing = 5 * drawInfo.InvertedZoom; + + //Min + Rect minRect = m_propertyDrawPos; + minRect.width = rangeWidth; + m_min = EditorGUIFloatField( minRect, m_min, UIUtils.MainSkin.textField ); + + //Value Area + Rect valRect = m_propertyDrawPos; + valRect.width = rangeWidth; + valRect.x = m_propertyDrawPos.xMax - rangeWidth - rangeWidth - rangeSpacing; + value = EditorGUIFloatField( valRect, value, UIUtils.MainSkin.textField ); + + //Max + Rect maxRect = m_propertyDrawPos; + maxRect.width = rangeWidth; + maxRect.x = m_propertyDrawPos.xMax - rangeWidth; + m_max = EditorGUIFloatField( maxRect, m_max, UIUtils.MainSkin.textField ); + + //Value Slider + Rect sliderValRect = m_propertyDrawPos; + sliderValRect.x = minRect.xMax + rangeSpacing; + sliderValRect.xMax = valRect.xMin - rangeSpacing; + Rect sliderBackRect = sliderValRect; + sliderBackRect.height = 5 * drawInfo.InvertedZoom; + sliderBackRect.center = new Vector2( sliderValRect.center.x, Mathf.Round( sliderValRect.center.y )); + GUI.Label( sliderBackRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SliderStyle ) ); + value = GUIHorizontalSlider( sliderValRect, value, m_min, m_max, GUIStyle.none, UIUtils.RangedFloatSliderThumbStyle ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + m_precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ); + + if ( m_currentParameterType != PropertyType.Constant ) + return PropertyData( dataCollector.PortCategory ); + + return IOUtils.Floatify( m_defaultValue ); + } + + public override string GetPropertyValue() + { + if ( m_floatMode ) + { + return PropertyAttributes + m_propertyName + "(\"" + m_propertyInspectorName + "\", Float) = " + m_defaultValue; + } + else + { + return PropertyAttributes + m_propertyName + "(\"" + m_propertyInspectorName + "\", Range( " + m_min + " , " + m_max + ")) = " + m_defaultValue; + } + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if ( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction ) + { + mat.SetFloat( m_propertyName, m_materialValue ); + } + } + + public override void SetMaterialMode( Material mat , bool fetchMaterialValues ) + { + base.SetMaterialMode( mat , fetchMaterialValues ); + if ( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) && mat.HasProperty( m_propertyName ) ) + { + m_materialValue = mat.GetFloat( m_propertyName ); + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( m_propertyName ) ) + { + m_materialValue = material.GetFloat( m_propertyName ); + PreviewIsDirty = true; + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_defaultValue = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 14101 ) + { + m_materialValue = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + } + + m_min = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + m_max = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + SetFloatMode( m_min == m_max ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_materialValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_min ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_max ); + } + + public override string GetPropertyValStr() + { + return ( m_materialMode && m_currentParameterType != PropertyType.Constant ) ? + m_materialValue.ToString( Mathf.Abs( m_materialValue ) > 1000 ? Constants.PropertyBigFloatFormatLabel : Constants.PropertyFloatFormatLabel ) : + m_defaultValue.ToString( Mathf.Abs( m_defaultValue ) > 1000 ? Constants.PropertyBigFloatFormatLabel : Constants.PropertyFloatFormatLabel ); + } + + public override void SetGlobalValue() { Shader.SetGlobalFloat( m_propertyName, m_defaultValue ); } + public override void FetchGlobalValue() { m_materialValue = Shader.GetGlobalFloat( m_propertyName ); } + public float Value + { + get { return m_defaultValue; } + set { m_defaultValue = value; } + } + + public void SetMaterialValueFromInline( float val ) + { + m_materialValue = val; + m_requireMaterialUpdate = true; + } + public override void GeneratePPSInfo( ref string propertyDeclaration, ref string propertySet ) + { + string additionalHeaders = string.Empty; + if( !m_floatMode ) + { + additionalHeaders = string.Format( "Range( {0}, {1} ),", m_min, m_max ); + } + propertyDeclaration += string.Format( ASEPPSHelperTool.PPSPropertyDecFormat, additionalHeaders, PropertyInspectorName, + ASEPPSHelperTool.WireToPPSType[ WirePortDataType.FLOAT ], PropertyName, m_defaultValue ); + + propertySet += string.Format( ASEPPSHelperTool.PPSPropertySetFormat, "Float", PropertyName ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/RangedFloatNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/RangedFloatNode.cs.meta new file mode 100644 index 0000000..dbf3243 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/RangedFloatNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e81453c5ad3b8224db874b56bf00cad2 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables.meta new file mode 100644 index 0000000..22447d4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 92f993d3ba8b1394eaf8c4fe308cab11 +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen.meta new file mode 100644 index 0000000..e1fbf68 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8c4b0845954941d4d9809abaa67bdc2b +folderAsset: yes +timeCreated: 1481126947 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraProjectionNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraProjectionNode.cs new file mode 100644 index 0000000..0591ba1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraProjectionNode.cs @@ -0,0 +1,100 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + public enum BuiltInShaderCameraTypes + { + unity_CameraProjection = 0, + unity_CameraInvProjection + } + + [Serializable] + [NodeAttributes( "Projection Matrices", "Camera And Screen", "Camera's Projection/Inverse Projection matrix" )] + public sealed class CameraProjectionNode : ShaderVariablesNode + { + private const string _projMatrixLabelStr = "Projection Matrix"; + private readonly string[] _projMatrixValuesStr = { "Camera Projection", + "Inverse Camera Projection"}; + + + [SerializeField] + private BuiltInShaderCameraTypes m_selectedType = BuiltInShaderCameraTypes.unity_CameraProjection; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, _projMatrixValuesStr[ (int)m_selectedType ], WirePortDataType.FLOAT4x4 ); + m_textLabelWidth = 115; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_selectedType = (BuiltInShaderCameraTypes)m_upperLeftWidget.DrawWidget( this, (int)m_selectedType, _projMatrixValuesStr ); + if( EditorGUI.EndChangeCheck() ) + { + ChangeOutputName( 0, _projMatrixValuesStr[ (int)m_selectedType ] ); + SetSaveIsDirty(); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_selectedType = (BuiltInShaderCameraTypes)EditorGUILayoutPopup( _projMatrixLabelStr, (int)m_selectedType, _projMatrixValuesStr ); + if( EditorGUI.EndChangeCheck() ) + { + ChangeOutputName( 0, _projMatrixValuesStr[ (int)m_selectedType ] ); + SetSaveIsDirty(); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + GeneratorUtils.RegisterUnity2019MatrixDefines( ref dataCollector ); + return m_selectedType.ToString(); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedType = (BuiltInShaderCameraTypes)Enum.Parse( typeof( BuiltInShaderCameraTypes ), GetCurrentParam( ref nodeParams ) ); + ChangeOutputName( 0, _projMatrixValuesStr[ (int)m_selectedType ] ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedType ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraProjectionNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraProjectionNode.cs.meta new file mode 100644 index 0000000..11a1c16 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraProjectionNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f776bdd36b750304c8e0de8ee1f31fc0 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraWorldClipPlanes.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraWorldClipPlanes.cs new file mode 100644 index 0000000..fd23099 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraWorldClipPlanes.cs @@ -0,0 +1,115 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public enum BuiltInShaderClipPlanesTypes + { + Left = 0, + Right, + Bottom, + Top, + Near, + Far + } + + [Serializable] + [NodeAttributes( "Clip Planes", "Camera And Screen", "Camera World Clip Planes" )] + public sealed class CameraWorldClipPlanes : ShaderVariablesNode + { + [SerializeField] + private BuiltInShaderClipPlanesTypes m_selectedType = BuiltInShaderClipPlanesTypes.Left; + + private const string LabelStr = "Plane"; + private const string ValueStr = "unity_CameraWorldClipPlanes"; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + private int m_planeId; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "ABCD", WirePortDataType.FLOAT4 ); + m_textLabelWidth = 55; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_selectedType ) ); + m_previewShaderGUID = "6afe5a4ad7bbd0e4ab352c758f543a09"; + } + + public override void OnEnable() + { + base.OnEnable(); + m_planeId = Shader.PropertyToID( "_PlaneId" ); + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + m_upperLeftWidget.DrawWidget(ref m_selectedType, this, OnWidgetUpdate ); + } + + private readonly Action OnWidgetUpdate = ( x ) => { + x.SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, ( x as CameraWorldClipPlanes ).Type ) ); + }; + + public BuiltInShaderClipPlanesTypes Type { get { return m_selectedType; } } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_selectedType = ( BuiltInShaderClipPlanesTypes ) EditorGUILayoutEnumPopup( LabelStr, m_selectedType ); + if ( EditorGUI.EndChangeCheck() ) + { + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_selectedType ) ); + SetSaveIsDirty(); + } + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + PreviewMaterial.SetInt( m_planeId, (int)m_selectedType ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + return ValueStr + "[" + ( int ) m_selectedType + "]"; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedType = ( BuiltInShaderClipPlanesTypes ) Enum.Parse( typeof( BuiltInShaderClipPlanesTypes ), GetCurrentParam( ref nodeParams ) ); + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_selectedType ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedType ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraWorldClipPlanes.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraWorldClipPlanes.cs.meta new file mode 100644 index 0000000..3b17b84 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/CameraWorldClipPlanes.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e5a9a010f1c8dda449c8ca7ee9e25869 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/OrthoParams.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/OrthoParams.cs new file mode 100644 index 0000000..c2e93c2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/OrthoParams.cs @@ -0,0 +1,38 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Ortho Params", "Camera And Screen", "Orthographic Parameters" )] + public sealed class OrthoParams : ConstVecShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputName( 1, "Ortho Cam Width" ); + ChangeOutputName( 2, "Ortho Cam Height" ); + ChangeOutputName( 3, "Unused" ); + ChangeOutputName( 4, "Projection Mode" ); + m_value = "unity_OrthoParams"; + m_previewShaderGUID = "88a910ece3dce224793e669bb1bc158d"; + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( !m_outputPorts[ 0 ].IsConnected ) + { + m_outputPorts[ 0 ].Visible = false; + m_sizeIsDirty = true; + } + + if( !m_outputPorts[ 3 ].IsConnected ) + { + m_outputPorts[ 3 ].Visible = false; + m_sizeIsDirty = true; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/OrthoParams.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/OrthoParams.cs.meta new file mode 100644 index 0000000..d406a63 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/OrthoParams.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f9431cdf8e81c1d4f902b3fa7d04f7ac +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ProjectionParams.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ProjectionParams.cs new file mode 100644 index 0000000..9e4357b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ProjectionParams.cs @@ -0,0 +1,32 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Projection Params", "Camera And Screen", "Projection Near/Far parameters" )] + public sealed class ProjectionParams : ConstVecShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputName( 1, "Flipped" ); + ChangeOutputName( 2, "Near Plane" ); + ChangeOutputName( 3, "Far Plane" ); + ChangeOutputName( 4, "1/Far Plane" ); + m_value = "_ProjectionParams"; + m_previewShaderGUID = "97ae846cb0a6b044388fad3bc03bb4c2"; + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( !m_outputPorts[ 0 ].IsConnected ) + { + m_outputPorts[ 0 ].Visible = false; + m_sizeIsDirty = true; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ProjectionParams.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ProjectionParams.cs.meta new file mode 100644 index 0000000..8e87d5a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ProjectionParams.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ba1ca8bace2c2dd4dafac6f73f4dfb1b +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ScreenParams.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ScreenParams.cs new file mode 100644 index 0000000..5446ac2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ScreenParams.cs @@ -0,0 +1,32 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Screen Params", "Camera And Screen", "Camera's Render Target size parameters" )] + public sealed class ScreenParams : ConstVecShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputName( 1, "RT Width" ); + ChangeOutputName( 2, "RT Height" ); + ChangeOutputName( 3, "1+1/Width" ); + ChangeOutputName( 4, "1+1/Height" ); + m_value = "_ScreenParams"; + m_previewShaderGUID = "78173633b803de4419206191fed3d61e"; + } + + //public override void RefreshExternalReferences() + //{ + // base.RefreshExternalReferences(); + // if( !m_outputPorts[ 0 ].IsConnected ) + // { + // m_outputPorts[ 0 ].Visible = false; + // m_sizeIsDirty = true; + // } + //} + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ScreenParams.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ScreenParams.cs.meta new file mode 100644 index 0000000..f43db82 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ScreenParams.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2e593f23857d59643b5b5f6dd6264e1b +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/WorldSpaceCameraPos.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/WorldSpaceCameraPos.cs new file mode 100644 index 0000000..2342f15 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/WorldSpaceCameraPos.cs @@ -0,0 +1,28 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "World Space Camera Pos", "Camera And Screen", "World Space Camera position" )] + public sealed class WorldSpaceCameraPos : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "XYZ", WirePortDataType.FLOAT3 ); + AddOutputPort( WirePortDataType.FLOAT, "X" ); + AddOutputPort( WirePortDataType.FLOAT, "Y" ); + AddOutputPort( WirePortDataType.FLOAT, "Z" ); + + m_value = "_WorldSpaceCameraPos"; + m_previewShaderGUID = "6b0c78411043dd24dac1152c84bb63ba"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + return GetOutputVectorItem( 0, outputId, base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/WorldSpaceCameraPos.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/WorldSpaceCameraPos.cs.meta new file mode 100644 index 0000000..8a47447 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/WorldSpaceCameraPos.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 972d92a6008896f4292a61726e18f667 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ZBufferParams.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ZBufferParams.cs new file mode 100644 index 0000000..4fcb5e1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ZBufferParams.cs @@ -0,0 +1,31 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Z-Buffer Params", "Camera And Screen", "Linearized Z buffer values" )] + public sealed class ZBufferParams : ConstVecShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputName( 1, "1-far/near" ); + ChangeOutputName( 2, "far/near" ); + ChangeOutputName( 3, "[0]/far" ); + ChangeOutputName( 4, "[1]/far" ); + m_value = "_ZBufferParams"; + m_previewShaderGUID = "56c42c106bcb497439187f5bb6b6f94d"; + } + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( !m_outputPorts[ 0 ].IsConnected ) + { + m_outputPorts[ 0 ].Visible = false; + m_sizeIsDirty = true; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ZBufferParams.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ZBufferParams.cs.meta new file mode 100644 index 0000000..e8b668c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/CameraAndScreen/ZBufferParams.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2765a41106f478f4982e859b978bdec4 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstVecShaderVariable.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstVecShaderVariable.cs new file mode 100644 index 0000000..d74d8a5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstVecShaderVariable.cs @@ -0,0 +1,39 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + public class ConstVecShaderVariable : ShaderVariablesNode + { + [SerializeField] + protected string m_value; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, " ", WirePortDataType.FLOAT4 ); + AddOutputPort( WirePortDataType.FLOAT, "0" ); + AddOutputPort( WirePortDataType.FLOAT, "1" ); + AddOutputPort( WirePortDataType.FLOAT, "2" ); + AddOutputPort( WirePortDataType.FLOAT, "3" ); + } + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + switch ( outputId ) + { + case 0: return m_value; + case 1: return ( m_value + ".x" ); + case 2: return ( m_value + ".y" ); + case 3: return ( m_value + ".z" ); + case 4: return ( m_value + ".w" ); + } + + UIUtils.ShowMessage( UniqueId, "ConstVecShaderVariable generating empty code", MessageSeverity.Warning ); + return string.Empty; + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstVecShaderVariable.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstVecShaderVariable.cs.meta new file mode 100644 index 0000000..97976c8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstVecShaderVariable.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9102c0b554fd5ad4785acf870dcc17eb +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstantShaderVariable.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstantShaderVariable.cs new file mode 100644 index 0000000..ff6279e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstantShaderVariable.cs @@ -0,0 +1,35 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class ConstantShaderVariable : ShaderVariablesNode + { + [SerializeField] + protected string m_value; + + [SerializeField] + protected string m_HDValue = string.Empty; + + [SerializeField] + protected string m_LWValue = string.Empty; + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + if( dataCollector.IsTemplate ) + { + if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD && !string.IsNullOrEmpty( m_HDValue ) ) + return m_HDValue; + + if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.Lightweight && !string.IsNullOrEmpty( m_LWValue )) + return m_LWValue; + } + return m_value; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstantShaderVariable.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstantShaderVariable.cs.meta new file mode 100644 index 0000000..5511016 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ConstantShaderVariable.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 266391c3c4308014e9ce246e5484b917 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient.meta new file mode 100644 index 0000000..e0c69e8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 78eb7b1e34d423c40a949c9e75b5f24a +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogAndAmbientColorsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogAndAmbientColorsNode.cs new file mode 100644 index 0000000..2af78f7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogAndAmbientColorsNode.cs @@ -0,0 +1,126 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + public enum BuiltInFogAndAmbientColors + { + UNITY_LIGHTMODEL_AMBIENT = 0, + unity_AmbientSky, + unity_AmbientEquator, + unity_AmbientGround, + unity_FogColor + } + + [Serializable] + [NodeAttributes( "Fog And Ambient Colors", "Light", "Fog and Ambient colors" )] + public sealed class FogAndAmbientColorsNode : ShaderVariablesNode + { + private const string ColorLabelStr = "Color"; + private readonly string[] ColorValuesStr = { + "Ambient light ( Legacy )", + "Sky ambient light", + "Equator ambient light", + "Ground ambient light", + "Fog" + }; + + [SerializeField] + private BuiltInFogAndAmbientColors m_selectedType = BuiltInFogAndAmbientColors.UNITY_LIGHTMODEL_AMBIENT; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, ColorValuesStr[ ( int ) m_selectedType ], WirePortDataType.COLOR ); + m_textLabelWidth = 50; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + m_previewShaderGUID = "937c7bde062f0f942b600d9950d2ebb2"; + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + m_previewMaterialPassId = (int)m_selectedType; + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_selectedType = (BuiltInFogAndAmbientColors)m_upperLeftWidget.DrawWidget( this, (int)m_selectedType, ColorValuesStr ); + if( EditorGUI.EndChangeCheck() ) + { + ChangeOutputName( 0, ColorValuesStr[ (int)m_selectedType ] ); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_selectedType = ( BuiltInFogAndAmbientColors ) EditorGUILayoutPopup( ColorLabelStr, ( int ) m_selectedType, ColorValuesStr ); + + if ( EditorGUI.EndChangeCheck() ) + { + ChangeOutputName( 0, ColorValuesStr[ ( int ) m_selectedType ] ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + if( dataCollector.IsTemplate && dataCollector.CurrentSRPType == TemplateSRPType.HD ) + { + switch( m_selectedType ) + { + case BuiltInFogAndAmbientColors.unity_AmbientSky: + return "_Ambient_ColorSky"; + case BuiltInFogAndAmbientColors.unity_AmbientEquator: + return "_Ambient_Equator"; + case BuiltInFogAndAmbientColors.unity_AmbientGround: + return "_Ambient_Ground"; + case BuiltInFogAndAmbientColors.unity_FogColor: + return "_FogColor"; + } + } + return m_selectedType.ToString(); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedType = ( BuiltInFogAndAmbientColors ) Enum.Parse( typeof( BuiltInFogAndAmbientColors ), GetCurrentParam( ref nodeParams ) ); + ChangeOutputName( 0, ColorValuesStr[ ( int ) m_selectedType ] ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedType ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogAndAmbientColorsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogAndAmbientColorsNode.cs.meta new file mode 100644 index 0000000..f2ab7d0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogAndAmbientColorsNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e2bdfc2fa6fcd0640b01a8b7448a1a11 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogParamsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogParamsNode.cs new file mode 100644 index 0000000..63a635d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogParamsNode.cs @@ -0,0 +1,32 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Fog Params", "Light", "Parameters for fog calculation" )] + public sealed class FogParamsNode : ConstVecShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputName( 1, "Density/Sqrt(Ln(2))" ); + ChangeOutputName( 2, "Density/Ln(2)" ); + ChangeOutputName( 3, "-1/(End-Start)" ); + ChangeOutputName( 4, "End/(End-Start))" ); + m_value = "unity_FogParams"; + m_previewShaderGUID = "42abde3281b1848438c3b53443c91a1e"; + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( !m_outputPorts[ 0 ].IsConnected ) + { + m_outputPorts[ 0 ].Visible = false; + m_sizeIsDirty = true; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogParamsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogParamsNode.cs.meta new file mode 100644 index 0000000..ccc0df5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/FogAndAmbient/FogParamsNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a3d8c31159e07bc419a7484ab5e894ed +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting.meta new file mode 100644 index 0000000..86287e6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 47f503bcb5935b649beee3296dd40260 +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/CustomStandardSurface.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/CustomStandardSurface.cs new file mode 100644 index 0000000..d985714 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/CustomStandardSurface.cs @@ -0,0 +1,197 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + + public enum ASEStandardSurfaceWorkflow + { + Metallic = 0, + Specular + } + + [Serializable] + [NodeAttributes( "Standard Surface Light", "Light", "Provides a way to create a standard surface light model in custom lighting mode", NodeAvailabilityFlags = (int)NodeAvailability.CustomLighting )] + public sealed class CustomStandardSurface : ParentNode + { + private const string WorkflowStr = "Workflow"; + + [SerializeField] + private ASEStandardSurfaceWorkflow m_workflow = ASEStandardSurfaceWorkflow.Metallic; + + [SerializeField] + private ViewSpace m_normalSpace = ViewSpace.Tangent; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "Albedo" ); + AddInputPort( WirePortDataType.FLOAT3, false, "Normal" ); + m_inputPorts[ 1 ].Vector3InternalData = Vector3.forward; + AddInputPort( WirePortDataType.FLOAT3, false, "Emission" ); + AddInputPort( WirePortDataType.FLOAT, false, "Metallic" ); + AddInputPort( WirePortDataType.FLOAT, false, "Smoothness" ); + AddInputPort( WirePortDataType.FLOAT, false, "Occlusion" ); + m_inputPorts[ 5 ].FloatInternalData = 1; + AddOutputPort( WirePortDataType.FLOAT3, "RGB" ); + m_autoWrapProperties = true; + m_textLabelWidth = 100; + m_errorMessageTypeIsError = NodeMessageType.Warning; + m_errorMessageTooltip = "This node only returns correct information using a custom light model, otherwise returns 0"; + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + if( m_inputPorts[ 1 ].IsConnected && m_normalSpace == ViewSpace.Tangent ) + dataCollector.DirtyNormal = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_workflow = (ASEStandardSurfaceWorkflow)EditorGUILayoutEnumPopup( WorkflowStr, m_workflow ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateSpecularMetallicPorts(); + } + + EditorGUI.BeginChangeCheck(); + m_normalSpace = (ViewSpace)EditorGUILayoutEnumPopup( "Normal Space", m_normalSpace ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePort(); + } + } + + private void UpdatePort() + { + if( m_normalSpace == ViewSpace.World ) + m_inputPorts[ 1 ].Name = "World Normal"; + else + m_inputPorts[ 1 ].Name = "Normal"; + + m_sizeIsDirty = true; + } + + void UpdateSpecularMetallicPorts() + { + if( m_workflow == ASEStandardSurfaceWorkflow.Specular ) + m_inputPorts[ 3 ].ChangeProperties( "Specular", WirePortDataType.FLOAT3, false ); + else + m_inputPorts[ 3 ].ChangeProperties( "Metallic", WirePortDataType.FLOAT, false ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.GenType == PortGenType.NonCustomLighting || dataCollector.CurrentCanvasMode != NodeAvailability.CustomLighting ) + return "float3(0,0,0)"; + + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string specularMode = string.Empty; + if( m_workflow == ASEStandardSurfaceWorkflow.Specular ) + specularMode = "Specular"; + + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + + if( dataCollector.DirtyNormal ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + dataCollector.ForceNormal = true; + } + + dataCollector.AddLocalVariable( UniqueId, "SurfaceOutputStandard" + specularMode + " s" + OutputId + " = (SurfaceOutputStandard" + specularMode + " ) 0;" ); + dataCollector.AddLocalVariable( UniqueId, "s" + OutputId + ".Albedo = " + m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) + ";" ); + + string normal = string.Empty; + + if( m_inputPorts[ 1 ].IsConnected ) + { + normal = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + if( m_normalSpace == ViewSpace.Tangent ) + { + normal = "WorldNormalVector( " + Constants.InputVarStr + " , " + normal + " )"; + } + } + else + { + normal = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId ); + } + + + + dataCollector.AddLocalVariable( UniqueId, "s" + OutputId + ".Normal = "+ normal + ";" ); + dataCollector.AddLocalVariable( UniqueId, "s" + OutputId + ".Emission = " + m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ) + ";" ); + if( m_workflow == ASEStandardSurfaceWorkflow.Specular ) + dataCollector.AddLocalVariable( UniqueId, "s" + OutputId + ".Specular = " + m_inputPorts[ 3 ].GeneratePortInstructions( ref dataCollector ) + ";" ); + else + dataCollector.AddLocalVariable( UniqueId, "s" + OutputId + ".Metallic = " + m_inputPorts[ 3 ].GeneratePortInstructions( ref dataCollector ) + ";" ); + dataCollector.AddLocalVariable( UniqueId, "s" + OutputId + ".Smoothness = " + m_inputPorts[ 4 ].GeneratePortInstructions( ref dataCollector ) + ";" ); + dataCollector.AddLocalVariable( UniqueId, "s" + OutputId + ".Occlusion = " + m_inputPorts[ 5 ].GeneratePortInstructions( ref dataCollector ) + ";\n" ); + + dataCollector.AddLocalVariable( UniqueId, "data.light = gi.light;\n", true ); + + dataCollector.AddLocalVariable( UniqueId, "UnityGI gi" + OutputId + " = gi;" ); + dataCollector.AddLocalVariable( UniqueId, "#ifdef UNITY_PASS_FORWARDBASE", true ); + + dataCollector.AddLocalVariable( UniqueId, "Unity_GlossyEnvironmentData g" + OutputId + " = UnityGlossyEnvironmentSetup( s" + OutputId + ".Smoothness, data.worldViewDir, s" + OutputId + ".Normal, float3(0,0,0));" ); + dataCollector.AddLocalVariable( UniqueId, "gi" + OutputId + " = UnityGlobalIllumination( data, s" + OutputId + ".Occlusion, s" + OutputId + ".Normal, g" + OutputId + " );" ); + dataCollector.AddLocalVariable( UniqueId, "#endif\n", true ); + dataCollector.AddLocalVariable( UniqueId, "float3 surfResult" + OutputId + " = LightingStandard" + specularMode + " ( s" + OutputId + ", viewDir, gi" + OutputId + " ).rgb;" ); + //Emission must be always added to trick Unity, so it knows what needs to be created p.e. world pos + dataCollector.AddLocalVariable( UniqueId, "surfResult" + OutputId + " += s" + OutputId + ".Emission;\n" ); + + m_outputPorts[ 0 ].SetLocalValue( "surfResult" + OutputId, dataCollector.PortCategory ); + + //Remove emission contribution from Forward Add + dataCollector.AddLocalVariable( UniqueId, "#ifdef UNITY_PASS_FORWARDADD//" + OutputId ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "surfResult{0} -= s{0}.Emission;", OutputId )); + dataCollector.AddLocalVariable( UniqueId, "#endif//" + OutputId ); + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( ContainerGraph.CurrentCanvasMode == NodeAvailability.TemplateShader || ( ContainerGraph.CurrentStandardSurface != null && ContainerGraph.CurrentStandardSurface.CurrentLightingModel != StandardShaderLightModel.CustomLighting ) ) + m_showErrorMessage = true; + else + m_showErrorMessage = false; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() < 13204 ) + { + m_workflow = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ) ? ASEStandardSurfaceWorkflow.Specular : ASEStandardSurfaceWorkflow.Metallic; + } + else + { + m_workflow = (ASEStandardSurfaceWorkflow)Enum.Parse( typeof( ASEStandardSurfaceWorkflow ), GetCurrentParam( ref nodeParams ) ); + } + UpdateSpecularMetallicPorts(); + + if( UIUtils.CurrentShaderVersion() >= 14402 ) + { + m_normalSpace = (ViewSpace)Enum.Parse( typeof( ViewSpace ), GetCurrentParam( ref nodeParams ) ); + } + UpdatePort(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_workflow ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalSpace ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/CustomStandardSurface.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/CustomStandardSurface.cs.meta new file mode 100644 index 0000000..172f37c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/CustomStandardSurface.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 78916999fd7bc3c4e9767bc9cf0698c0 +timeCreated: 1500054866 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectDiffuseLighting.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectDiffuseLighting.cs new file mode 100644 index 0000000..bfef92c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectDiffuseLighting.cs @@ -0,0 +1,367 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Indirect Diffuse Light", "Light", "Indirect Lighting", NodeAvailabilityFlags = (int)( NodeAvailability.CustomLighting | NodeAvailability.TemplateShader ) )] + public sealed class IndirectDiffuseLighting : ParentNode + { + [SerializeField] + private ViewSpace m_normalSpace = ViewSpace.Tangent; + + private int m_cachedIntensityId = -1; + + private const string FwdBasePragma = "#pragma multi_compile_fwdbase"; + + private readonly string LWIndirectDiffuseHeader = "ASEIndirectDiffuse( {0}, {1})"; + private readonly string[] LWIndirectDiffuseBody = + { + "float3 ASEIndirectDiffuse( float2 uvStaticLightmap, float3 normalWS )\n", + "{\n", + "#ifdef LIGHTMAP_ON\n", + "\treturn SampleLightmap( uvStaticLightmap, normalWS );\n", + "#else\n", + "\treturn SampleSH(normalWS);\n", + "#endif\n", + "}\n" + }; + + + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "Normal" ); + AddOutputPort( WirePortDataType.FLOAT3, "RGB" ); + m_inputPorts[ 0 ].Vector3InternalData = Vector3.forward; + m_autoWrapProperties = true; + m_errorMessageTypeIsError = NodeMessageType.Warning; + m_errorMessageTooltip = "This node only returns correct information using a custom light model, otherwise returns 0"; + m_previewShaderGUID = "b45d57fa606c1ea438fe9a2c08426bc7"; + m_drawPreviewAsSphere = true; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_inputPorts[ 0 ].IsConnected ) + { + if( m_normalSpace == ViewSpace.Tangent ) + m_previewMaterialPassId = 1; + else + m_previewMaterialPassId = 2; + } + else + { + m_previewMaterialPassId = 0; + } + + if( m_cachedIntensityId == -1 ) + m_cachedIntensityId = Shader.PropertyToID( "_Intensity" ); + + PreviewMaterial.SetFloat( m_cachedIntensityId, RenderSettings.ambientIntensity ); + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + // This needs to be rechecked + //if( m_inputPorts[ 0 ].IsConnected ) + dataCollector.DirtyNormal = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + + EditorGUI.BeginChangeCheck(); + m_normalSpace = (ViewSpace)EditorGUILayoutEnumPopup( "Normal Space", m_normalSpace ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePort(); + } + } + + private void UpdatePort() + { + if( m_normalSpace == ViewSpace.World ) + m_inputPorts[ 0 ].ChangeProperties( "World Normal", m_inputPorts[ 0 ].DataType, false ); + else + m_inputPorts[ 0 ].ChangeProperties( "Normal", m_inputPorts[ 0 ].DataType, false ); + + m_sizeIsDirty = true; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( ( ContainerGraph.CurrentStandardSurface != null && ContainerGraph.CurrentStandardSurface.CurrentLightingModel != StandardShaderLightModel.CustomLighting ) ) + m_showErrorMessage = true; + else + m_showErrorMessage = false; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + string finalValue = string.Empty; + + if( dataCollector.IsTemplate && dataCollector.IsFragmentCategory ) + { + if( !dataCollector.IsSRP ) + { + dataCollector.AddToIncludes( UniqueId, Constants.UnityLightingLib ); + dataCollector.AddToDirectives( FwdBasePragma ); + string texcoord1 = string.Empty; + string texcoord2 = string.Empty; + + if( dataCollector.TemplateDataCollectorInstance.HasInfo( TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex ) ) + texcoord1 = dataCollector.TemplateDataCollectorInstance.GetInfo( TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex ).VarName; + else + texcoord1 = dataCollector.TemplateDataCollectorInstance.RegisterInfoOnSemantic( MasterNodePortCategory.Vertex, TemplateInfoOnSematics.TEXTURE_COORDINATES1, TemplateSemantics.TEXCOORD1, "texcoord1", WirePortDataType.FLOAT4, PrecisionType.Float, false ); + + if( dataCollector.TemplateDataCollectorInstance.HasInfo( TemplateInfoOnSematics.TEXTURE_COORDINATES2, false, MasterNodePortCategory.Vertex ) ) + texcoord2 = dataCollector.TemplateDataCollectorInstance.GetInfo( TemplateInfoOnSematics.TEXTURE_COORDINATES2, false, MasterNodePortCategory.Vertex ).VarName; + else + texcoord2 = dataCollector.TemplateDataCollectorInstance.RegisterInfoOnSemantic( MasterNodePortCategory.Vertex, TemplateInfoOnSematics.TEXTURE_COORDINATES2, TemplateSemantics.TEXCOORD2, "texcoord2", WirePortDataType.FLOAT4, PrecisionType.Float, false ); + + string vOutName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData.OutVarName; + string fInName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.FragmentFunctionData.InVarName; + TemplateVertexData data = dataCollector.TemplateDataCollectorInstance.RequestNewInterpolator( WirePortDataType.FLOAT4, false, "ase_lmap" ); + + string varName = "ase_lmap"; + if( data != null ) + varName = data.VarName; + + dataCollector.AddToVertexLocalVariables( UniqueId, "#ifdef DYNAMICLIGHTMAP_ON //dynlm" ); + dataCollector.AddToVertexLocalVariables( UniqueId, vOutName + "." + varName + ".zw = " + texcoord2 + ".xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;" ); + dataCollector.AddToVertexLocalVariables( UniqueId, "#endif //dynlm" ); + dataCollector.AddToVertexLocalVariables( UniqueId, "#ifdef LIGHTMAP_ON //stalm" ); + dataCollector.AddToVertexLocalVariables( UniqueId, vOutName + "." + varName + ".xy = " + texcoord1 + ".xy * unity_LightmapST.xy + unity_LightmapST.zw;" ); + dataCollector.AddToVertexLocalVariables( UniqueId, "#endif //stalm" ); + + TemplateVertexData shdata = dataCollector.TemplateDataCollectorInstance.RequestNewInterpolator( WirePortDataType.FLOAT3, false, "ase_sh" ); + string worldPos = dataCollector.TemplateDataCollectorInstance.GetWorldPos( false, MasterNodePortCategory.Vertex ); + string worldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( PrecisionType.Float, false, MasterNodePortCategory.Vertex ); + //Debug.Log( shdata ); + string shVarName = "ase_sh"; + if( shdata != null ) + shVarName = shdata.VarName; + string outSH = vOutName + "." + shVarName + ".xyz"; + dataCollector.AddToVertexLocalVariables( UniqueId, "#ifndef LIGHTMAP_ON //nstalm" ); + dataCollector.AddToVertexLocalVariables( UniqueId, "#if UNITY_SHOULD_SAMPLE_SH //sh" ); + dataCollector.AddToVertexLocalVariables( UniqueId, outSH + " = 0;" ); + dataCollector.AddToVertexLocalVariables( UniqueId, "#ifdef VERTEXLIGHT_ON //vl" ); + dataCollector.AddToVertexLocalVariables( UniqueId, outSH + " += Shade4PointLights (" ); + dataCollector.AddToVertexLocalVariables( UniqueId, "unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0," ); + dataCollector.AddToVertexLocalVariables( UniqueId, "unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb," ); + dataCollector.AddToVertexLocalVariables( UniqueId, "unity_4LightAtten0, " + worldPos + ", " + worldNormal + ");" ); + dataCollector.AddToVertexLocalVariables( UniqueId, "#endif //vl" ); + dataCollector.AddToVertexLocalVariables( UniqueId, outSH + " = ShadeSHPerVertex (" + worldNormal + ", " + outSH + ");" ); + dataCollector.AddToVertexLocalVariables( UniqueId, "#endif //sh" ); + dataCollector.AddToVertexLocalVariables( UniqueId, "#endif //nstalm" ); + + //dataCollector.AddToPragmas( UniqueId, "multi_compile_fwdbase" ); + + string fragWorldNormal = string.Empty; + if( m_inputPorts[ 0 ].IsConnected ) + { + if( m_normalSpace == ViewSpace.Tangent ) + fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( UniqueId, CurrentPrecisionType, m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ), OutputId ); + else + fragWorldNormal = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + } + else + { + fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( PrecisionType.Float, false, MasterNodePortCategory.Fragment ); + } + + dataCollector.AddLocalVariable( UniqueId, "UnityGIInput data" + OutputId + ";" ); + dataCollector.AddLocalVariable( UniqueId, "UNITY_INITIALIZE_OUTPUT( UnityGIInput, data" + OutputId + " );" ); + + dataCollector.AddLocalVariable( UniqueId, "#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON) //dylm" + OutputId ); + dataCollector.AddLocalVariable( UniqueId, "data" + OutputId + ".lightmapUV = " + fInName + "." + varName + ";" ); + dataCollector.AddLocalVariable( UniqueId, "#endif //dylm" + OutputId ); + + dataCollector.AddLocalVariable( UniqueId, "#if UNITY_SHOULD_SAMPLE_SH //fsh" + OutputId ); + dataCollector.AddLocalVariable( UniqueId, "data" + OutputId + ".ambient = " + fInName + "." + shVarName + ";" ); + dataCollector.AddLocalVariable( UniqueId, "#endif //fsh" + OutputId ); + + dataCollector.AddToFragmentLocalVariables( UniqueId, "UnityGI gi" + OutputId + " = UnityGI_Base(data" + OutputId + ", 1, " + fragWorldNormal + ");" ); + + finalValue = "gi" + OutputId + ".indirect.diffuse"; + m_outputPorts[ 0 ].SetLocalValue( finalValue, dataCollector.PortCategory ); + return finalValue; + } + else + { + if( dataCollector.CurrentSRPType == TemplateSRPType.Lightweight ) + { + string texcoord1 = string.Empty; + + if( dataCollector.TemplateDataCollectorInstance.HasInfo( TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex ) ) + texcoord1 = dataCollector.TemplateDataCollectorInstance.GetInfo( TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex ).VarName; + else + texcoord1 = dataCollector.TemplateDataCollectorInstance.RegisterInfoOnSemantic( MasterNodePortCategory.Vertex, TemplateInfoOnSematics.TEXTURE_COORDINATES1, TemplateSemantics.TEXCOORD1, "texcoord1", WirePortDataType.FLOAT4, PrecisionType.Float, false ); + + string vOutName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData.OutVarName; + string fInName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.FragmentFunctionData.InVarName; + + + if( !dataCollector.TemplateDataCollectorInstance.HasRawInterpolatorOfName( "lightmapUVOrVertexSH" ) ) + { + string worldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( PrecisionType.Float, false, MasterNodePortCategory.Vertex ); + dataCollector.TemplateDataCollectorInstance.RequestNewInterpolator( WirePortDataType.FLOAT4, false, "lightmapUVOrVertexSH" ); + + dataCollector.AddToVertexLocalVariables( UniqueId, "OUTPUT_LIGHTMAP_UV( " + texcoord1 + ", unity_LightmapST, " + vOutName + ".lightmapUVOrVertexSH.xy );" ); + dataCollector.AddToVertexLocalVariables( UniqueId, "OUTPUT_SH( " + worldNormal + ", " + vOutName + ".lightmapUVOrVertexSH.xyz );" ); + + dataCollector.AddToPragmas( UniqueId, "multi_compile _ DIRLIGHTMAP_COMBINED" ); + dataCollector.AddToPragmas( UniqueId, "multi_compile _ LIGHTMAP_ON" ); + } + + string fragWorldNormal = string.Empty; + if( m_inputPorts[ 0 ].IsConnected ) + { + if( m_normalSpace == ViewSpace.Tangent ) + fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( UniqueId, CurrentPrecisionType, m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ), OutputId ); + else + fragWorldNormal = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + } + else + { + fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( PrecisionType.Float, false, MasterNodePortCategory.Fragment ); + } + + //SAMPLE_GI + + //This function may not do full pixel and does not behave correctly with given normal thus is commented out + //dataCollector.AddLocalVariable( UniqueId, "float3 bakedGI" + OutputId + " = SAMPLE_GI( " + fInName + ".lightmapUVOrVertexSH.xy, " + fInName + ".lightmapUVOrVertexSH.xyz, " + fragWorldNormal + " );" ); + dataCollector.AddFunction( LWIndirectDiffuseBody[ 0 ], LWIndirectDiffuseBody, false ); + finalValue = "bakedGI" + OutputId; + string result = string.Format( LWIndirectDiffuseHeader, fInName + ".lightmapUVOrVertexSH.xy", fragWorldNormal ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, finalValue, result ); + + m_outputPorts[ 0 ].SetLocalValue( finalValue, dataCollector.PortCategory ); + return finalValue; + } + else if( dataCollector.CurrentSRPType == TemplateSRPType.HD ) + { + string texcoord1 = string.Empty; + string texcoord2 = string.Empty; + + if( dataCollector.TemplateDataCollectorInstance.HasInfo( TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex ) ) + texcoord1 = dataCollector.TemplateDataCollectorInstance.GetInfo( TemplateInfoOnSematics.TEXTURE_COORDINATES1, false, MasterNodePortCategory.Vertex ).VarName; + else + texcoord1 = dataCollector.TemplateDataCollectorInstance.RegisterInfoOnSemantic( MasterNodePortCategory.Vertex, TemplateInfoOnSematics.TEXTURE_COORDINATES1, TemplateSemantics.TEXCOORD1, "texcoord1", WirePortDataType.FLOAT4, PrecisionType.Float, false ); + + if( dataCollector.TemplateDataCollectorInstance.HasInfo( TemplateInfoOnSematics.TEXTURE_COORDINATES2, false, MasterNodePortCategory.Vertex ) ) + texcoord2 = dataCollector.TemplateDataCollectorInstance.GetInfo( TemplateInfoOnSematics.TEXTURE_COORDINATES2, false, MasterNodePortCategory.Vertex ).VarName; + else + texcoord2 = dataCollector.TemplateDataCollectorInstance.RegisterInfoOnSemantic( MasterNodePortCategory.Vertex, TemplateInfoOnSematics.TEXTURE_COORDINATES2, TemplateSemantics.TEXCOORD2, "texcoord2", WirePortDataType.FLOAT4, PrecisionType.Float, false ); + + dataCollector.TemplateDataCollectorInstance.RequestNewInterpolator( WirePortDataType.FLOAT4, false, "ase_lightmapUVs" ); + + string vOutName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData.OutVarName; + string fInName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.FragmentFunctionData.InVarName; + + dataCollector.AddToVertexLocalVariables( UniqueId, vOutName + ".ase_lightmapUVs.xy = " + texcoord1 + ".xy * unity_LightmapST.xy + unity_LightmapST.zw;" ); + dataCollector.AddToVertexLocalVariables( UniqueId, vOutName + ".ase_lightmapUVs.zw = " + texcoord2 + ".xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;" ); + + string worldPos = dataCollector.TemplateDataCollectorInstance.GetWorldPos( false, MasterNodePortCategory.Fragment ); + + dataCollector.AddToPragmas( UniqueId, "multi_compile _ LIGHTMAP_ON" ); + dataCollector.AddToPragmas( UniqueId, "multi_compile _ DIRLIGHTMAP_COMBINED" ); + dataCollector.AddToPragmas( UniqueId, "multi_compile _ DYNAMICLIGHTMAP_ON" ); + + string fragWorldNormal = string.Empty; + if( m_inputPorts[ 0 ].IsConnected ) + { + if( m_normalSpace == ViewSpace.Tangent ) + fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( UniqueId, CurrentPrecisionType, m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ), OutputId ); + else + fragWorldNormal = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + } + else + { + fragWorldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( PrecisionType.Float, false, MasterNodePortCategory.Fragment ); + } + + //SAMPLE_GI + dataCollector.AddLocalVariable( UniqueId, "float3 bakedGI" + OutputId + " = SampleBakedGI( " + worldPos + ", " + fragWorldNormal + ", " + fInName + ".ase_lightmapUVs.xy, " + fInName + ".ase_lightmapUVs.zw );" ); + finalValue = "bakedGI" + OutputId; + m_outputPorts[ 0 ].SetLocalValue( finalValue, dataCollector.PortCategory ); + return finalValue; + } + } + } + if( dataCollector.GenType == PortGenType.NonCustomLighting || dataCollector.CurrentCanvasMode != NodeAvailability.CustomLighting ) + return "float3(0,0,0)"; + + string normal = string.Empty; + if( m_inputPorts[ 0 ].IsConnected ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + dataCollector.ForceNormal = true; + + normal = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + if( m_normalSpace == ViewSpace.Tangent ) + normal = "WorldNormalVector( " + Constants.InputVarStr + " , " + normal + " )"; + } + else + { + if( dataCollector.IsFragmentCategory ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + if( dataCollector.DirtyNormal ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + dataCollector.ForceNormal = true; + } + } + + normal = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId ); + } + + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, "indirectDiffuse" + OutputId, "ShadeSH9( float4( " + normal + ", 1 ) )" ); + } + else + { + dataCollector.AddLocalVariable( UniqueId, "UnityGI gi" + OutputId + " = gi;" ); + dataCollector.AddLocalVariable( UniqueId, PrecisionType.Float, WirePortDataType.FLOAT3, "diffNorm" + OutputId, normal ); + dataCollector.AddLocalVariable( UniqueId, "gi" + OutputId + " = UnityGI_Base( data, 1, diffNorm" + OutputId + " );" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, "indirectDiffuse" + OutputId, "gi" + OutputId + ".indirect.diffuse + diffNorm" + OutputId + " * 0.0001" ); + } + + finalValue = "indirectDiffuse" + OutputId; + m_outputPorts[ 0 ].SetLocalValue( finalValue, dataCollector.PortCategory ); + return finalValue; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 13002 ) + m_normalSpace = (ViewSpace)Enum.Parse( typeof( ViewSpace ), GetCurrentParam( ref nodeParams ) ); + + UpdatePort(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalSpace ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectDiffuseLighting.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectDiffuseLighting.cs.meta new file mode 100644 index 0000000..2e9b5ba --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectDiffuseLighting.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 11bf17b0757d57c47add2eb50c62c75e +timeCreated: 1495726164 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectSpecularLight.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectSpecularLight.cs new file mode 100644 index 0000000..197e193 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectSpecularLight.cs @@ -0,0 +1,268 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Indirect Specular Light", "Light", "Indirect Specular Light", NodeAvailabilityFlags = (int)( NodeAvailability.CustomLighting | NodeAvailability.TemplateShader ) )] + public sealed class IndirectSpecularLight : ParentNode + { + [SerializeField] + private ViewSpace m_normalSpace = ViewSpace.Tangent; + + private const string DefaultErrorMessage = "This node only returns correct information using a custom light model, otherwise returns 0"; + private bool m_upgradeMessage = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "Normal" ); + AddInputPort( WirePortDataType.FLOAT, false, "Smoothness" ); + AddInputPort( WirePortDataType.FLOAT, false, "Occlusion" ); + m_inputPorts[ 0 ].Vector3InternalData = Vector3.forward; + m_inputPorts[ 1 ].FloatInternalData = 0.5f; + m_inputPorts[ 2 ].FloatInternalData = 1; + m_inputPorts[ 1 ].AutoDrawInternalData = true; + m_inputPorts[ 2 ].AutoDrawInternalData = true; + m_autoWrapProperties = true; + AddOutputPort( WirePortDataType.FLOAT3, "RGB" ); + m_errorMessageTypeIsError = NodeMessageType.Warning; + m_errorMessageTooltip = DefaultErrorMessage; + m_previewShaderGUID = "d6e441d0a8608954c97fa347d3735e92"; + m_drawPreviewAsSphere = true; + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + if( m_inputPorts[ 0 ].IsConnected ) + dataCollector.DirtyNormal = true; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_inputPorts[ 0 ].IsConnected ) + { + if( m_normalSpace == ViewSpace.Tangent ) + m_previewMaterialPassId = 1; + else + m_previewMaterialPassId = 2; + } + else + { + m_previewMaterialPassId = 0; + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + + EditorGUI.BeginChangeCheck(); + m_normalSpace = (ViewSpace)EditorGUILayoutEnumPopup( "Normal Space", m_normalSpace ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePort(); + } + if( !m_inputPorts[ 1 ].IsConnected ) + m_inputPorts[ 1 ].FloatInternalData = EditorGUILayout.FloatField( m_inputPorts[ 1 ].Name, m_inputPorts[ 1 ].FloatInternalData ); + if( !m_inputPorts[ 2 ].IsConnected ) + m_inputPorts[ 2 ].FloatInternalData = EditorGUILayout.FloatField( m_inputPorts[ 2 ].Name, m_inputPorts[ 2 ].FloatInternalData ); + } + + private void UpdatePort() + { + if( m_normalSpace == ViewSpace.World ) + m_inputPorts[ 0 ].ChangeProperties( "World Normal", m_inputPorts[ 0 ].DataType, false ); + else + m_inputPorts[ 0 ].ChangeProperties( "Normal", m_inputPorts[ 0 ].DataType, false ); + + m_sizeIsDirty = true; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( m_upgradeMessage || ( ContainerGraph.CurrentStandardSurface != null && ContainerGraph.CurrentStandardSurface.CurrentLightingModel != StandardShaderLightModel.CustomLighting ) ) + m_showErrorMessage = true; + else + m_showErrorMessage = false; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate ) + { + if( !dataCollector.IsSRP ) + { + dataCollector.AddToIncludes( UniqueId, Constants.UnityLightingLib ); + string worldPos = dataCollector.TemplateDataCollectorInstance.GetWorldPos(); + string worldViewDir = dataCollector.TemplateDataCollectorInstance.GetViewDir( false, MasterNodePortCategory.Fragment ); + + string worldNormal = string.Empty; + if( m_inputPorts[ 0 ].IsConnected ) + { + if( m_normalSpace == ViewSpace.Tangent ) + worldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( UniqueId, CurrentPrecisionType, m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ), OutputId ); + else + worldNormal = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + } + else + { + worldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( PrecisionType.Float, false, MasterNodePortCategory.Fragment ); + } + + string tempsmoothness = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string tempocclusion = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + + dataCollector.AddLocalVariable( UniqueId, "UnityGIInput data;" ); + dataCollector.AddLocalVariable( UniqueId, "UNITY_INITIALIZE_OUTPUT( UnityGIInput, data );" ); + dataCollector.AddLocalVariable( UniqueId, "data.worldPos = " + worldPos + ";" ); + dataCollector.AddLocalVariable( UniqueId, "data.worldViewDir = " + worldViewDir + ";" ); + dataCollector.AddLocalVariable( UniqueId, "data.probeHDR[0] = unity_SpecCube0_HDR;" ); + dataCollector.AddLocalVariable( UniqueId, "data.probeHDR[1] = unity_SpecCube1_HDR;" ); + dataCollector.AddLocalVariable( UniqueId, "#if UNITY_SPECCUBE_BLENDING || UNITY_SPECCUBE_BOX_PROJECTION //specdataif0" ); + dataCollector.AddLocalVariable( UniqueId, "\tdata.boxMin[0] = unity_SpecCube0_BoxMin;" ); + dataCollector.AddLocalVariable( UniqueId, "#endif //specdataif0" ); + dataCollector.AddLocalVariable( UniqueId, "#if UNITY_SPECCUBE_BOX_PROJECTION //specdataif1" ); + dataCollector.AddLocalVariable( UniqueId, "\tdata.boxMax[0] = unity_SpecCube0_BoxMax;" ); + dataCollector.AddLocalVariable( UniqueId, "\tdata.probePosition[0] = unity_SpecCube0_ProbePosition;" ); + dataCollector.AddLocalVariable( UniqueId, "\tdata.boxMax[1] = unity_SpecCube1_BoxMax;" ); + dataCollector.AddLocalVariable( UniqueId, "\tdata.boxMin[1] = unity_SpecCube1_BoxMin;" ); + dataCollector.AddLocalVariable( UniqueId, "\tdata.probePosition[1] = unity_SpecCube1_ProbePosition;" ); + dataCollector.AddLocalVariable( UniqueId, "#endif //specdataif1" ); + + dataCollector.AddLocalVariable( UniqueId, "Unity_GlossyEnvironmentData g" + OutputId + " = UnityGlossyEnvironmentSetup( " + tempsmoothness + ", " + worldViewDir + ", " + worldNormal + ", float3(0,0,0));" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, "indirectSpecular" + OutputId, "UnityGI_IndirectSpecular( data, " + tempocclusion + ", " + worldNormal + ", g" + OutputId + " )" ); + return "indirectSpecular" + OutputId; + } + else + { + if( dataCollector.CurrentSRPType == TemplateSRPType.Lightweight ) + { + string worldViewDir = dataCollector.TemplateDataCollectorInstance.GetViewDir( false, MasterNodePortCategory.Fragment ); + string worldNormal = string.Empty; + if( m_inputPorts[ 0 ].IsConnected ) + { + if( m_normalSpace == ViewSpace.Tangent ) + worldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( UniqueId, CurrentPrecisionType, m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ), OutputId ); + else + worldNormal = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + } + else + { + worldNormal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( PrecisionType.Float, false, MasterNodePortCategory.Fragment ); + } + + string tempsmoothness = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string tempocclusion = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + + dataCollector.AddLocalVariable( UniqueId, "half3 reflectVector" + OutputId + " = reflect( -" + worldViewDir + ", " + worldNormal + " );" ); + dataCollector.AddLocalVariable( UniqueId, "float3 indirectSpecular" + OutputId + " = GlossyEnvironmentReflection( reflectVector" + OutputId + ", 1.0 - " + tempsmoothness + ", " + tempocclusion + " );" ); + return "indirectSpecular" + OutputId; + } + else if( dataCollector.CurrentSRPType == TemplateSRPType.HD ) + { + UIUtils.ShowMessage( UniqueId, "Indirect Specular Light node currently not supported on HDRP" ); + return m_outputPorts[0].ErrorValue; + } + } + } + + if( dataCollector.GenType == PortGenType.NonCustomLighting || dataCollector.CurrentCanvasMode != NodeAvailability.CustomLighting ) + return m_outputPorts[0].ErrorValue; + + string normal = string.Empty; + if( m_inputPorts[ 0 ].IsConnected ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + dataCollector.ForceNormal = true; + + normal = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + if( m_normalSpace == ViewSpace.Tangent ) + normal = "WorldNormalVector( " + Constants.InputVarStr + " , " + normal + " )"; + + dataCollector.AddLocalVariable( UniqueId, "float3 indirectNormal" + OutputId + " = " + normal + ";" ); + normal = "indirectNormal" + OutputId; + } + else + { + if( dataCollector.IsFragmentCategory ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + if( dataCollector.DirtyNormal ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + dataCollector.ForceNormal = true; + } + } + + normal = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId ); + } + + string smoothness = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string occlusion = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + string viewDir = "data.worldViewDir"; + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + string worldPos = GeneratorUtils.GenerateWorldPosition( ref dataCollector, UniqueId ); + viewDir = GeneratorUtils.GenerateViewDirection( ref dataCollector, UniqueId ); + + dataCollector.AddLocalVariable( UniqueId, "UnityGIInput data;" ); + dataCollector.AddLocalVariable( UniqueId, "UNITY_INITIALIZE_OUTPUT( UnityGIInput, data );" ); + dataCollector.AddLocalVariable( UniqueId, "data.worldPos = " + worldPos + ";" ); + dataCollector.AddLocalVariable( UniqueId, "data.worldViewDir = " + viewDir + ";" ); + dataCollector.AddLocalVariable( UniqueId, "data.probeHDR[0] = unity_SpecCube0_HDR;" ); + dataCollector.AddLocalVariable( UniqueId, "data.probeHDR[1] = unity_SpecCube1_HDR;" ); + dataCollector.AddLocalVariable( UniqueId, "#if UNITY_SPECCUBE_BLENDING || UNITY_SPECCUBE_BOX_PROJECTION //specdataif0" ); + dataCollector.AddLocalVariable( UniqueId, "data.boxMin[0] = unity_SpecCube0_BoxMin;" ); + dataCollector.AddLocalVariable( UniqueId, "#endif //specdataif0" ); + dataCollector.AddLocalVariable( UniqueId, "#if UNITY_SPECCUBE_BOX_PROJECTION //specdataif1" ); + dataCollector.AddLocalVariable( UniqueId, "data.boxMax[0] = unity_SpecCube0_BoxMax;" ); + dataCollector.AddLocalVariable( UniqueId, "data.probePosition[0] = unity_SpecCube0_ProbePosition;" ); + dataCollector.AddLocalVariable( UniqueId, "data.boxMax[1] = unity_SpecCube1_BoxMax;" ); + dataCollector.AddLocalVariable( UniqueId, "data.boxMin[1] = unity_SpecCube1_BoxMin;" ); + dataCollector.AddLocalVariable( UniqueId, "data.probePosition[1] = unity_SpecCube1_ProbePosition;" ); + dataCollector.AddLocalVariable( UniqueId, "#endif //specdataif1" ); + } + + dataCollector.AddLocalVariable( UniqueId, "Unity_GlossyEnvironmentData g" + OutputId + " = UnityGlossyEnvironmentSetup( " + smoothness + ", " + viewDir + ", " + normal + ", float3(0,0,0));" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, "indirectSpecular" + OutputId, "UnityGI_IndirectSpecular( data, " + occlusion + ", " + normal + ", g" + OutputId + " )" ); + + return "indirectSpecular" + OutputId; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 13002 ) + m_normalSpace = (ViewSpace)Enum.Parse( typeof( ViewSpace ), GetCurrentParam( ref nodeParams ) ); + + if( UIUtils.CurrentShaderVersion() < 13804 ) + { + m_errorMessageTooltip = "Smoothness port was previously being used as Roughness, please check if you are correctly using it and save to confirm."; + m_upgradeMessage = true; + UIUtils.ShowMessage( UniqueId, "Indirect Specular Light node: Smoothness port was previously being used as Roughness, please check if you are correctly using it and save to confirm." ); + } + + UpdatePort(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalSpace ); + + m_errorMessageTooltip = DefaultErrorMessage; + m_upgradeMessage = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectSpecularLight.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectSpecularLight.cs.meta new file mode 100644 index 0000000..0c0bb14 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/IndirectSpecularLight.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0820850e74009954188ff84e2f5cc4f2 +timeCreated: 1495817589 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightAttenuation.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightAttenuation.cs new file mode 100644 index 0000000..f42f73b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightAttenuation.cs @@ -0,0 +1,134 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Light Attenuation", "Light", "Contains light attenuation for all types of light", NodeAvailabilityFlags = (int)( NodeAvailability.CustomLighting | NodeAvailability.TemplateShader ) )] + public sealed class LightAttenuation : ParentNode + { + static readonly string SurfaceError = "This node only returns correct information using a custom light model, otherwise returns 1"; + static readonly string TemplateError = "This node will only produce proper attenuation if the template contains a shadow caster pass"; + + private const string ASEAttenVarName = "ase_lightAtten"; + + private readonly string[] LightweightPragmaMultiCompiles = + { + "multi_compile _ _MAIN_LIGHT_SHADOWS", + "multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE", + "multi_compile _ _SHADOWS_SOFT" + }; + + //private readonly string[] LightweightVertexInstructions = + //{ + // /*local vertex position*/"VertexPositionInputs ase_vertexInput = GetVertexPositionInputs ({0});", + // "#ifdef _MAIN_LIGHT_SHADOWS//ase_lightAtten_vert", + // /*available interpolator*/"{0} = GetShadowCoord( ase_vertexInput );", + // "#endif//ase_lightAtten_vert" + //}; + private const string LightweightLightAttenDecl = "float ase_lightAtten = 0;"; + private readonly string[] LightweightFragmentInstructions = + { + /*shadow coords*/"Light ase_lightAtten_mainLight = GetMainLight( {0} );", + "ase_lightAtten = ase_lightAtten_mainLight.distanceAttenuation * ase_lightAtten_mainLight.shadowAttenuation;" + }; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputPort( WirePortDataType.FLOAT, "Out" ); + m_errorMessageTypeIsError = NodeMessageType.Warning; + m_errorMessageTooltip = SurfaceError; + m_previewShaderGUID = "4b12227498a5c8d46b6c44ea018e5b56"; + m_drawPreviewAsSphere = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate ) + { + if( !dataCollector.IsSRP ) + { + string result = string.Empty; + if( dataCollector.TemplateDataCollectorInstance.ContainsSpecialLocalFragVar( TemplateInfoOnSematics.SHADOWCOORDS, WirePortDataType.FLOAT4, ref result ) ) + { + return result; + } + + return dataCollector.TemplateDataCollectorInstance.GetLightAtten( UniqueId ); + } + else + { + if( dataCollector.CurrentSRPType == TemplateSRPType.Lightweight ) + { + if( dataCollector.HasLocalVariable( LightweightLightAttenDecl )) + return ASEAttenVarName; + + // Pragmas + for( int i = 0; i < LightweightPragmaMultiCompiles.Length; i++ ) + dataCollector.AddToPragmas( UniqueId, LightweightPragmaMultiCompiles[ i ] ); + + string shadowCoords = dataCollector.TemplateDataCollectorInstance.GetShadowCoords( UniqueId/*, false, dataCollector.PortCategory*/ ); + //return shadowCoords; + // Vertex Instructions + //TemplateVertexData shadowCoordsData = dataCollector.TemplateDataCollectorInstance.RequestNewInterpolator( WirePortDataType.FLOAT4, false ); + //string vertexInterpName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData.OutVarName; + //string vertexShadowCoords = vertexInterpName + "." + shadowCoordsData.VarNameWithSwizzle; + //string vertexPos = dataCollector.TemplateDataCollectorInstance.GetVertexPosition( WirePortDataType.FLOAT3, PrecisionType.Float ,false,MasterNodePortCategory.Vertex ); + + //dataCollector.AddToVertexLocalVariables( UniqueId, string.Format( LightweightVertexInstructions[ 0 ], vertexPos )); + //dataCollector.AddToVertexLocalVariables( UniqueId, LightweightVertexInstructions[ 1 ]); + //dataCollector.AddToVertexLocalVariables( UniqueId, string.Format( LightweightVertexInstructions[ 2 ], vertexShadowCoords ) ); + //dataCollector.AddToVertexLocalVariables( UniqueId, LightweightVertexInstructions[ 3 ]); + + // Fragment Instructions + //string fragmentInterpName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.FragmentFunctionData.InVarName; + //string fragmentShadowCoords = fragmentInterpName + "." + shadowCoordsData.VarNameWithSwizzle; + + dataCollector.AddLocalVariable( UniqueId, LightweightLightAttenDecl ); + dataCollector.AddLocalVariable( UniqueId, string.Format( LightweightFragmentInstructions[ 0 ], shadowCoords ) ); + dataCollector.AddLocalVariable( UniqueId, LightweightFragmentInstructions[ 1 ] ); + return ASEAttenVarName; + } + else + { + UIUtils.ShowMessage( UniqueId, "Light Attenuation node currently not supported on HDRP" ); + return "1"; + } + } + } + + if ( dataCollector.GenType == PortGenType.NonCustomLighting || dataCollector.CurrentCanvasMode != NodeAvailability.CustomLighting ) + { + UIUtils.ShowMessage( UniqueId, "Light Attenuation node currently not supported on non-custom lighting surface shaders" ); + return "1"; + } + + dataCollector.UsingLightAttenuation = true; + return ASEAttenVarName; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( ContainerGraph.CurrentCanvasMode == NodeAvailability.TemplateShader && ContainerGraph.CurrentSRPType != TemplateSRPType.Lightweight ) + { + m_showErrorMessage = true; + m_errorMessageTypeIsError = NodeMessageType.Warning; + m_errorMessageTooltip = TemplateError; + } else + { + m_errorMessageTypeIsError = NodeMessageType.Error; + m_errorMessageTooltip = SurfaceError; + if ( ( ContainerGraph.CurrentStandardSurface != null && ContainerGraph.CurrentStandardSurface.CurrentLightingModel != StandardShaderLightModel.CustomLighting ) ) + m_showErrorMessage = true; + else + m_showErrorMessage = false; + } + + + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightAttenuation.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightAttenuation.cs.meta new file mode 100644 index 0000000..05a8aa7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightAttenuation.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4e205b44d56609f459ffc558febe2792 +timeCreated: 1495449979 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightColorNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightColorNode.cs new file mode 100644 index 0000000..a422669 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightColorNode.cs @@ -0,0 +1,90 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Light Color", "Light", "Light Color, RGB value already contains light intensity while A only contains light intensity" )] + public sealed class LightColorNode : ShaderVariablesNode + { + private const string m_lightColorValue = "_LightColor0"; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "RGBA", WirePortDataType.COLOR ); + AddOutputPort( WirePortDataType.FLOAT3, "Color" ); + AddOutputPort( WirePortDataType.FLOAT, "Intensity" ); + m_previewShaderGUID = "43f5d3c033eb5044e9aeb40241358349"; + } + + public override void RenderNodePreview() + { + //Runs at least one time + if( !m_initialized ) + { + // nodes with no preview don't update at all + PreviewIsDirty = false; + return; + } + + if( !PreviewIsDirty ) + return; + if( !Preferences.GlobalDisablePreviews ) + { + int count = m_outputPorts.Count; + for( int i = 0 ; i < count ; i++ ) + { + RenderTexture temp = RenderTexture.active; + RenderTexture.active = m_outputPorts[ i ].OutputPreviewTexture; + Graphics.Blit( null , m_outputPorts[ i ].OutputPreviewTexture , PreviewMaterial , i ); + RenderTexture.active = temp; + } + } + + PreviewIsDirty = m_continuousPreviewRefresh; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate && !dataCollector.IsSRP ) + dataCollector.AddToIncludes( -1, Constants.UnityLightingLib ); + + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + + string finalVar = m_lightColorValue; + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + { + dataCollector.TemplateDataCollectorInstance.AddHDLightInfo(); + finalVar = string.Format( TemplateHelperFunctions.HDLightInfoFormat, "0", "color" ); ; + } + else + { + finalVar = "_MainLightColor"; + } + } + else + { + dataCollector.AddLocalVariable( UniqueId, "#if defined(LIGHTMAP_ON) && ( UNITY_VERSION < 560 || ( defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN) ) )//aselc" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT4, "ase_lightColor", "0" ); + dataCollector.AddLocalVariable( UniqueId, "#else //aselc" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT4, "ase_lightColor", finalVar ); + dataCollector.AddLocalVariable( UniqueId, "#endif //aselc" ); + finalVar = "ase_lightColor"; + } + //else if( ContainerGraph.CurrentStandardSurface.CurrentLightingModel == StandardShaderLightModel.CustomLighting ) + // finalVar = "gi.light.color"; + + switch( outputId ) + { + default: + case 0: return finalVar; + case 1: return finalVar + ".rgb"; + case 2: return finalVar + ".a"; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightColorNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightColorNode.cs.meta new file mode 100644 index 0000000..9acf2a1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/LightColorNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 275270020c577924caf04492f73b2ea6 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/WorldSpaceLightPos.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/WorldSpaceLightPos.cs new file mode 100644 index 0000000..c1dc68e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/WorldSpaceLightPos.cs @@ -0,0 +1,93 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEditor; +using UnityEngine; +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "World Space Light Pos", "Light", "Light Position" )] + public sealed class WorldSpaceLightPos : ShaderVariablesNode + { + private const string HelperText = + "This node will behave differently according to light type." + + "\n\n- For directional lights the Dir/Pos output will specify a world space direction and Type will be set to 0." + + "\n\n- For other light types the Dir/Pos output will specify a world space position and Type will be set to 1."; + private const string m_lightPosValue = "_WorldSpaceLightPos0"; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, Constants.EmptyPortValue, WirePortDataType.FLOAT4 ); + AddOutputPort( WirePortDataType.FLOAT3, "Dir/Pos" ); + AddOutputPort( WirePortDataType.FLOAT, "Type" ); + m_previewShaderGUID = "2292a614672283c41a367b22cdde4620"; + m_drawPreviewAsSphere = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUILayout.HelpBox( HelperText, MessageType.Info ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + string finalVar = m_lightPosValue; + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.IsSRP ) + finalVar = "_MainLightPosition"; + if( outputId == 1 ) + { + return finalVar + ".xyz"; + } + else if( outputId == 2 ) + { + return finalVar + ".w"; + } + else + { + return finalVar; + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( !m_outputPorts[ 0 ].IsConnected ) + { + m_outputPorts[ 0 ].Visible = false; + m_sizeIsDirty = true; + } + } + + public override void RenderNodePreview() + { + //Runs at least one time + if( !m_initialized ) + { + // nodes with no preview don't update at all + PreviewIsDirty = false; + return; + } + + if( !PreviewIsDirty ) + return; + + SetPreviewInputs(); + if( !Preferences.GlobalDisablePreviews ) + { + RenderTexture temp = RenderTexture.active; + + RenderTexture.active = m_outputPorts[ 0 ].OutputPreviewTexture; + Graphics.Blit( null , m_outputPorts[ 0 ].OutputPreviewTexture , PreviewMaterial , 0 ); + Graphics.Blit( m_outputPorts[ 0 ].OutputPreviewTexture , m_outputPorts[ 1 ].OutputPreviewTexture ); + + RenderTexture.active = m_outputPorts[ 2 ].OutputPreviewTexture; + Graphics.Blit( null , m_outputPorts[ 2 ].OutputPreviewTexture , PreviewMaterial , 1 ); + RenderTexture.active = temp; + } + PreviewIsDirty = m_continuousPreviewRefresh; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/WorldSpaceLightPos.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/WorldSpaceLightPos.cs.meta new file mode 100644 index 0000000..79f4fc5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Lighting/WorldSpaceLightPos.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: db94d973647dae9488d3ef5ee2fd95a4 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ShaderVariablesNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ShaderVariablesNode.cs new file mode 100644 index 0000000..499999f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ShaderVariablesNode.cs @@ -0,0 +1,27 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class ShaderVariablesNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputPort( WirePortDataType.OBJECT, "Out" ); + } + public override string GetIncludes() + { + return Constants.UnityShaderVariables; + } + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( !( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.IsSRP ) ) + dataCollector.AddToIncludes( UniqueId, Constants.UnityShaderVariables ); + return string.Empty; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ShaderVariablesNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ShaderVariablesNode.cs.meta new file mode 100644 index 0000000..dce292d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/ShaderVariablesNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1eb723e6ceff9a345a9dbfe04aa3dc11 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time.meta new file mode 100644 index 0000000..bfd7fd9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7c77e88b33fec7c429412624a7b2c620 +folderAsset: yes +timeCreated: 1481126947 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/CosTime.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/CosTime.cs new file mode 100644 index 0000000..096676f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/CosTime.cs @@ -0,0 +1,55 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Cos Time", "Time", "Cosine of time" )] + public sealed class CosTime : ConstVecShaderVariable + { +#if UNITY_2018_3_OR_NEWER + private readonly string[] SRPTime = + { + "cos( _TimeParameters.x * 0.125 )", + "cos( _TimeParameters.x * 0.25 )", + "cos( _TimeParameters.x * 0.5 )", + "_TimeParameters.z", + }; +#endif + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputName( 1, "t/8" ); + ChangeOutputName( 2, "t/4" ); + ChangeOutputName( 3, "t/2" ); + ChangeOutputName( 4, "t" ); + m_value = "_CosTime"; + m_previewShaderGUID = "3093999b42c3c0940a71799511d7781c"; + m_continuousPreviewRefresh = true; + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( !m_outputPorts[ 0 ].IsConnected ) + { + m_outputPorts[ 0 ].Visible = false; + m_sizeIsDirty = true; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { +#if UNITY_2018_3_OR_NEWER + if( outputId > 0 && dataCollector.IsTemplate ) + { + if( ( dataCollector.TemplateDataCollectorInstance.IsHDRP && ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_5_16_1 ) || + ( dataCollector.TemplateDataCollectorInstance.IsLWRP && ASEPackageManagerHelper.CurrentLWVersion > ASESRPVersions.ASE_SRP_5_16_1 ) ) + return SRPTime[ outputId - 1 ]; + } +#endif + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/CosTime.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/CosTime.cs.meta new file mode 100644 index 0000000..80373c1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/CosTime.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 447e504f2ca5aaf4bbf0fdbce33596bc +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/DeltaTime.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/DeltaTime.cs new file mode 100644 index 0000000..a1f3380 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/DeltaTime.cs @@ -0,0 +1,33 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Delta Time", "Time", "Delta time" )] + public sealed class DeltaTime : ConstVecShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputName( 1, "dt" ); + ChangeOutputName( 2, "1/dt" ); + ChangeOutputName( 3, "smoothDt" ); + ChangeOutputName( 4, "1/smoothDt" ); + m_value = "unity_DeltaTime"; + m_previewShaderGUID = "9d69a693042c443498f96d6da60535eb"; + m_continuousPreviewRefresh = true; + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( !m_outputPorts[ 0 ].IsConnected ) + { + m_outputPorts[ 0 ].Visible = false; + m_sizeIsDirty = true; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/DeltaTime.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/DeltaTime.cs.meta new file mode 100644 index 0000000..400f94f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/DeltaTime.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3ddde7ed1ab4f8044a9a6aa3891f5ca4 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SimpleTimeNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SimpleTimeNode.cs new file mode 100644 index 0000000..8445f90 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SimpleTimeNode.cs @@ -0,0 +1,48 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Time", "Time", "Time in seconds with a scale multiplier" )] + public sealed class SimpleTimeNode : ShaderVariablesNode + { + private const string TimeStandard = "_Time.y"; +#if UNITY_2018_3_OR_NEWER + private const string TimeSRP = "_TimeParameters.x"; +#endif + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT ); + AddInputPort( WirePortDataType.FLOAT, false, "Scale" ); + m_inputPorts[ 0 ].FloatInternalData = 1; + m_useInternalPortData = true; + m_previewShaderGUID = "45b7107d5d11f124fad92bcb1fa53661"; + m_continuousPreviewRefresh = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + string multiplier = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string timeGlobalVar = TimeStandard; +#if UNITY_2018_3_OR_NEWER + if( dataCollector.IsTemplate ) + { + if( ( dataCollector.TemplateDataCollectorInstance.IsHDRP && ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_5_16_1 ) || + ( dataCollector.TemplateDataCollectorInstance.IsLWRP && ASEPackageManagerHelper.CurrentLWVersion > ASESRPVersions.ASE_SRP_5_16_1 ) ) + timeGlobalVar = TimeSRP; + } +#endif + if( multiplier == "1.0" ) + return timeGlobalVar; + + string scaledVarName = "mulTime" + OutputId; + string scaledVarValue = timeGlobalVar + " * " + multiplier; + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, scaledVarName, scaledVarValue ); + return scaledVarName; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SimpleTimeNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SimpleTimeNode.cs.meta new file mode 100644 index 0000000..313b931 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SimpleTimeNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f36e4491ee33fe74fa51cfb5ad450c6e +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SinTimeNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SinTimeNode.cs new file mode 100644 index 0000000..aac2b1e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SinTimeNode.cs @@ -0,0 +1,58 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEditor; +using UnityEngine; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Sin Time", "Time", "Unity sin time" )] + public sealed class SinTimeNode : ConstVecShaderVariable + { + //double m_time; +#if UNITY_2018_3_OR_NEWER + private readonly string[] SRPTime = + { + "sin( _TimeParameters.x * 0.125 )", + "sin( _TimeParameters.x * 0.25 )", + "sin( _TimeParameters.x * 0.5 )", + "_TimeParameters.y", + }; +#endif + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputName( 1, "t/8" ); + ChangeOutputName( 2, "t/4" ); + ChangeOutputName( 3, "t/2" ); + ChangeOutputName( 4, "t" ); + m_value = "_SinTime"; + m_previewShaderGUID = "e4ba809e0badeb94994170b2cbbbba10"; + m_continuousPreviewRefresh = true; + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( !m_outputPorts[ 0 ].IsConnected ) + { + m_outputPorts[ 0 ].Visible = false; + m_sizeIsDirty = true; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { +#if UNITY_2018_3_OR_NEWER + if( outputId > 0 && dataCollector.IsTemplate ) + { + if( ( dataCollector.TemplateDataCollectorInstance.IsHDRP && ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_5_16_1 ) || + ( dataCollector.TemplateDataCollectorInstance.IsLWRP && ASEPackageManagerHelper.CurrentLWVersion > ASESRPVersions.ASE_SRP_5_16_1 ) ) + return SRPTime[ outputId - 1 ]; + } +#endif + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SinTimeNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SinTimeNode.cs.meta new file mode 100644 index 0000000..876a774 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/SinTimeNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 796acd44fcf330e4e921855630007b9b +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/TimeNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/TimeNode.cs new file mode 100644 index 0000000..258d517 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/TimeNode.cs @@ -0,0 +1,55 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Time Parameters", "Time", "Time since level load" )] + public sealed class TimeNode : ConstVecShaderVariable + { +#if UNITY_2018_3_OR_NEWER + private readonly string[] SRPTime = + { + "( _TimeParameters.x * 0.05 )", + "( _TimeParameters.x )", + "( _TimeParameters.x * 2 )", + "( _TimeParameters.x * 3 )", + }; +#endif + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputName( 1, "t/20" ); + ChangeOutputName( 2, "t" ); + ChangeOutputName( 3, "t*2" ); + ChangeOutputName( 4, "t*3" ); + m_value = "_Time"; + m_previewShaderGUID = "73abc10c8d1399444827a7eeb9c24c2a"; + m_continuousPreviewRefresh = true; + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( !m_outputPorts[ 0 ].IsConnected ) + { + m_outputPorts[ 0 ].Visible = false; + m_sizeIsDirty = true; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { +#if UNITY_2018_3_OR_NEWER + if( outputId > 0 && dataCollector.IsTemplate ) + { + if( ( dataCollector.TemplateDataCollectorInstance.IsHDRP && ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_5_16_1 ) || + ( dataCollector.TemplateDataCollectorInstance.IsLWRP && ASEPackageManagerHelper.CurrentLWVersion > ASESRPVersions.ASE_SRP_5_16_1 )) + return SRPTime[ outputId - 1 ]; + } +#endif + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/TimeNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/TimeNode.cs.meta new file mode 100644 index 0000000..521dcf4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Time/TimeNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d8c6b7bfb7784e14d8708ab6fb981268 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform.meta new file mode 100644 index 0000000..008be40 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2ce97203c4871664493f8760d88d0d4d +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/CameraToWorldMatrix.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/CameraToWorldMatrix.cs new file mode 100644 index 0000000..1238566 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/CameraToWorldMatrix.cs @@ -0,0 +1,24 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Camera To World Matrix", "Matrix Transform", "Current camera to world matrix" )] + public sealed class CameraToWorldMatrix : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "unity_CameraToWorld"; + m_drawPreview = false; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + GeneratorUtils.RegisterUnity2019MatrixDefines( ref dataCollector ); + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/CameraToWorldMatrix.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/CameraToWorldMatrix.cs.meta new file mode 100644 index 0000000..2e13b7e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/CameraToWorldMatrix.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6accfe0f350cf064dae07041fe90446b +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseProjectionMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseProjectionMatrixNode.cs new file mode 100644 index 0000000..0b53040 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseProjectionMatrixNode.cs @@ -0,0 +1,46 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Inverse Projection Matrix", "Matrix Transform", "Current inverse projection matrix", NodeAvailabilityFlags = (int)( NodeAvailability.TemplateShader ) )] + public sealed class InverseProjectionMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_I_P"; + m_drawPreview = false; + m_matrixId = 1; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + else + { + return GeneratorUtils.GenerateIdentity4x4( ref dataCollector, UniqueId ); + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( ContainerGraph.IsSRP ) + { + m_showErrorMessage = false; + } + else + { + m_showErrorMessage = true; + m_errorMessageTypeIsError = NodeMessageType.Warning; + m_errorMessageTooltip = "This node only works for Scriptable Render Pipeline (LWRP, HDRP, URP)"; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseProjectionMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseProjectionMatrixNode.cs.meta new file mode 100644 index 0000000..302ccf2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseProjectionMatrixNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0fdbc380972c44b489c5f948a40b8e69 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseTranspMVMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseTranspMVMatrixNode.cs new file mode 100644 index 0000000..e4071ba --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseTranspMVMatrixNode.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Inverse Transpose Model View Matrix", "Matrix Transform", "All Transformation types" )] + public sealed class InverseTranspMVMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_IT_MV"; + m_drawPreview = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseTranspMVMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseTranspMVMatrixNode.cs.meta new file mode 100644 index 0000000..1b3b8fd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseTranspMVMatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3a71f1e560487aa4c8484c4153941884 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewMatrixNode.cs new file mode 100644 index 0000000..c21aa19 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewMatrixNode.cs @@ -0,0 +1,19 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Inverse View Matrix", "Matrix Transform", "Current inverse view matrix" )] + public sealed class InverseViewMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_I_V"; + m_drawPreview = false; + m_matrixId = 0; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewMatrixNode.cs.meta new file mode 100644 index 0000000..61b2324 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewMatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: dd0c1c252c062184e9ad592b91e7fcd2 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewProjectionMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewProjectionMatrixNode.cs new file mode 100644 index 0000000..d812cc2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewProjectionMatrixNode.cs @@ -0,0 +1,46 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Inverse View Projection Matrix", "Matrix Transform", "Current view inverse projection matrix", NodeAvailabilityFlags = (int)( NodeAvailability.TemplateShader ) )] + public sealed class InverseViewProjectionMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_I_VP"; + m_drawPreview = false; + m_matrixId = 1; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + else + { + return GeneratorUtils.GenerateIdentity4x4( ref dataCollector, UniqueId ); + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( ContainerGraph.IsSRP ) + { + m_showErrorMessage = false; + } + else + { + m_showErrorMessage = true; + m_errorMessageTypeIsError = NodeMessageType.Warning; + m_errorMessageTooltip = "This node only works for Scriptable Render Pipeline (LWRP, HDRP, URP)"; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewProjectionMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewProjectionMatrixNode.cs.meta new file mode 100644 index 0000000..6b22161 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/InverseViewProjectionMatrixNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f6f151774e252dd4fb2b9ee440ec8eed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MMatrixNode.cs new file mode 100644 index 0000000..ed90339 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MMatrixNode.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Model Matrix", "Matrix Transform", "Current model matrix" )] + public sealed class MMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_M"; + m_drawPreview = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MMatrixNode.cs.meta new file mode 100644 index 0000000..51c6d1f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MMatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 503a386043991354eaca2410683d836a +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVMatrixNode.cs new file mode 100644 index 0000000..a99d851 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVMatrixNode.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Model View Matrix", "Matrix Transform", "Current model * view matrix" )] + public sealed class MVMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_MV"; + m_drawPreview = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVMatrixNode.cs.meta new file mode 100644 index 0000000..6c0355e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVMatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 30c7936db4e6fe5488076d799841f857 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVPMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVPMatrixNode.cs new file mode 100644 index 0000000..324a153 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVPMatrixNode.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Model View Projection Matrix", "Matrix Transform", "Current model * view * projection matrix" )] + public sealed class MVPMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_MVP"; + m_drawPreview = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVPMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVPMatrixNode.cs.meta new file mode 100644 index 0000000..8275def --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/MVPMatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 74e00fb3d8e161f498c078795184bae4 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ObjectToWorldMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ObjectToWorldMatrixNode.cs new file mode 100644 index 0000000..2f5873b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ObjectToWorldMatrixNode.cs @@ -0,0 +1,19 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Object To World Matrix", "Matrix Transform", "Current model matrix" )] + public sealed class ObjectToWorldMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "unity_ObjectToWorld"; + m_HDValue = "GetObjectToWorldMatrix()"; + m_LWValue = "GetObjectToWorldMatrix()"; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ObjectToWorldMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ObjectToWorldMatrixNode.cs.meta new file mode 100644 index 0000000..7d008d9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ObjectToWorldMatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a0c0180a327eba54c832fbb695dd282f +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ProjectionMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ProjectionMatrixNode.cs new file mode 100644 index 0000000..a80058d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ProjectionMatrixNode.cs @@ -0,0 +1,19 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Projection Matrix", "Matrix Transform", "Current projection matrix" )] + public sealed class ProjectionMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_P"; + m_drawPreview = false; + m_matrixId = 1; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ProjectionMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ProjectionMatrixNode.cs.meta new file mode 100644 index 0000000..5f2d19b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ProjectionMatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 008fd07cf3f9a7140a9e23be43733f7c +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture0MatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture0MatrixNode.cs new file mode 100644 index 0000000..4f56872 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture0MatrixNode.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Texture 0 Matrix", "Matrix Transform", "Texture 0 Matrix", null, UnityEngine.KeyCode.None, true, true )] + public sealed class Texture0MatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_TEXTURE0"; + m_drawPreview = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture0MatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture0MatrixNode.cs.meta new file mode 100644 index 0000000..fbdf611 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture0MatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f57a1d05f7a9c5847912566ff1605c6d +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture1MatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture1MatrixNode.cs new file mode 100644 index 0000000..a9debbe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture1MatrixNode.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Texture 1 Matrix", "Matrix Transform", "Texture 1 Matrix", null, UnityEngine.KeyCode.None, true, true )] + public sealed class Texture1MatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_TEXTURE1"; + m_drawPreview = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture1MatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture1MatrixNode.cs.meta new file mode 100644 index 0000000..429b108 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture1MatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9ef360a7c6005ad479d7a3e6db1d32f4 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture2MatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture2MatrixNode.cs new file mode 100644 index 0000000..c0938e7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture2MatrixNode.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Texture 2 Matrix", "Matrix Transform", "Texture 2 Matrix", null, UnityEngine.KeyCode.None, true, true )] + public sealed class Texture2MatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_TEXTURE2"; + m_drawPreview = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture2MatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture2MatrixNode.cs.meta new file mode 100644 index 0000000..dc1e008 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture2MatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6cf4950dda0f6e6438ace404fbef19a7 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture3MatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture3MatrixNode.cs new file mode 100644 index 0000000..8b5f86a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture3MatrixNode.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Texture 3 Matrix", "Matrix Transform", "Texture 3 Matrix", null, UnityEngine.KeyCode.None, true, true )] + public sealed class Texture3MatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_TEXTURE3"; + m_drawPreview = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture3MatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture3MatrixNode.cs.meta new file mode 100644 index 0000000..00df6e3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/Texture3MatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 02a9fb7a3a104974e941f4109567b97f +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformDirectionNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformDirectionNode.cs new file mode 100644 index 0000000..743760d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformDirectionNode.cs @@ -0,0 +1,579 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public enum InverseTangentType + { + Fast, + Precise + } + + [Serializable] + [NodeAttributes( "Transform Direction", "Vector Operators", "Transforms a direction vector from one space to another" )] + public sealed class TransformDirectionNode : ParentNode + { + + [SerializeField] + private TransformSpaceFrom m_from = TransformSpaceFrom.Object; + + [SerializeField] + private TransformSpaceTo m_to = TransformSpaceTo.World; + + [SerializeField] + private bool m_normalize = false; + + [SerializeField] + private bool m_safeNormalize = false; + + [SerializeField] + private InverseTangentType m_inverseTangentType = InverseTangentType.Fast; + + private string InverseTBNStr = "Inverse TBN"; + + private const string NormalizeOptionStr = "Normalize"; + private const string SafeNormalizeOptionStr = "Safe"; + + private const string AseObjectToWorldDirVarName = "objToWorldDir"; + private const string AseObjectToWorldDirFormat = "mul( unity_ObjectToWorld, float4( {0}, 0 ) ).xyz"; + private const string AseSRPObjectToWorldDirFormat = "mul( GetObjectToWorldMatrix(), float4( {0}, 0 ) ).xyz"; + + private const string AseObjectToViewDirVarName = "objToViewDir"; + private const string AseObjectToViewDirFormat = "mul( UNITY_MATRIX_IT_MV, float4( {0}, 0 ) ).xyz"; + private const string AseHDObjectToViewDirFormat = "TransformWorldToViewDir( TransformObjectToWorldDir( {0} ))"; + + private const string AseWorldToObjectDirVarName = "worldToObjDir"; + private const string AseWorldToObjectDirFormat = "mul( unity_WorldToObject, float4( {0}, 0 ) ).xyz"; + private const string AseSRPWorldToObjectDirFormat = "mul( GetWorldToObjectMatrix(), float4( {0}, 0 ) ).xyz"; + + + private const string AseWorldToViewDirVarName = "worldToViewDir"; + private const string AseWorldToViewDirFormat = "mul( UNITY_MATRIX_V, float4( {0}, 0 ) ).xyz"; + + private const string AseViewToObjectDirVarName = "viewToObjDir"; + private const string AseViewToObjectDirFormat = "mul( UNITY_MATRIX_T_MV, float4( {0}, 0 ) ).xyz"; + + private const string AseViewToWorldDirVarName = "viewToWorldDir"; + private const string AseViewToWorldDirFormat = "mul( UNITY_MATRIX_I_V, float4( {0}, 0 ) ).xyz"; + + /////////////////////////////////////////////////////////// + private const string AseObjectToClipDirVarName = "objectToClipDir"; + private const string AseObjectToClipDirFormat = "mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4({0}, 0.0)))"; + private const string AseSRPObjectToClipDirFormat = "TransformWorldToHClipDir(TransformObjectToWorldDir({0}))"; + + private const string AseWorldToClipDirVarName = "worldToClipDir"; + private const string AseWorldToClipDirFormat = "mul(UNITY_MATRIX_VP, float4({0}, 0.0))"; + private const string AseSRPWorldToClipDirFormat = "TransformWorldToHClipDir({0})"; + + private const string AseViewToClipDirVarName = "viewToClipDir"; + private const string AseViewToClipDirFormat = "mul(UNITY_MATRIX_P, float4({0}, 0.0))"; + private const string AseSRPViewToClipDirFormat = "mul(GetViewToHClipMatrix(), float4({0}, 1.0))"; + // + private const string AseClipToObjectDirVarName = "clipToObjectDir"; + + private const string AseClipToObjectDirFormat = "mul( UNITY_MATRIX_IT_MV, mul( unity_CameraInvProjection,float4({0},0)) ).xyz"; + private const string AseClipToWorldDirFormat = "mul( UNITY_MATRIX_I_V, mul( unity_CameraInvProjection,float4({0},0)) ).xyz"; + private const string AseClipToViewDirFormat = " mul( unity_CameraInvProjection,float4({0},0)).xyz"; + private const string AseHDClipToObjectDirFormat = "mul( UNITY_MATRIX_I_M, mul( UNITY_MATRIX_I_VP,float4({0},0)) ).xyz"; + + private const string AseClipToWorldDirVarName = "clipToWorldDir"; + private const string AseHDClipToWorldDirFormat = "mul( UNITY_MATRIX_I_VP, float4({0},0) ).xyz"; + + private const string AseClipToViewDirVarName = "clipToViewDir"; + private const string AseHDClipToViewDirFormat = " mul( UNITY_MATRIX_I_P,float4({0},0)).xyz"; + private const string AseClipToNDC = "{0}.xyz/{0}.w"; + + ///////////////////////////////////////////////////// + private const string AseObjectToTangentDirVarName = "objectToTangentDir"; + private const string AseWorldToTangentDirVarName = "worldToTangentDir"; + private const string AseViewToTangentDirVarName = "viewToTangentDir"; + private const string AseClipToTangentDirVarName = "clipToTangentDir"; + private const string ASEWorldToTangentFormat = "mul( ase_worldToTangent, {0})"; + + + private const string AseTangentToObjectDirVarName = "tangentTobjectDir"; + private const string AseTangentToWorldDirVarName = "tangentToWorldDir"; + private const string AseTangentToViewDirVarName = "tangentToViewDir"; + private const string AseTangentToClipDirVarName = "tangentToClipDir"; + private const string ASEMulOpFormat = "mul( {0}, {1} )"; + + + + /////////////////////////////////////////////////////////// + private const string FromStr = "From"; + private const string ToStr = "To"; + private const string SubtitleFormat = "{0} to {1}"; + + private readonly string[] m_spaceOptionsFrom = + { + "Object", + "World", + "View", + "Tangent" + }; + + private readonly string[] m_spaceOptionsTo = + { + "Object", + "World", + "View", + "Tangent", + "Clip" + }; + + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, Constants.EmptyPortValue ); + AddOutputVectorPorts( WirePortDataType.FLOAT3, "XYZ" ); + m_useInternalPortData = true; + m_autoWrapProperties = true; + m_previewShaderGUID = "74e4d859fbdb2c0468de3612145f4929"; + m_textLabelWidth = 100; + UpdateSubtitle(); + } + + private void UpdateSubtitle() + { + SetAdditonalTitleText( string.Format( SubtitleFormat, m_from, m_to ) ); + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_from = (TransformSpaceFrom)EditorGUILayoutPopup( FromStr, (int)m_from, m_spaceOptionsFrom ); + m_to = (TransformSpaceTo)EditorGUILayoutPopup( ToStr, (int)m_to, m_spaceOptionsTo ); + if( m_from == TransformSpaceFrom.Tangent ) + { + m_inverseTangentType = (InverseTangentType)EditorGUILayoutEnumPopup( InverseTBNStr, m_inverseTangentType ); + } + + m_normalize = EditorGUILayoutToggle( NormalizeOptionStr, m_normalize ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateSubtitle(); + } + + if( m_normalize ) + { + EditorGUI.indentLevel++; + m_safeNormalize = EditorGUILayoutToggle( SafeNormalizeOptionStr , m_safeNormalize ); + EditorGUILayout.HelpBox( Constants.SafeNormalizeInfoStr , MessageType.Info ); + EditorGUI.indentLevel--; + } + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + if( (int)m_from != (int)m_to && ( m_from == TransformSpaceFrom.Tangent || m_to == TransformSpaceTo.Tangent ) ) + dataCollector.DirtyNormal = true; + } + + void CalculateTransform( TransformSpaceFrom from, TransformSpaceTo to, ref MasterNodeDataCollector dataCollector, ref string varName, ref string result ) + { + switch( from ) + { + case TransformSpaceFrom.Object: + { + switch( to ) + { + default: case TransformSpaceTo.Object: break; + case TransformSpaceTo.World: + { + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType != TemplateSRPType.BuiltIn ) + result = string.Format( AseSRPObjectToWorldDirFormat, result ); + else + result = string.Format( AseObjectToWorldDirFormat, result ); + varName = AseObjectToWorldDirVarName + OutputId; + } + break; + case TransformSpaceTo.View: + { + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + result = string.Format( AseHDObjectToViewDirFormat, result ); + else + result = string.Format( AseObjectToViewDirFormat, result ); + varName = AseObjectToViewDirVarName + OutputId; + } + break; + case TransformSpaceTo.Clip: + { + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType != TemplateSRPType.BuiltIn ) + { + result = string.Format( AseSRPObjectToClipDirFormat, result ); + } + else + { + result = string.Format( AseObjectToClipDirFormat, result ); + } + varName = AseObjectToClipDirVarName + OutputId; + } + break; + } + } + break; + case TransformSpaceFrom.World: + { + switch( to ) + { + case TransformSpaceTo.Object: + { + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType != TemplateSRPType.BuiltIn ) + result = string.Format( AseSRPWorldToObjectDirFormat, result ); + else + result = string.Format( AseWorldToObjectDirFormat, result ); + varName = AseWorldToObjectDirVarName + OutputId; + } + break; + default: + case TransformSpaceTo.World: break; + case TransformSpaceTo.View: + { + result = string.Format( AseWorldToViewDirFormat, result ); + varName = AseWorldToViewDirVarName + OutputId; + } + break; + case TransformSpaceTo.Clip: + { + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType != TemplateSRPType.BuiltIn ) + { + result = string.Format( AseSRPWorldToClipDirFormat, result ); + } + else + { + result = string.Format( AseWorldToClipDirFormat, result ); + } + varName = AseWorldToClipDirVarName + OutputId; + } + break; + } + } + break; + case TransformSpaceFrom.View: + { + switch( to ) + { + case TransformSpaceTo.Object: + { + result = string.Format( AseViewToObjectDirFormat, result ); + varName = AseViewToObjectDirVarName + OutputId; + } + break; + case TransformSpaceTo.World: + { + result = string.Format( AseViewToWorldDirFormat, result ); + varName = AseViewToWorldDirVarName + OutputId; + } + break; + default: case TransformSpaceTo.View: break; + case TransformSpaceTo.Clip: + { + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType != TemplateSRPType.BuiltIn ) + { + result = string.Format( AseSRPViewToClipDirFormat, result ); + } + else + { + result = string.Format( AseViewToClipDirFormat, result ); + } + varName = AseViewToClipDirVarName + OutputId; + } + break; + } + } + break; + //case TransformSpace.Clip: + //{ + // switch( to ) + // { + // case TransformSpace.Object: + // { + // if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + // { + // result = string.Format( AseHDClipToObjectDirFormat, result ); + // } + // else + // { + // result = string.Format( AseClipToObjectDirFormat, result ); + // } + // varName = AseClipToObjectDirVarName + OutputId; + // } + // break; + // case TransformSpace.World: + // { + // if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + // { + // result = string.Format( AseHDClipToWorldDirFormat, result ); + // } + // else + // { + // result = string.Format( AseClipToWorldDirFormat, result ); + // } + // varName = AseClipToWorldDirVarName + OutputId; + // } + // break; + // case TransformSpace.View: + // { + // if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + // { + // result = string.Format( AseHDClipToViewDirFormat, result ); + // } + // else + // { + // result = string.Format( AseClipToViewDirFormat, result ); + // } + // varName = AseClipToViewDirVarName + OutputId; + // } + // break; + // case TransformSpace.Clip: break; + // default: + // break; + // } + //} + //break; + default: break; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + GeneratorUtils.RegisterUnity2019MatrixDefines( ref dataCollector ); + + string result = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string varName = string.Empty; + + if( (int)m_from == (int)m_to ) + { + RegisterLocalVariable( 0, result, ref dataCollector ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + + switch( m_from ) + { + case TransformSpaceFrom.Object: + { + switch( m_to ) + { + default: case TransformSpaceTo.Object: break; + case TransformSpaceTo.World: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.View: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.Clip: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.Tangent: + { + GeneratorUtils.GenerateWorldToTangentMatrix( ref dataCollector, UniqueId, CurrentPrecisionType ); + CalculateTransform( m_from, TransformSpaceTo.World, ref dataCollector, ref varName, ref result ); + result = string.Format( ASEWorldToTangentFormat, result ); + varName = AseObjectToTangentDirVarName + OutputId; + } + break; + } + } + break; + case TransformSpaceFrom.World: + { + switch( m_to ) + { + case TransformSpaceTo.Object: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + default: + case TransformSpaceTo.World: break; + case TransformSpaceTo.View: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.Clip: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.Tangent: + { + GeneratorUtils.GenerateWorldToTangentMatrix( ref dataCollector, UniqueId, CurrentPrecisionType ); + result = string.Format( ASEWorldToTangentFormat, result ); + varName = AseWorldToTangentDirVarName + OutputId; + } + break; + } + } + break; + case TransformSpaceFrom.View: + { + switch( m_to ) + { + case TransformSpaceTo.Object: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.World: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + default: case TransformSpaceTo.View: break; + case TransformSpaceTo.Clip: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.Tangent: + { + GeneratorUtils.GenerateWorldToTangentMatrix( ref dataCollector, UniqueId, CurrentPrecisionType ); + CalculateTransform( m_from, TransformSpaceTo.World, ref dataCollector, ref varName, ref result ); + result = string.Format( ASEWorldToTangentFormat, result ); + varName = AseViewToTangentDirVarName + OutputId; + } + break; + } + } + break; + //case TransformSpace.Clip: + //{ + // switch( m_to ) + // { + // case TransformSpace.Object: + // { + // CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + // } + // break; + // case TransformSpace.World: + // { + // CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + // } + // break; + // case TransformSpace.View: + // { + // CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + // } + // break; + // case TransformSpace.Clip: break; + // case TransformSpace.Tangent: + // { + // GeneratorUtils.GenerateWorldToTangentMatrix( ref dataCollector, UniqueId, CurrentPrecisionType ); + // CalculateTransform( m_from, TransformSpace.World, ref dataCollector, ref varName, ref result ); + // result = string.Format( ASEWorldToTangentFormat, result ); + // varName = AseClipToTangentDirVarName + OutputId; + // } + // break; + // default: + // break; + // } + //}break; + case TransformSpaceFrom.Tangent: + { + string matrixVal = string.Empty; + if( m_inverseTangentType == InverseTangentType.Fast ) + matrixVal = GeneratorUtils.GenerateTangentToWorldMatrixFast( ref dataCollector, UniqueId, CurrentPrecisionType ); + else + matrixVal = GeneratorUtils.GenerateTangentToWorldMatrixPrecise( ref dataCollector, UniqueId, CurrentPrecisionType ); + + switch( m_to ) + { + case TransformSpaceTo.Object: + { + result = string.Format( ASEMulOpFormat, matrixVal, result ); + CalculateTransform( TransformSpaceFrom.World, m_to, ref dataCollector, ref varName, ref result ); + varName = AseTangentToObjectDirVarName + OutputId; + } + break; + case TransformSpaceTo.World: + { + result = string.Format( ASEMulOpFormat, matrixVal, result ); + varName = AseTangentToWorldDirVarName + OutputId; + } + break; + case TransformSpaceTo.View: + { + result = string.Format( ASEMulOpFormat, matrixVal, result ); + CalculateTransform( TransformSpaceFrom.World, m_to, ref dataCollector, ref varName, ref result ); + varName = AseTangentToViewDirVarName + OutputId; + } + break; + case TransformSpaceTo.Clip: + { + result = string.Format( ASEMulOpFormat, matrixVal, result ); + CalculateTransform( TransformSpaceFrom.World, m_to, ref dataCollector, ref varName, ref result ); + varName = AseTangentToClipDirVarName + OutputId; + } + break; + case TransformSpaceTo.Tangent: + default: + break; + } + } + break; + default: break; + } + + if( m_normalize ) + { + result = GeneratorUtils.NormalizeValue( ref dataCollector , m_safeNormalize , m_inputPorts[ 0 ].DataType , result ); + } + + RegisterLocalVariable( 0, result, ref dataCollector, varName ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + string from = GetCurrentParam( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() < 17500 && from.Equals( "Clip" ) ) + { + UIUtils.ShowMessage( UniqueId, "Clip Space no longer supported on From field over Transform Direction node" ); + } + else + { + m_from = (TransformSpaceFrom)Enum.Parse( typeof( TransformSpaceFrom ), from ); + } + m_to = (TransformSpaceTo)Enum.Parse( typeof( TransformSpaceTo ), GetCurrentParam( ref nodeParams ) ); + m_normalize = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 15800 ) + { + m_inverseTangentType = (InverseTangentType)Enum.Parse( typeof( InverseTangentType ), GetCurrentParam( ref nodeParams ) ); + } + if( UIUtils.CurrentShaderVersion() > 18814 ) + { + m_safeNormalize = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + UpdateSubtitle(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_from ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_to ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalize ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_inverseTangentType ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_safeNormalize ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformDirectionNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformDirectionNode.cs.meta new file mode 100644 index 0000000..123dc9f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformDirectionNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5088261e4c0031f4aba961a253707b80 +timeCreated: 1525857790 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformPositionNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformPositionNode.cs new file mode 100644 index 0000000..968f8df --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformPositionNode.cs @@ -0,0 +1,626 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Transform Position", "Object Transform", "Transforms a position value from one space to another" )] + public sealed class TransformPositionNode : ParentNode + { + [SerializeField] + private TransformSpaceFrom m_from = TransformSpaceFrom.Object; + + [SerializeField] + private TransformSpaceTo m_to = TransformSpaceTo.World; + + [SerializeField] + private bool m_perspectiveDivide = false; + + [SerializeField] + private InverseTangentType m_inverseTangentType = InverseTangentType.Fast; + + [SerializeField] + private bool m_absoluteWorldPos = true; + + private const string AbsoluteWorldPosStr = "Absolute"; + + private string InverseTBNStr = "Inverse TBN"; + + private const string AseObjectToWorldPosVarName = "objToWorld"; + private const string AseObjectToWorldPosFormat = "mul( unity_ObjectToWorld, float4( {0}, 1 ) ).xyz"; + private const string AseHDObjectToWorldPosFormat = "mul( GetObjectToWorldMatrix(), float4( {0}, 1 ) ).xyz"; + private const string ASEHDAbsoluteWordPos = "GetAbsolutePositionWS({0})"; + private const string ASEHDRelaviveCameraPos = "GetCameraRelativePositionWS({0})"; + private const string AseObjectToViewPosVarName = "objToView"; + private const string AseObjectToViewPosFormat = "mul( UNITY_MATRIX_MV, float4( {0}, 1 ) ).xyz"; + private const string AseHDObjectToViewPosFormat = "TransformWorldToView( TransformObjectToWorld({0}) )"; + + private const string AseWorldToObjectPosVarName = "worldToObj"; + private const string AseWorldToObjectPosFormat = "mul( unity_WorldToObject, float4( {0}, 1 ) ).xyz"; + private const string AseSRPWorldToObjectPosFormat = "mul( GetWorldToObjectMatrix(), float4( {0}, 1 ) ).xyz"; + + + private const string AseWorldToViewPosVarName = "worldToView"; + private const string AseWorldToViewPosFormat = "mul( UNITY_MATRIX_V, float4( {0}, 1 ) ).xyz"; + + private const string AseViewToObjectPosVarName = "viewToObj"; + private const string AseViewToObjectPosFormat = "mul( unity_WorldToObject, mul( UNITY_MATRIX_I_V , float4( {0}, 1 ) ) ).xyz"; + private const string AseHDViewToObjectPosFormat = "mul( GetWorldToObjectMatrix(), mul( UNITY_MATRIX_I_V , float4( {0}, 1 ) ) ).xyz"; + + private const string AseViewToWorldPosVarName = "viewToWorld"; + private const string AseViewToWorldPosFormat = "mul( UNITY_MATRIX_I_V, float4( {0}, 1 ) ).xyz"; + + /////////////////////////////////////////////////////////// + private const string AseObjectToClipPosVarName = "objectToClip"; + private const string AseObjectToClipPosFormat = "UnityObjectToClipPos({0})"; + private const string AseSRPObjectToClipPosFormat = "TransformWorldToHClip(TransformObjectToWorld({0}))"; + + private const string AseWorldToClipPosVarName = "worldToClip"; + private const string AseWorldToClipPosFormat = "mul(UNITY_MATRIX_VP, float4({0}, 1.0))"; + private const string AseSRPWorldToClipPosFormat = "TransformWorldToHClip({0})"; + + private const string AseViewToClipPosVarName = "viewToClip"; + private const string AseViewToClipPosFormat = "mul(UNITY_MATRIX_P, float4({0}, 1.0))"; + private const string AseSRPViewToClipPosFormat = "TransformWViewToHClip({0})"; + // + + private const string AseClipToObjectPosVarName = "clipToObject"; + private const string AseClipToObjectPosFormat = "mul( UNITY_MATRIX_IT_MV, mul( unity_CameraInvProjection,float4({0},1)) ).xyz"; + private const string AseHDClipToObjectPosFormat = "mul( UNITY_MATRIX_I_M, mul( UNITY_MATRIX_I_VP,float4({0},1)) ).xyz"; + + private const string AseClipToWorldPosVarName = "clipToWorld"; + private const string AseClipToWorldPosFormat = "mul( UNITY_MATRIX_I_V, mul( unity_CameraInvProjection,float4({0},1)) ).xyz"; + private const string AseHDClipToWorldPosFormat = "mul( UNITY_MATRIX_I_VP, float4({0},1) ).xyz"; + + private const string AseClipToViewPosVarName = "clipToView"; + private const string AseClipToViewPosFormat = " mul( unity_CameraInvProjection,float4({0},1)).xyz"; + private const string AseHDClipToViewPosFormat = " mul( UNITY_MATRIX_I_P,float4({0},1)).xyz"; + private const string AseClipToNDC = "{0}.xyz/{0}.w"; + ///////////////////////////////////////////////////// + private const string AseObjectToTangentPosVarName = "objectToTangentPos"; + private const string AseWorldToTangentPosVarName = "worldToTangentPos"; + private const string AseViewToTangentPosVarName = "viewToTangentPos"; + private const string AseClipToTangentPosVarName = "clipToTangentPos"; + private const string ASEWorldToTangentFormat = "mul( ase_worldToTangent, {0})"; + + + private const string AseTangentToObjectPosVarName = "tangentTobjectPos"; + private const string AseTangentToWorldPosVarName = "tangentToWorldPos"; + private const string AseTangentToViewPosVarName = "tangentToViewPos"; + private const string AseTangentToClipPosVarName = "tangentToClipPos"; + private const string ASEMulOpFormat = "mul( {0}, {1} )"; + + + /////////////////////////////////////////////////////////// + private const string FromStr = "From"; + private const string ToStr = "To"; + private const string PerpectiveDivideStr = "Perpective Divide"; + private const string SubtitleFormat = "{0} to {1}"; + + private readonly string[] m_spaceOptionsFrom = + { + "Object", + "World", + "View", + "Tangent" + }; + + private readonly string[] m_spaceOptionsTo = + { + "Object", + "World", + "View", + "Tangent", + "Clip" + }; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, Constants.EmptyPortValue ); + AddOutputVectorPorts( WirePortDataType.FLOAT3, "XYZ" ); + m_useInternalPortData = true; + m_autoWrapProperties = true; + m_previewShaderGUID = "74e4d859fbdb2c0468de3612145f4929"; + m_textLabelWidth = 120; + UpdateSubtitle(); + } + + private void UpdateSubtitle() + { + SetAdditonalTitleText( string.Format( SubtitleFormat, m_from, m_to ) ); + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_from = (TransformSpaceFrom)EditorGUILayoutPopup( FromStr, (int)m_from, m_spaceOptionsFrom ); + m_to = (TransformSpaceTo)EditorGUILayoutPopup( ToStr, (int)m_to, m_spaceOptionsTo ); + if( m_from == TransformSpaceFrom.Tangent ) + { + m_inverseTangentType = (InverseTangentType)EditorGUILayoutEnumPopup( InverseTBNStr, m_inverseTangentType ); + } + if( EditorGUI.EndChangeCheck() ) + { + UpdateSubtitle(); + } + + if( m_to == TransformSpaceTo.Clip ) + { + m_perspectiveDivide = EditorGUILayoutToggle( PerpectiveDivideStr, m_perspectiveDivide ); + } + + //if( m_containerGraph.IsHDRP && ( m_from == TransformSpace.Object && m_to == TransformSpace.World ) || + // ( m_from == TransformSpace.World && m_to == TransformSpace.Object ) ) + //{ + // m_absoluteWorldPos = EditorGUILayoutToggle( AbsoluteWorldPosStr, m_absoluteWorldPos ); + //} + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + if( (int)m_from != (int)m_to && ( m_from == TransformSpaceFrom.Tangent || m_to == TransformSpaceTo.Tangent ) ) + dataCollector.DirtyNormal = true; + } + + void CalculateTransform( TransformSpaceFrom from, TransformSpaceTo to, ref MasterNodeDataCollector dataCollector, ref string varName, ref string result ) + { + switch( from ) + { + case TransformSpaceFrom.Object: + { + switch( to ) + { + default: + case TransformSpaceTo.Object: break; + case TransformSpaceTo.World: + { + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + { + result = string.Format( AseHDObjectToWorldPosFormat, result ); + if( m_absoluteWorldPos ) + { + result = string.Format( ASEHDAbsoluteWordPos, result ); + } + } + else if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.Lightweight ) + { + result = string.Format( AseHDObjectToWorldPosFormat, result ); + } + } + else + result = string.Format( AseObjectToWorldPosFormat, result ); + + + varName = AseObjectToWorldPosVarName + OutputId; + } + break; + case TransformSpaceTo.View: + { + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + result = string.Format( AseHDObjectToViewPosFormat, result ); + else + result = string.Format( AseObjectToViewPosFormat, result ); + varName = AseObjectToViewPosVarName + OutputId; + } + break; + case TransformSpaceTo.Clip: + { + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType != TemplateSRPType.BuiltIn ) + { + result = string.Format( AseSRPObjectToClipPosFormat, result ); + } + else + { + result = string.Format( AseObjectToClipPosFormat, result ); + } + varName = AseObjectToClipPosVarName + OutputId; + } + break; + } + } + break; + case TransformSpaceFrom.World: + { + switch( to ) + { + case TransformSpaceTo.Object: + { + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + { + if( m_absoluteWorldPos ) + { + result = string.Format( ASEHDRelaviveCameraPos, result ); + } + result = string.Format( AseSRPWorldToObjectPosFormat, result ); + } + else if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.Lightweight ) + { + result = string.Format( AseSRPWorldToObjectPosFormat, result ); + } + + } + else + result = string.Format( AseWorldToObjectPosFormat, result ); + varName = AseWorldToObjectPosVarName + OutputId; + } + break; + default: + case TransformSpaceTo.World: break; + case TransformSpaceTo.View: + { + result = string.Format( AseWorldToViewPosFormat, result ); + varName = AseWorldToViewPosVarName + OutputId; + } + break; + case TransformSpaceTo.Clip: + { + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType != TemplateSRPType.BuiltIn ) + { + result = string.Format( AseSRPWorldToClipPosFormat, result ); + } + else + { + result = string.Format( AseWorldToClipPosFormat, result ); + } + varName = AseWorldToClipPosVarName + OutputId; + } + break; + } + } + break; + case TransformSpaceFrom.View: + { + switch( to ) + { + case TransformSpaceTo.Object: + { + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + result = string.Format( AseHDViewToObjectPosFormat, result ); + else + result = string.Format( AseViewToObjectPosFormat, result ); + varName = AseViewToObjectPosVarName + OutputId; + } + break; + case TransformSpaceTo.World: + { + result = string.Format( AseViewToWorldPosFormat, result ); + if( dataCollector.IsTemplate && + dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD && + m_absoluteWorldPos ) + { + result = string.Format( ASEHDAbsoluteWordPos , result ); + } + varName = AseViewToWorldPosVarName + OutputId; + } + break; + default: + case TransformSpaceTo.View: break; + case TransformSpaceTo.Clip: + { + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType != TemplateSRPType.BuiltIn ) + { + result = string.Format( AseSRPViewToClipPosFormat, result ); + } + else + { + result = string.Format( AseViewToClipPosFormat, result ); + } + varName = AseViewToClipPosVarName + OutputId; + } + break; + } + } + break; + //case TransformSpace.Clip: + //{ + // switch( to ) + // { + // case TransformSpace.Object: + // { + // if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + // { + // result = string.Format( AseHDClipToObjectPosFormat, result ); + // } + // else + // { + // result = string.Format( AseClipToObjectPosFormat, result ); + // } + // varName = AseClipToObjectPosVarName + OutputId; + // } + // break; + // case TransformSpace.World: + // { + // if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + // { + // result = string.Format( AseHDClipToWorldPosFormat, result ); + // } + // else + // { + // result = string.Format( AseClipToWorldPosFormat, result ); + // } + // varName = AseClipToWorldPosVarName + OutputId; + // } + // break; + // case TransformSpace.View: + // { + // if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + // { + // result = string.Format( AseHDClipToViewPosFormat, result ); + // } + // else + // { + // result = string.Format( AseClipToViewPosFormat, result ); + // } + // varName = AseClipToViewPosVarName + OutputId; + // } + // break; + // case TransformSpace.Clip: break; + // default: + // break; + // } + //} + //break; + default: break; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + GeneratorUtils.RegisterUnity2019MatrixDefines( ref dataCollector ); + + string result = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string varName = string.Empty; + + if( (int)m_from == (int)m_to ) + { + RegisterLocalVariable( 0, result, ref dataCollector ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + + switch( m_from ) + { + case TransformSpaceFrom.Object: + { + switch( m_to ) + { + default: + case TransformSpaceTo.Object: break; + case TransformSpaceTo.World: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.View: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.Clip: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.Tangent: + { + GeneratorUtils.GenerateWorldToTangentMatrix( ref dataCollector, UniqueId, CurrentPrecisionType ); + CalculateTransform( m_from, TransformSpaceTo.World, ref dataCollector, ref varName, ref result ); + result = string.Format( ASEWorldToTangentFormat, result ); + varName = AseObjectToTangentPosVarName + OutputId; + } + break; + } + } + break; + case TransformSpaceFrom.World: + { + switch( m_to ) + { + case TransformSpaceTo.Object: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + default: + case TransformSpaceTo.World: break; + case TransformSpaceTo.View: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.Clip: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.Tangent: + { + GeneratorUtils.GenerateWorldToTangentMatrix( ref dataCollector, UniqueId, CurrentPrecisionType ); + result = string.Format( ASEWorldToTangentFormat, result ); + varName = AseWorldToTangentPosVarName + OutputId; + } + break; + } + } + break; + case TransformSpaceFrom.View: + { + switch( m_to ) + { + case TransformSpaceTo.Object: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.World: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); ; + } + break; + default: + case TransformSpaceTo.View: break; + case TransformSpaceTo.Clip: + { + CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + } + break; + case TransformSpaceTo.Tangent: + { + GeneratorUtils.GenerateWorldToTangentMatrix( ref dataCollector, UniqueId, CurrentPrecisionType ); + CalculateTransform( m_from, TransformSpaceTo.World, ref dataCollector, ref varName, ref result ); + result = string.Format( ASEWorldToTangentFormat, result ); + varName = AseViewToTangentPosVarName + OutputId; + } + break; + } + } + break; + //case TransformSpace.Clip: + //{ + // switch( m_to ) + // { + // case TransformSpace.Object: + // { + // CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + // } + // break; + // case TransformSpace.World: + // { + // CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + // } + // break; + // case TransformSpace.View: + // { + // CalculateTransform( m_from, m_to, ref dataCollector, ref varName, ref result ); + // } + // break; + // case TransformSpace.Clip: break; + // case TransformSpace.Tangent: + // { + // GeneratorUtils.GenerateWorldToTangentMatrix( ref dataCollector, UniqueId, CurrentPrecisionType ); + // CalculateTransform( m_from, TransformSpace.World, ref dataCollector, ref varName, ref result ); + // result = string.Format( ASEWorldToTangentFormat, result ); + // varName = AseClipToTangentPosVarName + OutputId; + // } + // break; + // default: + // break; + // } + //} + //break; + case TransformSpaceFrom.Tangent: + { + string matrixVal = string.Empty; + if( m_inverseTangentType == InverseTangentType.Fast ) + matrixVal = GeneratorUtils.GenerateTangentToWorldMatrixFast( ref dataCollector, UniqueId, CurrentPrecisionType ); + else + matrixVal = GeneratorUtils.GenerateTangentToWorldMatrixPrecise( ref dataCollector, UniqueId, CurrentPrecisionType ); + + switch( m_to ) + { + case TransformSpaceTo.Object: + { + result = string.Format( ASEMulOpFormat, matrixVal, result ); + CalculateTransform( TransformSpaceFrom.World, m_to, ref dataCollector, ref varName, ref result ); + varName = AseTangentToObjectPosVarName + OutputId; + } + break; + case TransformSpaceTo.World: + { + result = string.Format( ASEMulOpFormat, matrixVal, result ); + varName = AseTangentToWorldPosVarName + OutputId; + } + break; + case TransformSpaceTo.View: + { + result = string.Format( ASEMulOpFormat, matrixVal, result ); + CalculateTransform( TransformSpaceFrom.World, m_to, ref dataCollector, ref varName, ref result ); + varName = AseTangentToViewPosVarName + OutputId; + } + break; + case TransformSpaceTo.Clip: + { + result = string.Format( ASEMulOpFormat, matrixVal, result ); + CalculateTransform( TransformSpaceFrom.World, m_to, ref dataCollector, ref varName, ref result ); + varName = AseTangentToClipPosVarName + OutputId; + } + break; + case TransformSpaceTo.Tangent: + default: + break; + } + } + break; + default: break; + } + + if( m_to == TransformSpaceTo.Clip ) + { + if( m_perspectiveDivide ) + { + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT4, varName, result ); + result = string.Format( AseClipToNDC, varName ); + varName += "NDC"; + } + else + { + result += ".xyz"; + } + } + + RegisterLocalVariable( 0, result, ref dataCollector, varName ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + string from = GetCurrentParam( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() < 17500 && from.Equals( "Clip" ) ) + { + UIUtils.ShowMessage( UniqueId, "Clip Space no longer supported on From field over Transform Position node" ); + } + else + { + m_from = (TransformSpaceFrom)Enum.Parse( typeof( TransformSpaceFrom ), from ); + } + m_to = (TransformSpaceTo)Enum.Parse( typeof( TransformSpaceTo ), GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 15701 ) + { + m_perspectiveDivide = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + if( UIUtils.CurrentShaderVersion() > 15800 ) + { + m_inverseTangentType = (InverseTangentType)Enum.Parse( typeof( InverseTangentType ), GetCurrentParam( ref nodeParams ) ); + } + if( UIUtils.CurrentShaderVersion() > 16103 ) + { + m_absoluteWorldPos = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + UpdateSubtitle(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_from ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_to ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_perspectiveDivide ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_inverseTangentType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_absoluteWorldPos ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformPositionNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformPositionNode.cs.meta new file mode 100644 index 0000000..84e1fcd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformPositionNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 274dde08d42e4b041b9be7a22a8c09d6 +timeCreated: 1525857790 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformVariables.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformVariables.cs new file mode 100644 index 0000000..1802fe5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformVariables.cs @@ -0,0 +1,166 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + public enum BuiltInShaderTransformTypes + { + UNITY_MATRIX_MVP = 0, + UNITY_MATRIX_MV, + UNITY_MATRIX_V, + UNITY_MATRIX_P, + UNITY_MATRIX_VP, + UNITY_MATRIX_T_MV, + UNITY_MATRIX_IT_MV, + //UNITY_MATRIX_TEXTURE0, + //UNITY_MATRIX_TEXTURE1, + //UNITY_MATRIX_TEXTURE2, + //UNITY_MATRIX_TEXTURE3, + _Object2World, + _World2Object//, + //unity_Scale + } + + [Serializable] + [NodeAttributes( "Common Transform Matrices", "Matrix Transform", "All Transformation types" )] + public sealed class TransformVariables : ShaderVariablesNode + { + [SerializeField] + private BuiltInShaderTransformTypes m_selectedType = BuiltInShaderTransformTypes.UNITY_MATRIX_MVP; + + private const string MatrixLabelStr = "Matrix"; + private readonly string[] ValuesStr = + { + "Model View Projection", + "Model View", + "View", + "Projection", + "View Projection", + "Transpose Model View", + "Inverse Transpose Model View", + "Object to World", + "Word to Object" + }; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, ValuesStr[ ( int ) m_selectedType ], WirePortDataType.FLOAT4x4 ); + m_textLabelWidth = 60; + m_hasLeftDropdown = true; + m_autoWrapProperties = true; + m_drawPreview = false; + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_selectedType = (BuiltInShaderTransformTypes)m_upperLeftWidget.DrawWidget( this, (int)m_selectedType, ValuesStr ); + if( EditorGUI.EndChangeCheck() ) + { + ChangeOutputName( 0, ValuesStr[ (int)m_selectedType ] ); + m_sizeIsDirty = true; + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_selectedType = ( BuiltInShaderTransformTypes ) EditorGUILayoutPopup( MatrixLabelStr, ( int ) m_selectedType, ValuesStr ); + if ( EditorGUI.EndChangeCheck() ) + { + ChangeOutputName( 0, ValuesStr[ ( int ) m_selectedType ] ); + m_sizeIsDirty = true; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + switch( m_selectedType ) + { + case BuiltInShaderTransformTypes.UNITY_MATRIX_MVP: + return "mul(GetWorldToHClipMatrix(),GetObjectToWorldMatrix())"; + case BuiltInShaderTransformTypes.UNITY_MATRIX_MV: + return "mul( GetWorldToViewMatrix(),GetObjectToWorldMatrix())"; + case BuiltInShaderTransformTypes.UNITY_MATRIX_V: + return "GetWorldToViewMatrix()"; + case BuiltInShaderTransformTypes.UNITY_MATRIX_P: + return "GetViewToHClipMatrix()"; + case BuiltInShaderTransformTypes.UNITY_MATRIX_VP: + return "GetWorldToHClipMatrix()"; + case BuiltInShaderTransformTypes._Object2World: + return "GetObjectToWorldMatrix()"; + case BuiltInShaderTransformTypes._World2Object: + return "GetWorldToObjectMatrix()"; + case BuiltInShaderTransformTypes.UNITY_MATRIX_T_MV: + case BuiltInShaderTransformTypes.UNITY_MATRIX_IT_MV: + default: + { + UIUtils.ShowMessage( UniqueId, "Matrix not declared natively on SRP. Must create it manually inside ASE" ); + return "float4x4(" + + "1,0,0,0," + + "0,1,0,0," + + "0,0,1,0," + + "0,0,0,1)"; + } + } + } + else + { + return m_selectedType.ToString(); + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + string selectedTypeStr = GetCurrentParam( ref nodeParams ); + try + { + BuiltInShaderTransformTypes selectedType = (BuiltInShaderTransformTypes)Enum.Parse( typeof( BuiltInShaderTransformTypes ), selectedTypeStr ); + m_selectedType = selectedType; + } + catch( Exception e ) + { + switch( selectedTypeStr ) + { + default: Debug.LogException( e );break; + case "UNITY_MATRIX_TEXTURE0":UIUtils.ShowMessage( UniqueId, "Texture 0 matrix is no longer supported",MessageSeverity.Warning);break; + case "UNITY_MATRIX_TEXTURE1":UIUtils.ShowMessage( UniqueId, "Texture 1 matrix is no longer supported",MessageSeverity.Warning);break; + case "UNITY_MATRIX_TEXTURE2":UIUtils.ShowMessage( UniqueId, "Texture 2 matrix is no longer supported",MessageSeverity.Warning);break; + case "UNITY_MATRIX_TEXTURE3":UIUtils.ShowMessage( UniqueId, "Texture 3 matrix is no longer supported",MessageSeverity.Warning); break; + case "unity_Scale": UIUtils.ShowMessage( UniqueId, "Scale matrix is no longer supported", MessageSeverity.Warning ); break; + } + } + + ChangeOutputName( 0, ValuesStr[ ( int ) m_selectedType ] ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedType ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformVariables.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformVariables.cs.meta new file mode 100644 index 0000000..d0e613a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransformVariables.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 04aad5172ee1d4d4795e20bfae0ff64d +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransposeMVMatrix.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransposeMVMatrix.cs new file mode 100644 index 0000000..c7c46fe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransposeMVMatrix.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Transpose Model View Matrix", "Matrix Transform", "Transpose of model * view matrix" )] + public sealed class TransposeMVMatrix : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_T_MV"; + m_drawPreview = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransposeMVMatrix.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransposeMVMatrix.cs.meta new file mode 100644 index 0000000..871d601 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/TransposeMVMatrix.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5762b195353d629448631bfb15fb8372 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorClipMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorClipMatrixNode.cs new file mode 100644 index 0000000..09325ec --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorClipMatrixNode.cs @@ -0,0 +1,23 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Projector Clip Matrix", "Matrix Transform", "Current Projector Clip matrix. To be used when working with Unity projector." )] + public sealed class UnityProjectorClipMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "unity_ProjectorClip"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + dataCollector.AddToUniforms( UniqueId, "float4x4 unity_ProjectorClip;" ); + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorClipMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorClipMatrixNode.cs.meta new file mode 100644 index 0000000..6bc17bd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorClipMatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6095e3e4dc186f146bc109813901ccc8 +timeCreated: 1512062884 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorMatrixNode.cs new file mode 100644 index 0000000..4cfb63c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorMatrixNode.cs @@ -0,0 +1,23 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Projector Matrix", "Matrix Transform", "Current Projector Clip matrix. To be used when working with Unity projector." )] + public sealed class UnityProjectorMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "unity_Projector"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + dataCollector.AddToUniforms( UniqueId, "float4x4 unity_Projector;" ); + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorMatrixNode.cs.meta new file mode 100644 index 0000000..0a62ab9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityProjectorMatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c3efd02b48473d94b92302654b671ddc +timeCreated: 1512062884 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityScaleMatrix.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityScaleMatrix.cs new file mode 100644 index 0000000..2d2f00c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityScaleMatrix.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Scale Matrix", "Matrix Transform", "Scale Matrix",null, UnityEngine.KeyCode.None, true, true, "Object Scale" )] + public sealed class UnityScaleMatrix : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "unity_Scale"; + m_drawPreview = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityScaleMatrix.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityScaleMatrix.cs.meta new file mode 100644 index 0000000..26f2df7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/UnityScaleMatrix.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 28a04286716e19f4aa58954888374428 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewMatrixNode.cs new file mode 100644 index 0000000..2291bc3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewMatrixNode.cs @@ -0,0 +1,19 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "View Matrix", "Matrix Transform", "Current view matrix" )] + public sealed class ViewMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_V"; + m_drawPreview = false; + m_matrixId = 0; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewMatrixNode.cs.meta new file mode 100644 index 0000000..bcfb2ed --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewMatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5aa75cc5e6044a44a9a4439eac1d948b +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewProjectionMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewProjectionMatrixNode.cs new file mode 100644 index 0000000..23e53e4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewProjectionMatrixNode.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "View Projection Matrix", "Matrix Transform", "Current view * projection matrix." )] + public sealed class ViewProjectionMatrixNode : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "UNITY_MATRIX_VP"; + m_drawPreview = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewProjectionMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewProjectionMatrixNode.cs.meta new file mode 100644 index 0000000..1a1cd1c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/ViewProjectionMatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: fe26c99932382e047aebc05b7e67a3d0 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToCameraMatrix.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToCameraMatrix.cs new file mode 100644 index 0000000..65d9e08 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToCameraMatrix.cs @@ -0,0 +1,23 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "World To Camera Matrix", "Matrix Transform", "Inverse of current camera to world matrix" )] + public sealed class WorldToCameraMatrix : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "unity_WorldToCamera"; + m_drawPreview = false; + } + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + GeneratorUtils.RegisterUnity2019MatrixDefines( ref dataCollector ); + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToCameraMatrix.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToCameraMatrix.cs.meta new file mode 100644 index 0000000..a8d0b7a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToCameraMatrix.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 584bea5554dc1b64c8965d8fcfc54e23 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToObjectMatrix.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToObjectMatrix.cs new file mode 100644 index 0000000..dd82ebb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToObjectMatrix.cs @@ -0,0 +1,20 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "World To Object Matrix", "Matrix Transform", "Inverse of current world matrix" )] + public sealed class WorldToObjectMatrix : ConstantShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputProperties( 0, "Out", WirePortDataType.FLOAT4x4 ); + m_value = "unity_WorldToObject"; + m_HDValue = "GetWorldToObjectMatrix()"; + m_LWValue = "GetWorldToObjectMatrix()"; + m_drawPreview = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToObjectMatrix.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToObjectMatrix.cs.meta new file mode 100644 index 0000000..dd284eb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToObjectMatrix.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d9e2a5077cc29de439d5c845eac35a04 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToTangentMatrix.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToTangentMatrix.cs new file mode 100644 index 0000000..194802e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToTangentMatrix.cs @@ -0,0 +1,47 @@ +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "World To Tangent Matrix", "Matrix Transform", "World to tangent transform matrix" )] + public sealed class WorldToTangentMatrix : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputPort( WirePortDataType.FLOAT3x3, "Out" ); + //UIUtils.AddNormalDependentCount(); + m_drawPreview = false; + } + + //public override void Destroy() + //{ + // ContainerGraph.RemoveNormalDependentCount(); + // base.Destroy(); + //} + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + dataCollector.DirtyNormal = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetWorldToTangentMatrix( CurrentPrecisionType ); + + if( dataCollector.IsFragmentCategory ) + { + dataCollector.ForceNormal = true; + + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + } + + GeneratorUtils.GenerateWorldToTangentMatrix( ref dataCollector, UniqueId, CurrentPrecisionType ); + + return GeneratorUtils.WorldToTangentStr; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToTangentMatrix.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToTangentMatrix.cs.meta new file mode 100644 index 0000000..ed19db7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Transform/WorldToTangentMatrix.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b598d9ebc2d7be44a97270732f55f9bc +timeCreated: 1484747592 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various.meta new file mode 100644 index 0000000..89ede46 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5bbb49ec7f4a3524d9950847c88d4afc +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/ColorSpaceDouble.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/ColorSpaceDouble.cs new file mode 100644 index 0000000..231a011 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/ColorSpaceDouble.cs @@ -0,0 +1,37 @@ +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Color Space Double", "Miscellaneous", "Color Space Double" )] + public class ColorSpaceDouble : ParentNode + { + private const string ColorSpaceDoubleStr = "unity_ColorSpaceDouble"; + + private readonly string[] ColorSpaceDoubleDef = + { + "#ifdef UNITY_COLORSPACE_GAMMA//ASE Color Space Def", + "#define unity_ColorSpaceDouble half4(2.0, 2.0, 2.0, 2.0)//ASE Color Space Def", + "#else // Linear values//ASE Color Space Def", + "#define unity_ColorSpaceDouble half4(4.59479380, 4.59479380, 4.59479380, 2.0)//ASE Color Space Def", + "#endif//ASE Color Space Def" + }; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputColorPorts( "RGBA" ); + m_previewShaderGUID = "ac680a8772bb97c46851a7f075fd04e3"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + for( int i = 0; i < ColorSpaceDoubleDef.Length; i++ ) + { + dataCollector.AddToDirectives( ColorSpaceDoubleDef[ i ], -1 ); + } + } + return GetOutputVectorItem( 0, outputId, ColorSpaceDoubleStr ); ; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/ColorSpaceDouble.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/ColorSpaceDouble.cs.meta new file mode 100644 index 0000000..32721b8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/ColorSpaceDouble.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7d1204234983b3c4499da752961185be +timeCreated: 1481888315 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/FaceVariableNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/FaceVariableNode.cs new file mode 100644 index 0000000..0570939 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/FaceVariableNode.cs @@ -0,0 +1,53 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Face", "Vertex Data", "Indicates whether the rendered surface is facing the camera (1), or facing away from the camera(-1)" )] + public class FaceVariableNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputPort( WirePortDataType.FLOAT, "Out" ); + m_previewShaderGUID = "4b0b5b9f16353b840a5f5ad2baab3c3c"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + UIUtils.ShowMessage( UniqueId, m_nodeAttribs.Name + " node does not work on Tessellation port" ); + return m_outputPorts[0].ErrorValue; + } + + if ( dataCollector.PortCategory == MasterNodePortCategory.Vertex ) + { + if ( dataCollector.TesselationActive ) + { + UIUtils.ShowMessage( UniqueId, m_nodeAttribs.Name + " node does not work properly on Vertex/Tessellation ports" ); + return m_outputPorts[ 0 ].ErrorValue; + } + else + { + UIUtils.ShowMessage( UniqueId, m_nodeAttribs.Name + " node does not work propery on Vertex ports" ); + return m_outputPorts[ 0 ].ErrorValue; + } + } + + if ( dataCollector.IsTemplate ) + { + return dataCollector.TemplateDataCollectorInstance.GetVFace( UniqueId ); + } + else + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.VFACE ); + string variable = ( dataCollector.PortCategory == MasterNodePortCategory.Vertex ) ? Constants.VertexShaderOutputStr : Constants.InputVarStr; + return variable + "." + Constants.VFaceVariable; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/FaceVariableNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/FaceVariableNode.cs.meta new file mode 100644 index 0000000..b583327 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/FaceVariableNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4b4a6f07436b05a4cbc2559e4e704000 +timeCreated: 1492513159 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/InstanceIdNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/InstanceIdNode.cs new file mode 100644 index 0000000..c845e06 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/InstanceIdNode.cs @@ -0,0 +1,43 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Instance ID", "Vertex Data", "Indicates the per-instance identifier" )] + public class InstanceIdNode : ParentNode + { + private readonly string[] InstancingVariableAttrib = + { "uint currInstanceId = 0;", + "#ifdef UNITY_INSTANCING_ENABLED", + "currInstanceId = unity_InstanceID;", + "#endif"}; + private const string InstancingInnerVariable = "currInstanceId"; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputPort( WirePortDataType.INT, "Out" ); + m_previewShaderGUID = "03febce56a8cf354b90e7d5180c1dbd7"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate ) + { + dataCollector.TemplateDataCollectorInstance.SetupInstancing(); + } + + if( !dataCollector.HasLocalVariable( InstancingVariableAttrib[ 0 ] ) ) + { + dataCollector.AddLocalVariable( UniqueId, InstancingVariableAttrib[ 0 ] ,true ); + dataCollector.AddLocalVariable( UniqueId, InstancingVariableAttrib[ 1 ] ,true ); + dataCollector.AddLocalVariable( UniqueId, InstancingVariableAttrib[ 2 ] ,true ); + dataCollector.AddLocalVariable( UniqueId, InstancingVariableAttrib[ 3 ] ,true ); + } + return InstancingInnerVariable; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/InstanceIdNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/InstanceIdNode.cs.meta new file mode 100644 index 0000000..efae4fb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/InstanceIdNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c449923583a9fbe4283acebc97756ea1 +timeCreated: 1547811127 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/LODFadeNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/LODFadeNode.cs new file mode 100644 index 0000000..57826f4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/LODFadeNode.cs @@ -0,0 +1,107 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "LOD Fade", "Miscellaneous", "LODFadeNode" )] + public sealed class LODFadeNode : ConstVecShaderVariable + { + [SerializeField] + private bool m_legacyBehavior = false; + + private const string LegacyVarName = "legacyFadeVal"; + private const string LegacyVarValue = "(( unity_LODFade.x < 0 ) ? ( 1 + unity_LODFade.x ) : ( unity_LODFade.x ))"; + + private const string LegacyVarLabel = "Legacy Behavior"; + private const string LegacyVarInfo = "Prior to Unity 2019 values given by unity_LODFade.x/Fade[0...1] port were always positive and complemented each other between LOD Groups.\n" + + "Now fade-out is represented with positive values and fade-in with negative ones.\n"+ + "Toggling Legacy Behavior on internally checks for negative values and calculate complement result."; + + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputName( 1, "Fade[0...1]" ); + ChangeOutputName( 2, "Fade[16Lvl]" ); + ChangeOutputName( 3, "Unused" ); + ChangeOutputName( 4, "Unused" ); + m_value = "unity_LODFade"; + m_previewShaderGUID = "fcd4d93f57ffc51458d4ade10df2fdb4"; +#if UNITY_2019_1_OR_NEWER + m_autoWrapProperties = true; +#endif + } + + public override string GenerateShaderForOutput( int outputId , ref MasterNodeDataCollector dataCollector , bool ignoreLocalvar ) + { +#if UNITY_2019_1_OR_NEWER + string result = base.GenerateShaderForOutput( outputId , ref dataCollector , ignoreLocalvar ); + if( m_legacyBehavior && outputId == 1) + { + if( m_outputPorts[ 1 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 1 ].LocalValue( dataCollector.PortCategory ); + + dataCollector.AddLocalVariable( UniqueId , PrecisionType.Float , WirePortDataType.FLOAT , LegacyVarName , LegacyVarValue ); + m_outputPorts[ 1 ].SetLocalValue( LegacyVarName , dataCollector.PortCategory ); + + return m_outputPorts[ 1 ].LocalValue( dataCollector.PortCategory ); + } + else + { + return result; + } +#else + return base.GenerateShaderForOutput( outputId , ref dataCollector , ignoreLocalvar ); +#endif + } +#if UNITY_2019_1_OR_NEWER + public override void DrawProperties() + { + base.DrawProperties(); + m_legacyBehavior = EditorGUILayoutToggle( LegacyVarLabel , m_legacyBehavior ); + EditorGUILayout.HelpBox( LegacyVarInfo , MessageType.Info ); + } +#endif + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( !m_outputPorts[ 0 ].IsConnected ) + { + m_outputPorts[ 0 ].Visible = false; + m_sizeIsDirty = true; + } + + if( !m_outputPorts[ 3 ].IsConnected ) + { + m_outputPorts[ 3 ].Visible = false; + m_sizeIsDirty = true; + } + + if( !m_outputPorts[ 4 ].IsConnected ) + { + m_outputPorts[ 4 ].Visible = false; + m_sizeIsDirty = true; + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 18902 ) + { + m_legacyBehavior = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo , ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo , ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_legacyBehavior ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/LODFadeNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/LODFadeNode.cs.meta new file mode 100644 index 0000000..a83635a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/LODFadeNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f96cf34c2936c96458403e9cf75e8e10 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/PrimitiveIdVariableNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/PrimitiveIdVariableNode.cs new file mode 100644 index 0000000..b60f847 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/PrimitiveIdVariableNode.cs @@ -0,0 +1,38 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +#if UNITY_EDITOR_WIN +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Primitive ID", "Vertex Data", "Per-primitive identifier automatically generated by the runtime" )] + public class PrimitiveIDVariableNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputPort( WirePortDataType.INT, "Out" ); + m_previewShaderGUID = "92c1b588d7658594cb219696f593f64b"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( !dataCollector.IsTemplate ) + { + UIUtils.ShowMessage( UniqueId, m_nodeAttribs.Name + " is not supported on surface shaders." ); + return m_outputPorts[0].ErrorValue; + } + + if ( dataCollector.PortCategory == MasterNodePortCategory.Vertex ) + { + UIUtils.ShowMessage( UniqueId, m_nodeAttribs.Name + " is not supported on Vertex ports" ); + return m_outputPorts[0].ErrorValue; + } + + return dataCollector.TemplateDataCollectorInstance.GetPrimitiveId(); + } + } +} +#endif + diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/PrimitiveIdVariableNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/PrimitiveIdVariableNode.cs.meta new file mode 100644 index 0000000..6d7d119 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/PrimitiveIdVariableNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: dd0af9fbbba750341a7b09316178f285 +timeCreated: 1492513159 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/SwitchByFaceNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/SwitchByFaceNode.cs new file mode 100644 index 0000000..6bfd7f3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/SwitchByFaceNode.cs @@ -0,0 +1,70 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Switch by Face", "Miscellaneous", "Switch which automaticaly uses a Face variable to select which input to use" )] + public class SwitchByFaceNode : DynamicTypeNode + { + private const string SwitchOp = "((({0}>0)?({1}):({2})))"; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].Name = "Front"; + m_inputPorts[ 1 ].Name = "Back"; + m_textLabelWidth = 50; + m_previewShaderGUID = "f4edf6febb54dc743b25bd5b56facea8"; + } + + + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + UIUtils.ShowMessage( UniqueId, m_nodeAttribs.Name + " does not work on Tessellation port" ); + return GenerateErrorValue(); + } + + if ( dataCollector.PortCategory == MasterNodePortCategory.Vertex ) + { + if ( dataCollector.TesselationActive ) + { + UIUtils.ShowMessage( UniqueId, m_nodeAttribs.Name + " does not work properly on Vertex/Tessellation ports" ); + return GenerateErrorValue(); + } + else + { + UIUtils.ShowMessage( UniqueId, m_nodeAttribs.Name + " does not work properly on Vertex ports" ); + return GenerateErrorValue(); + } + } + + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string front = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string back = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + dataCollector.AddToInput( UniqueId, SurfaceInputs.VFACE ); + string variable = string.Empty; + if ( dataCollector.IsTemplate ) + { + variable = dataCollector.TemplateDataCollectorInstance.GetVFace( UniqueId ); + } + else + { + variable = ( ( dataCollector.PortCategory == MasterNodePortCategory.Vertex ) ? Constants.VertexShaderOutputStr : Constants.InputVarStr ) + "." + Constants.VFaceVariable; + } + + string value = string.Format( SwitchOp, variable, front, back ); + RegisterLocalVariable( 0, value, ref dataCollector, "switchResult" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/SwitchByFaceNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/SwitchByFaceNode.cs.meta new file mode 100644 index 0000000..b12692c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/SwitchByFaceNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b0464d8b27caa7d4d8fa5d1828934da8 +timeCreated: 1492515561 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/VertexIdVariableNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/VertexIdVariableNode.cs new file mode 100644 index 0000000..d2b7519 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/VertexIdVariableNode.cs @@ -0,0 +1,54 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Vertex ID", "Vertex Data", "Indicates current vertex number" )] + public class VertexIdVariableNode : ParentNode + { + private const string VertexIdVarName = "ase_vertexId"; + private const string VertexIdRegistry = "uint "+ VertexIdVarName + " : SV_VertexID;"; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputPort( WirePortDataType.INT, "Out" ); + m_previewShaderGUID = "5934bf2c10b127a459177a3b622cea65"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + UIUtils.ShowMessage( UniqueId, m_nodeAttribs.Name + " does not work on Tessellation port" ); + return m_outputPorts[0].ErrorValue; + } + + if ( dataCollector.IsTemplate ) + { + return dataCollector.TemplateDataCollectorInstance.GetVertexId(); + } + else + { + if( dataCollector.IsFragmentCategory ) + { + GenerateValueInVertex( ref dataCollector, WirePortDataType.UINT, Constants.VertexShaderInputStr + "."+ VertexIdVarName, VertexIdVarName, true ); + return Constants.InputVarStr + "."+ VertexIdVarName; + } + else + { + return Constants.VertexShaderInputStr + "."+ VertexIdVarName; + } + } + } + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + if( !dataCollector.IsTemplate ) + dataCollector.AddCustomAppData( VertexIdRegistry ); + + base.PropagateNodeData( nodeData, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/VertexIdVariableNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/VertexIdVariableNode.cs.meta new file mode 100644 index 0000000..cad8fe0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/VertexIdVariableNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ce37a30cae7677942ad44f0945ab7b77 +timeCreated: 1492513159 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/WorldTransformParams.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/WorldTransformParams.cs new file mode 100644 index 0000000..49966a0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/WorldTransformParams.cs @@ -0,0 +1,32 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "World Transform Params", "Object Transform", "World Transform Params contains information about the transform, W is usually 1.0, or -1.0 for odd-negative scale transforms" )] + public sealed class WorldTransformParams : ConstVecShaderVariable + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeOutputName( 1, "X" ); + ChangeOutputName( 2, "Y" ); + ChangeOutputName( 3, "Z" ); + ChangeOutputName( 4, "W" ); + m_value = "unity_WorldTransformParams"; + m_previewShaderGUID = "5a2642605f085da458d6e03ade47b87a"; + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( !m_outputPorts[ 0 ].IsConnected ) + { + m_outputPorts[ 0 ].Visible = false; + m_sizeIsDirty = true; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/WorldTransformParams.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/WorldTransformParams.cs.meta new file mode 100644 index 0000000..b28aa84 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/ShaderVariables/Various/WorldTransformParams.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: aec376443deca354789bc36ba18af898 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/StaticSwitch.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/StaticSwitch.cs new file mode 100644 index 0000000..ed072c1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/StaticSwitch.cs @@ -0,0 +1,1240 @@ +// Amplify Shader Editor - Visual Shader vEditing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Static Switch", "Logical Operators", "Creates a shader keyword toggle", Available = true )] + public sealed class StaticSwitch : PropertyNode + { + private float InstanceIconWidth = 19; + private float InstanceIconHeight = 19; + private readonly Color ReferenceHeaderColor = new Color( 0f, 0.5f, 0.585f, 1.0f ); + + [SerializeField] + private int m_defaultValue = 0; + + [SerializeField] + private int m_materialValue = 0; + + [SerializeField] + private int m_multiCompile = 0; + + [SerializeField] + private int m_currentKeywordId = 0; + + [SerializeField] + private string m_currentKeyword = string.Empty; + + [SerializeField] + private bool m_createToggle = true; + + [SerializeField] + private bool m_lockKeyword = true; + + private const string IsLocalStr = "Is Local"; +#if UNITY_2019_1_OR_NEWER + [SerializeField] + private bool m_isLocal = true; +#else + [SerializeField] + private bool m_isLocal = false; +#endif + private GUIContent m_checkContent; + private GUIContent m_popContent; + + private int m_conditionId = -1; + + private const int MinComboSize = 50; + private const int MaxComboSize = 105; + + private Rect m_varRect; + private Rect m_imgRect; + private bool m_editing; + + public enum KeywordModeType + { + Toggle = 0, + ToggleOff, + KeywordEnum, + } + + public enum StaticSwitchVariableMode + { + Create = 0, + Fetch, + Reference + } + + [SerializeField] + private KeywordModeType m_keywordModeType = KeywordModeType.Toggle; + + [SerializeField] + private StaticSwitch m_reference = null; + + private const string StaticSwitchStr = "Static Switch"; + private const string MaterialToggleStr = "Material Toggle"; + + private const string ToggleMaterialValueStr = "Material Value"; + private const string ToggleDefaultValueStr = "Default Value"; + + private const string AmountStr = "Amount"; + private const string KeywordStr = "Keyword"; + private const string CustomStr = "Custom"; + private const string ToggleTypeStr = "Toggle Type"; + private const string TypeStr = "Type"; + private const string ModeStr = "Mode"; + private const string KeywordTypeStr = "Keyword Type"; + + private const string KeywordNameStr = "Keyword Name"; + public readonly static string[] KeywordTypeList = { "Shader Feature", "Multi Compile"/*, "Define Symbol"*/ }; + public readonly static int[] KeywordTypeInt = { 0, 1/*, 2*/ }; + + [SerializeField] + private string[] m_defaultKeywordNames = { "Key0", "Key1", "Key2", "Key3", "Key4", "Key5", "Key6", "Key7", "Key8" }; + + [SerializeField] + private string[] m_keywordEnumList = { "Key0", "Key1" }; + + [SerializeField] + private StaticSwitchVariableMode m_staticSwitchVarMode = StaticSwitchVariableMode.Create; + + [SerializeField] + private int m_referenceArrayId = -1; + + [SerializeField] + private int m_referenceNodeId = -1; + + private int m_keywordEnumAmount = 2; + + private bool m_isStaticSwitchDirty = false; + + private Rect m_iconPos; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + AddInputPort( WirePortDataType.FLOAT, false, "False", -1, MasterNodePortCategory.Fragment, 1 ); + AddInputPort( WirePortDataType.FLOAT, false, "True", -1, MasterNodePortCategory.Fragment, 0 ); + for( int i = 2; i < 9; i++ ) + { + AddInputPort( WirePortDataType.FLOAT, false, m_defaultKeywordNames[ i ] ); + m_inputPorts[ i ].Visible = false; + } + m_headerColor = new Color( 0.0f, 0.55f, 0.45f, 1f ); + m_customPrefix = KeywordStr + " "; + m_autoWrapProperties = false; + m_freeType = false; + m_useVarSubtitle = true; + m_allowPropertyDuplicates = true; + m_showTitleWhenNotEditing = false; + m_currentParameterType = PropertyType.Property; + + m_checkContent = new GUIContent(); + m_checkContent.image = UIUtils.CheckmarkIcon; + + m_popContent = new GUIContent(); + m_popContent.image = UIUtils.PopupIcon; + + m_previewShaderGUID = "0b708c11c68e6a9478ac97fe3643eab1"; + m_showAutoRegisterUI = true; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_conditionId == -1 ) + m_conditionId = Shader.PropertyToID( "_Condition" ); + + StaticSwitch node = ( m_staticSwitchVarMode == StaticSwitchVariableMode.Reference && m_reference != null ) ? m_reference : this; + + if( m_createToggle ) + PreviewMaterial.SetInt( m_conditionId, node.MaterialValue ); + else + PreviewMaterial.SetInt( m_conditionId, node.DefaultValue ); + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + + if( m_createToggle ) + UIUtils.RegisterPropertyNode( this ); + else + UIUtils.UnregisterPropertyNode( this ); + + if( CurrentVarMode != StaticSwitchVariableMode.Reference ) + { + ContainerGraph.StaticSwitchNodes.AddNode( this ); + } + + if( UniqueId > -1 ) + ContainerGraph.StaticSwitchNodes.OnReorderEventComplete += OnReorderEventComplete; + } + + public override void Destroy() + { + base.Destroy(); + UIUtils.UnregisterPropertyNode( this ); + if( CurrentVarMode != StaticSwitchVariableMode.Reference ) + { + ContainerGraph.StaticSwitchNodes.RemoveNode( this ); + } + + if( UniqueId > -1 ) + ContainerGraph.StaticSwitchNodes.OnReorderEventComplete -= OnReorderEventComplete; + } + + void OnReorderEventComplete() + { + if( CurrentVarMode == StaticSwitchVariableMode.Reference ) + { + if( m_reference != null ) + { + m_referenceArrayId = ContainerGraph.StaticSwitchNodes.GetNodeRegisterIdx( m_reference.UniqueId ); + } + } + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnections(); + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + UpdateConnections(); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + UpdateConnections(); + } + + private void UpdateConnections() + { + WirePortDataType mainType = WirePortDataType.FLOAT; + + int highest = UIUtils.GetPriority( mainType ); + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + WirePortDataType portType = m_inputPorts[ i ].GetOutputConnection().DataType; + if( UIUtils.GetPriority( portType ) > highest ) + { + mainType = portType; + highest = UIUtils.GetPriority( portType ); + } + } + } + + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + m_inputPorts[ i ].ChangeType( mainType, false ); + } + + m_outputPorts[ 0 ].ChangeType( mainType, false ); + } + + public override string GetPropertyValue() + { + if( m_createToggle ) + if( m_keywordModeType == KeywordModeType.KeywordEnum && m_keywordEnumAmount > 0 ) + return PropertyAttributes + "[" + m_keywordModeType.ToString() + "(" + GetKeywordEnumPropertyList() + ")] " + m_propertyName + "(\"" + m_propertyInspectorName + "\", Float) = " + m_defaultValue; + else + return PropertyAttributes + "[" + m_keywordModeType.ToString() + "(" + GetPropertyValStr() + ")] " + m_propertyName + "(\"" + m_propertyInspectorName + "\", Float) = " + m_defaultValue; + else + return string.Empty; + } + + public string KeywordEnum( int index ) + { + if( m_createToggle ) + { + return string.IsNullOrEmpty( PropertyName ) ? KeywordEnumList( index ) : ( PropertyName + "_" + KeywordEnumList( index ) ); + } + else + { + return string.IsNullOrEmpty( PropertyName ) ? KeywordEnumList( index ) : ( PropertyName + KeywordEnumList( index ) ); + } + } + + public string KeywordEnumList( int index ) + { + if( CurrentVarMode == StaticSwitchVariableMode.Fetch ) + return m_keywordEnumList[ index ]; + else + { + return m_createToggle ? m_keywordEnumList[ index ].ToUpper() : m_keywordEnumList[ index ]; + } + + } + public override string PropertyName + { + get + { + if( CurrentVarMode == StaticSwitchVariableMode.Fetch ) + return m_currentKeyword; + else + { + return m_createToggle ? base.PropertyName.ToUpper() : base.PropertyName; + } + } + } + + public override string GetPropertyValStr() + { + if( m_keywordModeType == KeywordModeType.KeywordEnum ) + return PropertyName; + else if( !m_lockKeyword ) + return CurrentKeyword; + else if( CurrentVarMode == StaticSwitchVariableMode.Fetch ) + return m_currentKeyword; + else + return PropertyName + OnOffStr; + } + + private string GetKeywordEnumPropertyList() + { + string result = string.Empty; + for( int i = 0; i < m_keywordEnumList.Length; i++ ) + { + if( i == 0 ) + result = m_keywordEnumList[ i ]; + else + result += "," + m_keywordEnumList[ i ]; + } + return result; + } + + private string GetKeywordEnumPragmaList() + { + string result = string.Empty; + for( int i = 0; i < m_keywordEnumList.Length; i++ ) + { + if( i == 0 ) + result = KeywordEnum( i ); + else + result += " " + KeywordEnum( i ); + } + return result; + } + + public override string GetUniformValue() + { + return string.Empty; + } + + public override bool GetUniformData( out string dataType, out string dataName, ref bool fullValue ) + { + dataType = string.Empty; + dataName = string.Empty; + return false; + } + + public override void DrawProperties() + { + //base.DrawProperties(); + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr, PropertyGroup ); + NodeUtils.DrawPropertyGroup( ref m_visibleCustomAttrFoldout, CustomAttrStr, DrawCustomAttributes, DrawCustomAttrAddRemoveButtons ); + CheckPropertyFromInspector(); + } + + void DrawEnumList() + { + EditorGUI.BeginChangeCheck(); + KeywordEnumAmount = EditorGUILayoutIntSlider( AmountStr, KeywordEnumAmount, 2, 9 ); + if( EditorGUI.EndChangeCheck() ) + { + CurrentSelectedInput = Mathf.Clamp( CurrentSelectedInput, 0, KeywordEnumAmount - 1 ); + UpdateLabels(); + } + EditorGUI.indentLevel++; + for( int i = 0; i < m_keywordEnumList.Length; i++ ) + { + EditorGUI.BeginChangeCheck(); + m_keywordEnumList[ i ] = EditorGUILayoutTextField( "Item " + i, m_keywordEnumList[ i ] ); + if( EditorGUI.EndChangeCheck() ) + { + m_keywordEnumList[ i ] = UIUtils.RemoveInvalidEnumCharacters( m_keywordEnumList[ i ] ); + m_keywordEnumList[ i ] = m_keywordEnumList[ i ].Replace( " ", "" ); // sad face :( does not support spaces + m_inputPorts[ i ].Name = m_keywordEnumList[ i ]; + m_defaultKeywordNames[ i ] = m_inputPorts[ i ].Name; + } + } + EditorGUI.indentLevel--; + } + + public void UpdateLabels() + { + int maxinputs = m_keywordModeType == KeywordModeType.KeywordEnum ? KeywordEnumAmount : 2; + KeywordEnumAmount = Mathf.Clamp( KeywordEnumAmount, 0, maxinputs ); + m_keywordEnumList = new string[ maxinputs ]; + + for( int i = 0; i < maxinputs; i++ ) + { + m_keywordEnumList[ i ] = m_defaultKeywordNames[ i ]; + m_inputPorts[ i ].Name = m_keywordEnumList[ i ]; + } + + if( m_keywordModeType != KeywordModeType.KeywordEnum ) + { + m_inputPorts[ 0 ].Name = "False"; + m_inputPorts[ 1 ].Name = "True"; + } + + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + m_inputPorts[ i ].Visible = ( i < maxinputs ); + } + m_sizeIsDirty = true; + m_isStaticSwitchDirty = true; + } + + void PropertyGroup() + { + EditorGUI.BeginChangeCheck(); + CurrentVarMode = (StaticSwitchVariableMode)EditorGUILayoutEnumPopup( ModeStr, CurrentVarMode ); + if( EditorGUI.EndChangeCheck() ) + { + if( CurrentVarMode == StaticSwitchVariableMode.Fetch ) + { + m_keywordModeType = KeywordModeType.Toggle; + UpdateLabels(); + } + + if( CurrentVarMode == StaticSwitchVariableMode.Reference ) + { + UIUtils.UnregisterPropertyNode( this ); + } + else + { + if( m_createToggle ) + UIUtils.RegisterPropertyNode( this ); + else + UIUtils.UnregisterPropertyNode( this ); + } + } + + if( CurrentVarMode == StaticSwitchVariableMode.Create ) + { + EditorGUI.BeginChangeCheck(); + m_multiCompile = EditorGUILayoutIntPopup( KeywordTypeStr, m_multiCompile, KeywordTypeList, KeywordTypeInt ); + if( EditorGUI.EndChangeCheck() ) + { + BeginPropertyFromInspectorCheck(); + } + } + else if( CurrentVarMode == StaticSwitchVariableMode.Reference ) + { + string[] arr = ContainerGraph.StaticSwitchNodes.NodesArr; + bool guiEnabledBuffer = GUI.enabled; + if( arr != null && arr.Length > 0 ) + { + GUI.enabled = true; + } + else + { + m_referenceArrayId = -1; + GUI.enabled = false; + } + + EditorGUI.BeginChangeCheck(); + m_referenceArrayId = EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceArrayId, arr ); + if( EditorGUI.EndChangeCheck() ) + { + m_reference = ContainerGraph.StaticSwitchNodes.GetNode( m_referenceArrayId ); + if( m_reference != null ) + { + m_referenceNodeId = m_reference.UniqueId; + CheckReferenceValues( true ); + } + else + { + m_referenceArrayId = -1; + m_referenceNodeId = -1; + } + } + GUI.enabled = guiEnabledBuffer; + + return; + } + + if( CurrentVarMode == StaticSwitchVariableMode.Create || m_createToggle ) + { + EditorGUI.BeginChangeCheck(); + m_keywordModeType = (KeywordModeType)EditorGUILayoutEnumPopup( TypeStr, m_keywordModeType ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateLabels(); + } + } + + if( m_keywordModeType != KeywordModeType.KeywordEnum ) + { + if( CurrentVarMode == StaticSwitchVariableMode.Create || m_createToggle ) + { + ShowPropertyInspectorNameGUI(); + ShowPropertyNameGUI( true ); + if( CurrentVarMode == StaticSwitchVariableMode.Create ) + { + EditorGUILayout.BeginHorizontal(); + bool guiEnabledBuffer = GUI.enabled; + GUI.enabled = !m_lockKeyword; + if( m_lockKeyword ) + EditorGUILayout.TextField( KeywordNameStr, GetPropertyValStr() ); + else + m_currentKeyword = EditorGUILayoutTextField( KeywordNameStr, m_currentKeyword ); + GUI.enabled = guiEnabledBuffer; + m_lockKeyword = GUILayout.Toggle( m_lockKeyword, ( m_lockKeyword ? UIUtils.LockIconOpen : UIUtils.LockIconClosed ), "minibutton", GUILayout.Width( 22 ) ); + EditorGUILayout.EndHorizontal(); + } + } + + } + else + { + if( CurrentVarMode == StaticSwitchVariableMode.Create || m_createToggle ) + { + ShowPropertyInspectorNameGUI(); + ShowPropertyNameGUI( true ); + DrawEnumList(); + } + + } + + if( CurrentVarMode == StaticSwitchVariableMode.Fetch ) + { + //ShowPropertyInspectorNameGUI(); + EditorGUI.BeginChangeCheck(); + m_currentKeywordId = EditorGUILayoutPopup( KeywordStr, m_currentKeywordId, UIUtils.AvailableKeywords ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_currentKeywordId != 0 ) + { + m_currentKeyword = UIUtils.AvailableKeywords[ m_currentKeywordId ]; + } + } + + if( m_currentKeywordId == 0 ) + { + EditorGUI.BeginChangeCheck(); + m_currentKeyword = EditorGUILayoutTextField( CustomStr, m_currentKeyword ); + if( EditorGUI.EndChangeCheck() ) + { + m_currentKeyword = UIUtils.RemoveInvalidCharacters( m_currentKeyword ); + } + } + } + +#if UNITY_2019_1_OR_NEWER + m_isLocal = EditorGUILayoutToggle( IsLocalStr, m_isLocal ); +#endif + + //if( CurrentVarMode == StaticSwitchVariableMode.Create ) + { + ShowAutoRegister(); + } + + EditorGUI.BeginChangeCheck(); + m_createToggle = EditorGUILayoutToggle( MaterialToggleStr, m_createToggle ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_createToggle ) + UIUtils.RegisterPropertyNode( this ); + else + UIUtils.UnregisterPropertyNode( this ); + } + + + if( m_createToggle ) + { + EditorGUILayout.BeginHorizontal(); + GUILayout.Space( 20 ); + m_propertyTab = GUILayout.Toolbar( m_propertyTab, LabelToolbarTitle ); + EditorGUILayout.EndHorizontal(); + switch( m_propertyTab ) + { + default: + case 0: + { + EditorGUI.BeginChangeCheck(); + if( m_keywordModeType != KeywordModeType.KeywordEnum ) + m_materialValue = EditorGUILayoutToggle( ToggleMaterialValueStr, m_materialValue == 1 ) ? 1 : 0; + else + m_materialValue = EditorGUILayoutPopup( ToggleMaterialValueStr, m_materialValue, m_keywordEnumList ); + if( EditorGUI.EndChangeCheck() ) + m_requireMaterialUpdate = true; + } + break; + case 1: + { + if( m_keywordModeType != KeywordModeType.KeywordEnum ) + m_defaultValue = EditorGUILayoutToggle( ToggleDefaultValueStr, m_defaultValue == 1 ) ? 1 : 0; + else + m_defaultValue = EditorGUILayoutPopup( ToggleDefaultValueStr, m_defaultValue, m_keywordEnumList ); + } + break; + } + } + + //EditorGUILayout.HelpBox( "Keyword Type:\n" + + // "The difference is that unused variants of \"Shader Feature\" shaders will not be included into game build while \"Multi Compile\" variants are included regardless of their usage.\n\n" + + // "So \"Shader Feature\" makes most sense for keywords that will be set on the materials, while \"Multi Compile\" for keywords that will be set from code globally.\n\n" + + // "You can set keywords using the material property using the \"Property Name\" or you can set the keyword directly using the \"Keyword Name\".", MessageType.None ); + } + + public override void CheckPropertyFromInspector( bool forceUpdate = false ) + { + if( m_propertyFromInspector ) + { + if( forceUpdate || ( EditorApplication.timeSinceStartup - m_propertyFromInspectorTimestamp ) > MaxTimestamp ) + { + m_propertyFromInspector = false; + RegisterPropertyName( true, m_propertyInspectorName, m_autoGlobalName, m_underscoredGlobal ); + m_propertyNameIsDirty = true; + + if( CurrentVarMode != StaticSwitchVariableMode.Reference ) + { + ContainerGraph.StaticSwitchNodes.UpdateDataOnNode( UniqueId, DataToArray ); + } + } + } + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + float finalSize = 0; + if( m_keywordModeType == KeywordModeType.KeywordEnum ) + { + GUIContent dropdown = new GUIContent( m_inputPorts[ CurrentSelectedInput ].Name ); + int cacheSize = UIUtils.GraphDropDown.fontSize; + UIUtils.GraphDropDown.fontSize = 10; + Vector2 calcSize = UIUtils.GraphDropDown.CalcSize( dropdown ); + UIUtils.GraphDropDown.fontSize = cacheSize; + finalSize = Mathf.Clamp( calcSize.x, MinComboSize, MaxComboSize ); + if( m_insideSize.x != finalSize ) + { + m_insideSize.Set( finalSize, 25 ); + m_sizeIsDirty = true; + } + } + + base.OnNodeLayout( drawInfo ); + + if( m_keywordModeType != KeywordModeType.KeywordEnum ) + { + m_varRect = m_remainingBox; + m_varRect.size = Vector2.one * 22 * drawInfo.InvertedZoom; + m_varRect.center = m_remainingBox.center; + if( m_showPreview ) + m_varRect.y = m_remainingBox.y; + } + else + { + m_varRect = m_remainingBox; + m_varRect.width = finalSize * drawInfo.InvertedZoom; + m_varRect.height = 16 * drawInfo.InvertedZoom; + m_varRect.x = m_remainingBox.xMax - m_varRect.width; + m_varRect.y += 1 * drawInfo.InvertedZoom; + + m_imgRect = m_varRect; + m_imgRect.x = m_varRect.xMax - 16 * drawInfo.InvertedZoom; + m_imgRect.width = 16 * drawInfo.InvertedZoom; + m_imgRect.height = m_imgRect.width; + } + + CheckReferenceValues( false ); + + if( m_staticSwitchVarMode == StaticSwitchVariableMode.Reference ) + { + m_iconPos = m_globalPosition; + m_iconPos.width = InstanceIconWidth * drawInfo.InvertedZoom; + m_iconPos.height = InstanceIconHeight * drawInfo.InvertedZoom; + + m_iconPos.y += 10 * drawInfo.InvertedZoom; + m_iconPos.x += /*m_globalPosition.width - m_iconPos.width - */5 * drawInfo.InvertedZoom; + } + + } + + void CheckReferenceValues( bool forceUpdate ) + { + if( m_staticSwitchVarMode == StaticSwitchVariableMode.Reference ) + { + if( m_reference == null && m_referenceNodeId > 0 ) + { + m_reference = ContainerGraph.GetNode( m_referenceNodeId ) as StaticSwitch; + m_referenceArrayId = ContainerGraph.StaticSwitchNodes.GetNodeRegisterIdx( m_referenceNodeId ); + } + + if( m_reference != null ) + { + if( forceUpdate || m_reference.IsStaticSwitchDirty ) + { + int count = m_inputPorts.Count; + for( int i = 0; i < count; i++ ) + { + m_inputPorts[ i ].Name = m_reference.InputPorts[ i ].Name; + m_inputPorts[ i ].Visible = m_reference.InputPorts[ i ].Visible; + } + m_sizeIsDirty = true; + } + } + } + else + { + m_isStaticSwitchDirty = false; + } + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if( drawInfo.CurrentEventType != EventType.MouseDown || !m_createToggle ) + return; + + if( m_varRect.Contains( drawInfo.MousePosition ) ) + { + m_editing = true; + } + else if( m_editing ) + { + m_editing = false; + } + } + + private int CurrentSelectedInput + { + get + { + return m_materialMode ? m_materialValue : m_defaultValue; + } + set + { + if( m_materialMode ) + m_materialValue = value; + else + m_defaultValue = value; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( m_staticSwitchVarMode == StaticSwitchVariableMode.Reference ) + return; + + if( m_editing ) + { + if( m_keywordModeType != KeywordModeType.KeywordEnum ) + { + if( GUI.Button( m_varRect, GUIContent.none, UIUtils.GraphButton ) ) + { + CurrentSelectedInput = CurrentSelectedInput == 1 ? 0 : 1; + PreviewIsDirty = true; + m_editing = false; + if( m_materialMode ) + m_requireMaterialUpdate = true; + } + + if( CurrentSelectedInput == 1 ) + { + GUI.Label( m_varRect, m_checkContent, UIUtils.GraphButtonIcon ); + } + } + else + { + EditorGUI.BeginChangeCheck(); + CurrentSelectedInput = EditorGUIPopup( m_varRect, CurrentSelectedInput, m_keywordEnumList, UIUtils.GraphDropDown ); + if( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + m_editing = false; + if( m_materialMode ) + m_requireMaterialUpdate = true; + } + } + } + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + + if( !m_isVisible ) + return; + + if( m_staticSwitchVarMode == StaticSwitchVariableMode.Reference ) + { + GUI.Label( m_iconPos, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerTextureIcon ) ); + return; + } + + if( m_createToggle && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + { + if( !m_editing ) + { + if( m_keywordModeType != KeywordModeType.KeywordEnum ) + { + GUI.Label( m_varRect, GUIContent.none, UIUtils.GraphButton ); + + if( CurrentSelectedInput == 1 ) + GUI.Label( m_varRect, m_checkContent, UIUtils.GraphButtonIcon ); + } + else + { + GUI.Label( m_varRect, m_keywordEnumList[ CurrentSelectedInput ], UIUtils.GraphDropDown ); + GUI.Label( m_imgRect, m_popContent, UIUtils.GraphButtonIcon ); + } + } + } + } + + private string OnOffStr + { + get + { + if( !m_lockKeyword ) + return string.Empty; + + StaticSwitch node = null; + switch( CurrentVarMode ) + { + default: + case StaticSwitchVariableMode.Create: + case StaticSwitchVariableMode.Fetch: + node = this; + break; + case StaticSwitchVariableMode.Reference: + { + node = ( m_reference != null ) ? m_reference : this; + } + break; + } + + if( !node.CreateToggle ) + return string.Empty; + + switch( node.KeywordModeTypeValue ) + { + default: + case KeywordModeType.Toggle: + return "_ON"; + case KeywordModeType.ToggleOff: + return "_OFF"; + } + } + } + string GetStaticSwitchType() + { + string staticSwitchType = ( m_multiCompile == 1 ) ? "multi_compile" : "shader_feature"; +#if UNITY_2019_1_OR_NEWER + if( m_isLocal ) + staticSwitchType += "_local"; +#endif + return staticSwitchType; + } + + void RegisterPragmas( ref MasterNodeDataCollector dataCollector ) + { + if( CurrentVarMode == StaticSwitchVariableMode.Create ) + { + string staticSwitchType = GetStaticSwitchType(); + if( m_keywordModeType == KeywordModeType.KeywordEnum ) + { + if( m_multiCompile == 1 ) + dataCollector.AddToPragmas( UniqueId, staticSwitchType + " " + GetKeywordEnumPragmaList() ); + else if( m_multiCompile == 0 ) + dataCollector.AddToPragmas( UniqueId, staticSwitchType + " " + GetKeywordEnumPragmaList() ); + } + else + { + if( m_multiCompile == 1 ) + dataCollector.AddToPragmas( UniqueId, staticSwitchType + " __ " + CurrentKeyword ); + else if( m_multiCompile == 0 ) + dataCollector.AddToPragmas( UniqueId, staticSwitchType + " " + CurrentKeyword ); + } + } + } + + protected override void RegisterProperty( ref MasterNodeDataCollector dataCollector ) + { + if( m_staticSwitchVarMode == StaticSwitchVariableMode.Reference && m_reference != null ) + { + m_reference.RegisterProperty( ref dataCollector ); + m_reference.RegisterPragmas( ref dataCollector ); + } + else + { + if( m_createToggle ) + base.RegisterProperty( ref dataCollector ); + + RegisterPragmas( ref dataCollector ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + + StaticSwitch node = ( m_staticSwitchVarMode == StaticSwitchVariableMode.Reference && m_reference != null ) ? m_reference : this; + + this.OrderIndex = node.RawOrderIndex; + this.OrderIndexOffset = node.OrderIndexOffset; + //if( m_keywordModeType == KeywordModeType.KeywordEnum ) + + //node.RegisterPragmas( ref dataCollector ); + + string outType = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ); + + if( node.KeywordModeTypeValue == KeywordModeType.KeywordEnum ) + { + string defaultKey = "\t" + outType + " staticSwitch" + OutputId + " = " + m_inputPorts[ node.DefaultValue ].GeneratePortInstructions( ref dataCollector ) + ";"; + + string[] allOutputs = new string[ node.KeywordEnumAmount ]; + for( int i = 0; i < node.KeywordEnumAmount; i++ ) + allOutputs[ i ] = m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ); + + for( int i = 0; i < node.KeywordEnumAmount; i++ ) + { + string keyword = node.KeywordEnum( i ); + if( i == 0 ) + dataCollector.AddLocalVariable( UniqueId, "#if defined(" + keyword + ")", true ); + else + dataCollector.AddLocalVariable( UniqueId, "#elif defined(" + keyword + ")", true ); + + if( node.DefaultValue == i ) + dataCollector.AddLocalVariable( UniqueId, defaultKey, true ); + else + dataCollector.AddLocalVariable( UniqueId, "\t" + outType + " staticSwitch" + OutputId + " = " + allOutputs[ i ] + ";", true ); + } + dataCollector.AddLocalVariable( UniqueId, "#else", true ); + dataCollector.AddLocalVariable( UniqueId, defaultKey, true ); + dataCollector.AddLocalVariable( UniqueId, "#endif", true ); + } + else + { + string falseCode = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string trueCode = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + //if( node.CurrentVarMode == StaticSwitchVariableMode.Fetch ) + dataCollector.AddLocalVariable( UniqueId, "#ifdef " + node.CurrentKeyword, true ); + //else + // dataCollector.AddLocalVariable( UniqueId, "#ifdef " + node.PropertyName + OnOffStr, true ); + dataCollector.AddLocalVariable( UniqueId, "\t" + outType + " staticSwitch" + OutputId + " = " + trueCode + ";", true ); + dataCollector.AddLocalVariable( UniqueId, "#else", true ); + dataCollector.AddLocalVariable( UniqueId, "\t" + outType + " staticSwitch" + OutputId + " = " + falseCode + ";", true ); + dataCollector.AddLocalVariable( UniqueId, "#endif", true ); + } + + m_outputPorts[ 0 ].SetLocalValue( "staticSwitch" + OutputId, dataCollector.PortCategory ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void DrawTitle( Rect titlePos ) + { + bool referenceMode = m_staticSwitchVarMode == StaticSwitchVariableMode.Reference && m_reference != null; + string subTitle = string.Empty; + string subTitleFormat = string.Empty; + if( referenceMode ) + { + subTitle = m_reference.GetPropertyValStr(); + subTitleFormat = Constants.SubTitleRefNameFormatStr; + } + else + { + subTitle = GetPropertyValStr(); + subTitleFormat = Constants.SubTitleVarNameFormatStr; + } + + SetAdditonalTitleTextOnCallback( subTitle, ( instance, newSubTitle ) => instance.AdditonalTitleContent.text = string.Format( subTitleFormat, newSubTitle ) ); + + if( !m_isEditing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + GUI.Label( titlePos, StaticSwitchStr, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + } + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction ) + { + if( m_keywordModeType == KeywordModeType.KeywordEnum ) + { + for( int i = 0; i < m_keywordEnumAmount; i++ ) + { + string key = KeywordEnum( i ); + mat.DisableKeyword( key ); + } + mat.EnableKeyword( KeywordEnum( m_materialValue )); + mat.SetFloat( m_propertyName, m_materialValue ); + } + else + { + int final = m_materialValue; + if( m_keywordModeType == KeywordModeType.ToggleOff ) + final = final == 1 ? 0 : 1; + mat.SetFloat( m_propertyName, m_materialValue ); + if( final == 1 ) + mat.EnableKeyword( GetPropertyValStr() ); + else + mat.DisableKeyword( GetPropertyValStr() ); + } + } + } + + public override void SetMaterialMode( Material mat, bool fetchMaterialValues ) + { + base.SetMaterialMode( mat, fetchMaterialValues ); + if( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) && mat.HasProperty( m_propertyName ) ) + { + m_materialValue = mat.GetInt( m_propertyName ); + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( m_propertyName ) ) + { + m_materialValue = material.GetInt( m_propertyName ); + PreviewIsDirty = true; + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_multiCompile = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 14403 ) + { + m_defaultValue = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 14101 ) + { + m_materialValue = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } + else + { + m_defaultValue = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ) ? 1 : 0; + if( UIUtils.CurrentShaderVersion() > 14101 ) + { + m_materialValue = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ) ? 1 : 0; + } + } + + if( UIUtils.CurrentShaderVersion() > 13104 ) + { + m_createToggle = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_currentKeyword = GetCurrentParam( ref nodeParams ); + m_currentKeywordId = UIUtils.GetKeywordId( m_currentKeyword ); + } + if( UIUtils.CurrentShaderVersion() > 14001 ) + { + m_keywordModeType = (KeywordModeType)Enum.Parse( typeof( KeywordModeType ), GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 14403 ) + { + KeywordEnumAmount = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + for( int i = 0; i < KeywordEnumAmount; i++ ) + { + m_defaultKeywordNames[ i ] = GetCurrentParam( ref nodeParams ); + } + + UpdateLabels(); + } + + if( UIUtils.CurrentShaderVersion() > 16304 ) + { + string currentVarMode = GetCurrentParam( ref nodeParams ); + CurrentVarMode = (StaticSwitchVariableMode)Enum.Parse( typeof( StaticSwitchVariableMode ), currentVarMode ); + if( CurrentVarMode == StaticSwitchVariableMode.Reference ) + { + m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } + else + { + CurrentVarMode = (StaticSwitchVariableMode)m_variableMode; + //Resetting m_variableMode to its default value since it will no longer be used and interfere released ransom properties behavior + m_variableMode = VariableMode.Create; + } + + if( CurrentVarMode == StaticSwitchVariableMode.Reference ) + { + UIUtils.UnregisterPropertyNode( this ); + } + else + { + if( m_createToggle ) + UIUtils.RegisterPropertyNode( this ); + else + UIUtils.UnregisterPropertyNode( this ); + } + + if( UIUtils.CurrentShaderVersion() > 16700 ) + { + m_isLocal = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 18401 ) + m_lockKeyword = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + + SetMaterialToggleRetrocompatibility(); + + if( !m_isNodeBeingCopied && CurrentVarMode != StaticSwitchVariableMode.Reference ) + { + ContainerGraph.StaticSwitchNodes.UpdateDataOnNode( UniqueId, DataToArray ); + } + } + + public override void ReleaseRansomedProperty() + { + //on old ASE, the property node m_variableMode was used on defining the static switch type, now we have a specific m_staticSwitchVarMode over here + //the problem with this is the fix made to release ransomend property names( hash deb232819fff0f1aeaf029a21c55ef597b3424de ) uses m_variableMode and + //makes old static switches to attempt and register an already registered name when doing this: + //CurrentVariableMode = VariableMode.Create; + //So we need to disable this release ransom property behavior as m_variableMode should never be on VariableMode.Create + //The m_variableMode is set to its default value over the ReadFromString method after its value as been set over the new m_staticSwitchVarMode variable + } + + void SetMaterialToggleRetrocompatibility() + { + if( UIUtils.CurrentShaderVersion() < 17108 ) + { + if( !m_createToggle && m_staticSwitchVarMode == StaticSwitchVariableMode.Create ) + { + if( m_keywordModeType != KeywordModeType.KeywordEnum ) + { + m_propertyName = m_propertyName.ToUpper() + "_ON"; + } + else + { + m_propertyName = m_propertyName.ToUpper(); + for( int i = 0; i < m_keywordEnumList.Length; i++ ) + { + m_keywordEnumList[ i ] = "_" + m_keywordEnumList[ i ].ToUpper(); + } + } + m_autoGlobalName = false; + } + } + } + + public override void ReadFromDeprecated( ref string[] nodeParams, Type oldType = null ) + { + base.ReadFromDeprecated( ref nodeParams, oldType ); + { + m_currentKeyword = GetCurrentParam( ref nodeParams ); + m_currentKeywordId = UIUtils.GetKeywordId( m_currentKeyword ); + m_createToggle = false; + m_keywordModeType = KeywordModeType.Toggle; + m_variableMode = VariableMode.Fetch; + CurrentVarMode = StaticSwitchVariableMode.Fetch; + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_multiCompile ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_materialValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_createToggle ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentKeyword ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_keywordModeType ); + IOUtils.AddFieldValueToString( ref nodeInfo, KeywordEnumAmount ); + for( int i = 0; i < KeywordEnumAmount; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_keywordEnumList[ i ] ); + } + + IOUtils.AddFieldValueToString( ref nodeInfo, CurrentVarMode ); + if( CurrentVarMode == StaticSwitchVariableMode.Reference ) + { + int referenceId = ( m_reference != null ) ? m_reference.UniqueId : -1; + IOUtils.AddFieldValueToString( ref nodeInfo, referenceId ); + } + IOUtils.AddFieldValueToString( ref nodeInfo, m_isLocal ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_lockKeyword ); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + CheckReferenceValues( true ); + } + + StaticSwitchVariableMode CurrentVarMode + { + get { return m_staticSwitchVarMode; } + set + { + if( m_staticSwitchVarMode != value ) + { + if( value == StaticSwitchVariableMode.Reference ) + { + ContainerGraph.StaticSwitchNodes.RemoveNode( this ); + m_referenceArrayId = -1; + m_referenceNodeId = -1; + m_reference = null; + m_headerColorModifier = ReferenceHeaderColor; + } + else + { + m_headerColorModifier = Color.white; + ContainerGraph.StaticSwitchNodes.AddNode( this ); + UpdateLabels(); + } + } + m_staticSwitchVarMode = value; + } + } + public bool IsStaticSwitchDirty { get { return m_isStaticSwitchDirty; } } + public KeywordModeType KeywordModeTypeValue { get { return m_keywordModeType; } } + public int DefaultValue { get { return m_defaultValue; } } + public int MaterialValue { get { return m_materialValue; } } + //public string CurrentKeyword { get { return m_currentKeyword; } } + public string CurrentKeyword + { + get + { + if( CurrentVarMode == StaticSwitchVariableMode.Fetch ) + return m_currentKeyword; + + return ( m_lockKeyword || string.IsNullOrEmpty( m_currentKeyword ) ? PropertyName + OnOffStr : m_currentKeyword ); + } + } + public bool CreateToggle { get { return m_createToggle; } } + + public int KeywordEnumAmount + { + get + { + return m_keywordEnumAmount; + } + set + { + m_keywordEnumAmount = value; + m_defaultValue = Mathf.Clamp( m_defaultValue, 0, m_keywordEnumAmount - 1 ); + m_materialValue = Mathf.Clamp( m_defaultValue, 0, m_keywordEnumAmount - 1 ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/StaticSwitch.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/StaticSwitch.cs.meta new file mode 100644 index 0000000..e1b216a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/StaticSwitch.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b1d1a233ea65ccd478fb6caf4327da48 +timeCreated: 1497289190 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TauNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TauNode.cs new file mode 100644 index 0000000..4901dbb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TauNode.cs @@ -0,0 +1,32 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node TAU +// Donated by The Four Headed Cat - @fourheadedcat + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Tau", "Constants And Properties", "Tau constant (2*PI): 6.28318530718", null, KeyCode.None, true, false, null,null, "The Four Headed Cat - @fourheadedcat" )] + public sealed class TauNode : ParentNode + { + private readonly string Tau = ( 2.0 * Mathf.PI ).ToString(); + public TauNode() : base() { } + public TauNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_previewShaderGUID = "701bc295c0d75d8429eabcf45e8e008d"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + return dataCollector.IsSRP? "TWO_PI": Tau; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TauNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TauNode.cs.meta new file mode 100644 index 0000000..96b9694 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TauNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1a6ded4f5e42f6d4684a6131a3cf4d33 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TextureArrayNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TextureArrayNode.cs new file mode 100644 index 0000000..36ae3e1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TextureArrayNode.cs @@ -0,0 +1,990 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + //[NodeAttributes( "Texture Array", "Textures", "Texture Array fetches a texture from a texture2DArray asset file given a index value", KeyCode.None, true, 0, int.MaxValue, typeof( Texture2DArray ) )] + [NodeAttributes( "[Old]Texture Array", "Textures", "Texture Array fetches a texture from a texture2DArray asset file given a index value", null, KeyCode.None, true, true, "SamplerNode", typeof( SamplerNode ) )] + public class TextureArrayNode : PropertyNode + { + [SerializeField] + private Texture2DArray m_defaultTextureArray; + + [SerializeField] + private Texture2DArray m_materialTextureArray; + + [SerializeField] + private TexReferenceType m_referenceType = TexReferenceType.Object; + + [SerializeField] + private int m_uvSet = 0; + + [SerializeField] + private MipType m_mipMode = MipType.Auto; + + private readonly string[] m_mipOptions = { "Auto", "Mip Level", "Derivative" }; + + private TextureArrayNode m_referenceSampler = null; + + [SerializeField] + private int m_referenceArrayId = -1; + + [SerializeField] + private int m_referenceNodeId = -1; + + [SerializeField] + private bool m_autoUnpackNormals = false; + + private InputPort m_texPort; + private InputPort m_uvPort; + private InputPort m_indexPort; + private InputPort m_lodPort; + private InputPort m_normalPort; + private InputPort m_ddxPort; + private InputPort m_ddyPort; + + private OutputPort m_colorPort; + + private const string AutoUnpackNormalsStr = "Normal"; + private const string NormalScaleStr = "Scale"; + + private string m_labelText = "None (Texture2DArray)"; + + private readonly Color ReferenceHeaderColor = new Color( 2.66f, 1.02f, 0.6f, 1.0f ); + + private int m_cachedUvsId = -1; + private int m_cachedSamplerId = -1; + private int m_texConnectedId = -1; + private int m_cachedUnpackId = -1; + private int m_cachedLodId = -1; + + private Rect m_iconPos; + private bool m_isEditingPicker; + + private bool m_linearTexture; + protected bool m_drawPicker; + + private ReferenceState m_state = ReferenceState.Self; + private ParentNode m_previewTextProp = null; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputColorPorts( "RGBA" ); + m_colorPort = m_outputPorts[ 0 ]; + AddInputPort( WirePortDataType.SAMPLER2D, false, "Tex", -1, MasterNodePortCategory.Fragment, 6 ); + AddInputPort( WirePortDataType.FLOAT2, false, "UV", -1, MasterNodePortCategory.Fragment, 0 ); + AddInputPort( WirePortDataType.FLOAT, false, "Index", -1, MasterNodePortCategory.Fragment, 1 ); + AddInputPort( WirePortDataType.FLOAT, false, "Level", -1, MasterNodePortCategory.Fragment, 2 ); + AddInputPort( WirePortDataType.FLOAT, false, NormalScaleStr, -1, MasterNodePortCategory.Fragment, 3 ); + AddInputPort( WirePortDataType.FLOAT2, false, "DDX", -1, MasterNodePortCategory.Fragment, 4 ); + AddInputPort( WirePortDataType.FLOAT2, false, "DDY", -1, MasterNodePortCategory.Fragment, 5 ); + m_inputPorts[ 2 ].AutoDrawInternalData = true; + + m_texPort = m_inputPorts[ 0 ]; + m_uvPort = m_inputPorts[ 1 ]; + m_indexPort = m_inputPorts[ 2 ]; + m_lodPort = m_inputPorts[ 3 ]; + + m_lodPort.Visible = false; + m_normalPort = m_inputPorts[ 4 ]; + m_normalPort.Visible = m_autoUnpackNormals; + m_normalPort.FloatInternalData = 1.0f; + m_ddxPort = m_inputPorts[ 5 ]; + m_ddxPort.Visible = false; + m_ddyPort = m_inputPorts[ 6 ]; + m_ddyPort.Visible = false; + m_insideSize.Set( 128, 128 + 5 ); + m_drawPrecisionUI = false; + m_currentParameterType = PropertyType.Property; + + m_availableAttribs.Add( new PropertyAttributes( "No Scale Offset", "[NoScaleOffset]" ) ); + + m_freeType = false; + m_showPreview = true; + m_drawPreviewExpander = false; + m_drawPreview = false; + m_drawPicker = true; + m_customPrefix = "Texture Array "; + m_selectedLocation = PreviewLocation.TopCenter; + m_previewShaderGUID = "2e6d093df2d289f47b827b36efb31a81"; + m_showAutoRegisterUI = false; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_cachedUvsId == -1 ) + m_cachedUvsId = Shader.PropertyToID( "_CustomUVs" ); + + if( m_cachedSamplerId == -1 ) + m_cachedSamplerId = Shader.PropertyToID( "_Sampler" ); + + if( m_texConnectedId == -1 ) + m_texConnectedId = Shader.PropertyToID( "_TexConnected" ); + + if( m_cachedUnpackId == -1 ) + m_cachedUnpackId = Shader.PropertyToID( "_Unpack" ); + + if( m_cachedLodId == -1 ) + m_cachedLodId = Shader.PropertyToID( "_LodType" ); + + PreviewMaterial.SetFloat( m_cachedLodId, ( m_mipMode == MipType.MipLevel ? 1 : 0 ) ); + PreviewMaterial.SetFloat( m_cachedUnpackId, m_autoUnpackNormals ? 1 : 0 ); + if( m_referenceType == TexReferenceType.Instance && m_referenceSampler != null ) + { + if( (ParentNode)m_referenceSampler != m_referenceSampler.PreviewTextProp ) + { + PreviewMaterial.SetInt( m_texConnectedId, 1 ); + PreviewMaterial.SetTexture( "_G", m_referenceSampler.PreviewTextProp.PreviewTexture ); + } + else + { + PreviewMaterial.SetInt( m_texConnectedId, 0 ); + PreviewMaterial.SetTexture( m_cachedSamplerId, m_referenceSampler.TextureArray ); + } + } + else if( m_texPort.IsConnected ) + { + PreviewMaterial.SetInt( m_texConnectedId, 1 ); + } + else + { + PreviewMaterial.SetInt( m_texConnectedId, 0 ); + PreviewMaterial.SetTexture( m_cachedSamplerId, TextureArray ); + } + PreviewMaterial.SetFloat( m_cachedUvsId, ( m_uvPort.IsConnected ? 1 : 0 ) ); + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + if( m_referenceType == TexReferenceType.Object ) + { + UIUtils.RegisterTextureArrayNode( this ); + UIUtils.RegisterPropertyNode( this ); + } + + if( UniqueId > -1 ) + ContainerGraph.TextureArrayNodes.OnReorderEventComplete += OnReorderEventComplete; + + } + + private void OnReorderEventComplete() + { + if( m_referenceType == TexReferenceType.Instance && m_referenceSampler != null ) + { + m_referenceArrayId = ContainerGraph.TextureArrayNodes.GetNodeRegisterIdx( m_referenceSampler.UniqueId ); + } + } + + new void ShowDefaults() + { + m_uvSet = EditorGUILayoutIntPopup( Constants.AvailableUVSetsLabel, m_uvSet, Constants.AvailableUVSetsStr, Constants.AvailableUVSets ); + + MipType newMipMode = (MipType)EditorGUILayoutPopup( "Mip Mode", (int)m_mipMode, m_mipOptions ); + if( newMipMode != m_mipMode ) + { + m_mipMode = newMipMode; + } + + switch( m_mipMode ) + { + case MipType.Auto: + m_lodPort.Visible = false; + m_ddxPort.Visible = false; + m_ddyPort.Visible = false; + break; + case MipType.MipLevel: + m_lodPort.Visible = true; + m_ddxPort.Visible = false; + m_ddyPort.Visible = false; + break; + case MipType.MipBias: + case MipType.Derivative: + m_ddxPort.Visible = true; + m_ddyPort.Visible = true; + m_lodPort.Visible = false; + break; + } + + if( m_ddxPort.Visible ) + { + EditorGUILayout.HelpBox( "Warning: Derivative Mip Mode only works on some platforms (D3D11 XBOXONE GLES3 GLCORE)", MessageType.Warning ); + } + + if( !m_lodPort.IsConnected && m_lodPort.Visible ) + { + m_lodPort.FloatInternalData = EditorGUILayoutFloatField( "Mip Level", m_lodPort.FloatInternalData ); + } + + if( !m_indexPort.IsConnected ) + { + m_indexPort.FloatInternalData = EditorGUILayoutFloatField( "Index", m_indexPort.FloatInternalData ); + } + + + } + + public override void DrawMainPropertyBlock() + { + EditorGUI.BeginChangeCheck(); + m_referenceType = (TexReferenceType)EditorGUILayoutPopup( Constants.ReferenceTypeStr, (int)m_referenceType, Constants.ReferenceArrayLabels ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_referenceType == TexReferenceType.Object ) + { + UIUtils.RegisterTextureArrayNode( this ); + UIUtils.RegisterPropertyNode( this ); + + SetTitleText( m_propertyInspectorName ); + SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) ); + m_referenceArrayId = -1; + m_referenceNodeId = -1; + m_referenceSampler = null; + } + else + { + UIUtils.UnregisterTextureArrayNode( this ); + UIUtils.UnregisterPropertyNode( this ); + } + UpdateHeaderColor(); + } + + if( m_referenceType == TexReferenceType.Object ) + { + EditorGUI.BeginChangeCheck(); + base.DrawMainPropertyBlock(); + if( EditorGUI.EndChangeCheck() ) + { + OnPropertyNameChanged(); + } + } + else + { + string[] arr = UIUtils.TextureArrayNodeArr(); + bool guiEnabledBuffer = GUI.enabled; + if( arr != null && arr.Length > 0 ) + { + GUI.enabled = true; + } + else + { + m_referenceArrayId = -1; + GUI.enabled = false; + } + + m_referenceArrayId = EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceArrayId, arr ); + GUI.enabled = guiEnabledBuffer; + + ShowDefaults(); + + DrawSamplerOptions(); + } + } + + public override void OnPropertyNameChanged() + { + base.OnPropertyNameChanged(); + UIUtils.UpdateTextureArrayDataNode( UniqueId, PropertyInspectorName ); + } + + public override void DrawSubProperties() + { + ShowDefaults(); + + DrawSamplerOptions(); + + EditorGUI.BeginChangeCheck(); + m_defaultTextureArray = EditorGUILayoutObjectField( Constants.DefaultValueLabel, m_defaultTextureArray, typeof( Texture2DArray ), false ) as Texture2DArray; + if( EditorGUI.EndChangeCheck() ) + { + CheckTextureImporter( true ); + SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) ); + } + } + + public override void DrawMaterialProperties() + { + ShowDefaults(); + + DrawSamplerOptions(); + + EditorGUI.BeginChangeCheck(); + m_materialTextureArray = EditorGUILayoutObjectField( Constants.MaterialValueLabel, m_materialTextureArray, typeof( Texture2DArray ), false ) as Texture2DArray; + if( EditorGUI.EndChangeCheck() ) + { + CheckTextureImporter( true ); + SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) ); + m_requireMaterialUpdate = true; + } + } + + public void DrawSamplerOptions() + { + EditorGUI.BeginChangeCheck(); + bool autoUnpackNormals = EditorGUILayoutToggle( "Normal Map", m_autoUnpackNormals ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_autoUnpackNormals != autoUnpackNormals ) + { + AutoUnpackNormals = autoUnpackNormals; + + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + } + + if( m_autoUnpackNormals && !m_normalPort.IsConnected ) + { + m_normalPort.FloatInternalData = EditorGUILayoutFloatField( NormalScaleStr, m_normalPort.FloatInternalData ); + } + } + + public void ConfigureInputPorts() + { + m_normalPort.Visible = AutoUnpackNormals; + + m_sizeIsDirty = true; + } + + public void ConfigureOutputPorts() + { + m_outputPorts[ m_colorPort.PortId + 4 ].Visible = !AutoUnpackNormals; + + if( !AutoUnpackNormals ) + { + m_colorPort.ChangeProperties( "RGBA", WirePortDataType.FLOAT4, false ); + m_outputPorts[ m_colorPort.PortId + 1 ].ChangeProperties( "R", WirePortDataType.FLOAT, false ); + m_outputPorts[ m_colorPort.PortId + 2 ].ChangeProperties( "G", WirePortDataType.FLOAT, false ); + m_outputPorts[ m_colorPort.PortId + 3 ].ChangeProperties( "B", WirePortDataType.FLOAT, false ); + m_outputPorts[ m_colorPort.PortId + 4 ].ChangeProperties( "A", WirePortDataType.FLOAT, false ); + + } + else + { + m_colorPort.ChangeProperties( "XYZ", WirePortDataType.FLOAT3, false ); + m_outputPorts[ m_colorPort.PortId + 1 ].ChangeProperties( "X", WirePortDataType.FLOAT, false ); + m_outputPorts[ m_colorPort.PortId + 2 ].ChangeProperties( "Y", WirePortDataType.FLOAT, false ); + m_outputPorts[ m_colorPort.PortId + 3 ].ChangeProperties( "Z", WirePortDataType.FLOAT, false ); + } + + m_sizeIsDirty = true; + } + + public virtual void CheckTextureImporter( bool additionalCheck ) + { + m_requireMaterialUpdate = true; + Texture2DArray texture = m_materialMode ? m_materialTextureArray : m_defaultTextureArray; + + UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath( AssetDatabase.GetAssetPath( texture ), typeof( UnityEngine.Object ) ); + + if( obj != null ) + { + SerializedObject serializedObject = new UnityEditor.SerializedObject( obj ); + + if( serializedObject != null ) + { + SerializedProperty colorSpace = serializedObject.FindProperty( "m_ColorSpace" ); + m_linearTexture = ( colorSpace.intValue == 0 ); + } + } + } + + void UpdateHeaderColor() + { + m_headerColorModifier = ( m_referenceType == TexReferenceType.Object ) ? Color.white : ReferenceHeaderColor; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if( !( drawInfo.CurrentEventType == EventType.MouseDown || drawInfo.CurrentEventType == EventType.MouseUp || drawInfo.CurrentEventType == EventType.ExecuteCommand || drawInfo.CurrentEventType == EventType.DragPerform ) ) + return; + + bool insideBox = m_previewRect.Contains( drawInfo.MousePosition ); + + if( insideBox ) + { + m_isEditingPicker = true; + } + else if( m_isEditingPicker && !insideBox && drawInfo.CurrentEventType != EventType.ExecuteCommand ) + { + GUI.FocusControl( null ); + m_isEditingPicker = false; + } + + if( m_state != ReferenceState.Self && drawInfo.CurrentEventType == EventType.MouseDown && m_previewRect.Contains( drawInfo.MousePosition ) ) + { + UIUtils.FocusOnNode( m_previewTextProp, 1, true ); + Event.current.Use(); + } + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + if( m_drawPreview ) + { + m_iconPos = m_globalPosition; + m_iconPos.width = 19 * drawInfo.InvertedZoom; + m_iconPos.height = 19 * drawInfo.InvertedZoom; + + m_iconPos.y += 10 * drawInfo.InvertedZoom; + m_iconPos.x += m_globalPosition.width - m_iconPos.width - 5 * drawInfo.InvertedZoom; + } + + bool instanced = CheckReference(); + if( instanced ) + { + m_state = ReferenceState.Instance; + m_previewTextProp = m_referenceSampler; + } + else if( m_texPort.IsConnected ) + { + m_state = ReferenceState.Connected; + m_previewTextProp = m_texPort.GetOutputNode( 0 ) as ParentNode; + } + else + { + m_state = ReferenceState.Self; + m_previewTextProp = this; + } + + if( m_previewTextProp == null ) + m_previewTextProp = this; + + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( m_isEditingPicker && m_drawPicker ) + { + Rect hitRect = m_previewRect; + hitRect.height = 14 * drawInfo.InvertedZoom; + hitRect.y = m_previewRect.yMax - hitRect.height; + hitRect.width = 4 * 14 * drawInfo.InvertedZoom; + + bool restoreMouse = false; + if( Event.current.type == EventType.MouseDown && hitRect.Contains( drawInfo.MousePosition ) ) + { + restoreMouse = true; + Event.current.type = EventType.Ignore; + } + + EditorGUI.BeginChangeCheck(); + m_colorBuffer = GUI.color; + GUI.color = Color.clear; + if( m_materialMode ) + m_materialTextureArray = EditorGUIObjectField( m_previewRect, m_materialTextureArray, typeof( Texture2DArray ), false ) as Texture2DArray; + else + m_defaultTextureArray = EditorGUIObjectField( m_previewRect, m_defaultTextureArray, typeof( Texture2DArray ), false ) as Texture2DArray; + GUI.color = m_colorBuffer; + + if( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + CheckTextureImporter( true ); + SetTitleText( PropertyInspectorName ); + SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) ); + ConfigureInputPorts(); + ConfigureOutputPorts(); + BeginDelayedDirtyProperty(); + m_requireMaterialUpdate = true; + } + + if( restoreMouse ) + { + Event.current.type = EventType.MouseDown; + } + + if( ( drawInfo.CurrentEventType == EventType.MouseDown || drawInfo.CurrentEventType == EventType.MouseUp ) ) + DrawPreviewMaskButtonsLayout( drawInfo, m_previewRect ); + } + + if( drawInfo.CurrentEventType != EventType.Repaint ) + return; + + switch( m_state ) + { + default: + case ReferenceState.Self: + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + m_drawPreview = false; + m_drawPicker = true; + + DrawTexturePicker( drawInfo ); + } + break; + case ReferenceState.Connected: + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + m_drawPreview = true; + m_drawPicker = false; + + if( m_previewTextProp != null ) + { + SetTitleTextOnCallback( m_previewTextProp.TitleContent.text, ( instance, newTitle ) => instance.TitleContent.text = newTitle + " (Input)" ); + SetAdditonalTitleText( m_previewTextProp.AdditonalTitleContent.text ); + } + + // Draw chain lock + GUI.Label( m_iconPos, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerTextureIcon ) ); + + // Draw frame around preview + GUI.Label( m_previewRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + } + break; + case ReferenceState.Instance: + { + m_drawPreview = true; + m_drawPicker = false; + + if( m_referenceSampler != null ) + { + SetTitleTextOnCallback( m_referenceSampler.PreviewTextProp.TitleContent.text, ( instance, newTitle ) => instance.TitleContent.text = newTitle + Constants.InstancePostfixStr ); + SetAdditonalTitleText( m_referenceSampler.PreviewTextProp.AdditonalTitleContent.text ); + } + + // Draw chain lock + GUI.Label( m_iconPos, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerTextureIcon ) ); + + // Draw frame around preview + GUI.Label( m_previewRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + } + break; + } + } + + protected void DrawTexturePicker( DrawInfo drawInfo ) + { + Rect newRect = m_previewRect; + Texture2DArray currentValue = m_materialMode ? m_materialTextureArray : m_defaultTextureArray; + + if( currentValue == null ) + GUI.Label( newRect, string.Empty, UIUtils.ObjectFieldThumb ); + else + DrawPreview( drawInfo, m_previewRect ); + + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + { + Rect butRect = m_previewRect; + butRect.y -= 1; + butRect.x += 1; + + Rect smallButton = newRect; + smallButton.height = 14 * drawInfo.InvertedZoom; + smallButton.y = newRect.yMax - smallButton.height - 2; + smallButton.width = 40 * drawInfo.InvertedZoom; + smallButton.x = newRect.xMax - smallButton.width - 2; + if( currentValue == null ) + { + GUI.Label( newRect, m_labelText, UIUtils.ObjectFieldThumbOverlay ); + } + else + { + DrawPreviewMaskButtonsRepaint( drawInfo, butRect ); + } + GUI.Label( smallButton, "Select", UIUtils.GetCustomStyle( CustomStyle.SamplerButton ) ); + } + + GUI.Label( newRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + + OnPropertyNameChanged(); + + if( CheckReference() ) + { + OrderIndex = m_referenceSampler.RawOrderIndex; + OrderIndexOffset = m_referenceSampler.OrderIndexOffset; + } + + bool isVertex = ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ); + + bool instanced = false; + + if( m_referenceType == TexReferenceType.Instance && m_referenceSampler != null ) + instanced = true; + + if( instanced ) + { + if( !m_referenceSampler.TexPort.IsConnected ) + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + else if( !m_texPort.IsConnected ) + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + + string level = string.Empty; + if( m_lodPort.Visible ) + { + level = m_lodPort.GeneratePortInstructions( ref dataCollector ); + } + + if( isVertex && !m_lodPort.Visible ) + level = "0"; + + string propertyName = string.Empty; + if( instanced ) + { + if( m_referenceSampler.TexPort.IsConnected ) + propertyName = m_referenceSampler.TexPort.GeneratePortInstructions( ref dataCollector ); + else + propertyName = m_referenceSampler.PropertyName; + } + else if( m_texPort.IsConnected ) + propertyName = m_texPort.GeneratePortInstructions( ref dataCollector ); + else + propertyName = PropertyName; + + string uvs = string.Empty; + if( m_uvPort.IsConnected ) + { + uvs = m_uvPort.GeneratePortInstructions( ref dataCollector ); + } + else + { + if( dataCollector.IsTemplate ) + { + uvs = dataCollector.TemplateDataCollectorInstance.GetTextureCoord( m_uvSet, propertyName/*( instanced ? m_referenceSampler.PropertyName : PropertyName )*/, UniqueId, CurrentPrecisionType ); + } + else + { + if( isVertex ) + uvs = TexCoordVertexDataNode.GenerateVertexUVs( ref dataCollector, UniqueId, m_uvSet, propertyName ); + else + uvs = TexCoordVertexDataNode.GenerateFragUVs( ref dataCollector, UniqueId, m_uvSet, propertyName ); + } + } + string index = m_indexPort.GeneratePortInstructions( ref dataCollector ); + + string result = string.Empty; + + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + //CAREFUL mipbias here means derivative (this needs index changes) + //TODO: unity now supports bias as well + if( m_mipMode == MipType.MipBias ) + { + GeneratorUtils.AddCustomArraySamplingMacros( ref dataCollector ); + result = propertyName + ".SampleGrad(sampler" + propertyName + ", float3(" + uvs + ", " + index + "), " + m_ddxPort.GeneratePortInstructions( ref dataCollector ) + ", " + m_ddyPort.GeneratePortInstructions( ref dataCollector ) + ");"; + } + else if( m_lodPort.Visible || isVertex ) + { + result = "SAMPLE_TEXTURE2D_ARRAY_LOD(" + propertyName + ", sampler" + propertyName + ", " + uvs + ", " + index + ", " + level + " )"; + } + else + { + result = "SAMPLE_TEXTURE2D_ARRAY(" + propertyName + ", sampler" + propertyName + ", " + uvs + ", " + index + " )"; + } + } + else + { + //CAREFUL mipbias here means derivative (this needs index changes) + if( m_mipMode == MipType.MipBias ) + { + GeneratorUtils.AddCustomArraySamplingMacros( ref dataCollector ); + result = "ASE_SAMPLE_TEX2DARRAY_GRAD(" + propertyName + ", float3(" + uvs + ", " + index + "), " + m_ddxPort.GeneratePortInstructions( ref dataCollector ) + ", " + m_ddyPort.GeneratePortInstructions( ref dataCollector ) + " )"; + } + else if( m_lodPort.Visible || isVertex ) + { + result = "UNITY_SAMPLE_TEX2DARRAY_LOD(" + propertyName + ", float3(" + uvs + ", " + index + "), " + level + " )"; + } + else + { + result = "UNITY_SAMPLE_TEX2DARRAY" + ( m_lodPort.Visible || isVertex ? "_LOD" : "" ) + "(" + propertyName + ", float3(" + uvs + ", " + index + ") " + ( m_lodPort.Visible || isVertex ? ", " + level : "" ) + " )"; + } + } + + if( m_autoUnpackNormals ) + { + bool isScaledNormal = false; + if( m_normalPort.IsConnected ) + { + isScaledNormal = true; + } + else + { + if( m_normalPort.FloatInternalData != 1 ) + { + isScaledNormal = true; + } + } + + string scaleValue = isScaledNormal ? m_normalPort.GeneratePortInstructions( ref dataCollector ) : "1.0"; + result = GeneratorUtils.GenerateUnpackNormalStr( ref dataCollector, CurrentPrecisionType, UniqueId, OutputId, result, isScaledNormal, scaleValue ); + if( isScaledNormal && ( !dataCollector.IsTemplate || !dataCollector.IsSRP ) ) + { + dataCollector.AddToIncludes( UniqueId, Constants.UnityStandardUtilsLibFuncs ); + } + } + + RegisterLocalVariable( 0, result, ref dataCollector, "texArray" + OutputId ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + + public override string PropertyName + { + get + { + if( m_referenceType == TexReferenceType.Instance && m_referenceSampler != null ) + return m_referenceSampler.PropertyName; + else + return base.PropertyName; + } + } + + public override string PropertyInspectorName + { + get + { + if( m_referenceType == TexReferenceType.Instance && m_referenceSampler != null ) + return m_referenceSampler.PropertyInspectorName; + else + return base.PropertyInspectorName; + } + } + + public override string GetPropertyValue() + { + return PropertyAttributes + PropertyName + "(\"" + PropertyInspectorName + "\", 2DArray ) = \"\" {}"; + } + + public override bool GetUniformData( out string dataType, out string dataName, ref bool fullValue ) + { + MasterNode currMasterNode = ( m_containerGraph.CurrentMasterNode != null ) ? m_containerGraph.CurrentMasterNode : m_containerGraph.ParentWindow.OutsideGraph.CurrentMasterNode; + if( currMasterNode != null && currMasterNode.CurrentDataCollector.IsTemplate && currMasterNode.CurrentDataCollector.IsSRP ) + { + dataType = "TEXTURE2D_ARRAY( " + PropertyName + ""; + dataName = ");\nuniform SAMPLER( sampler" + PropertyName + " )"; + return true; + } + dataType = "UNITY_DECLARE_TEX2DARRAY("; + dataName = PropertyName + " )"; + return true; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + string textureName = GetCurrentParam( ref nodeParams ); + m_defaultTextureArray = AssetDatabase.LoadAssetAtPath( textureName ); + m_uvSet = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_referenceType = (TexReferenceType)Enum.Parse( typeof( TexReferenceType ), GetCurrentParam( ref nodeParams ) ); + m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 3202 ) + m_mipMode = (MipType)Enum.Parse( typeof( MipType ), GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 5105 ) + m_autoUnpackNormals = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + + if( m_referenceType == TexReferenceType.Instance ) + { + UIUtils.UnregisterTextureArrayNode( this ); + UIUtils.UnregisterPropertyNode( this ); + } + + ConfigureInputPorts(); + ConfigureOutputPorts(); + + m_lodPort.Visible = ( m_mipMode == MipType.MipLevel ); + m_ddxPort.Visible = ( m_mipMode == MipType.MipBias ); //not really bias, it's derivative + m_ddyPort.Visible = ( m_mipMode == MipType.MipBias ); //not really bias, it's derivative + + UpdateHeaderColor(); + + if( m_defaultTextureArray ) + { + m_materialTextureArray = m_defaultTextureArray; + } + + if( !m_isNodeBeingCopied && m_referenceType == TexReferenceType.Object ) + { + ContainerGraph.TextureArrayNodes.UpdateDataOnNode( UniqueId, DataToArray ); + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + + m_referenceSampler = UIUtils.GetNode( m_referenceNodeId ) as TextureArrayNode; + m_referenceArrayId = UIUtils.GetTextureArrayNodeRegisterId( m_referenceNodeId ); + OnPropertyNameChanged(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_defaultTextureArray != null ) ? AssetDatabase.GetAssetPath( m_defaultTextureArray ) : Constants.NoStringValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_uvSet.ToString() ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_referenceType ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( ( m_referenceSampler != null ) ? m_referenceSampler.UniqueId : -1 ) ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_mipMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_autoUnpackNormals ); + } + + public override void ReadAdditionalClipboardData( ref string[] nodeParams ) + { + base.ReadAdditionalClipboardData( ref nodeParams ); + string textureName = GetCurrentParam( ref nodeParams ); + m_materialTextureArray = AssetDatabase.LoadAssetAtPath( textureName ); + } + + public override void WriteAdditionalClipboardData( ref string nodeInfo ) + { + base.WriteAdditionalClipboardData( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_materialTextureArray != null ) ? AssetDatabase.GetAssetPath( m_materialTextureArray ) : Constants.NoStringValue ); + } + + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction && m_referenceType == TexReferenceType.Object ) + { + OnPropertyNameChanged(); + if( mat.HasProperty( PropertyName ) ) + { + mat.SetTexture( PropertyName, m_materialTextureArray ); + } + } + } + + public override void SetMaterialMode( Material mat, bool fetchMaterialValues ) + { + base.SetMaterialMode( mat, fetchMaterialValues ); + if( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) ) + { + if( mat.HasProperty( PropertyName ) ) + { + m_materialTextureArray = (Texture2DArray)mat.GetTexture( PropertyName ); + if( m_materialTextureArray == null ) + m_materialTextureArray = m_defaultTextureArray; + } + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( PropertyName ) ) + { + m_materialTextureArray = (Texture2DArray)material.GetTexture( PropertyName ); + if( m_materialTextureArray == null ) + m_materialTextureArray = m_defaultTextureArray; + + PreviewIsDirty = true; + } + } + + public override bool UpdateShaderDefaults( ref Shader shader, ref TextureDefaultsDataColector defaultCol ) + { + if( m_defaultTextureArray != null ) + { + defaultCol.AddValue( PropertyName, m_defaultTextureArray ); + } + + return true; + } + + public override string GetPropertyValStr() + { + return m_materialMode ? ( m_materialTextureArray != null ? m_materialTextureArray.name : IOUtils.NO_TEXTURES ) : ( m_defaultTextureArray != null ? m_defaultTextureArray.name : IOUtils.NO_TEXTURES ); + } + + public bool CheckReference() + { + if( m_referenceType == TexReferenceType.Instance && m_referenceArrayId > -1 ) + { + m_referenceSampler = UIUtils.GetTextureArrayNode( m_referenceArrayId ); + + if( m_referenceSampler == null ) + { + m_texPort.Locked = false; + m_referenceArrayId = -1; + } + else + m_texPort.Locked = true; + } + else + { + m_texPort.Locked = false; + } + + return m_referenceSampler != null; + } + + public override void SetupFromCastObject( UnityEngine.Object obj ) + { + base.SetupFromCastObject( obj ); + SetupFromObject( obj ); + } + + public override void OnObjectDropped( UnityEngine.Object obj ) + { + SetupFromObject( obj ); + } + + private void SetupFromObject( UnityEngine.Object obj ) + { + if( m_materialMode ) + m_materialTextureArray = obj as Texture2DArray; + else + m_defaultTextureArray = obj as Texture2DArray; + } + + public Texture2DArray TextureArray { get { return ( m_materialMode ? m_materialTextureArray : m_defaultTextureArray ); } } + + public bool IsLinearTexture { get { return m_linearTexture; } } + + public bool AutoUnpackNormals + { + get { return m_autoUnpackNormals; } + set { m_autoUnpackNormals = value; } + } + + public override string DataToArray { get { return PropertyInspectorName; } } + + public override void Destroy() + { + base.Destroy(); + m_defaultTextureArray = null; + m_materialTextureArray = null; + + m_texPort = null; + m_uvPort = null; + m_indexPort = null; + m_lodPort = null; + m_normalPort = null; + m_ddxPort = null; + m_ddyPort = null; + + if( m_referenceType == TexReferenceType.Object ) + { + UIUtils.UnregisterTextureArrayNode( this ); + UIUtils.UnregisterPropertyNode( this ); + } + + if( UniqueId > -1 ) + ContainerGraph.TextureArrayNodes.OnReorderEventComplete -= OnReorderEventComplete; + } + + public ParentNode PreviewTextProp { get { return m_previewTextProp; } } + public InputPort TexPort { get { return m_texPort; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TextureArrayNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TextureArrayNode.cs.meta new file mode 100644 index 0000000..54332f0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/TextureArrayNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3c5be6f9c03445d4fb70955f594877dc +timeCreated: 1485801067 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector2Node.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector2Node.cs new file mode 100644 index 0000000..306816b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector2Node.cs @@ -0,0 +1,301 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Vector2", "Constants And Properties", "Vector2 property", null, KeyCode.Alpha2 )] + public sealed class Vector2Node : PropertyNode + { + [SerializeField] + private Vector2 m_defaultValue = Vector2.zero; + + [SerializeField] + private Vector2 m_materialValue = Vector2.zero; + + private const float LabelWidth = 8; + + private int m_cachedPropertyId = -1; + + private bool m_isEditingFields; + private Vector2 m_previousValue = Vector2.zero; + private string[] m_fieldText = new string[] { "0", "0" }; + + public Vector2Node() : base() { } + public Vector2Node( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + GlobalTypeWarningText = string.Format( GlobalTypeWarningText, "Vector" ); + m_insideSize.Set(50,20); + m_selectedLocation = PreviewLocation.BottomCenter; + AddOutputVectorPorts( WirePortDataType.FLOAT2, "XY" ); + m_availableAttribs.Add( new PropertyAttributes( "Remap Sliders", "[RemapSliders]" ) ); + m_previewShaderGUID = "88b4191eb06084d4da85d1dd2f984085"; + m_srpBatcherCompatible = true; + m_showHybridInstancedUI = true; + } + + public override void CopyDefaultsToMaterial() + { + m_materialValue = m_defaultValue; + } + + public override void DrawSubProperties() + { + m_defaultValue = EditorGUILayoutVector2Field( Constants.DefaultValueLabel, m_defaultValue ); + } + + public override void DrawMaterialProperties() + { + if ( m_materialMode ) + EditorGUI.BeginChangeCheck(); + + m_materialValue = EditorGUILayoutVector2Field( Constants.MaterialValueLabel, m_materialValue ); + if ( m_materialMode && EditorGUI.EndChangeCheck() ) + m_requireMaterialUpdate = true; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if ( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_InputVector" ); + + if ( m_materialMode && m_currentParameterType != PropertyType.Constant ) + PreviewMaterial.SetVector( m_cachedPropertyId, new Vector4( m_materialValue[ 0 ], m_materialValue[ 1 ], 0, 0 ) ); + else + PreviewMaterial.SetVector( m_cachedPropertyId, new Vector4( m_defaultValue[ 0 ], m_defaultValue[ 1 ], 0, 0 ) ); + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_propertyDrawPos = m_remainingBox; + m_propertyDrawPos.x = m_remainingBox.x - LabelWidth * drawInfo.InvertedZoom; + m_propertyDrawPos.width = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_WIDTH_FIELD_SIZE; + m_propertyDrawPos.height = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if ( drawInfo.CurrentEventType != EventType.MouseDown ) + return; + + Rect hitBox = m_remainingBox; + hitBox.xMin -= LabelWidth * drawInfo.InvertedZoom; + bool insideBox = hitBox.Contains( drawInfo.MousePosition ); + + if ( insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = true; + } + else if ( m_isEditingFields && !insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = false; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if ( !m_isVisible ) + return; + + if ( m_isEditingFields && m_currentParameterType != PropertyType.Global) + { + EditorGUI.BeginChangeCheck(); + for ( int i = 0; i < 2; i++ ) + { + m_propertyDrawPos.y = m_outputPorts[ i + 1 ].Position.y - 2 * drawInfo.InvertedZoom; + if ( m_materialMode && m_currentParameterType != PropertyType.Constant ) + { + float val = m_materialValue[ i ]; + UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref val, LabelWidth * drawInfo.InvertedZoom ); + m_materialValue[ i ] = val; + } + else + { + float val = m_defaultValue[ i ]; + UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref val, LabelWidth * drawInfo.InvertedZoom ); + m_defaultValue[ i ] = val; + } + } + if ( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + m_requireMaterialUpdate = m_materialMode; + BeginDelayedDirtyProperty(); + } + } + else if ( drawInfo.CurrentEventType == EventType.Repaint && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + { + bool guiEnabled = GUI.enabled; + GUI.enabled = m_currentParameterType != PropertyType.Global; + for ( int i = 0; i < 2; i++ ) + { + m_propertyDrawPos.y = m_outputPorts[ i + 1 ].Position.y - 2 * drawInfo.InvertedZoom; + + Rect fakeField = m_propertyDrawPos; + fakeField.xMin += LabelWidth * drawInfo.InvertedZoom; + if( GUI.enabled ) + { + Rect fakeLabel = m_propertyDrawPos; + fakeLabel.xMax = fakeField.xMin; + EditorGUIUtility.AddCursorRect( fakeLabel, MouseCursor.SlideArrow ); + EditorGUIUtility.AddCursorRect( fakeField, MouseCursor.Text ); + } + if ( m_materialMode && m_currentParameterType != PropertyType.Constant ) + { + if ( m_previousValue[ i ] != m_materialValue[ i ] ) + { + m_previousValue[ i ] = m_materialValue[ i ]; + m_fieldText[ i ] = m_materialValue[ i ].ToString(); + } + } + else + { + if ( m_previousValue[ i ] != m_defaultValue[ i ] ) + { + m_previousValue[ i ] = m_defaultValue[ i ]; + m_fieldText[ i ] = m_defaultValue[ i ].ToString(); + } + } + + GUI.Label( fakeField, m_fieldText[ i ], UIUtils.MainSkin.textField ); + } + GUI.enabled = guiEnabled; + } + } + + public override void ConfigureLocalVariable( ref MasterNodeDataCollector dataCollector ) + { + Vector2 value = m_defaultValue; + dataCollector.AddLocalVariable( UniqueId, CreateLocalVarDec( value.x + "," + value.y ) ); + m_outputPorts[ 0 ].SetLocalValue( m_propertyName, dataCollector.PortCategory ); + m_outputPorts[ 1 ].SetLocalValue( m_propertyName + ".x" , dataCollector.PortCategory); + m_outputPorts[ 2 ].SetLocalValue( m_propertyName + ".y", dataCollector.PortCategory ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId,ref dataCollector, ignoreLocalvar ); + m_precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ); + + if ( m_currentParameterType != PropertyType.Constant ) + return GetOutputVectorItem( 0, outputId, PropertyData( dataCollector.PortCategory ) ); + + if ( m_outputPorts[ outputId ].IsLocalValue( dataCollector.PortCategory ) ) + { + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + if ( CheckLocalVariable( ref dataCollector ) ) + { + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + Vector2 value = m_defaultValue; + string result = string.Empty; + switch ( outputId ) + { + case 0: + { + result = m_precisionString+"( " + value.x + "," + value.y + " )"; + } + break; + + case 1: + { + result = value.x.ToString(); + } + break; + case 2: + { + result = value.y.ToString(); + } + break; + } + + if ( result.Equals( string.Empty ) ) + { + UIUtils.ShowMessage( UniqueId, "Vector2Node generating empty code", MessageSeverity.Warning ); + } + return result; + } + + public override string GetPropertyValue() + { + return PropertyAttributes + m_propertyName + "(\"" + m_propertyInspectorName + "\", Vector) = (" + m_defaultValue.x + "," + m_defaultValue.y + ",0,0)"; + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if ( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction ) + { + mat.SetVector( m_propertyName, m_materialValue ); + } + } + + public override void SetMaterialMode( Material mat , bool fetchMaterialValues ) + { + base.SetMaterialMode( mat , fetchMaterialValues ); + if ( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) && mat.HasProperty( m_propertyName ) ) + { + m_materialValue = mat.GetVector( m_propertyName ); + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( m_propertyName ) ) + { + m_materialValue = material.GetVector( m_propertyName ); + PreviewIsDirty = true; + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_defaultValue = IOUtils.StringToVector2( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 14101 ) + m_materialValue = IOUtils.StringToVector2( GetCurrentParam( ref nodeParams ) ); + } + + public override void SetGlobalValue() { Shader.SetGlobalVector( m_propertyName, m_defaultValue ); } + public override void FetchGlobalValue() { m_materialValue = Shader.GetGlobalVector( m_propertyName ); } + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Vector2ToString( m_defaultValue ) ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Vector2ToString( m_materialValue ) ); + } + + public override string GetPropertyValStr() + { + return ( m_materialMode && m_currentParameterType != PropertyType.Constant ) ? m_materialValue.x.ToString( Mathf.Abs( m_materialValue.x ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_materialValue.y.ToString( Mathf.Abs( m_materialValue.y ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) : + m_defaultValue.x.ToString( Mathf.Abs( m_defaultValue.x ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_defaultValue.y.ToString( Mathf.Abs( m_defaultValue.y ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ); + } + + public Vector2 Value + { + get { return m_defaultValue; } + set { m_defaultValue = value; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector2Node.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector2Node.cs.meta new file mode 100644 index 0000000..a241974 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector2Node.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6ca8f5d67cf4c5f428a6dd646099897c +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector3Node.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector3Node.cs new file mode 100644 index 0000000..62be069 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector3Node.cs @@ -0,0 +1,315 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Vector3", "Constants And Properties", "Vector3 property", null, KeyCode.Alpha3 )] + public sealed class Vector3Node : PropertyNode + { + [SerializeField] + private Vector3 m_defaultValue = Vector3.zero; + + [SerializeField] + private Vector3 m_materialValue = Vector3.zero; + + private const float LabelWidth = 8; + + private int m_cachedPropertyId = -1; + + public Vector3Node() : base() { } + public Vector3Node( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + GlobalTypeWarningText = string.Format( GlobalTypeWarningText, "Vector" ); + m_insideSize.Set( 50, 30 ); + m_selectedLocation = PreviewLocation.BottomCenter; + AddOutputVectorPorts( WirePortDataType.FLOAT3, "XYZ" ); + m_previewShaderGUID = "8a44d38f06246bf48944b3f314bc7920"; + m_srpBatcherCompatible = true; + m_showHybridInstancedUI = true; + } + + public override void CopyDefaultsToMaterial() + { + m_materialValue = m_defaultValue; + } + + public override void DrawSubProperties() + { + m_defaultValue = EditorGUILayoutVector3Field( Constants.DefaultValueLabel, m_defaultValue ); + } + + public override void DrawMaterialProperties() + { + EditorGUI.BeginChangeCheck(); + + m_materialValue = EditorGUILayoutVector3Field( Constants.MaterialValueLabel, m_materialValue ); + + if( EditorGUI.EndChangeCheck() ) + { + //MarkForPreviewUpdate(); + if( m_materialMode ) + m_requireMaterialUpdate = true; + } + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_InputVector" ); + + if( m_materialMode && m_currentParameterType != PropertyType.Constant ) + PreviewMaterial.SetVector( m_cachedPropertyId, new Vector4( m_materialValue[ 0 ], m_materialValue[ 1 ], m_materialValue[ 2 ], 0 ) ); + else + PreviewMaterial.SetVector( m_cachedPropertyId, new Vector4( m_defaultValue[ 0 ], m_defaultValue[ 1 ], m_defaultValue[ 2 ], 0 ) ); + } + + private bool m_isEditingFields; + private Vector3 m_previousValue = Vector3.zero; + private string[] m_fieldText = new string[] { "0", "0", "0" }; + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( !m_isVisible ) + return; + + if( m_isEditingFields && m_currentParameterType != PropertyType.Global) + { + EditorGUI.BeginChangeCheck(); + for( int i = 0; i < 3; i++ ) + { + m_propertyDrawPos.y = m_outputPorts[ i + 1 ].Position.y - 2 * drawInfo.InvertedZoom; + if( m_materialMode && m_currentParameterType != PropertyType.Constant ) + { + float val = m_materialValue[ i ]; + UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref val, LabelWidth * drawInfo.InvertedZoom ); + m_materialValue[ i ] = val; + } + else + { + float val = m_defaultValue[ i ]; + UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref val, LabelWidth * drawInfo.InvertedZoom ); + m_defaultValue[ i ] = val; + } + } + if( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + m_requireMaterialUpdate = m_materialMode; + BeginDelayedDirtyProperty(); + } + } + else if( drawInfo.CurrentEventType == EventType.Repaint && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + { + bool guiEnabled = GUI.enabled; + GUI.enabled = m_currentParameterType != PropertyType.Global; + + for( int i = 0; i < 3; i++ ) + { + m_propertyDrawPos.y = m_outputPorts[ i + 1 ].Position.y - 2 * drawInfo.InvertedZoom; + + Rect fakeField = m_propertyDrawPos; + fakeField.xMin += LabelWidth * drawInfo.InvertedZoom; + if( GUI.enabled ) + { + Rect fakeLabel = m_propertyDrawPos; + fakeLabel.xMax = fakeField.xMin; + EditorGUIUtility.AddCursorRect( fakeLabel, MouseCursor.SlideArrow ); + EditorGUIUtility.AddCursorRect( fakeField, MouseCursor.Text ); + } + + if( m_materialMode && m_currentParameterType != PropertyType.Constant ) + { + if( m_previousValue[ i ] != m_materialValue[ i ] ) + { + m_previousValue[ i ] = m_materialValue[ i ]; + m_fieldText[ i ] = m_materialValue[ i ].ToString(); + } + } + else + { + if( m_previousValue[ i ] != m_defaultValue[ i ] ) + { + m_previousValue[ i ] = m_defaultValue[ i ]; + m_fieldText[ i ] = m_defaultValue[ i ].ToString(); + } + } + + GUI.Label( fakeField, m_fieldText[ i ], UIUtils.MainSkin.textField ); + } + GUI.enabled = guiEnabled; + } + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_propertyDrawPos = m_remainingBox; + m_propertyDrawPos.x = m_remainingBox.x - LabelWidth * drawInfo.InvertedZoom; + m_propertyDrawPos.width = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_WIDTH_FIELD_SIZE; + m_propertyDrawPos.height = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if( drawInfo.CurrentEventType != EventType.MouseDown ) + return; + + Rect hitBox = m_remainingBox; + hitBox.xMin -= LabelWidth * drawInfo.InvertedZoom; + bool insideBox = hitBox.Contains( drawInfo.MousePosition ); + + if( insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = true; + } + else if( m_isEditingFields && !insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = false; + } + } + + public override void ConfigureLocalVariable( ref MasterNodeDataCollector dataCollector ) + { + Vector3 value = m_defaultValue; + dataCollector.AddLocalVariable( UniqueId, CreateLocalVarDec( value.x + "," + value.y + "," + value.z ) ); + m_outputPorts[ 0 ].SetLocalValue( m_propertyName , dataCollector.PortCategory ); + m_outputPorts[ 1 ].SetLocalValue( m_propertyName + ".x" , dataCollector.PortCategory ); + m_outputPorts[ 2 ].SetLocalValue( m_propertyName + ".y" , dataCollector.PortCategory ); + m_outputPorts[ 3 ].SetLocalValue( m_propertyName + ".z", dataCollector.PortCategory ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + m_precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ); + + if( m_currentParameterType != PropertyType.Constant ) + return GetOutputVectorItem( 0, outputId, PropertyData( dataCollector.PortCategory ) ); + + if( m_outputPorts[ outputId ].IsLocalValue( dataCollector.PortCategory ) ) + { + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + if( CheckLocalVariable( ref dataCollector ) ) + { + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + Vector3 value = m_defaultValue; + string result = string.Empty; + switch( outputId ) + { + case 0: + { + result = m_precisionString + "(" + value.x + "," + value.y + "," + value.z + ")"; + } + break; + + case 1: + { + result = value.x.ToString(); + } + break; + case 2: + { + result = value.y.ToString(); + } + break; + case 3: + { + result = value.z.ToString(); + } + break; + } + + if( result.Equals( string.Empty ) ) + { + UIUtils.ShowMessage( UniqueId, "Vector3Node generating empty code", MessageSeverity.Warning ); + } + return result; + } + + public override string GetPropertyValue() + { + return PropertyAttributes + m_propertyName + "(\"" + m_propertyInspectorName + "\", Vector) = (" + m_defaultValue.x + "," + m_defaultValue.y + "," + m_defaultValue.z + ",0)"; + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction ) + { + mat.SetVector( m_propertyName, m_materialValue ); + } + } + + public override void SetMaterialMode( Material mat, bool fetchMaterialValues ) + { + base.SetMaterialMode( mat, fetchMaterialValues ); + if( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) && mat.HasProperty( m_propertyName ) ) + { + m_materialValue = mat.GetVector( m_propertyName ); + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( m_propertyName ) ) + { + m_materialValue = material.GetVector( m_propertyName ); + PreviewIsDirty = true; + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_defaultValue = IOUtils.StringToVector3( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 14101 ) + m_materialValue = IOUtils.StringToVector3( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Vector3ToString( m_defaultValue ) ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Vector3ToString( m_materialValue ) ); + } + + public override void SetGlobalValue() { Shader.SetGlobalVector( m_propertyName, m_defaultValue ); } + public override void FetchGlobalValue() { m_materialValue = Shader.GetGlobalVector( m_propertyName ); } + + public override string GetPropertyValStr() + { + return ( m_materialMode && m_currentParameterType != PropertyType.Constant ) ? m_materialValue.x.ToString( Mathf.Abs( m_materialValue.x ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_materialValue.y.ToString( Mathf.Abs( m_materialValue.y ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_materialValue.z.ToString( Mathf.Abs( m_materialValue.z ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) : + m_defaultValue.x.ToString( Mathf.Abs( m_defaultValue.x ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_defaultValue.y.ToString( Mathf.Abs( m_defaultValue.y ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_defaultValue.z.ToString( Mathf.Abs( m_defaultValue.z ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ); + } + + public Vector3 Value + { + get { return m_defaultValue; } + set { m_defaultValue = value; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector3Node.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector3Node.cs.meta new file mode 100644 index 0000000..467beba --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector3Node.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 943f4b4fc1fa5214b8934bf4fb76474b +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector4Node.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector4Node.cs new file mode 100644 index 0000000..447222f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector4Node.cs @@ -0,0 +1,321 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Vector4", "Constants And Properties", "Vector4 property", null, KeyCode.Alpha4 )] + public sealed class Vector4Node : PropertyNode + { + [SerializeField] + private Vector4 m_defaultValue = Vector4.zero; + + [SerializeField] + private Vector4 m_materialValue = Vector4.zero; + + private const float LabelWidth = 8; + + private int m_cachedPropertyId = -1; + + private bool m_isEditingFields; + private Vector4 m_previousValue = Vector4.zero; + private string[] m_fieldText = new string[] { "0", "0", "0", "0" }; + + public Vector4Node() : base() { } + public Vector4Node( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + GlobalTypeWarningText = string.Format( GlobalTypeWarningText, "Vector" ); + m_insideSize.Set( 50, 40 ); + m_selectedLocation = PreviewLocation.BottomCenter; + AddOutputVectorPorts( WirePortDataType.FLOAT4, "XYZW" ); + m_previewShaderGUID = "aac241d0e47a5a84fbd2edcd640788dc"; + m_availableAttribs.Add( new PropertyAttributes( "Remap Sliders", "[RemapSlidersFull]" ) ); + m_srpBatcherCompatible = true; + m_showHybridInstancedUI = true; + } + + public override void CopyDefaultsToMaterial() + { + m_materialValue = m_defaultValue; + } + + public override void DrawSubProperties() + { + m_defaultValue = EditorGUILayoutVector4Field( Constants.DefaultValueLabel, m_defaultValue ); + } + + public override void DrawMaterialProperties() + { + if ( m_materialMode ) + EditorGUI.BeginChangeCheck(); + + m_materialValue = EditorGUILayoutVector4Field( Constants.MaterialValueLabel, m_materialValue ); + if ( m_materialMode && EditorGUI.EndChangeCheck() ) + m_requireMaterialUpdate = true; + + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if ( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_InputVector" ); + + if ( m_materialMode && m_currentParameterType != PropertyType.Constant ) + PreviewMaterial.SetVector( m_cachedPropertyId, new Vector4( m_materialValue[ 0 ], m_materialValue[ 1 ], m_materialValue[ 2 ], m_materialValue[ 3 ] ) ); + else + PreviewMaterial.SetVector( m_cachedPropertyId, new Vector4( m_defaultValue[ 0 ], m_defaultValue[ 1 ], m_defaultValue[ 2 ], m_defaultValue[ 3 ] ) ); + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_propertyDrawPos = m_remainingBox; + m_propertyDrawPos.x = m_remainingBox.x - LabelWidth * drawInfo.InvertedZoom; + m_propertyDrawPos.width = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_WIDTH_FIELD_SIZE; + m_propertyDrawPos.height = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if ( drawInfo.CurrentEventType != EventType.MouseDown ) + return; + + Rect hitBox = m_remainingBox; + hitBox.xMin -= LabelWidth * drawInfo.InvertedZoom; + bool insideBox = hitBox.Contains( drawInfo.MousePosition ); + + if ( insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = true; + } + else if ( m_isEditingFields && !insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = false; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if ( !m_isVisible ) + return; + + if ( m_isEditingFields && m_currentParameterType != PropertyType.Global ) + { + EditorGUI.BeginChangeCheck(); + for ( int i = 0; i < 4; i++ ) + { + m_propertyDrawPos.y = m_outputPorts[ i + 1 ].Position.y - 2 * drawInfo.InvertedZoom; + if ( m_materialMode && m_currentParameterType != PropertyType.Constant ) + { + float val = m_materialValue[ i ]; + UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref val, LabelWidth * drawInfo.InvertedZoom ); + m_materialValue[ i ] = val; + } + else + { + float val = m_defaultValue[ i ]; + UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref val, LabelWidth * drawInfo.InvertedZoom ); + m_defaultValue[ i ] = val; + } + } + if ( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + m_requireMaterialUpdate = m_materialMode; + BeginDelayedDirtyProperty(); + //m_propertyNameIsDirty = true; + } + } + else if ( drawInfo.CurrentEventType == EventType.Repaint && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + { + bool guiEnabled = GUI.enabled; + GUI.enabled = m_currentParameterType != PropertyType.Global; + + for( int i = 0; i < 4; i++ ) + { + m_propertyDrawPos.y = m_outputPorts[ i + 1 ].Position.y - 2 * drawInfo.InvertedZoom; + + Rect fakeField = m_propertyDrawPos; + fakeField.xMin += LabelWidth * drawInfo.InvertedZoom; + if( GUI.enabled ) + { + Rect fakeLabel = m_propertyDrawPos; + fakeLabel.xMax = fakeField.xMin; + EditorGUIUtility.AddCursorRect( fakeLabel, MouseCursor.SlideArrow ); + EditorGUIUtility.AddCursorRect( fakeField, MouseCursor.Text ); + } + if ( m_materialMode && m_currentParameterType != PropertyType.Constant ) + { + if ( m_previousValue[ i ] != m_materialValue[ i ] ) + { + m_previousValue[ i ] = m_materialValue[ i ]; + m_fieldText[ i ] = m_materialValue[ i ].ToString(); + } + } + else + { + if ( m_previousValue[ i ] != m_defaultValue[ i ] ) + { + m_previousValue[ i ] = m_defaultValue[ i ]; + m_fieldText[ i ] = m_defaultValue[ i ].ToString(); + } + } + + GUI.Label( fakeField, m_fieldText[ i ], UIUtils.MainSkin.textField ); + } + GUI.enabled = guiEnabled; + } + } + + public override void ConfigureLocalVariable( ref MasterNodeDataCollector dataCollector ) + { + Vector4 value = m_defaultValue; + dataCollector.AddLocalVariable( UniqueId, CreateLocalVarDec( value.x + "," + value.y + "," + value.z + "," + value.w ) ); + m_outputPorts[ 0 ].SetLocalValue( m_propertyName, dataCollector.PortCategory ); + m_outputPorts[ 1 ].SetLocalValue( m_propertyName + ".x" , dataCollector.PortCategory ); + m_outputPorts[ 2 ].SetLocalValue( m_propertyName + ".y" , dataCollector.PortCategory ); + m_outputPorts[ 3 ].SetLocalValue( m_propertyName + ".z" , dataCollector.PortCategory ); + m_outputPorts[ 4 ].SetLocalValue( m_propertyName + ".w", dataCollector.PortCategory ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + m_precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ); + + if ( m_currentParameterType != PropertyType.Constant ) + return GetOutputVectorItem( 0, outputId, PropertyData( dataCollector.PortCategory ) ); + + if ( m_outputPorts[ outputId ].IsLocalValue( dataCollector.PortCategory ) ) + { + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + if ( CheckLocalVariable( ref dataCollector ) ) + { + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + Vector4 value = m_defaultValue; + string result = string.Empty; + switch ( outputId ) + { + case 0: + { + result = m_precisionString+"(" + value.x + "," + value.y + "," + value.z + "," + value.w + ")"; + } + break; + + case 1: + { + result = value.x.ToString(); + } + break; + case 2: + { + result = value.y.ToString(); + } + break; + case 3: + { + result = value.z.ToString(); + } + break; + case 4: + { + result = value.w.ToString(); + } + break; + } + + if ( result.Equals( string.Empty ) ) + { + UIUtils.ShowMessage( UniqueId, "Vector4Node generating empty code", MessageSeverity.Warning ); + } + return result; + } + + public override string GetPropertyValue() + { + return PropertyAttributes + m_propertyName + "(\"" + m_propertyInspectorName + "\", Vector) = (" + m_defaultValue.x + "," + m_defaultValue.y + "," + m_defaultValue.z + "," + m_defaultValue.w + ")"; + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if ( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction ) + { + mat.SetVector( m_propertyName, m_materialValue ); + } + } + + public override void SetMaterialMode( Material mat , bool fetchMaterialValues ) + { + base.SetMaterialMode( mat , fetchMaterialValues ); + if ( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) && mat.HasProperty( m_propertyName ) ) + { + m_materialValue = mat.GetVector( m_propertyName ); + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( m_propertyName ) ) + { + m_materialValue = material.GetVector( m_propertyName ); + PreviewIsDirty = true; + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_defaultValue = IOUtils.StringToVector4( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 14101 ) + m_materialValue = IOUtils.StringToVector4( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Vector4ToString( m_defaultValue ) ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Vector4ToString( m_materialValue ) ); + } + + public override void SetGlobalValue() { Shader.SetGlobalVector( m_propertyName, m_defaultValue ); } + public override void FetchGlobalValue() { m_materialValue = Shader.GetGlobalVector( m_propertyName ); } + + public override string GetPropertyValStr() + { + return ( m_materialMode && m_currentParameterType != PropertyType.Constant ) ? m_materialValue.x.ToString( Mathf.Abs( m_materialValue.x ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_materialValue.y.ToString( Mathf.Abs( m_materialValue.y ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_materialValue.z.ToString( Mathf.Abs( m_materialValue.z ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_materialValue.w.ToString( Mathf.Abs( m_materialValue.w ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) : + m_defaultValue.x.ToString( Mathf.Abs( m_defaultValue.x ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_defaultValue.y.ToString( Mathf.Abs( m_defaultValue.y ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_defaultValue.z.ToString( Mathf.Abs( m_defaultValue.z ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ) + IOUtils.VECTOR_SEPARATOR + + m_defaultValue.w.ToString( Mathf.Abs( m_defaultValue.w ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ); + } + + public Vector4 Value + { + get { return m_defaultValue; } + set { m_defaultValue = value; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector4Node.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector4Node.cs.meta new file mode 100644 index 0000000..1cccc21 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Constants/Vector4Node.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3bc3c79c7cc57df49bedb9d9b64b0bea +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomAddNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomAddNode.cs new file mode 100644 index 0000000..c057097 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomAddNode.cs @@ -0,0 +1,19 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Custom Add Node", "Debug", "Custom Node Debug ( Only for debug purposes)", null, UnityEngine.KeyCode.None, false )] + public sealed class CustomAddNode : CustomNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputsFromString( "customOut0", "#IP2*(#IP0 + #IP1 / #IP2)" ); + AddOutputsFromString( "customOut1", "#IP3 + #IP0*#IP2 + #IP1 / #IP2" ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomAddNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomAddNode.cs.meta new file mode 100644 index 0000000..771b8a6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomAddNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6fdecc48f5be618428240490565e9d8b +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomNode.cs new file mode 100644 index 0000000..bffd2b4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomNode.cs @@ -0,0 +1,183 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class CustomNodeOutputData + { + public string expression; + public string name; + public List inputData; + + public CustomNodeOutputData( string newName, string newExpression ) + { + name = newName; + expression = newExpression; + inputData = new List(); + } + public void Destroy() + { + inputData.Clear(); + inputData = null; + } + + public override string ToString() + { + string result = "name: " + name + " outputExpression: " + expression + '\n'; + for ( int i = 0; i < inputData.Count; i++ ) + { + result += inputData[ i ].ToString() + '\n'; + } + return result; + } + } + + [Serializable] + public class CustomNodeInputData + { + public int index; + public int length; + public string name; + public CustomNodeInputData( int newIndex, int newLength, string newName ) + { + index = newIndex; + length = newLength; + name = newName; + + } + + public override string ToString() + { + return "index: " + index + " length: " + length + " name: " + name; + } + } + + [Serializable] + public class CustomNode : ParentNode + { + [SerializeField] + private List m_includes; + + [SerializeField] + private List m_outputData; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_outputData = new List(); + } + + public void AddIncludes( string newInclude ) + { + m_includes.Add( newInclude ); + } + + protected void AddOutputsFromString( string outputName, string output ) + { + AddOutputPort( WirePortDataType.OBJECT, outputName ); + + CustomNodeOutputData currOutputData = new CustomNodeOutputData( outputName, output ); + + + // Get existing input nodes so we can test for duplicates + Dictionary existingPorts = InputPortsDict; + + // Create dictionary to prevent duplicates when dealing with expresssions with multiple occurences of an input + Dictionary inputDuplicatePrevention = new Dictionary(); + + + // Get all inputs on the expression and save their info + int[] indexes = output.AllIndexesOf( Constants.CNIP ); + for ( int i = 0; i < indexes.Length; i++ ) + { + string name = output.Substring( indexes[ i ], Constants.CNIP.Length + 1 ); + currOutputData.inputData.Add( new CustomNodeInputData( indexes[ i ], Constants.CNIP.Length + 1, name ) ); + + if ( !inputDuplicatePrevention.ContainsKey( name ) && !existingPorts.ContainsKey( name ) ) + { + inputDuplicatePrevention.Add( name, name ); + AddInputPort( WirePortDataType.OBJECT, false, name ); + } + } + + inputDuplicatePrevention.Clear(); + inputDuplicatePrevention = null; + + existingPorts.Clear(); + existingPorts = null; + + m_outputData.Add( currOutputData ); + + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + if ( outputId < m_outputData.Count ) + { + Dictionary inputs = InputPortsDict; + + string value = m_outputData[ outputId ].expression; + for ( int i = 0; i < m_outputData[ outputId ].inputData.Count; i++ ) + { + if ( inputs.ContainsKey( m_outputData[ outputId ].inputData[ i ].name ) ) + { + InputPort inputPort = inputs[ m_outputData[ outputId ].inputData[ i ].name ]; + if ( inputPort != null ) + { + string inputValue = inputPort.GenerateShaderForOutput( ref dataCollector, WirePortDataType.OBJECT, ignoreLocalvar ); + value = value.Replace( m_outputData[ outputId ].inputData[ i ].name, inputValue ); + } + else + { + UIUtils.ShowMessage( UniqueId, m_outputData[ outputId ].inputData[ i ].name + " invalid on the inputs list", MessageSeverity.Error ); + return string.Empty; + } + } + else + { + UIUtils.ShowMessage( UniqueId, m_outputData[ outputId ].inputData[ i ].name + " Not found on the inputs list", MessageSeverity.Error ); + return string.Empty; + } + } + return value; + + } + + return string.Empty; + } + public void DumpOutputData() + { + for ( int i = 0; i < m_outputData.Count; i++ ) + { + Debug.Log( m_outputData[ i ] ); + } + } + + public override void Destroy() + { + base.Destroy(); + + if ( m_outputData != null ) + { + for ( int i = 0; i < m_outputData.Count; i++ ) + { + m_outputData[ i ].Destroy(); + } + m_outputData.Clear(); + m_outputData = null; + } + if ( m_includes != null ) + { + m_includes.Clear(); + m_includes = null; + } + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomNode.cs.meta new file mode 100644 index 0000000..d5cd5ec --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/CustomNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c89fd369755de3e49a669e8e5daa8c2f +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DrawInfo.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DrawInfo.cs new file mode 100644 index 0000000..6a42344 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DrawInfo.cs @@ -0,0 +1,19 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +namespace AmplifyShaderEditor +{ + public class DrawInfo + { + public Rect TransformedCameraArea; + public Rect CameraArea; + public Vector2 MousePosition; + public Vector2 CameraOffset; + public float InvertedZoom; + public bool LeftMouseButtonPressed; + public EventType CurrentEventType; + public Vector2 TransformedMousePos; + public bool ZoomChanged; + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DrawInfo.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DrawInfo.cs.meta new file mode 100644 index 0000000..8783ef2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DrawInfo.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 36f40ed0b172d8f45810b3f6b8e2243d +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DynamicTypeNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DynamicTypeNode.cs new file mode 100644 index 0000000..2649803 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DynamicTypeNode.cs @@ -0,0 +1,521 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class DynamicTypeNode : ParentNode + { + protected string m_inputA = string.Empty; + protected string m_inputB = string.Empty; + protected List m_extensibleInputResults; + protected bool m_dynamicOutputType = true; + + protected bool m_extensibleInputPorts = false; + protected bool m_allowMatrixCheck = false; + protected bool m_vectorMatrixOps = false; + //[SerializeField] + private int m_inputCount = 2; + + //[SerializeField] + private int m_lastInputCount = 2; + + private bool m_previouslyDragging = false; + private int m_beforePreviewCount = 0; + + [UnityEngine.SerializeField] + protected WirePortDataType m_mainDataType = WirePortDataType.FLOAT; + + protected WirePortDataType[] m_dynamicRestrictions = + { + WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT, + WirePortDataType.UINT + }; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_useInternalPortData = true; + m_textLabelWidth = 35; + AddPorts(); + } + + protected virtual void AddPorts() + { + AddInputPort( WirePortDataType.FLOAT, false, "A" ); + AddInputPort( WirePortDataType.FLOAT, false, "B" ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_inputPorts[ 0 ].CreatePortRestrictions( m_dynamicRestrictions ); + m_inputPorts[ 1 ].CreatePortRestrictions( m_dynamicRestrictions ); + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + UpdateConnection( inputPortId ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnection( portId ); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + UpdateDisconnectedConnection( portId ); + UpdateConnection( portId ); + UpdateEmptyInputPorts( true ); + } + + void UpdateDisconnectedConnection( int portId ) + { + if( m_extensibleInputPorts || m_allowMatrixCheck ) + { + int higher = 0; + int groupOneType = 0; + int groupTwoType = 0; + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + int currentPriority = UIUtils.GetPriority( m_inputPorts[ i ].DataType ); + if( !m_vectorMatrixOps && currentPriority < 3 ) + currentPriority += 7; + if( currentPriority > higher && currentPriority > 2 ) + { + higher = currentPriority; + m_mainDataType = m_inputPorts[ i ].DataType; + } + switch( m_inputPorts[ i ].DataType ) + { + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + { + groupOneType++; + groupTwoType++; + } + break; + case WirePortDataType.FLOAT3x3: + { + groupOneType++; + } + break; + case WirePortDataType.FLOAT4x4: + { + groupTwoType++; + } + break; + } + } + } + + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( !m_inputPorts[ i ].IsConnected ) + { + m_inputPorts[ i ].ChangeType( m_mainDataType, false ); + } + } + + if( groupOneType > 0 && m_mainDataType == WirePortDataType.FLOAT4x4 ) + { + m_errorMessageTooltip = "Doing this operation with FLOAT4x4 value only works against other FLOAT4x4 or FLOAT values"; + m_showErrorMessage = true; + } + else if( groupTwoType > 0 && m_mainDataType == WirePortDataType.FLOAT3x3 ) + { + m_errorMessageTooltip = "Doing this operation with FLOAT3x3 value only works against other FLOAT3x3 or FLOAT values"; + m_showErrorMessage = true; + } + else + { + m_showErrorMessage = false; + } + + if( m_dynamicOutputType ) + m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + } + else + + if( m_inputPorts[ 0 ].DataType != m_inputPorts[ 1 ].DataType ) + { + int otherPortId = ( portId + 1 ) % 2; + if( m_inputPorts[ otherPortId ].IsConnected ) + { + m_mainDataType = m_inputPorts[ otherPortId ].DataType; + m_inputPorts[ portId ].ChangeType( m_mainDataType, false ); + if( m_dynamicOutputType ) + m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + } + else + { + if( UIUtils.GetPriority( m_inputPorts[ 0 ].DataType ) > UIUtils.GetPriority( m_inputPorts[ 1 ].DataType ) ) + { + m_mainDataType = m_inputPorts[ 0 ].DataType; + m_inputPorts[ 1 ].ChangeType( m_mainDataType, false ); + } + else + { + m_mainDataType = m_inputPorts[ 1 ].DataType; + m_inputPorts[ 0 ].ChangeType( m_mainDataType, false ); + } + + if( m_dynamicOutputType ) + { + if( m_mainDataType != m_outputPorts[ 0 ].DataType ) + { + m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + } + } + } + } + } + + void UpdateConnection( int portId ) + { + if( m_extensibleInputPorts || m_allowMatrixCheck ) + { + m_inputPorts[ portId ].MatchPortToConnection(); + + int higher = 0; + int groupOneType = 0; + int groupTwoType = 0; + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + int currentPriority = UIUtils.GetPriority( m_inputPorts[ i ].DataType ); + if( !m_vectorMatrixOps && currentPriority < 3 ) + currentPriority += 7; + if( currentPriority > higher ) + { + higher = currentPriority; + m_mainDataType = m_inputPorts[ i ].DataType; + } + switch( m_inputPorts[ i ].DataType ) + { + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + { + groupOneType++; + groupTwoType++; + } + break; + case WirePortDataType.FLOAT3x3: + { + groupOneType++; + } + break; + case WirePortDataType.FLOAT4x4: + { + groupTwoType++; + } + break; + } + } + } + + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( !m_inputPorts[ i ].IsConnected ) + { + m_inputPorts[ i ].ChangeType( m_mainDataType, false ); + } + } + if( groupOneType > 0 && m_mainDataType == WirePortDataType.FLOAT4x4 ) + { + m_errorMessageTooltip = "Doing this operation with FLOAT4x4 value only works against other FLOAT4x4 or FLOAT values"; + m_showErrorMessage = true; + } + else if( groupTwoType > 0 && m_mainDataType == WirePortDataType.FLOAT3x3 ) + { + m_errorMessageTooltip = "Doing this operation with FLOAT3x3 value only works against other FLOAT3x3 or FLOAT values"; + m_showErrorMessage = true; + } + else + { + m_showErrorMessage = false; + } + + if( m_dynamicOutputType ) + m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + } + + else + { + m_inputPorts[ portId ].MatchPortToConnection(); + int otherPortId = ( portId + 1 ) % 2; + if( !m_inputPorts[ otherPortId ].IsConnected ) + { + m_inputPorts[ otherPortId ].ChangeType( m_inputPorts[ portId ].DataType, false ); + } + + if( m_inputPorts[ 0 ].DataType == m_inputPorts[ 1 ].DataType ) + { + m_mainDataType = m_inputPorts[ 0 ].DataType; + if( m_dynamicOutputType ) + m_outputPorts[ 0 ].ChangeType( InputPorts[ 0 ].DataType, false ); + } + else + { + if( UIUtils.GetPriority( m_inputPorts[ 0 ].DataType ) > UIUtils.GetPriority( m_inputPorts[ 1 ].DataType ) ) + { + m_mainDataType = m_inputPorts[ 0 ].DataType; + } + else + { + m_mainDataType = m_inputPorts[ 1 ].DataType; + } + + if( m_dynamicOutputType ) + { + if( m_mainDataType != m_outputPorts[ 0 ].DataType ) + { + m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + } + } + } + } + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + + if( !m_extensibleInputPorts ) + return; + + if( m_previouslyDragging != m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid && m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.NodeId != UniqueId ) + { + if( m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid ) + { + m_beforePreviewCount = 2; + for( int i = 2; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + m_beforePreviewCount++; + } + } + + m_inputCount = m_beforePreviewCount + 1; + if( m_inputCount <= 10 ) + { + if( m_inputCount > m_lastInputCount ) + { + Undo.RegisterCompleteObjectUndo( m_containerGraph.ParentWindow, Constants.UndoCreateDynamicPortId ); + RecordObject( Constants.UndoCreateDynamicPortId ); + + AddInputPort( m_mainDataType, false, ( ( char ) ( 'A' + m_inputCount - 1 ) ).ToString() ); + m_inputPorts[ m_inputCount - 1 ].CreatePortRestrictions( m_dynamicRestrictions ); + } + + m_lastInputCount = m_inputCount; + m_sizeIsDirty = true; + m_isDirty = true; + SetSaveIsDirty(); + } + } + else + { + bool hasEmpty = CheckValidConnections(); + if( hasEmpty ) + UpdateEmptyInputPorts( false ); + } + + m_previouslyDragging = m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid; + } + + UpdateEmptyInputPorts( false ); + } + + private bool CheckValidConnections() + { + if( !m_extensibleInputPorts ) + return false; + + bool hasEmptyConnections = false; + + bool hasMatrix = m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT3x3 || m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT4x4 || m_inputPorts[ 1 ].DataType == WirePortDataType.FLOAT3x3 || m_inputPorts[ 1 ].DataType == WirePortDataType.FLOAT4x4; + + if( m_inputPorts.Count != m_beforePreviewCount ) + { + if( hasMatrix ) + { + bool showError = false; + for( int i = m_inputPorts.Count - 1; i >= 2; i-- ) + { + if( m_inputPorts[ i ].IsConnected ) + { + showError = true; + m_inputPorts[ i ].FullDeleteConnections(); + } + + hasEmptyConnections = true; + } + if( showError ) + m_containerGraph.ParentWindow.ShowMessage( UniqueId, "Matrix operations are only valid for the first two inputs to prevent errors" ); + } + else + { + for( int i = m_inputPorts.Count - 1; i >= 2; i-- ) + { + if( m_inputPorts[ i ].DataType == WirePortDataType.FLOAT3x3 || m_inputPorts[ i ].DataType == WirePortDataType.FLOAT4x4 ) + { + m_containerGraph.ParentWindow.ShowMessage( UniqueId, "Matrix operations are only valid for the first two inputs to prevent errors" ); + m_inputPorts[ i ].FullDeleteConnections(); + hasEmptyConnections = true; + } + else if( !m_inputPorts[ i ].IsConnected ) + { + hasEmptyConnections = true; + } + } + } + } + + return hasEmptyConnections; + } + + private void UpdateEmptyInputPorts( bool recordUndo ) + { + if( !m_extensibleInputPorts ) + return; + NodeWireReferencesUtils wireReferenceUtils = m_containerGraph.ParentWindow.WireReferenceUtils; + if( !wireReferenceUtils.OutputPortReference.IsValid ) + { + if( recordUndo ) + { + Undo.RegisterCompleteObjectUndo( m_containerGraph.ParentWindow, Constants.UndoDeleteDynamicPortId ); + RecordObject( Constants.UndoDeleteDynamicPortId ); + } + + bool hasDeleted = false; + m_inputCount = 2; + for( int i = m_inputPorts.Count - 1; i >= 2; i-- ) + { + if( !m_inputPorts[ i ].IsConnected ) + { + hasDeleted = true; + if( wireReferenceUtils.InputPortReference.IsValid && + wireReferenceUtils.InputPortReference.NodeId == UniqueId && + wireReferenceUtils.InputPortReference.PortId == m_inputPorts[ i ].PortId ) + { + wireReferenceUtils.InputPortReference.Invalidate(); + } + DeleteInputPortByArrayIdx( i ); + } + else + { + m_inputCount++; + } + } + + if( hasDeleted || m_inputCount != m_lastInputCount ) + { + for( int i = 2; i < m_inputPorts.Count; i++ ) + { + m_inputPorts[ i ].Name = ( ( char ) ( 'A' + i ) ).ToString(); + } + + m_beforePreviewCount = m_inputPorts.Count; + m_inputCount = m_beforePreviewCount; + m_lastInputCount = m_inputCount; + m_sizeIsDirty = true; + m_isDirty = true; + SetSaveIsDirty(); + } + } + + m_inputCount = Mathf.Clamp( m_inputCount, 2, 10 ); + } + + public virtual string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( !m_extensibleInputPorts ) + SetInputData( outputId, ref dataCollector, ignoreLocalvar ); + else + SetExtensibleInputData( outputId, ref dataCollector, ignoreLocalvar ); + return string.Empty; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + string result = BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + + protected void SetInputData( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + m_inputA = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + if( m_inputPorts[ 0 ].DataType != m_mainDataType ) + { + m_inputA = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), m_inputA, m_inputPorts[ 0 ].DataType, m_mainDataType, m_inputA ); + } + m_inputB = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + if( m_inputPorts[ 1 ].DataType != m_mainDataType ) + { + m_inputB = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), m_inputB, m_inputPorts[ 1 ].DataType, m_mainDataType, m_inputB ); + } + } + + protected void SetExtensibleInputData( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + m_extensibleInputResults = new List(); + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + m_extensibleInputResults.Add( m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ) ); + if( m_inputPorts[ i ].DataType != m_mainDataType && m_inputPorts[ i ].DataType != WirePortDataType.FLOAT && m_inputPorts[ i ].DataType != WirePortDataType.INT ) + { + m_extensibleInputResults[ i ] = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), m_extensibleInputResults[ i ], m_inputPorts[ i ].DataType, m_mainDataType, m_extensibleInputResults[ i ] ); + } + } + } + + void UpdatePorts() + { + m_lastInputCount = Mathf.Clamp( m_inputCount, 2, 10 ); + + for( int i = 2; i < m_inputCount; i++ ) + { + AddInputPort( m_mainDataType, false, ( ( char ) ( 'A' + i ) ).ToString() ); + m_inputPorts[ i ].CreatePortRestrictions( m_dynamicRestrictions ); + } + + m_sizeIsDirty = true; + SetSaveIsDirty(); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( m_extensibleInputPorts && UIUtils.CurrentShaderVersion() > 10005 ) + { + m_inputCount = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + UpdatePorts(); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + if( m_extensibleInputPorts ) + IOUtils.AddFieldValueToString( ref nodeInfo, m_inputCount ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DynamicTypeNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DynamicTypeNode.cs.meta new file mode 100644 index 0000000..bac40f9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/DynamicTypeNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5b60c440b5db81c4d9df9c048aa22b48 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs.meta new file mode 100644 index 0000000..2eaea63 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 868823c936b45494aa7f3ce9f16b5372 +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/CameraDepthFade.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/CameraDepthFade.cs new file mode 100644 index 0000000..e8c9fc5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/CameraDepthFade.cs @@ -0,0 +1,130 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Camera Depth Fade", "Camera And Screen", "Outputs a 0 - 1 gradient representing the distance between the surface of this object and camera near plane" )] + public sealed class CameraDepthFade : ParentNode + { + //{0} - Eye Depth + //{1} - Offset + //{2} - Distance + private const string CameraDepthFadeFormat = "(( {0} -_ProjectionParams.y - {1} ) / {2})"; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "Vertex Position", -1, MasterNodePortCategory.Fragment, 2 ); + AddInputPort( WirePortDataType.FLOAT, false, "Length", -1, MasterNodePortCategory.Fragment, 0 ); + AddInputPort( WirePortDataType.FLOAT, false, "Offset", -1, MasterNodePortCategory.Fragment, 1 ); + GetInputPortByUniqueId( 0 ).FloatInternalData = 1; + AddOutputPort( WirePortDataType.FLOAT, "Out" ); + m_useInternalPortData = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + InputPort vertexPort = GetInputPortByUniqueId( 2 ); + InputPort lengthPort = GetInputPortByUniqueId( 0 ); + InputPort offsetPort = GetInputPortByUniqueId( 1 ); + + string distance = lengthPort.GeneratePortInstructions( ref dataCollector ); + string offset = offsetPort.GeneratePortInstructions( ref dataCollector ); + + string value = string.Empty; + string eyeDepth = string.Empty; + + if( dataCollector.IsTemplate ) + { + if( vertexPort.IsConnected ) + { + string varName = "customSurfaceDepth" + OutputId; + GenerateInputInVertex( ref dataCollector, 2, varName, false ); + + string formatStr = string.Empty; + if( dataCollector.IsSRP ) + formatStr = "-TransformWorldToView(TransformObjectToWorld({0})).z"; + else + formatStr = "-UnityObjectToViewPos({0}).z"; + + string eyeInstruction = string.Format( formatStr, varName ); + eyeDepth = "customEye" + OutputId; + dataCollector.TemplateDataCollectorInstance.RegisterCustomInterpolatedData( eyeDepth, WirePortDataType.FLOAT, CurrentPrecisionType, eyeInstruction ); + } + else + { + eyeDepth = dataCollector.TemplateDataCollectorInstance.GetEyeDepth( CurrentPrecisionType ); + } + + value = string.Format( CameraDepthFadeFormat, eyeDepth, offset, distance ); + RegisterLocalVariable( 0, value, ref dataCollector, "cameraDepthFade" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + string vertexVarName = string.Empty; + if( vertexPort.IsConnected ) + { + vertexVarName = vertexPort.GeneratePortInstructions( ref dataCollector ); + } + else + { + vertexVarName = Constants.VertexShaderInputStr + ".vertex.xyz"; + } + + //dataCollector.AddVertexInstruction( "float cameraDepthFade" + UniqueId + " = (( -UnityObjectToViewPos( " + Constants.VertexShaderInputStr + ".vertex.xyz ).z -_ProjectionParams.y - " + offset + " ) / " + distance + ");", UniqueId ); + value = string.Format( CameraDepthFadeFormat, "-UnityObjectToViewPos( " + vertexVarName + " ).z", offset, distance ); + RegisterLocalVariable( 0, value, ref dataCollector, "cameraDepthFade" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + dataCollector.AddToIncludes( UniqueId, Constants.UnityShaderVariables ); + + if( dataCollector.TesselationActive ) + { + if( vertexPort.IsConnected ) + { + string vertexValue = vertexPort.GeneratePortInstructions( ref dataCollector ); + eyeDepth = "customSurfaceDepth" + OutputId; + RegisterLocalVariable( 0, string.Format( "-UnityObjectToViewPos( {0} ).z", vertexValue ), ref dataCollector, eyeDepth ); + } + else + { + eyeDepth = GeneratorUtils.GenerateScreenDepthOnFrag( ref dataCollector, UniqueId, CurrentPrecisionType ); + } + } + else + { + + if( vertexPort.IsConnected ) + { + string varName = "customSurfaceDepth" + OutputId; + GenerateInputInVertex( ref dataCollector, 2, varName, false ); + dataCollector.AddToInput( UniqueId, varName, WirePortDataType.FLOAT ); + string vertexInstruction = "-UnityObjectToViewPos( " + varName + " ).z"; + dataCollector.AddToVertexLocalVariables( UniqueId, Constants.VertexShaderOutputStr + "." + varName + " = " + vertexInstruction + ";" ); + eyeDepth = Constants.InputVarStr + "." + varName; + } + else + { + dataCollector.AddToInput( UniqueId, "eyeDepth", WirePortDataType.FLOAT ); + string instruction = "-UnityObjectToViewPos( " + Constants.VertexShaderInputStr + ".vertex.xyz ).z"; + dataCollector.AddToVertexLocalVariables( UniqueId, Constants.VertexShaderOutputStr + ".eyeDepth = " + instruction + ";" ); + eyeDepth = Constants.InputVarStr + ".eyeDepth"; + } + } + + value = string.Format( CameraDepthFadeFormat, eyeDepth, offset, distance ); + RegisterLocalVariable( 0, value, ref dataCollector, "cameraDepthFade" + OutputId ); + //dataCollector.AddToLocalVariables( UniqueId, "float cameraDepthFade" + UniqueId + " = (( " + Constants.InputVarStr + ".eyeDepth -_ProjectionParams.y - "+ offset + " ) / " + distance + ");" ); + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/CameraDepthFade.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/CameraDepthFade.cs.meta new file mode 100644 index 0000000..2e13b8f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/CameraDepthFade.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 96f38a9f14906ca49b505b8e305c37ec +timeCreated: 1491316341 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeGrabScreenPosHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeGrabScreenPosHlpNode.cs new file mode 100644 index 0000000..362415d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeGrabScreenPosHlpNode.cs @@ -0,0 +1,54 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Compute Grab Screen Pos", "Camera And Screen", "Computes texture coordinate for doing a screenspace-mapped texture sample. Input is clip space position" )] + public sealed class ComputeGrabScreenPosHlpNode : HelperParentNode + { + private readonly string[] ComputeGrabScreenPosFunction = + { + "inline float4 ComputeGrabScreenPos( float4 pos )\n", + "{\n", + "#if UNITY_UV_STARTS_AT_TOP\n", + "\tfloat scale = -1.0;\n", + "#else\n", + "\tfloat scale = 1.0;\n", + "#endif\n", + "\tfloat4 o = pos * 0.5f;\n", + "\to.xy = float2( o.x, o.y*scale ) + o.w;\n", + "#ifdef UNITY_SINGLE_PASS_STEREO\n", + "\to.xy = TransformStereoScreenSpaceTex ( o.xy, pos.w );\n", + "#endif\n", + "\to.zw = pos.zw;\n", + "\treturn o;\n", + "}\n" + }; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "ComputeGrabScreenPos"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_outputPorts[ 0 ].Name = "XYZW"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "computeGrabScreenPos" + OutputId; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + { + dataCollector.AddFunction( m_funcType, ComputeGrabScreenPosFunction, false ); + } + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeGrabScreenPosHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeGrabScreenPosHlpNode.cs.meta new file mode 100644 index 0000000..4e68be7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeGrabScreenPosHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5fe7f4be962b9e8459eb156503b99d41 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeScreenPosHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeScreenPosHlpNode.cs new file mode 100644 index 0000000..883009b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeScreenPosHlpNode.cs @@ -0,0 +1,76 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using UnityEngine; +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Compute Screen Pos", "Camera And Screen", "Computes texture coordinate for doing a screenspace-mapped texture sample. Input is clip space position" )] + public sealed class ComputeScreenPosHlpNode : HelperParentNode + { + [SerializeField] + private bool m_normalize = false; + private string NormalizeStr = "Normalize"; + private readonly string[] NormalizeOps = + { "{0} = {0} / {0}.w;", + "{0}.z = ( UNITY_NEAR_CLIP_VALUE >= 0 ) ? {0}.z : {0}.z* 0.5 + 0.5;" + }; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "ComputeScreenPos"; + m_funcHDFormatOverride = "ComputeScreenPos( {0} , _ProjectionParams.x )"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_outputPorts[ 0 ].Name = "XYZW"; + m_autoWrapProperties = true; + m_previewShaderGUID = "97bd4895d847d764eb21d2bf7aa13671"; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + m_previewMaterialPassId = m_normalize ? 1 : 0; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "computeScreenPos" + OutputId; + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_normalize = EditorGUILayoutToggle( NormalizeStr, m_normalize ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + string result = base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + if( m_normalize ) + { + dataCollector.AddLocalVariable( UniqueId, string.Format( NormalizeOps[ 0 ], m_localVarName ) ); + dataCollector.AddLocalVariable( UniqueId, string.Format( NormalizeOps[ 1 ], m_localVarName ) ); + } + return result; + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalize ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 15404 ) + { + m_normalize = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeScreenPosHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeScreenPosHlpNode.cs.meta new file mode 100644 index 0000000..a5dba00 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ComputeScreenPosHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c220606396d6e6048a901f217be1435e +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeDepthNormalNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeDepthNormalNode.cs new file mode 100644 index 0000000..79ebf7e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeDepthNormalNode.cs @@ -0,0 +1,46 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Decode Depth Normal", "Miscellaneous", "Decodes both Depth and Normal from a previously encoded pixel value" )] + public sealed class DecodeDepthNormalNode : ParentNode + { + // URP will only have support for depth normals texture over v.10 ... must revisit this node when it comes out + private const string SRPErrorMessage = "This node is only currently supported on the Built-in pipeline"; + private const string DecodeDepthNormalFunc = "DecodeDepthNormal( {0}, {1}, {2} );"; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT4, false, "Encoded" ); + AddOutputPort( WirePortDataType.FLOAT, "Depth" ); + AddOutputPort( WirePortDataType.FLOAT3, "Normal" ); + m_previewShaderGUID = "dbf37c4d3ce0f0b41822584d6c9ba203"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsSRP ) + { + UIUtils.ShowMessage( SRPErrorMessage, MessageSeverity.Error ); + return GenerateErrorValue( outputId ); + } + + if( m_outputPorts[ outputId ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + + dataCollector.AddToIncludes( UniqueId, Constants.UnityCgLibFuncs ); + string encodedValue = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string depthDecodedVal = "depthDecodedVal" + OutputId; + string normalDecodedVal = "normalDecodedVal" + OutputId; + RegisterLocalVariable( 0, "0", ref dataCollector, depthDecodedVal ); + RegisterLocalVariable( 1, "float3(0,0,0)", ref dataCollector, normalDecodedVal ); + dataCollector.AddLocalVariable( UniqueId, string.Format( DecodeDepthNormalFunc, encodedValue , depthDecodedVal, normalDecodedVal) ); + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeDepthNormalNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeDepthNormalNode.cs.meta new file mode 100644 index 0000000..032de06 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeDepthNormalNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1cc4e3c718669d54c97614ac6abcfaff +timeCreated: 1513695160 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGBAHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGBAHlpNode.cs new file mode 100644 index 0000000..a80ad39 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGBAHlpNode.cs @@ -0,0 +1,27 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Decode Float RGBA", "Miscellaneous", "Decodes RGBA color into a float" )] + public sealed class DecodeFloatRGBAHlpNode : HelperParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "DecodeFloatRGBA"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_inputPorts[ 0 ].Name = "RGBA"; + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT, false ); + m_previewShaderGUID = "f71b31b15ff3f2042bafbed40acd29f4"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "decodeFloatRGBA" + OutputId; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGBAHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGBAHlpNode.cs.meta new file mode 100644 index 0000000..132cd57 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGBAHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2c5479ff48207cf43a308ec9f110fa9f +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGHlpNode.cs new file mode 100644 index 0000000..3751b22 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGHlpNode.cs @@ -0,0 +1,27 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Decode Float RG", "Miscellaneous", "Decodes a previously-encoded RG float" )] + public sealed class DecodeFloatRGHlpNode : HelperParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "DecodeFloatRG"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT2, false ); + m_inputPorts[ 0 ].Name = "RG"; + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT, false ); + m_previewShaderGUID = "1fb3121b1c8febb4dbcc2a507a2df2db"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "decodeFloatRG" + OutputId; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGHlpNode.cs.meta new file mode 100644 index 0000000..e436b07 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeFloatRGHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a965812ada2b83343a1f511273fcfc52 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeLightmapHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeLightmapHlpNode.cs new file mode 100644 index 0000000..a7f52dd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeLightmapHlpNode.cs @@ -0,0 +1,109 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Decode Lightmap", "Miscellaneous", "Decodes color from Unity lightmap (RGBM or dLDR depending on platform)" )] + public sealed class DecodeLightmapHlpNode : ParentNode + { + private const string m_funcStandard = "DecodeLightmap({0})"; + private string m_funcSRP = "DecodeLightmap({0},{1})"; + + private const string DecodeInstructionsLWValueStr = "half4 decodeLightmapInstructions = half4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0.0h, 0.0h);"; + private const string DecodeInstructionsNameStr = "decodeLightmapInstructions"; + private readonly string[] DecodeInstructionsHDValueStr = + { + "#ifdef UNITY_LIGHTMAP_FULL_HDR//ase_decode_lightmap_0", + "\tbool useRGBMLightmap = false;//ase_decode_lightmap_1", + "\tfloat4 decodeLightmapInstructions = float4( 0.0, 0.0, 0.0, 0.0 );//ase_decode_lightmap_2", + "#else//ase_decode_lightmap//ase_decode_lightmap_3", + "\tbool useRGBMLightmap = true;//ase_decode_lightmap_4", + "#if defined(UNITY_LIGHTMAP_RGBM_ENCODING)//ase_decode_lightmap_5", + "\tfloat4 decodeLightmapInstructions = float4(34.493242, 2.2, 0.0, 0.0);//ase_decode_lightmap_6", + "#else//ase_decode_lightmap_7", + "\tfloat4 decodeLightmapInstructions = float4( 2.0, 2.2, 0.0, 0.0 );//ase_decode_lightmap_8", + "#endif//ase_decode_lightmap_9", + "#endif//ase_decode_lightmap_10" + }; + private string m_localVarName = null; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT4, false, "Value" ); + AddInputPort( WirePortDataType.FLOAT4, false, "Instructions" ); + + AddOutputPort( WirePortDataType.FLOAT3, Constants.EmptyPortValue ); + + m_previewShaderGUID = "c2d3bee1aee183343b31b9208cb402e9"; + m_useInternalPortData = true; + } + + public override string GetIncludes() + { + return Constants.UnityCgLibFuncs; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "decodeLightMap" + OutputId; + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + m_inputPorts[ 1 ].Visible = m_containerGraph.ParentWindow.IsShaderFunctionWindow || m_containerGraph.IsSRP; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string finalResult = string.Empty; + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + string instructions = string.Empty; + if( m_inputPorts[ 1 ].IsConnected ) + { + instructions = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + } + else + { + if( dataCollector.TemplateDataCollectorInstance.IsHDRP ) + { + for( int i = 0; i < DecodeInstructionsHDValueStr.Length; i++ ) + { + dataCollector.AddLocalVariable( UniqueId, DecodeInstructionsHDValueStr[ i ] ); + } + } + else + { + dataCollector.AddLocalVariable( UniqueId, DecodeInstructionsLWValueStr ); + } + instructions = DecodeInstructionsNameStr; + + } + + finalResult = string.Format( m_funcSRP, value , instructions ); + + } + else + { + dataCollector.AddToIncludes( UniqueId, Constants.UnityCgLibFuncs ); + finalResult = string.Format( m_funcStandard, value ); + } + + RegisterLocalVariable( 0, finalResult, ref dataCollector, m_localVarName ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeLightmapHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeLightmapHlpNode.cs.meta new file mode 100644 index 0000000..07aca76 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeLightmapHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b3d1879d1e402b34f98b8e8cdf94d719 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeViewNormalStereoHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeViewNormalStereoHlpNode.cs new file mode 100644 index 0000000..a69b499 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeViewNormalStereoHlpNode.cs @@ -0,0 +1,27 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Decode View Normal Stereo", "Miscellaneous", "Decodes view space normal from enc4.xy" )] + public sealed class DecodeViewNormalStereoHlpNode : HelperParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "DecodeViewNormalStereo"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_outputPorts[ 0 ].Name = "XYZ"; + m_previewShaderGUID = "e996db1cc4510c84185cb9f933f916bb"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "decodeViewNormalStereo" + OutputId; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeViewNormalStereoHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeViewNormalStereoHlpNode.cs.meta new file mode 100644 index 0000000..0bf4466 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DecodeViewNormalStereoHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 94df47461b7e6244eaf92b0dab7cc7ee +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DepthFade.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DepthFade.cs new file mode 100644 index 0000000..cc6db43 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DepthFade.cs @@ -0,0 +1,168 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Depth Fade", "Surface Data", "Outputs a linear gradient representing the distance between the surface of this object and geometry behind" )] + public sealed class DepthFade : ParentNode + { + private const string ConvertToLinearStr = "Convert To Linear"; + private const string SaturateStr = "Saturate"; + private const string MirrorStr = "Mirror"; + + [SerializeField] + private bool m_convertToLinear = true; + + [SerializeField] + private bool m_saturate = false; + + [SerializeField] + private bool m_mirror = true; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "Vertex Position", -1, MasterNodePortCategory.Fragment, 1 ); + AddInputPort( WirePortDataType.FLOAT, false, "Distance",-1,MasterNodePortCategory.Fragment,0 ); + GetInputPortByUniqueId(0).FloatInternalData = 1; + AddOutputPort( WirePortDataType.FLOAT, "Out" ); + m_useInternalPortData = true; + m_autoWrapProperties = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + UIUtils.ShowNoVertexModeNodeMessage( this ); + return "0"; + } + + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputColorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + if( !( dataCollector.IsTemplate && dataCollector.IsSRP ) ) + dataCollector.AddToIncludes( UniqueId, Constants.UnityCgLibFuncs ); + + if( !dataCollector.IsTemplate || dataCollector.TemplateDataCollectorInstance.CurrentSRPType != TemplateSRPType.HD ) + { + if( dataCollector.IsTemplate && dataCollector.CurrentSRPType == TemplateSRPType.Lightweight ) + { + //dataCollector.AddToUniforms( UniqueId, Constants.CameraDepthTextureSRPVar ); + //dataCollector.AddToUniforms( UniqueId, Constants.CameraDepthTextureSRPSampler ); + dataCollector.AddToDirectives( Constants.CameraDepthTextureLWEnabler, -1, AdditionalLineType.Define ); + } + else + { + dataCollector.AddToUniforms( UniqueId, Constants.CameraDepthTextureValue ); + } + + dataCollector.AddToUniforms( UniqueId, Constants.CameraDepthTextureTexelSize ); + } + + string screenPosNorm = string.Empty; + InputPort vertexPosPort = GetInputPortByUniqueId( 1 ); + if( vertexPosPort.IsConnected ) + { + string vertexPosVar = "vertexPos" + OutputId; + GenerateInputInVertex( ref dataCollector, 1, vertexPosVar, false ); + screenPosNorm = GeneratorUtils.GenerateScreenPositionNormalizedForValue( vertexPosVar, OutputId, ref dataCollector, UniqueId, CurrentPrecisionType, !dataCollector.UsingCustomScreenPos ); + } + else + { + if( dataCollector.IsTemplate ) + { + string ppsScreenPos = string.Empty; + if( !dataCollector.TemplateDataCollectorInstance.GetCustomInterpolatedData( TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED, WirePortDataType.FLOAT4, PrecisionType.Float, ref ppsScreenPos, true, MasterNodePortCategory.Fragment ) ) + { + screenPosNorm = GeneratorUtils.GenerateScreenPositionNormalized( ref dataCollector, UniqueId, CurrentPrecisionType, !dataCollector.UsingCustomScreenPos ); + } + else + { + screenPosNorm = ppsScreenPos; + } + } + else + { + screenPosNorm = GeneratorUtils.GenerateScreenPositionNormalized( ref dataCollector, UniqueId, CurrentPrecisionType, !dataCollector.UsingCustomScreenPos ); + } + } + + string screenDepth = TemplateHelperFunctions.CreateDepthFetch( dataCollector, screenPosNorm ); + if( m_convertToLinear ) + { + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + screenDepth = string.Format( "LinearEyeDepth({0},_ZBufferParams)", screenDepth ); + else + screenDepth = string.Format( "LinearEyeDepth({0})", screenDepth ); + } + else + { + screenDepth = string.Format( "({0}*( _ProjectionParams.z - _ProjectionParams.y ))", screenDepth ); + } + + string distance = GetInputPortByUniqueId( 0 ).GeneratePortInstructions( ref dataCollector ); + + dataCollector.AddLocalVariable( UniqueId, "float screenDepth" + OutputId + " = " + screenDepth + ";" ); + + string finalVarName = "distanceDepth" + OutputId; + string finalVarValue = string.Empty; + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + finalVarValue = "( screenDepth" + OutputId + " - LinearEyeDepth( " + screenPosNorm + ".z,_ZBufferParams ) ) / ( " + distance + " )"; + else + finalVarValue = "( screenDepth" + OutputId + " - LinearEyeDepth( " + screenPosNorm + ".z ) ) / ( " + distance + " )"; + + if( m_mirror ) + { + finalVarValue = string.Format( "abs( {0} )", finalVarValue ); + } + + if( m_saturate ) + { + finalVarValue = string.Format( "saturate( {0} )", finalVarValue ); + } + + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, finalVarName, finalVarValue ); + m_outputPorts[ 0 ].SetLocalValue( finalVarName, dataCollector.PortCategory ); + return GetOutputColorItem( 0, outputId, finalVarName ); + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_convertToLinear = EditorGUILayoutToggle( ConvertToLinearStr, m_convertToLinear ); + m_mirror = EditorGUILayoutToggle( MirrorStr, m_mirror ); + m_saturate = EditorGUILayoutToggle( SaturateStr, m_saturate ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() >= 13901 ) + { + m_convertToLinear = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + if( UIUtils.CurrentShaderVersion() > 15607 ) + { + m_saturate = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 15700 ) + { + m_mirror = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_convertToLinear ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_saturate ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_mirror ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DepthFade.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DepthFade.cs.meta new file mode 100644 index 0000000..c302a61 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DepthFade.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 279c74ce44e24204d803be6ec743c290 +timeCreated: 1491316341 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DiffuseAndSpecularFromMetallicNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DiffuseAndSpecularFromMetallicNode.cs new file mode 100644 index 0000000..af59933 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DiffuseAndSpecularFromMetallicNode.cs @@ -0,0 +1,59 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Diffuse And Specular From Metallic", "Miscellaneous", "Gets Diffuse and Specular values from Metallic. Uses DiffuseAndSpecularFromMetallic function from UnityStandardUtils." )] + public class DiffuseAndSpecularFromMetallicNode : ParentNode + { + //half3 DiffuseAndSpecularFromMetallic (half3 albedo, half metallic, out half3 specColor, out half oneMinusReflectivity) + private const string FuncFormat = "DiffuseAndSpecularFromMetallic({0},{1},{2},{3})"; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "Albedo" ); + AddInputPort( WirePortDataType.FLOAT, false, "Metallic" ); + AddOutputPort( WirePortDataType.FLOAT3, "Out" ); + AddOutputPort( WirePortDataType.FLOAT3, "Spec Color" ); + AddOutputPort( WirePortDataType.FLOAT, "One Minus Reflectivity" ); + m_previewShaderGUID = "c7c4485750948a045b5dab0985896e17"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsSRP ) + { + UIUtils.ShowMessage( UniqueId, "Diffuse And Specular From Metallic Node not compatible with SRP" ); + return m_outputPorts[0].ErrorValue; + } + + if( m_outputPorts[ outputId ].IsLocalValue( dataCollector.PortCategory ) ) + { + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + dataCollector.AddToIncludes( UniqueId, Constants.UnityStandardUtilsLibFuncs ); + + string albedo = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string metallic = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + string specColorVar = "specColor" + OutputId; + string oneMinusReflectivityVar = "oneMinusReflectivity" + OutputId; + string varName = "diffuseAndSpecularFromMetallic" + OutputId; + + dataCollector.AddLocalVariable( UniqueId, PrecisionType.Half, WirePortDataType.FLOAT3, specColorVar, "(0).xxx" ); + dataCollector.AddLocalVariable( UniqueId, PrecisionType.Half, WirePortDataType.FLOAT, oneMinusReflectivityVar, "0" ); + + + string varValue = string.Format( FuncFormat, albedo, metallic, specColorVar, oneMinusReflectivityVar ); + dataCollector.AddLocalVariable( UniqueId, PrecisionType.Half, WirePortDataType.FLOAT3, varName, varValue ); + m_outputPorts[ 0 ].SetLocalValue( varName, dataCollector.PortCategory ); + m_outputPorts[ 1 ].SetLocalValue( specColorVar, dataCollector.PortCategory ); + m_outputPorts[ 2 ].SetLocalValue( oneMinusReflectivityVar, dataCollector.PortCategory ); + + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DiffuseAndSpecularFromMetallicNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DiffuseAndSpecularFromMetallicNode.cs.meta new file mode 100644 index 0000000..4ab9e6f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DiffuseAndSpecularFromMetallicNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a792f114a5433af499dce78ebe05a9e6 +timeCreated: 1534266498 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DitheringNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DitheringNode.cs new file mode 100644 index 0000000..fb55b83 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DitheringNode.cs @@ -0,0 +1,311 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Dither", "Camera And Screen", "Generates a dithering pattern" )] + public sealed class DitheringNode : ParentNode + { + private const string InputTypeStr = "Pattern"; + private const string CustomScreenPosStr = "screenPosition"; + + private string m_functionHeader = "Dither4x4Bayer( {0}, {1} )"; + private string m_functionBody = string.Empty; + + [SerializeField] + private int m_selectedPatternInt = 0; + + [SerializeField] + private bool m_customScreenPos = false; + + private readonly string[] PatternsFuncStr = { "4x4Bayer", "8x8Bayer", "NoiseTex" }; + private readonly string[] PatternsStr = { "4x4 Bayer", "8x8 Bayer", "Noise Texture" }; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + private InputPort m_texPort; + private InputPort m_ssPort; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + AddInputPort( WirePortDataType.SAMPLER2D, false, "Pattern"); + m_inputPorts[ 1 ].CreatePortRestrictions( WirePortDataType.SAMPLER2D ); + m_texPort = m_inputPorts[ 1 ]; + AddInputPort( WirePortDataType.FLOAT4, false, "Screen Position" ); + + AddInputPort( WirePortDataType.SAMPLERSTATE, false, "SS" ); + m_inputPorts[ 3 ].CreatePortRestrictions( WirePortDataType.SAMPLERSTATE ); + m_ssPort = m_inputPorts[ 3 ]; + + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_textLabelWidth = 110; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, PatternsStr[ m_selectedPatternInt ] ) ); + UpdatePorts(); + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + m_texPort = null; + m_ssPort = null; + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + if( !m_texPort.CheckValidType( type ) ) + { + m_texPort.FullDeleteConnections(); + UIUtils.ShowMessage( UniqueId, "Dithering node only accepts SAMPLER2D input type.\nTexture Object connected changed to " + type + ", connection was lost, please review and update accordingly.", MessageSeverity.Warning ); + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_selectedPatternInt = m_upperLeftWidget.DrawWidget( this, m_selectedPatternInt, PatternsStr ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePorts(); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_selectedPatternInt = EditorGUILayoutPopup( "Pattern", m_selectedPatternInt, PatternsStr ); + if ( EditorGUI.EndChangeCheck() ) + { + UpdatePorts(); + } + EditorGUI.BeginChangeCheck(); + m_customScreenPos = EditorGUILayoutToggle( "Screen Position", m_customScreenPos ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePorts(); + } + } + + private void UpdatePorts() + { + m_texPort.Visible = ( m_selectedPatternInt == 2 ); + m_ssPort.Visible = ( m_selectedPatternInt == 2 ); + m_inputPorts[ 2 ].Visible = m_customScreenPos; + m_sizeIsDirty = true; + } + + private void GeneratePattern( ref MasterNodeDataCollector dataCollector ) + { + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, PatternsStr[ m_selectedPatternInt ] ) ); + switch ( m_selectedPatternInt ) + { + default: + case 0: + { + m_functionBody = string.Empty; + m_functionHeader = "Dither" + PatternsFuncStr[ m_selectedPatternInt ] + "( {0}, {1} )"; + IOUtils.AddFunctionHeader( ref m_functionBody, "inline float Dither" + PatternsFuncStr[ m_selectedPatternInt ] + "( int x, int y )" ); + IOUtils.AddFunctionLine( ref m_functionBody, "const float dither[ 16 ] = {" ); + IOUtils.AddFunctionLine( ref m_functionBody, " 1, 9, 3, 11," ); + IOUtils.AddFunctionLine( ref m_functionBody, " 13, 5, 15, 7," ); + IOUtils.AddFunctionLine( ref m_functionBody, " 4, 12, 2, 10," ); + IOUtils.AddFunctionLine( ref m_functionBody, " 16, 8, 14, 6 };" ); + IOUtils.AddFunctionLine( ref m_functionBody, "int r = y * 4 + x;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "return dither[r] / 16; // same # of instructions as pre-dividing due to compiler magic" ); + IOUtils.CloseFunctionBody( ref m_functionBody ); + } + break; + case 1: + { + m_functionBody = string.Empty; + m_functionHeader = "Dither" + PatternsFuncStr[ m_selectedPatternInt ] + "( {0}, {1} )"; + IOUtils.AddFunctionHeader( ref m_functionBody, "inline float Dither" + PatternsFuncStr[ m_selectedPatternInt ] + "( int x, int y )" ); + IOUtils.AddFunctionLine( ref m_functionBody, "const float dither[ 64 ] = {" ); + IOUtils.AddFunctionLine( ref m_functionBody, " 1, 49, 13, 61, 4, 52, 16, 64," ); + IOUtils.AddFunctionLine( ref m_functionBody, " 33, 17, 45, 29, 36, 20, 48, 32," ); + IOUtils.AddFunctionLine( ref m_functionBody, " 9, 57, 5, 53, 12, 60, 8, 56," ); + IOUtils.AddFunctionLine( ref m_functionBody, " 41, 25, 37, 21, 44, 28, 40, 24," ); + IOUtils.AddFunctionLine( ref m_functionBody, " 3, 51, 15, 63, 2, 50, 14, 62," ); + IOUtils.AddFunctionLine( ref m_functionBody, " 35, 19, 47, 31, 34, 18, 46, 30," ); + IOUtils.AddFunctionLine( ref m_functionBody, " 11, 59, 7, 55, 10, 58, 6, 54," ); + IOUtils.AddFunctionLine( ref m_functionBody, " 43, 27, 39, 23, 42, 26, 38, 22};" ); + IOUtils.AddFunctionLine( ref m_functionBody, "int r = y * 8 + x;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "return dither[r] / 64; // same # of instructions as pre-dividing due to compiler magic" ); + IOUtils.CloseFunctionBody( ref m_functionBody ); + } + break; + case 2: + { + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; + + m_functionBody = string.Empty; + m_functionHeader = "Dither" + PatternsFuncStr[ m_selectedPatternInt ] + "({0}, {1}, {2})"; + + IOUtils.AddFunctionHeader( ref m_functionBody, "inline float Dither" + PatternsFuncStr[ m_selectedPatternInt ] + "( float4 screenPos, " + GeneratorUtils.GetPropertyDeclaraction( "noiseTexture", TextureType.Texture2D, ", " ) + GeneratorUtils.GetSamplerDeclaraction( "samplernoiseTexture", TextureType.Texture2D, ", " ) + "float4 noiseTexelSize )" ); + + string samplingCall = GeneratorUtils.GenerateSamplingCall( ref dataCollector, WirePortDataType.SAMPLER2D, "noiseTexture", "samplernoiseTexture", "screenPos.xy * _ScreenParams.xy * noiseTexelSize.xy", MipType.MipLevel, "0" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float dither = "+ samplingCall + ".g;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float ditherRate = noiseTexelSize.x * noiseTexelSize.y;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "dither = ( 1 - ditherRate ) * dither + ditherRate;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "return dither;" ); + IOUtils.CloseFunctionBody( ref m_functionBody ); + } + break; + } + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + dataCollector.UsingCustomScreenPos = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + GeneratePattern( ref dataCollector ); + + if( !( dataCollector.IsTemplate && dataCollector.IsSRP ) ) + dataCollector.AddToIncludes( UniqueId, Constants.UnityShaderVariables ); + string varName = string.Empty; + bool isFragment = dataCollector.IsFragmentCategory; + if( m_customScreenPos && m_inputPorts[ 2 ].IsConnected ) + { + varName = "ditherCustomScreenPos" + OutputId; + string customScreenPosVal = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT4, varName, customScreenPosVal ); + } + else + { + if( dataCollector.TesselationActive && isFragment ) + { + varName = GeneratorUtils.GenerateClipPositionOnFrag( ref dataCollector, UniqueId, CurrentPrecisionType ); + } + else + { + if( dataCollector.IsTemplate ) + { + varName = dataCollector.TemplateDataCollectorInstance.GetScreenPosNormalized( CurrentPrecisionType ); + } + else + { + varName = GeneratorUtils.GenerateScreenPositionNormalized( ref dataCollector, UniqueId, CurrentPrecisionType, !dataCollector.UsingCustomScreenPos ); + } + } + } + string surfInstruction = varName + ".xy * _ScreenParams.xy"; + m_showErrorMessage = false; + string functionResult = ""; + string noiseTex = string.Empty; + switch ( m_selectedPatternInt ) + { + default: + case 0: + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT2, "clipScreen" + OutputId, surfInstruction ); + functionResult = dataCollector.AddFunctions( m_functionHeader, m_functionBody, "fmod(" + "clipScreen" + OutputId + ".x, 4)", "fmod(" + "clipScreen" + OutputId + ".y, 4)" ); + break; + case 1: + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT2, "clipScreen" + OutputId, surfInstruction ); + functionResult = dataCollector.AddFunctions( m_functionHeader, m_functionBody, "fmod(" + "clipScreen" + OutputId + ".x, 8)", "fmod(" + "clipScreen" + OutputId + ".y, 8)" ); + break; + case 2: + { + if( !m_texPort.IsConnected ) + { + m_showErrorMessage = true; + m_errorMessageTypeIsError = NodeMessageType.Warning; + m_errorMessageTooltip = "Please connect a texture object to the Pattern input port to generate a proper dithered pattern"; + return "0"; + } else + { + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; + noiseTex = m_texPort.GeneratePortInstructions( ref dataCollector ); + //GeneratePattern( ref dataCollector ); + dataCollector.AddToUniforms( UniqueId, "float4 " + noiseTex + "_TexelSize;", dataCollector.IsSRP ); +#if UNITY_2018_1_OR_NEWER + if( outsideGraph.SamplingMacros ) +#else + if( outsideGraph.SamplingMacros && !outsideGraph.IsStandardSurface ) +#endif + { + string sampler = string.Empty; + if( m_ssPort.IsConnected ) + { + sampler = m_ssPort.GeneratePortInstructions( ref dataCollector ); + } + else + { + sampler = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, noiseTex, VariableMode.Create ); + } + //if( outsideGraph.IsSRP ) + // functionResult = dataCollector.AddFunctions( m_functionHeader, m_functionBody, varName, noiseTex + ", " + sampler, noiseTex + "_TexelSize" ); + //else + functionResult = dataCollector.AddFunctions( m_functionHeader, m_functionBody, varName, noiseTex + ", " + sampler, noiseTex + "_TexelSize" ); + } + else + { + functionResult = dataCollector.AddFunctions( m_functionHeader, m_functionBody, varName, noiseTex, noiseTex + "_TexelSize" ); + } + } + } + break; + } + + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, "dither" + OutputId, functionResult ); + + if( m_inputPorts[ 0 ].IsConnected ) + { + string driver = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + dataCollector.AddLocalVariable( UniqueId, "dither" + OutputId+" = step( dither"+ OutputId + ", "+ driver + " );" ); + } + + //RegisterLocalVariable( 0, functionResult, ref dataCollector, "dither" + OutputId ); + m_outputPorts[ 0 ].SetLocalValue( "dither" + OutputId, dataCollector.PortCategory ); + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedPatternInt = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 15404 ) + { + m_customScreenPos = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + UpdatePorts(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedPatternInt ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_customScreenPos ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DitheringNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DitheringNode.cs.meta new file mode 100644 index 0000000..0fc9587 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/DitheringNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 284ebed5f88c13e45bc331b2df93aa75 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeDepthNormalNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeDepthNormalNode.cs new file mode 100644 index 0000000..eec5532 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeDepthNormalNode.cs @@ -0,0 +1,34 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Encode Depth Normal", "Miscellaneous", "Encodes both Depth and Normal values into a Float4 value" )] + public sealed class EncodeDepthNormalNode : ParentNode + { + private const string EncodeDepthNormalFunc = "EncodeDepthNormal( {0}, {1} )"; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "Depth" ); + AddInputPort( WirePortDataType.FLOAT3, false, "Normal" ); + AddOutputPort( WirePortDataType.FLOAT4, Constants.EmptyPortValue ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + dataCollector.AddToIncludes( UniqueId, Constants.UnityCgLibFuncs ); + string depthValue = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string normalValue = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + RegisterLocalVariable( 0, string.Format( EncodeDepthNormalFunc, depthValue, normalValue ), ref dataCollector, "encodedDepthNormal" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeDepthNormalNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeDepthNormalNode.cs.meta new file mode 100644 index 0000000..acc45fc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeDepthNormalNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cabbbe25e4b26b54c84e27007c08a7dd +timeCreated: 1513695146 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGBAHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGBAHlpNode.cs new file mode 100644 index 0000000..b3f95a0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGBAHlpNode.cs @@ -0,0 +1,27 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Encode Float RGBA", "Miscellaneous", "Encodes [0..1] range float into RGBA color, for storage in low precision render target" )] + public sealed class EncodeFloatRGBAHlpNode : HelperParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "EncodeFloatRGBA"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT, false ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_outputPorts[ 0 ].Name = "RGBA"; + m_previewShaderGUID = "c21569bf5b9371b4ca13c0c00abd5562"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "encodeFloatRGBA" + OutputId; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGBAHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGBAHlpNode.cs.meta new file mode 100644 index 0000000..0d25dc4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGBAHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6532496dc1791d94cbb46004000bda61 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGHlpNode.cs new file mode 100644 index 0000000..093389e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGHlpNode.cs @@ -0,0 +1,27 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Encode Float RG ", "Miscellaneous", "Encodes [0..1] range float into a float2" )] + public sealed class EncodeFloatRGHlpNode : HelperParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "EncodeFloatRG "; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT, false ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT2, false ); + m_outputPorts[ 0 ].Name = "RG"; + m_previewShaderGUID = "a44b520baa5c39e41bc69a22ea46f24d"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "encodeFloatRG" + OutputId; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGHlpNode.cs.meta new file mode 100644 index 0000000..e5ce8e8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeFloatRGHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d8bce5e7063ac6b4d93aaf15f7fd1b10 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeViewNormalStereoHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeViewNormalStereoHlpNode.cs new file mode 100644 index 0000000..767097b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeViewNormalStereoHlpNode.cs @@ -0,0 +1,27 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Encode View Normal Stereo", "Miscellaneous", "Encodes view space normal into two numbers in [0..1] range" )] + public sealed class EncodeViewNormalStereoHlpNode : HelperParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "EncodeViewNormalStereo"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ 0 ].Name = "XYZ"; + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT2, false ); + m_previewShaderGUID = "3d0b3d482b7246c4cb60fa73e6ceac6c"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "encodeViewNormalStereo" + OutputId; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeViewNormalStereoHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeViewNormalStereoHlpNode.cs.meta new file mode 100644 index 0000000..48043ee --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/EncodeViewNormalStereoHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 17511ec398441ac479a2dd77d2531837 +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/GammaToLinearNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/GammaToLinearNode.cs new file mode 100644 index 0000000..afeaae0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/GammaToLinearNode.cs @@ -0,0 +1,122 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Gamma To Linear", "Image Effects", "Converts color from gamma space to linear space" )] + public sealed class GammaToLinearNode : HelperParentNode + { + public readonly static string[] ModeListStr = { "Fast sRGB to Linear", "Exact sRGB to Linear" }; + public readonly static int[] ModeListInt = { 0, 1 }; + + public readonly static string[] ModeListStrLW = { "Fast sRGB to Linear", "Exact sRGB to Linear", "Gamma 2.0 to Linear", "Gamma 2.2 to Linear" }; + public readonly static int[] ModeListIntLW = { 0, 1, 2, 3 }; + + [SerializeField] + public int m_selectedMode = 0; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "GammaToLinearSpace"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ 0 ].Name = "RGB"; + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_autoWrapProperties = true; + m_previewShaderGUID = "e82a888a6ebdb1443823aafceaa051b9"; + m_textLabelWidth = 120; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "gammaToLinear" + OutputId; + } + + public override void DrawProperties() + { + base.DrawProperties(); + if( ContainerGraph.IsSRP ) + { + m_selectedMode = EditorGUILayoutIntPopup( "Mode", m_selectedMode, ModeListStrLW, ModeListIntLW ); + EditorGUILayout.HelpBox( "Fast sRGB: fast approximation from sRGB to Linear\n\nExact sRGB: a more expensive but exact calculation from sRGB to Linear.\n\nGamma 2.0: crude approximation from Gamma to Linear using a power of 2.0 gamma value\n\nGamma 2.2: an approximation from Gamma to Linear using a power of 2.2 gamma value", MessageType.None ); + } + else + { + m_selectedMode = EditorGUILayoutIntPopup( "Mode", m_selectedMode, ModeListStr, ModeListInt ); + EditorGUILayout.HelpBox( "Fast sRGB: fast approximation from sRGB to Linear\n\nExact sRGB: a more expensive but exact calculation from sRGB to Linear.", MessageType.None ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + string result = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + if( !dataCollector.IsSRP ) + { + m_selectedMode = Mathf.Min( m_selectedMode, 1 ); + + if( m_selectedMode == 1 ) + { + dataCollector.AddLocalVariable( UniqueId, "half3 " + m_localVarName + " = " + result + ";" ); + dataCollector.AddLocalVariable( UniqueId, m_localVarName + " = half3( GammaToLinearSpaceExact(" + m_localVarName + ".r), GammaToLinearSpaceExact(" + m_localVarName + ".g), GammaToLinearSpaceExact(" + m_localVarName + ".b) );" ); + return m_localVarName; + } + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + else + { + dataCollector.AddToIncludes( UniqueId, TemplateHelperFunctions.CoreCommonLib ); + dataCollector.AddToIncludes( UniqueId, TemplateHelperFunctions.CoreColorLib ); + switch( m_selectedMode ) + { + default: + case 0: + m_funcLWFormatOverride = "FastSRGBToLinear( {0} )"; + m_funcHDFormatOverride = "FastSRGBToLinear( {0} )"; + break; + case 1: + m_funcLWFormatOverride = "SRGBToLinear( {0} )"; + m_funcHDFormatOverride = "SRGBToLinear( {0} )"; + break; + case 2: + m_funcLWFormatOverride = "Gamma20ToLinear( {0} )"; + m_funcHDFormatOverride = "Gamma20ToLinear( {0} )"; + break; + case 3: + m_funcLWFormatOverride = "Gamma22ToLinear( {0} )"; + m_funcHDFormatOverride = "Gamma22ToLinear( {0} )"; + break; + } + + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedMode ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 11003 && UIUtils.CurrentShaderVersion() <= 14503 ) + { + bool fast = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + if( fast ) + m_selectedMode = 1; + } + + if( UIUtils.CurrentShaderVersion() > 14503 ) + { + m_selectedMode = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/GammaToLinearNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/GammaToLinearNode.cs.meta new file mode 100644 index 0000000..5c2ec6a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/GammaToLinearNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cb2775ac410d0134c85b7f1ac0a0399f +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/HelperParentNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/HelperParentNode.cs new file mode 100644 index 0000000..79c18bb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/HelperParentNode.cs @@ -0,0 +1,93 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +//https://docs.unity3d.com/Manual/SL-BuiltinFunctions.html + +using System; +using UnityEngine; +namespace AmplifyShaderEditor +{ + [Serializable] + public class HelperParentNode : ParentNode + { + [SerializeField] + protected string m_funcType = string.Empty; + + [SerializeField] + protected string m_funcLWFormatOverride = string.Empty; + + [SerializeField] + protected string m_funcHDFormatOverride = string.Empty; + + protected string m_localVarName = null; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_useInternalPortData = true; + } + + public override string GetIncludes() + { + return Constants.UnityCgLibFuncs; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + + if( !( dataCollector.IsTemplate && dataCollector.IsSRP ) ) + dataCollector.AddToIncludes( UniqueId, Constants.UnityCgLibFuncs ); + + string concatResults = string.Empty; + bool first = true; + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].Visible ) + { + if( !first ) + { + concatResults += " , "; + } + else + { + first = false; + } + + string result = string.Empty; + if( m_inputPorts[ i ].IsConnected ) + { + result = m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ); + } + else + { + result = m_inputPorts[ i ].WrappedInternalData; + } + + concatResults += result; + } + } + string finalResult = m_funcType + "( " + concatResults + " )"; + if( dataCollector.IsTemplate ) + { + if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.Lightweight && !string.IsNullOrEmpty( m_funcLWFormatOverride ) ) + { + finalResult = string.Format( m_funcLWFormatOverride, concatResults ); + } + else if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD && !string.IsNullOrEmpty( m_funcHDFormatOverride ) ) + { + finalResult = string.Format( m_funcHDFormatOverride, concatResults ); + } + + } + + RegisterLocalVariable( 0, finalResult, ref dataCollector, m_localVarName ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/HelperParentNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/HelperParentNode.cs.meta new file mode 100644 index 0000000..504a4cc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/HelperParentNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0eba64bdadd330743894a0623677cb83 +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LinearToGammaNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LinearToGammaNode.cs new file mode 100644 index 0000000..81171cc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LinearToGammaNode.cs @@ -0,0 +1,127 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Linear To Gamma", "Image Effects", "Converts color from linear space to gamma space" )] + public sealed class LinearToGammaNode : HelperParentNode + { + //[SerializeField] + //private bool m_exact = false; + + //private readonly static GUIContent LGExactContent = new GUIContent( "Exact Conversion", "Uses a precise version of the conversion, it's more expensive and often not needed." ); + + public readonly static string[] ModeListStr = { "Fast Linear to sRGB", "Exact Linear to sRGB" }; + public readonly static int[] ModeListInt = { 0, 1 }; + + public readonly static string[] ModeListStrLW = { "Fast Linear to sRGB", "Exact Linear to sRGB", "Linear to Gamma 2.0", "Linear to Gamma 2.2" }; + public readonly static int[] ModeListIntLW = { 0, 1, 2, 3 }; + + [SerializeField] + public int m_selectedMode = 0; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "LinearToGammaSpace"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ 0 ].Name = "RGB"; + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_autoWrapProperties = true; + m_previewShaderGUID = "9027c408b928c5c4d8b450712049d541"; + m_textLabelWidth = 120; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "linearToGamma" + OutputId; + } + + public override void DrawProperties() + { + base.DrawProperties(); + if( ContainerGraph.IsSRP ) + { + m_selectedMode = EditorGUILayoutIntPopup( "Mode", m_selectedMode, ModeListStrLW, ModeListIntLW ); + EditorGUILayout.HelpBox( "Fast Linear: fast approximation from Linear to sRGB\n\nExact Linear: a more expensive but exact calculation from Linear to sRGB.\n\nLinear 2.0: crude approximation from Linear to Gamma using a power of 1/2.0 gamma value\n\nLinear 2.2: an approximation from Linear to Gamma using a power of 1/2.2 gamma value", MessageType.None ); + } + else + { + m_selectedMode = EditorGUILayoutIntPopup( "Mode", m_selectedMode, ModeListStr, ModeListInt ); + EditorGUILayout.HelpBox( "Fast Linear: fast approximation from Linear to sRGB\n\nExact Linear: a more expensive but exact calculation from Linear to sRGB.", MessageType.None ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + string result = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + if( !dataCollector.IsSRP ) + { + m_selectedMode = Mathf.Min( m_selectedMode, 1 ); + + if( m_selectedMode == 1 ) + { + dataCollector.AddLocalVariable( UniqueId, "half3 " + m_localVarName + " = " + result + ";" ); + dataCollector.AddLocalVariable( UniqueId, m_localVarName + " = half3( LinearToGammaSpaceExact(" + m_localVarName + ".r), LinearToGammaSpaceExact(" + m_localVarName + ".g), LinearToGammaSpaceExact(" + m_localVarName + ".b) );" ); + return m_localVarName; + } + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + else + { + dataCollector.AddToIncludes( UniqueId, TemplateHelperFunctions.CoreCommonLib ); + dataCollector.AddToIncludes( UniqueId, TemplateHelperFunctions.CoreColorLib ); + switch( m_selectedMode ) + { + default: + case 0: + m_funcLWFormatOverride = "FastLinearToSRGB( {0} )"; + m_funcHDFormatOverride = "FastLinearToSRGB( {0} )"; + break; + case 1: + m_funcLWFormatOverride = "LinearToSRGB( {0} )"; + m_funcHDFormatOverride = "LinearToSRGB( {0} )"; + break; + case 2: + m_funcLWFormatOverride = "LinearToGamma20( {0} )"; + m_funcHDFormatOverride = "LinearToGamma20( {0} )"; + break; + case 3: + m_funcLWFormatOverride = "LinearToGamma22( {0} )"; + m_funcHDFormatOverride = "LinearToGamma22( {0} )"; + break; + } + + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedMode ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 11003 && UIUtils.CurrentShaderVersion() <= 14503 ) + { + bool fast = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + if( fast ) + m_selectedMode = 1; + } + + if( UIUtils.CurrentShaderVersion() > 14503 ) + { + m_selectedMode = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LinearToGammaNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LinearToGammaNode.cs.meta new file mode 100644 index 0000000..a4065b8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LinearToGammaNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a5b8a474628aeca4e86b1599f0b26ebc +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LuminanceHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LuminanceHlpNode.cs new file mode 100644 index 0000000..6f9dd6c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LuminanceHlpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Luminance", "Image Effects", "Converts color to luminance (grayscale)", Deprecated = true, DeprecatedAlternativeType = typeof( TFHCGrayscale ), DeprecatedAlternative = "Grayscale" )] + public sealed class LuminanceHlpNode : HelperParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "Luminance"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ 0 ].Name = "RGB"; + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT, false ); + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "luminance" + OutputId; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LuminanceHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LuminanceHlpNode.cs.meta new file mode 100644 index 0000000..0b33efd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/LuminanceHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e8567c2e3eb634a428819fbdfbff110f +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceLightDirHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceLightDirHlpNode.cs new file mode 100644 index 0000000..d862fda --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceLightDirHlpNode.cs @@ -0,0 +1,43 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Object Space Light Dir", "Light", "Computes object space light direction (not normalized)" )] + public sealed class ObjSpaceLightDirHlpNode : HelperParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "ObjSpaceLightDir"; + m_inputPorts[ 0 ].Visible = false; + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_outputPorts[ 0 ].Name = "XYZ"; + + AddOutputPort( WirePortDataType.FLOAT, "X" ); + AddOutputPort( WirePortDataType.FLOAT, "Y" ); + AddOutputPort( WirePortDataType.FLOAT, "Z" ); + + m_useInternalPortData = false; + m_previewShaderGUID = "c7852de24cec4a744b5358921e23feee"; + m_drawPreviewAsSphere = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate ) + { + //Template must have its Light Mode correctly configured on tags to work as intended + return GetOutputVectorItem( 0, outputId, dataCollector.TemplateDataCollectorInstance.GetObjectSpaceLightDir( CurrentPrecisionType ) ); + } + + dataCollector.AddToIncludes( UniqueId, Constants.UnityCgLibFuncs ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_POS ); + + string vertexPos = GeneratorUtils.GenerateVertexPosition( ref dataCollector, UniqueId, WirePortDataType.FLOAT4 ); + return GetOutputVectorItem( 0, outputId, GeneratorUtils.GenerateObjectLightDirection( ref dataCollector, UniqueId, CurrentPrecisionType, vertexPos ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceLightDirHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceLightDirHlpNode.cs.meta new file mode 100644 index 0000000..b8965aa --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceLightDirHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0da9baf35c74c7e468cbe50c3d23ccf0 +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceViewDirHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceViewDirHlpNode.cs new file mode 100644 index 0000000..12c1ef8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceViewDirHlpNode.cs @@ -0,0 +1,34 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Object Space View Dir", "Object Transform", "Object space direction (not normalized) from given object space vertex position towards the camera" )] + public sealed class ObjSpaceViewDirHlpNode : HelperParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "ObjSpaceViewDir"; + //TODO: revisit this later + m_funcLWFormatOverride = "( mul(GetWorldToObjectMatrix(), float4(_WorldSpaceCameraPos.xyz, 1)).xyz - {0}.xyz )"; + m_funcHDFormatOverride = "( mul(GetWorldToObjectMatrix(), float4(_WorldSpaceCameraPos.xyz, 1)).xyz - {0}.xyz )"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_inputPorts[ 0 ].Vector4InternalData = new UnityEngine.Vector4( 0, 0, 0, 1 ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_outputPorts[ 0 ].Name = "XYZ"; + AddOutputPort( WirePortDataType.FLOAT, "X" ); + AddOutputPort( WirePortDataType.FLOAT, "Y" ); + AddOutputPort( WirePortDataType.FLOAT, "Z" ); + m_previewShaderGUID = "c7852de24cec4a744b5358921e23feee"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "objectSpaceViewDir" + OutputId; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceViewDirHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceViewDirHlpNode.cs.meta new file mode 100644 index 0000000..fc6c58f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ObjSpaceViewDirHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 590b8e54b63ad344f8d8c372e4fc5ed5 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxMappingNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxMappingNode.cs new file mode 100644 index 0000000..929f41b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxMappingNode.cs @@ -0,0 +1,148 @@ +using UnityEngine; +using UnityEditor; + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Parallax Mapping", "UV Coordinates", "Calculates offseted UVs for parallax mapping" )] + public sealed class ParallaxMappingNode : ParentNode + { + private enum ParallaxType { Normal, Planar } + + [SerializeField] + private int m_selectedParallaxTypeInt = 0; + + [SerializeField] + private ParallaxType m_selectedParallaxType = ParallaxType.Normal; + + private readonly string[] m_parallaxTypeStr = { "Normal", "Planar" }; + + private int m_cachedPropertyId = -1; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT2, false, "UV" ); + AddInputPort( WirePortDataType.FLOAT, false, "Height" ); + AddInputPort( WirePortDataType.FLOAT, false, "Scale" ); + AddInputPort( WirePortDataType.FLOAT3, false, "ViewDir (tan)" ); + AddOutputPort( WirePortDataType.FLOAT2, "Out" ); + m_useInternalPortData = true; + m_autoDrawInternalPortData = true; + m_autoWrapProperties = true; + m_textLabelWidth = 105; + UpdateTitle(); + m_forceDrawPreviewAsPlane = true; + m_hasLeftDropdown = true; + m_previewShaderGUID = "589f12f68e00ac74286815aa56053fcc"; + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_ParallaxType" ); + + PreviewMaterial.SetFloat( m_cachedPropertyId, ( m_selectedParallaxType == ParallaxType.Normal ? 0 : 1 ) ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + + string textcoords = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string height = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string scale = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + string viewDirTan = m_inputPorts[ 3 ].GeneratePortInstructions( ref dataCollector ); + string localVarName = "Offset" + OutputId; + string calculation = ""; + + switch( m_selectedParallaxType ) + { + default: + case ParallaxType.Normal: + calculation = "( ( " + height + " - 1 ) * " + viewDirTan + ".xy * " + scale + " ) + " + textcoords; + break; + case ParallaxType.Planar: + calculation = "( ( " + height + " - 1 ) * ( " + viewDirTan + ".xy / " + viewDirTan + ".z ) * " + scale + " ) + " + textcoords; + break; + } + + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_outputPorts[ 0 ].DataType, localVarName, calculation ); + //dataCollector.AddToLocalVariables( UniqueId, m_currentPrecisionType, m_outputPorts[ 0 ].DataType, localVarName, calculation ); + return GetOutputVectorItem( 0, outputId, localVarName ); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_selectedParallaxTypeInt = m_upperLeftWidget.DrawWidget( this, m_selectedParallaxTypeInt, m_parallaxTypeStr ); + if( EditorGUI.EndChangeCheck() ) + { + switch( m_selectedParallaxTypeInt ) + { + default: + case 0: m_selectedParallaxType = ParallaxType.Normal; break; + case 1: m_selectedParallaxType = ParallaxType.Planar; break; + } + UpdateTitle(); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + + EditorGUI.BeginChangeCheck(); + m_selectedParallaxTypeInt = EditorGUILayoutPopup( "Parallax Type", m_selectedParallaxTypeInt, m_parallaxTypeStr ); + if( EditorGUI.EndChangeCheck() ) + { + switch( m_selectedParallaxTypeInt ) + { + default: + case 0: m_selectedParallaxType = ParallaxType.Normal; break; + case 1: m_selectedParallaxType = ParallaxType.Planar; break; + } + UpdateTitle(); + } + + EditorGUILayout.HelpBox( "Normal type does a cheaper approximation thats view dependent while Planar is more accurate but generates higher aliasing artifacts at steep angles.", MessageType.None ); + } + + + void UpdateTitle() + { + m_additionalContent.text = string.Format( Constants.SubTitleTypeFormatStr, m_parallaxTypeStr[ m_selectedParallaxTypeInt ] ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedParallaxType = (ParallaxType)Enum.Parse( typeof( ParallaxType ), GetCurrentParam( ref nodeParams ) ); + switch( m_selectedParallaxType ) + { + default: + case ParallaxType.Normal: m_selectedParallaxTypeInt = 0; break; + case ParallaxType.Planar: m_selectedParallaxTypeInt = 1; break; + } + UpdateTitle(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedParallaxType ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxMappingNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxMappingNode.cs.meta new file mode 100644 index 0000000..97f1c33 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxMappingNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 96d8f50a7481d5247b16cb16c053d5f6 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOcclusionMappingNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOcclusionMappingNode.cs new file mode 100644 index 0000000..7ebfe3c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOcclusionMappingNode.cs @@ -0,0 +1,650 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; + +using System; +namespace AmplifyShaderEditor +{ + enum POMTexTypes + { + Texture2D, + Texture3D, + TextureArray + }; + + [Serializable] + [NodeAttributes( "Parallax Occlusion Mapping", "UV Coordinates", "Calculates offseted UVs for parallax occlusion mapping" )] + public sealed class ParallaxOcclusionMappingNode : ParentNode + { + private const string ArrayIndexStr = "Array Index"; + private const string Tex3DSliceStr = "Tex3D Slice"; + + private readonly string[] m_channelTypeStr = { "Red Channel", "Green Channel", "Blue Channel", "Alpha Channel" }; + private readonly string[] m_channelTypeVal = { "r", "g", "b", "a" }; + + [SerializeField] + private int m_selectedChannelInt = 0; + + //[SerializeField] + //private int m_minSamples = 8; + + //[SerializeField] + //private int m_maxSamples = 16; + [SerializeField] + private InlineProperty m_inlineMinSamples = new InlineProperty( 8 ); + + [SerializeField] + private InlineProperty m_inlineMaxSamples = new InlineProperty( 16 ); + + [ SerializeField] + private int m_sidewallSteps = 2; + + [SerializeField] + private float m_defaultScale = 0.02f; + + [SerializeField] + private float m_defaultRefPlane = 0f; + + [SerializeField] + private bool m_clipEnds = false; + + [SerializeField] + private Vector2 m_tilling = new Vector2( 1, 1 ); + + [SerializeField] + private bool m_useCurvature = false; + + [SerializeField] + private Vector2 m_CurvatureVector = new Vector2( 0, 0 ); + + private string m_functionHeader = "POM( {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13} )"; + private string m_functionBody = string.Empty; + + //private const string WorldDirVarStr = "worldViewDir"; + + private InputPort m_uvPort; + private InputPort m_texPort; + private InputPort m_ssPort; + private InputPort m_scalePort; + private InputPort m_viewdirTanPort; + private InputPort m_refPlanePort; + private InputPort m_curvaturePort; + private InputPort m_arrayIndexPort; + + private OutputPort m_pomUVPort; + + private Vector4Node m_texCoordsHelper; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT2, false, "UV",-1,MasterNodePortCategory.Fragment,0); + AddInputPort( WirePortDataType.SAMPLER2D, false, "Tex", -1, MasterNodePortCategory.Fragment, 1 ); + AddInputPort( WirePortDataType.SAMPLERSTATE, false, "SS", -1, MasterNodePortCategory.Fragment, 7 ); + AddInputPort( WirePortDataType.FLOAT, false, "Scale", -1, MasterNodePortCategory.Fragment, 2 ); + AddInputPort( WirePortDataType.FLOAT3, false, "ViewDir (tan)", -1, MasterNodePortCategory.Fragment, 3 ); + AddInputPort( WirePortDataType.FLOAT, false, "Ref Plane", -1, MasterNodePortCategory.Fragment, 4 ); + AddInputPort( WirePortDataType.FLOAT2, false, "Curvature", -1, MasterNodePortCategory.Fragment, 5 ); + AddInputPort( WirePortDataType.FLOAT, false, ArrayIndexStr, -1, MasterNodePortCategory.Fragment, 6 ); + + AddOutputPort( WirePortDataType.FLOAT2, "Out" ); + + m_uvPort = GetInputPortByUniqueId( 0 ); + m_texPort = GetInputPortByUniqueId( 1 ); + m_texPort.CreatePortRestrictions( WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLER2DARRAY ); + m_ssPort = GetInputPortByUniqueId( 7 ); + m_ssPort.CreatePortRestrictions( WirePortDataType.SAMPLERSTATE ); + m_scalePort = GetInputPortByUniqueId( 2 ); + m_viewdirTanPort = GetInputPortByUniqueId( 3 ); + m_refPlanePort = GetInputPortByUniqueId( 4 ); + m_pomUVPort = m_outputPorts[ 0 ]; + m_curvaturePort = GetInputPortByUniqueId( 5 ); + m_arrayIndexPort = GetInputPortByUniqueId( 6 ); + + m_scalePort.FloatInternalData = 0.02f; + m_useInternalPortData = false; + m_textLabelWidth = 130; + m_autoWrapProperties = true; + m_curvaturePort.Visible = false; + m_arrayIndexPort.Visible = false; + UpdateSampler(); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_texPort.MatchPortToConnection(); + UpdateIndexPort(); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + if( !m_texPort.CheckValidType( type ) ) + { + m_texPort.FullDeleteConnections(); + UIUtils.ShowMessage( UniqueId, "Parallax Occlusion Mapping node only accepts SAMPLER2D, SAMPLER3D and SAMPLER2DARRAY input types.\nTexture Object connected changed to "+ type + ", connection was lost, please review and update accordingly.", MessageSeverity.Warning ); + } else + { + m_texPort.MatchPortToConnection(); + } + UpdateIndexPort(); + } + + public override void DrawProperties() + { + base.DrawProperties(); + + EditorGUI.BeginChangeCheck(); + m_selectedChannelInt = EditorGUILayoutPopup( "Channel", m_selectedChannelInt, m_channelTypeStr ); + if ( EditorGUI.EndChangeCheck() ) + { + UpdateSampler(); + } + //EditorGUIUtility.labelWidth = 105; + + //m_minSamples = EditorGUILayoutIntSlider( "Min Samples", m_minSamples, 1, 128 ); + UndoParentNode inst = this; + m_inlineMinSamples.CustomDrawer( ref inst, ( x ) => { m_inlineMinSamples.IntValue = EditorGUILayoutIntSlider( "Min Samples", m_inlineMinSamples.IntValue, 1, 128 ); }, "Min Samples" ); + //m_maxSamples = EditorGUILayoutIntSlider( "Max Samples", m_maxSamples, 1, 128 ); + m_inlineMaxSamples.CustomDrawer( ref inst, ( x ) => { m_inlineMaxSamples.IntValue = EditorGUILayoutIntSlider( "Max Samples", m_inlineMaxSamples.IntValue, 1, 128 ); }, "Max Samples" ); + + m_sidewallSteps = EditorGUILayoutIntSlider( "Sidewall Steps", m_sidewallSteps, 0, 10 ); + + EditorGUI.BeginDisabledGroup(m_scalePort.IsConnected ); + m_defaultScale = EditorGUILayoutSlider( "Default Scale", m_defaultScale, 0, 1 ); + EditorGUI.EndDisabledGroup(); + + EditorGUI.BeginDisabledGroup( m_refPlanePort.IsConnected ); + m_defaultRefPlane = EditorGUILayoutSlider( "Default Ref Plane", m_defaultRefPlane, 0, 1 ); + EditorGUI.EndDisabledGroup(); + //EditorGUIUtility.labelWidth = m_textLabelWidth; + + if( m_arrayIndexPort.Visible && !m_arrayIndexPort.IsConnected ) + { + m_arrayIndexPort.FloatInternalData = EditorGUILayoutFloatField( "Array Index", m_arrayIndexPort.FloatInternalData ); + } + + //float cached = EditorGUIUtility.labelWidth; + //EditorGUIUtility.labelWidth = 70; + m_clipEnds = EditorGUILayoutToggle( "Clip Edges", m_clipEnds ); + //EditorGUIUtility.labelWidth = -1; + //EditorGUIUtility.labelWidth = 100; + //EditorGUILayout.BeginHorizontal(); + //EditorGUI.BeginDisabledGroup( !m_clipEnds ); + //m_tilling = EditorGUILayout.Vector2Field( string.Empty, m_tilling ); + //EditorGUI.EndDisabledGroup(); + //EditorGUILayout.EndHorizontal(); + //EditorGUIUtility.labelWidth = cached; + + EditorGUI.BeginChangeCheck(); + m_useCurvature = EditorGUILayoutToggle( "Clip Silhouette", m_useCurvature ); + if ( EditorGUI.EndChangeCheck() ) + { + UpdateCurvaturePort(); + } + + EditorGUI.BeginDisabledGroup( !(m_useCurvature && !m_curvaturePort.IsConnected) ); + m_CurvatureVector = EditorGUILayoutVector2Field( string.Empty, m_CurvatureVector ); + EditorGUI.EndDisabledGroup(); + + EditorGUILayout.HelpBox( "WARNING:\nTex must be connected to a Texture Object for this node to work\n\nMin and Max samples:\nControl the minimum and maximum number of layers extruded\n\nSidewall Steps:\nThe number of interpolations done to smooth the extrusion result on the side of the layer extrusions, min is used at steep angles while max is used at orthogonal angles\n\n"+ + "Ref Plane:\nReference plane lets you adjust the starting reference height, 0 = deepen ground, 1 = raise ground, any value above 0 might cause distortions at higher angles\n\n"+ + "Clip Edges:\nThis will clip the ends of your uvs to give a more 3D look at the edges. It'll use the tilling given by your Heightmap input.\n\n"+ + "Clip Silhouette:\nTurning this on allows you to use the UV coordinates to clip the effect curvature in U or V axis, useful for cylinders, works best with 'Clip Edges' turned OFF", MessageType.None ); + } + + private void UpdateIndexPort() + { + m_arrayIndexPort.Visible = m_texPort.DataType != WirePortDataType.SAMPLER2D; + if( m_arrayIndexPort.Visible ) + { + m_arrayIndexPort.Name = m_texPort.DataType == WirePortDataType.SAMPLER3D ? Tex3DSliceStr : ArrayIndexStr; + } + SizeIsDirty = true; + } + + private void UpdateSampler() + { + m_texPort.Name = "Tex (" + m_channelTypeVal[ m_selectedChannelInt ].ToUpper() + ")"; + } + + private void UpdateCurvaturePort() + { + if ( m_useCurvature ) + m_curvaturePort.Visible = true; + else + m_curvaturePort.Visible = false; + + m_sizeIsDirty = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( !m_texPort.IsConnected ) + { + UIUtils.ShowMessage( UniqueId, "Parallax Occlusion Mapping node only works if a Texture Object is connected to its Tex (R) port" ); + return "0"; + } + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; + + string arrayIndex = m_arrayIndexPort.Visible?m_arrayIndexPort.GeneratePortInstructions( ref dataCollector ):"0"; + string textcoords = m_uvPort.GeneratePortInstructions( ref dataCollector ); + if( m_texPort.DataType == WirePortDataType.SAMPLER3D ) + { + string texName = "pomTexCoord" + OutputId; + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, texName, string.Format( "float3({0},{1})", textcoords, arrayIndex ) ); + textcoords = texName; + } + + string texture = m_texPort.GeneratePortInstructions( ref dataCollector ); + GeneratePOMfunction( ref dataCollector ); + string scale = m_defaultScale.ToString(); + if( m_scalePort.IsConnected ) + scale = m_scalePort.GeneratePortInstructions( ref dataCollector ); + + string viewDirTan = ""; + if ( !m_viewdirTanPort.IsConnected ) + { + if ( !dataCollector.DirtyNormal ) + dataCollector.ForceNormal = true; + + + if ( dataCollector.IsTemplate ) + { + viewDirTan = dataCollector.TemplateDataCollectorInstance.GetTangentViewDir( CurrentPrecisionType ); + } + else + { + viewDirTan = GeneratorUtils.GenerateViewDirection( ref dataCollector, UniqueId, ViewSpace.Tangent ); + //dataCollector.AddToInput( UniqueId, SurfaceInputs.VIEW_DIR, m_currentPrecisionType ); + //viewDirTan = Constants.InputVarStr + "." + UIUtils.GetInputValueFromType( SurfaceInputs.VIEW_DIR ); + } + } + else + { + viewDirTan = m_viewdirTanPort.GeneratePortInstructions( ref dataCollector ); + } + + //generate world normal + string normalWorld = string.Empty; + if ( dataCollector.IsTemplate ) + { + normalWorld = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( CurrentPrecisionType ); + } + else + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + normalWorld = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId ); + } + + string worldViewDir = GeneratorUtils.GenerateViewDirection( ref dataCollector, UniqueId, ViewSpace.World ); + + string dx = "ddx("+ textcoords + ")"; + string dy = "ddy(" + textcoords + ")"; + + string refPlane = m_defaultRefPlane.ToString(); + if ( m_refPlanePort.IsConnected ) + refPlane = m_refPlanePort.GeneratePortInstructions( ref dataCollector ); + + + string curvature = "float2("+ m_CurvatureVector.x + "," + m_CurvatureVector.y + ")"; + if ( m_useCurvature ) + { + dataCollector.AddToProperties( UniqueId, "[Header(Parallax Occlusion Mapping)]", 300 ); + dataCollector.AddToProperties( UniqueId, "_CurvFix(\"Curvature Bias\", Range( 0 , 1)) = 1", 301 ); + dataCollector.AddToUniforms( UniqueId, "uniform float _CurvFix;" ); + + if ( m_curvaturePort.IsConnected ) + curvature = m_curvaturePort.GeneratePortInstructions( ref dataCollector ); + } + + + string localVarName = "OffsetPOM" + OutputId; + string textCoordsST = string.Empty; + //string textureSTType = dataCollector.IsSRP ? "float4 " : "uniform float4 "; + //dataCollector.AddToUniforms( UniqueId, textureSTType + texture +"_ST;"); + if( m_texCoordsHelper == null ) + { + m_texCoordsHelper = CreateInstance(); + m_texCoordsHelper.ContainerGraph = ContainerGraph; + m_texCoordsHelper.SetBaseUniqueId( UniqueId, true ); + m_texCoordsHelper.RegisterPropertyOnInstancing = false; + m_texCoordsHelper.AddGlobalToSRPBatcher = true; + } + + if( outsideGraph.IsInstancedShader ) + { + m_texCoordsHelper.CurrentParameterType = PropertyType.InstancedProperty; + } + else + { + m_texCoordsHelper.CurrentParameterType = PropertyType.Global; + } + m_texCoordsHelper.ResetOutputLocals(); + m_texCoordsHelper.SetRawPropertyName( texture + "_ST" ); + textCoordsST = m_texCoordsHelper.GenerateShaderForOutput( 0, ref dataCollector, false ); + ////// + + string textureArgs = string.Empty; +#if UNITY_2018_1_OR_NEWER + if( outsideGraph.SamplingMacros || m_texPort.DataType == WirePortDataType.SAMPLER2DARRAY ) +#else + if( ( outsideGraph.SamplingMacros && !outsideGraph.IsStandardSurface ) || m_texPort.DataType == WirePortDataType.SAMPLER2DARRAY ) +#endif + { + string sampler = string.Empty; + if( m_ssPort.IsConnected ) + { + sampler = m_ssPort.GeneratePortInstructions( ref dataCollector ); + } + else + { + sampler = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, texture , VariableMode.Create ); + } + if( outsideGraph.IsSRP ) + { + textureArgs = texture + ", " + sampler; + } + else + { +#if !UNITY_2018_1_OR_NEWER + if( outsideGraph.IsStandardSurface ) + textureArgs = "UNITY_PASS_TEX2DARRAY(" + texture + ")"; + else +#endif + textureArgs = texture + ", " + sampler; + } + } + else + { + textureArgs = texture; + } + //string functionResult = dataCollector.AddFunctions( m_functionHeader, m_functionBody, ( (m_pomTexType == POMTexTypes.TextureArray) ? "UNITY_PASS_TEX2DARRAY(" + texture + ")": texture), textcoords, dx, dy, normalWorld, worldViewDir, viewDirTan, m_minSamples, m_maxSamples, scale, refPlane, texture+"_ST.xy", curvature, arrayIndex ); + string functionResult = dataCollector.AddFunctions( m_functionHeader, m_functionBody, textureArgs, textcoords, dx, dy, normalWorld, worldViewDir, viewDirTan, m_inlineMinSamples.GetValueOrProperty(false), m_inlineMinSamples.GetValueOrProperty(false), scale, refPlane, textCoordsST + ".xy", curvature, arrayIndex ); + + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_pomUVPort.DataType, localVarName, functionResult ); + + return GetOutputVectorItem( 0, outputId, localVarName ); + } + + private void GeneratePOMfunction( ref MasterNodeDataCollector dataCollector ) + { + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; + m_functionBody = string.Empty; + switch( m_texPort.DataType ) + { + default: + case WirePortDataType.SAMPLER2D: + { + string sampleParam = string.Empty; + sampleParam = GeneratorUtils.GetPropertyDeclaraction( "heightMap", TextureType.Texture2D, ", " ) + GeneratorUtils.GetSamplerDeclaraction( "samplerheightMap", TextureType.Texture2D, ", " ); + IOUtils.AddFunctionHeader( ref m_functionBody, string.Format("inline float2 POM( {0}float2 uvs, float2 dx, float2 dy, float3 normalWorld, float3 viewWorld, float3 viewDirTan, int minSamples, int maxSamples, float parallax, float refPlane, float2 tilling, float2 curv, int index )", sampleParam )); + } + break; + case WirePortDataType.SAMPLER3D: + { + string sampleParam = string.Empty; + sampleParam = GeneratorUtils.GetPropertyDeclaraction( "heightMap", TextureType.Texture3D, ", " ) + GeneratorUtils.GetSamplerDeclaraction( "samplerheightMap", TextureType.Texture3D, ", " ); + IOUtils.AddFunctionHeader( ref m_functionBody, string.Format("inline float2 POM( {0}float3 uvs, float3 dx, float3 dy, float3 normalWorld, float3 viewWorld, float3 viewDirTan, int minSamples, int maxSamples, float parallax, float refPlane, float2 tilling, float2 curv, int index )", sampleParam ) ); + } + break; + case WirePortDataType.SAMPLER2DARRAY: + if( outsideGraph.IsSRP ) + IOUtils.AddFunctionHeader( ref m_functionBody, "inline float2 POM( TEXTURE2D_ARRAY(heightMap), SAMPLER(samplerheightMap), float2 uvs, float2 dx, float2 dy, float3 normalWorld, float3 viewWorld, float3 viewDirTan, int minSamples, int maxSamples, float parallax, float refPlane, float2 tilling, float2 curv, int index )" ); + else +#if !UNITY_2018_1_OR_NEWER + if( outsideGraph.IsStandardSurface ) + IOUtils.AddFunctionHeader( ref m_functionBody, "inline float2 POM( UNITY_ARGS_TEX2DARRAY(heightMap), float2 uvs, float2 dx, float2 dy, float3 normalWorld, float3 viewWorld, float3 viewDirTan, int minSamples, int maxSamples, float parallax, float refPlane, float2 tilling, float2 curv, int index )" ); + else +#endif + IOUtils.AddFunctionHeader( ref m_functionBody, "inline float2 POM( UNITY_DECLARE_TEX2DARRAY_NOSAMPLER(heightMap), SamplerState samplerheightMap, float2 uvs, float2 dx, float2 dy, float3 normalWorld, float3 viewWorld, float3 viewDirTan, int minSamples, int maxSamples, float parallax, float refPlane, float2 tilling, float2 curv, int index )" ); + break; + } + + IOUtils.AddFunctionLine( ref m_functionBody, "float3 result = 0;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "int stepIndex = 0;" ); + //IOUtils.AddFunctionLine( ref m_functionBody, "int numSteps = ( int )( minSamples + dot( viewWorld, normalWorld ) * ( maxSamples - minSamples ) );" ); + //IOUtils.AddFunctionLine( ref m_functionBody, "int numSteps = ( int )lerp( maxSamples, minSamples, length( fwidth( uvs ) ) * 10 );" ); + IOUtils.AddFunctionLine( ref m_functionBody, "int numSteps = ( int )lerp( (float)maxSamples, (float)minSamples, saturate( dot( normalWorld, viewWorld ) ) );" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float layerHeight = 1.0 / numSteps;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float2 plane = parallax * ( viewDirTan.xy / viewDirTan.z );" ); + IOUtils.AddFunctionLine( ref m_functionBody, "uvs.xy += refPlane * plane;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float2 deltaTex = -plane * layerHeight;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float2 prevTexOffset = 0;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float prevRayZ = 1.0f;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float prevHeight = 0.0f;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float2 currTexOffset = deltaTex;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float currRayZ = 1.0f - layerHeight;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float currHeight = 0.0f;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float intersection = 0;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float2 finalTexOffset = 0;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "while ( stepIndex < numSteps + 1 )" ); + IOUtils.AddFunctionLine( ref m_functionBody, "{" ); + + string textureProp = "heightMap"; + string sampleState = "samplerheightMap"; + + string uvs = "uvs + currTexOffset"; + if( m_texPort.DataType == WirePortDataType.SAMPLER3D ) + uvs = "float3(uvs.xy + currTexOffset, uvs.z)"; + else if( m_texPort.DataType == WirePortDataType.SAMPLER2DARRAY ) + uvs = outsideGraph.IsSRP ? uvs + ", index" : "float3(" + uvs + ", index)"; + + string samplingCall = GeneratorUtils.GenerateSamplingCall( ref dataCollector, m_texPort.DataType, textureProp, sampleState, uvs, MipType.Derivative, "dx", "dy" ); + if( m_useCurvature ) + { + IOUtils.AddFunctionLine( ref m_functionBody, " \tresult.z = dot( curv, currTexOffset * currTexOffset );" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \tcurrHeight = " + samplingCall + "." + m_channelTypeVal[ m_selectedChannelInt ] + " * ( 1 - result.z );" ); + } + else + { + IOUtils.AddFunctionLine( ref m_functionBody, " \tcurrHeight = " + samplingCall + "." + m_channelTypeVal[ m_selectedChannelInt ] + ";" ); + } + IOUtils.AddFunctionLine( ref m_functionBody, " \tif ( currHeight > currRayZ )" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t{" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tstepIndex = numSteps + 1;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t}" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \telse" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t{" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tstepIndex++;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tprevTexOffset = currTexOffset;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tprevRayZ = currRayZ;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tprevHeight = currHeight;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tcurrTexOffset += deltaTex;" ); + if ( m_useCurvature ) + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tcurrRayZ -= layerHeight * ( 1 - result.z ) * (1+_CurvFix);" ); + else + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tcurrRayZ -= layerHeight;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t}" ); + IOUtils.AddFunctionLine( ref m_functionBody, "}" ); + + if ( m_sidewallSteps > 0 ) + { + IOUtils.AddFunctionLine( ref m_functionBody, "int sectionSteps = " + m_sidewallSteps + ";" ); + IOUtils.AddFunctionLine( ref m_functionBody, "int sectionIndex = 0;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float newZ = 0;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float newHeight = 0;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "while ( sectionIndex < sectionSteps )" ); + IOUtils.AddFunctionLine( ref m_functionBody, "{" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \tintersection = ( prevHeight - prevRayZ ) / ( prevHeight - currHeight + currRayZ - prevRayZ );" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \tfinalTexOffset = prevTexOffset + intersection * deltaTex;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \tnewZ = prevRayZ - intersection * layerHeight;" ); + + string uvs2 = "uvs + finalTexOffset"; + if( m_texPort.DataType == WirePortDataType.SAMPLER3D ) + uvs2 = "float3(uvs.xy + finalTexOffset, uvs.z)"; + else if( m_texPort.DataType == WirePortDataType.SAMPLER2DARRAY ) + uvs2 = outsideGraph.IsSRP ? uvs2 + ", index" : "float3(" + uvs2 + ", index)"; + + string samplingCall2 = GeneratorUtils.GenerateSamplingCall( ref dataCollector, m_texPort.DataType, textureProp, sampleState, uvs2, MipType.Derivative, "dx", "dy" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \tnewHeight = " + samplingCall2 + "." + m_channelTypeVal[ m_selectedChannelInt ] + ";" ); + + IOUtils.AddFunctionLine( ref m_functionBody, " \tif ( newHeight > newZ )" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t{" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tcurrTexOffset = finalTexOffset;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tcurrHeight = newHeight;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tcurrRayZ = newZ;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tdeltaTex = intersection * deltaTex;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tlayerHeight = intersection * layerHeight;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t}" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \telse" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t{" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tprevTexOffset = finalTexOffset;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tprevHeight = newHeight;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tprevRayZ = newZ;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tdeltaTex = ( 1 - intersection ) * deltaTex;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tlayerHeight = ( 1 - intersection ) * layerHeight;" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t}" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \tsectionIndex++;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "}" ); + } + else + { + IOUtils.AddFunctionLine( ref m_functionBody, "finalTexOffset = currTexOffset;" ); + } + + if ( m_useCurvature ) + { + IOUtils.AddFunctionLine( ref m_functionBody, "#ifdef UNITY_PASS_SHADOWCASTER" ); + IOUtils.AddFunctionLine( ref m_functionBody, "if ( unity_LightShadowBias.z == 0.0 )" ); + IOUtils.AddFunctionLine( ref m_functionBody, "{" ); + IOUtils.AddFunctionLine( ref m_functionBody, "#endif" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \tif ( result.z > 1 )" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tclip( -1 );" ); + IOUtils.AddFunctionLine( ref m_functionBody, "#ifdef UNITY_PASS_SHADOWCASTER" ); + IOUtils.AddFunctionLine( ref m_functionBody, "}" ); + IOUtils.AddFunctionLine( ref m_functionBody, "#endif" ); + } + + if ( m_clipEnds ) + { + IOUtils.AddFunctionLine( ref m_functionBody, "result.xy = uvs.xy + finalTexOffset;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "#ifdef UNITY_PASS_SHADOWCASTER" ); + IOUtils.AddFunctionLine( ref m_functionBody, "if ( unity_LightShadowBias.z == 0.0 )" ); + IOUtils.AddFunctionLine( ref m_functionBody, "{" ); + IOUtils.AddFunctionLine( ref m_functionBody, "#endif" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \tif ( result.x < 0 )" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tclip( -1 );" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \tif ( result.x > tilling.x )" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tclip( -1 );" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \tif ( result.y < 0 )" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tclip( -1 );" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \tif ( result.y > tilling.y )" ); + IOUtils.AddFunctionLine( ref m_functionBody, " \t \tclip( -1 );" ); + IOUtils.AddFunctionLine( ref m_functionBody, "#ifdef UNITY_PASS_SHADOWCASTER" ); + IOUtils.AddFunctionLine( ref m_functionBody, "}" ); + IOUtils.AddFunctionLine( ref m_functionBody, "#endif" ); + IOUtils.AddFunctionLine( ref m_functionBody, "return result.xy;" ); + } + else + { + IOUtils.AddFunctionLine( ref m_functionBody, "return uvs.xy + finalTexOffset;" ); + } + IOUtils.CloseFunctionBody( ref m_functionBody ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedChannelInt = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + //m_minSamples = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + //m_maxSamples = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() < 15406 ) + { + m_inlineMinSamples.IntValue = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_inlineMaxSamples.IntValue = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + else + { + m_inlineMinSamples.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + m_inlineMaxSamples.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + m_sidewallSteps = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_defaultScale = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + m_defaultRefPlane = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + if ( UIUtils.CurrentShaderVersion() > 3001 ) + { + m_clipEnds = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + string[] vector2Component = GetCurrentParam( ref nodeParams ).Split( IOUtils.VECTOR_SEPARATOR ); + if ( vector2Component.Length == 2 ) + { + m_tilling.x = Convert.ToSingle( vector2Component[ 0 ] ); + m_tilling.y = Convert.ToSingle( vector2Component[ 1 ] ); + } + } + + if ( UIUtils.CurrentShaderVersion() > 5005 ) + { + m_useCurvature = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_CurvatureVector = IOUtils.StringToVector2( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 13103 ) + { + //if( UIUtils.CurrentShaderVersion() < 15307 ) + //{ + // GetCurrentParam( ref nodeParams ); + // //bool arrayIndexVisible = false; + // //arrayIndexVisible = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + // //m_pomTexType = arrayIndexVisible ? POMTexTypes.TextureArray : POMTexTypes.Texture2D; + //} + //else + //{ + // GetCurrentParam( ref nodeParams ); + // //m_pomTexType = (POMTexTypes)Enum.Parse( typeof(POMTexTypes), GetCurrentParam( ref nodeParams ) ); + //} + if( UIUtils.CurrentShaderVersion() <= 18201 ) + { + GetCurrentParam( ref nodeParams ); + } + UpdateIndexPort(); + } + + UpdateSampler(); + //GeneratePOMfunction( string.Empty ); + UpdateCurvaturePort(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedChannelInt ); + //IOUtils.AddFieldValueToString( ref nodeInfo, m_minSamples ); + //IOUtils.AddFieldValueToString( ref nodeInfo, m_maxSamples ); + m_inlineMinSamples.WriteToString( ref nodeInfo ); + m_inlineMaxSamples.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_sidewallSteps ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultScale ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultRefPlane ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_clipEnds ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_tilling.x.ToString() + IOUtils.VECTOR_SEPARATOR + m_tilling.y.ToString() ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_useCurvature ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Vector2ToString( m_CurvatureVector ) ); + //IOUtils.AddFieldValueToString( ref nodeInfo, m_useTextureArray ); + //IOUtils.AddFieldValueToString( ref nodeInfo, true ); + } + + public override void Destroy() + { + base.Destroy(); + //Not calling m_texCoordsHelper.Destroy() on purpose so UIUtils does not incorrectly unregister stuff + if( m_texCoordsHelper != null ) + { + DestroyImmediate( m_texCoordsHelper ); + m_texCoordsHelper = null; + } + + + m_uvPort = null; + m_texPort = null; + m_scalePort = null; + m_viewdirTanPort = null; + m_pomUVPort = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOcclusionMappingNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOcclusionMappingNode.cs.meta new file mode 100644 index 0000000..3a7443c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOcclusionMappingNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b2350150f3f2a0443827ca8925d5e759 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOffsetHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOffsetHlpNode.cs new file mode 100644 index 0000000..26b8a54 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOffsetHlpNode.cs @@ -0,0 +1,47 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Parallax Offset", "UV Coordinates", "Calculates UV offset for parallax normal mapping" )] + public sealed class ParallaxOffsetHlpNode : HelperParentNode + { + public readonly string[] ParallaxOffsetFunc = + { + "inline float2 ParallaxOffset( half h, half height, half3 viewDir )\n", + "{\n", + "\th = h * height - height/2.0;\n", + "\tfloat3 v = normalize( viewDir );\n", + "\tv.z += 0.42;\n", + "\treturn h* (v.xy / v.z);\n", + "}\n" + }; + + void OnSRPActionEvent( int outputId, ref MasterNodeDataCollector dataCollector ) + { + dataCollector.AddFunction( ParallaxOffsetFunc[ 0 ], ParallaxOffsetFunc, false ); + } + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "ParallaxOffset"; + m_inputPorts[ 0 ].ChangeProperties( "H", WirePortDataType.FLOAT, false ); + AddInputPort( WirePortDataType.FLOAT, false, "Height" ); + AddInputPort( WirePortDataType.FLOAT3, false, "ViewDir (tan)" ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT2, false ); + m_outputPorts[ 0 ].Name = "Out"; + OnHDAction = OnSRPActionEvent; + OnLightweightAction = OnSRPActionEvent; + m_previewShaderGUID = "6085f804c6fbf354eac039c11feaa7cc"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "paralaxOffset" + OutputId; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOffsetHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOffsetHlpNode.cs.meta new file mode 100644 index 0000000..76316ee --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ParallaxOffsetHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 83b7d6fe57585b74d80c429aef719200 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ShadeVertexLightsHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ShadeVertexLightsHlpNode.cs new file mode 100644 index 0000000..e337326 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ShadeVertexLightsHlpNode.cs @@ -0,0 +1,105 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Shade Vertex Lights", "Light", "Computes illumination from four per-vertex lights and ambient, given object space position & normal" )] + public sealed class ShadeVertexLightsHlpNode : ParentNode + { + private const string HelperMessage = "Shade Vertex Lights node only outputs correct results on\nTemplate Vertex/Frag shaders with their LightMode set to Vertex."; + private const string ShadeVertexLightFunc = "ShadeVertexLightsFull({0},{1},{2},{3})"; + private const string LightCount = "Light Count"; + private const string IsSpotlight = "Is Spotlight"; + private const int MinLightCount = 0; + private const int MaxLightCount = 8; + [SerializeField] + private int m_lightCount = 4; + + [SerializeField] + private bool m_enableSpotlight = false; + + private int _LightCountId; + private int _IsSpotlightId; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT4, false, "Vertex Position" ); + AddInputPort( WirePortDataType.FLOAT3, false, "Vertex Normal" ); + AddOutputPort( WirePortDataType.FLOAT3, Constants.EmptyPortValue ); + m_useInternalPortData = true; + //m_autoWrapProperties = true; + m_textLabelWidth = 90; + m_previewShaderGUID = "3b6075034a85ad047be2d31dd213fb4f"; + } + + public override void OnEnable() + { + base.OnEnable(); + _LightCountId = Shader.PropertyToID( "_LightCount" ); + _IsSpotlightId = Shader.PropertyToID( "_IsSpotlight" ); + } + + public override void DrawProperties() + { + base.DrawProperties(); + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr, DrawGeneralProperties ); + EditorGUILayout.HelpBox( HelperMessage, MessageType.Info ); + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + PreviewMaterial.SetInt( _LightCountId, m_lightCount ); + PreviewMaterial.SetInt( _IsSpotlightId, ( m_enableSpotlight ? 1 : 0 ) ); + + } + + void DrawGeneralProperties() + { + m_lightCount = EditorGUILayoutIntSlider( LightCount, m_lightCount, MinLightCount, MaxLightCount ); + m_enableSpotlight = EditorGUILayoutToggle( IsSpotlight, m_enableSpotlight ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.SurfaceShader ) + UIUtils.ShowMessage( UniqueId, HelperMessage, MessageSeverity.Warning ); + + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + dataCollector.AddToIncludes( UniqueId, Constants.UnityCgLibFuncs ); + + string vertexPosition = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string vertexNormal = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + string value = string.Format( ShadeVertexLightFunc, vertexPosition, vertexNormal, m_lightCount, m_enableSpotlight.ToString().ToLower() ); + + RegisterLocalVariable( 0, value, ref dataCollector, "shadeVertexLight" + OutputId ); + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 14301 ) + { + m_lightCount = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_enableSpotlight = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_lightCount ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_enableSpotlight ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ShadeVertexLightsHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ShadeVertexLightsHlpNode.cs.meta new file mode 100644 index 0000000..100f876 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/ShadeVertexLightsHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 74f44334b702bce4ba8e2681dc80fe3c +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/SurfaceDepthNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/SurfaceDepthNode.cs new file mode 100644 index 0000000..93e01b4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/SurfaceDepthNode.cs @@ -0,0 +1,184 @@ +using UnityEngine; +using UnityEditor; + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Surface Depth", "Surface Data", "Returns the surface view depth" )] + public sealed class SurfaceDepthNode : ParentNode + { + [SerializeField] + private int m_viewSpaceInt = 0; + + private readonly string[] m_viewSpaceStr = { "Eye Space", "0-1 Space" }; + private readonly string[] m_vertexNameStr = { "eyeDepth", "clampDepth" }; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "Vertex Position" ); + AddOutputPort( WirePortDataType.FLOAT, "Depth" ); + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + SetAdditonalTitleText( string.Format( Constants.SubTitleSpaceFormatStr, m_viewSpaceStr[ m_viewSpaceInt ] ) ); + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_viewSpaceInt = m_upperLeftWidget.DrawWidget( this, m_viewSpaceInt, m_viewSpaceStr ); + if( EditorGUI.EndChangeCheck() ) + { + SetAdditonalTitleText( string.Format( Constants.SubTitleSpaceFormatStr, m_viewSpaceStr[ m_viewSpaceInt ] ) ); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_viewSpaceInt = EditorGUILayoutPopup( "View Space", m_viewSpaceInt, m_viewSpaceStr ); + if( EditorGUI.EndChangeCheck() ) + { + SetAdditonalTitleText( string.Format( Constants.SubTitleSpaceFormatStr, m_viewSpaceStr[ m_viewSpaceInt ] ) ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate ) + { + if( m_inputPorts[ 0 ].IsConnected ) + { + string space = string.Empty; + if( m_viewSpaceInt == 1 ) + space = " * _ProjectionParams.w"; + + string varName = "customSurfaceDepth" + OutputId; + GenerateInputInVertex( ref dataCollector, 0, varName, false ); + string instruction = "-UnityObjectToViewPos( " + varName + " ).z" + space; + if( dataCollector.IsSRP ) + instruction = "-TransformWorldToView(TransformObjectToWorld( " + varName + " )).z" + space; + string eyeVarName = "customEye" + OutputId; + dataCollector.TemplateDataCollectorInstance.RegisterCustomInterpolatedData( eyeVarName, WirePortDataType.FLOAT, CurrentPrecisionType, instruction ); + return eyeVarName; + } + else + { + return dataCollector.TemplateDataCollectorInstance.GetEyeDepth( CurrentPrecisionType, true, MasterNodePortCategory.Fragment, m_viewSpaceInt ); + } + } + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + string vertexVarName = string.Empty; + if( m_inputPorts[ 0 ].IsConnected ) + { + vertexVarName = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + } + else + { + vertexVarName = Constants.VertexShaderInputStr + ".vertex.xyz"; + } + + string vertexSpace = m_viewSpaceInt == 1 ? " * _ProjectionParams.w" : ""; + string vertexInstruction = "-UnityObjectToViewPos( " + vertexVarName + " ).z" + vertexSpace; + dataCollector.AddVertexInstruction( "float " + m_vertexNameStr[ m_viewSpaceInt ] + " = " + vertexInstruction, UniqueId ); + + return m_vertexNameStr[ m_viewSpaceInt ]; + } + + dataCollector.AddToIncludes( UniqueId, Constants.UnityShaderVariables ); + + + if( dataCollector.TesselationActive ) + { + if( m_inputPorts[ 0 ].IsConnected ) + { + string space = string.Empty; + if( m_viewSpaceInt == 1 ) + space = " * _ProjectionParams.w"; + + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + RegisterLocalVariable( 0, string.Format( "-UnityObjectToViewPos( {0} ).z", value ) + space, ref dataCollector, "customSurfaceDepth" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + else + { + string eyeDepth = GeneratorUtils.GenerateScreenDepthOnFrag( ref dataCollector, UniqueId, CurrentPrecisionType ); + if( m_viewSpaceInt == 1 ) + { + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, m_vertexNameStr[ 1 ], eyeDepth + " * _ProjectionParams.w" ); + return m_vertexNameStr[ 1 ]; + } + else + { + return eyeDepth; + } + } + } + else + { + + string space = string.Empty; + if( m_viewSpaceInt == 1 ) + space = " * _ProjectionParams.w"; + + if( m_inputPorts[ 0 ].IsConnected ) + { + string varName = "customSurfaceDepth" + OutputId; + GenerateInputInVertex( ref dataCollector, 0, varName, false ); + dataCollector.AddToInput( UniqueId, varName, WirePortDataType.FLOAT ); + string instruction = "-UnityObjectToViewPos( " + varName + " ).z" + space; + dataCollector.AddToVertexLocalVariables( UniqueId , Constants.VertexShaderOutputStr + "." + varName + " = " + instruction+";" ); + return Constants.InputVarStr + "." + varName; + } + else + { + dataCollector.AddToInput( UniqueId, m_vertexNameStr[ m_viewSpaceInt ], WirePortDataType.FLOAT ); + string instruction = "-UnityObjectToViewPos( " + Constants.VertexShaderInputStr + ".vertex.xyz ).z" + space; + dataCollector.AddToVertexLocalVariables( UniqueId , Constants.VertexShaderOutputStr + "." + m_vertexNameStr[ m_viewSpaceInt ] + " = " + instruction+";" ); + return Constants.InputVarStr + "." + m_vertexNameStr[ m_viewSpaceInt ]; + } + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_viewSpaceInt = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + SetAdditonalTitleText( string.Format( Constants.SubTitleSpaceFormatStr, m_viewSpaceStr[ m_viewSpaceInt ] ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_viewSpaceInt ); + } + } + +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/SurfaceDepthNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/SurfaceDepthNode.cs.meta new file mode 100644 index 0000000..e1aa08a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/SurfaceDepthNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d3b0855152b8c5d478f236423cfb1959 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/TriplanarNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/TriplanarNode.cs new file mode 100644 index 0000000..7e91741 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/TriplanarNode.cs @@ -0,0 +1,1536 @@ +using UnityEngine; +using UnityEditor; + +using System; +using System.Collections.Generic; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Triplanar Sample", "Textures", "Triplanar Mapping" )] + public sealed class TriplanarNode : ParentNode + { + [SerializeField] + private string m_uniqueName; + + private bool m_editPropertyNameMode = false; + [SerializeField] + private string m_propertyInspectorName = "Triplanar Sampler"; + + private enum TriplanarType { Spherical, Cylindrical } + + [SerializeField] + private TriplanarType m_selectedTriplanarType = TriplanarType.Spherical; + + private enum TriplanarSpace { Object, World } + + [SerializeField] + private TriplanarSpace m_selectedTriplanarSpace = TriplanarSpace.World; + + [SerializeField] + private bool m_normalCorrection = false; + + [SerializeField] + private ViewSpace m_normalSpace = ViewSpace.Tangent; + + [SerializeField] + private TexturePropertyNode m_topTexture; + [SerializeField] + private TexturePropertyNode m_midTexture; + [SerializeField] + private TexturePropertyNode m_botTexture; + + bool m_texturesInitialize = false; + + [SerializeField] + private string m_tempTopInspectorName = string.Empty; + [SerializeField] + private string m_tempTopName = string.Empty; + private TexturePropertyValues m_tempTopDefaultValue = TexturePropertyValues.white; + private int m_tempTopOrderIndex = -1; + private Texture2D m_tempTopDefaultTexture = null; + + private string m_tempMidInspectorName = string.Empty; + private string m_tempMidName = string.Empty; + private TexturePropertyValues m_tempMidDefaultValue = TexturePropertyValues.white; + private int m_tempMidOrderIndex = -1; + private Texture2D m_tempMidDefaultTexture = null; + + private string m_tempBotInspectorName = string.Empty; + private string m_tempBotName = string.Empty; + private TexturePropertyValues m_tempBotDefaultValue = TexturePropertyValues.white; + private int m_tempBotOrderIndex = -1; + private Texture2D m_tempBotDefaultTexture = null; + + private bool m_topTextureFoldout = true; + private bool m_midTextureFoldout = true; + private bool m_botTextureFoldout = true; + + private InputPort m_topTexPort; + private InputPort m_midTexPort; + private InputPort m_botTexPort; + private InputPort m_tilingPort; + private InputPort m_falloffPort; + private InputPort m_topIndexPort; + private InputPort m_midIndexPort; + private InputPort m_botIndexPort; + private InputPort m_scalePort; + private InputPort m_posPort; + + + private readonly string m_functionCall = "TriplanarSampling{0}( {1} )"; + private readonly string m_functionHeader = "inline {0} TriplanarSampling{1}( {2}float3 worldPos, float3 worldNormal, float falloff, float2 tiling, float3 normalScale, float3 index )"; + + private readonly List m_functionSamplingBodyProj = new List() { + "float3 projNormal = ( pow( abs( worldNormal ), falloff ) );", + "projNormal /= ( projNormal.x + projNormal.y + projNormal.z ) + 0.00001;",// 0.00001 is to prevent division by 0 + "float3 nsign = sign( worldNormal );" + }; + + private readonly List m_functionSamplingBodyNegProj = new List() { + "float negProjNormalY = max( 0, projNormal.y * -nsign.y );", + "projNormal.y = max( 0, projNormal.y * nsign.y );" + }; + + private readonly List m_functionSamplingBodySignsSphere = new List() { + "xNorm.xyz = half3( {0}( xNorm{1} ).xy * float2( nsign.x, 1.0 ) + worldNormal.zy, worldNormal.x ).zyx;", + "yNorm.xyz = half3( {0}( yNorm{1} ).xy * float2( nsign.y, 1.0 ) + worldNormal.xz, worldNormal.y ).xzy;", + "zNorm.xyz = half3( {0}( zNorm{1} ).xy * float2( -nsign.z, 1.0 ) + worldNormal.xy, worldNormal.z ).xyz;" + }; + + private readonly List m_functionSamplingBodySignsSphereScale = new List() { + "xNorm.xyz = half3( {0}( xNorm, normalScale.y ).xy * float2( nsign.x, 1.0 ) + worldNormal.zy, worldNormal.x ).zyx;", + "yNorm.xyz = half3( {0}( yNorm, normalScale.x ).xy * float2( nsign.y, 1.0 ) + worldNormal.xz, worldNormal.y ).xzy;", + "zNorm.xyz = half3( {0}( zNorm, normalScale.y ).xy * float2( -nsign.z, 1.0 ) + worldNormal.xy, worldNormal.z ).xyz;" + }; + + private readonly List m_functionSamplingBodySignsCylinder = new List() { + "yNormN.xyz = half3( {0}( yNormN {1}).xy * float2( nsign.y, 1.0 ) + worldNormal.xz, worldNormal.y ).xzy;" + }; + + private readonly List m_functionSamplingBodySignsCylinderScale = new List() { + "yNormN.xyz = half3( {0}( yNormN, normalScale.z ).xy * float2( nsign.y, 1.0 ) + worldNormal.xz, worldNormal.y ).xzy;" + }; + + private readonly List m_functionSamplingBodyReturnSphereNormalize = new List() { + "return normalize( xNorm.xyz * projNormal.x + yNorm.xyz * projNormal.y + zNorm.xyz * projNormal.z );" + }; + + private readonly List m_functionSamplingBodyReturnCylinderNormalize = new List() { + "return normalize( xNorm.xyz * projNormal.x + yNorm.xyz * projNormal.y + yNormN.xyz * negProjNormalY + zNorm.xyz * projNormal.z );" + }; + + private readonly List m_functionSamplingBodyReturnSphere = new List() { + "return xNorm * projNormal.x + yNorm * projNormal.y + zNorm * projNormal.z;" + }; + + private readonly List m_functionSamplingBodyReturnCylinder = new List() { + "return xNorm * projNormal.x + yNorm * projNormal.y + yNormN * negProjNormalY + zNorm * projNormal.z;" + }; + + private Rect m_allPicker; + private Rect m_startPicker; + private Rect m_pickerButton; + private bool m_editing; + + void ConvertListTo( MasterNodeDataCollector dataCollector, bool scaleInfo, List original, List dest ) + { + int count = original.Count; + string scale = string.Empty; + string func = string.Empty; + bool applyScale = false; + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + if( dataCollector.TemplateDataCollectorInstance.IsHDRP ) + { + func = "UnpackNormalmapRGorAG"; + } + else + { + func = "UnpackNormalScale"; + } + + if( !scaleInfo ) + { + scale = " , 1.0"; + applyScale = true; + } + } + else + { + func = scaleInfo ? "UnpackScaleNormal" : "UnpackNormal"; + applyScale = !scaleInfo; + } + + for( int i = 0; i < count; i++ ) + { + if( applyScale ) + dest.Add( string.Format( original[ i ], func, scale ) ); + else + dest.Add( string.Format( original[ i ], func ) ); + } + } + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.SAMPLER2D, false, "Top", -1, MasterNodePortCategory.Fragment, 0 ); + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER2DARRAY ); + AddInputPort( WirePortDataType.FLOAT, false, "Top Index", -1, MasterNodePortCategory.Fragment, 5 ); + AddInputPort( WirePortDataType.SAMPLER2D, false, "Middle", -1, MasterNodePortCategory.Fragment, 1 ); + m_inputPorts[ 2 ].CreatePortRestrictions( WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER2DARRAY ); + AddInputPort( WirePortDataType.FLOAT, false, "Mid Index", -1, MasterNodePortCategory.Fragment, 6 ); + AddInputPort( WirePortDataType.SAMPLER2D, false, "Bottom", -1, MasterNodePortCategory.Fragment, 2 ); + m_inputPorts[ 4 ].CreatePortRestrictions( WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER2DARRAY ); + AddInputPort( WirePortDataType.FLOAT, false, "Bot Index", -1, MasterNodePortCategory.Fragment, 7 ); + AddInputPort( WirePortDataType.FLOAT3, false, "Pos", -1, MasterNodePortCategory.Fragment, 9 ); + AddInputPort( WirePortDataType.FLOAT3, false, "Scale", -1, MasterNodePortCategory.Fragment, 8 ); + AddInputPort( WirePortDataType.FLOAT2, false, "Tiling", -1, MasterNodePortCategory.Fragment, 3 ); + AddInputPort( WirePortDataType.FLOAT, false, "Falloff", -1, MasterNodePortCategory.Fragment, 4 ); + AddOutputColorPorts( "RGBA" ); + m_useInternalPortData = true; + m_topTexPort = InputPorts[ 0 ]; + m_topIndexPort = InputPorts[ 1 ]; + m_midTexPort = InputPorts[ 2 ]; + m_midIndexPort = InputPorts[ 3 ]; + m_botTexPort = InputPorts[ 4 ]; + m_botIndexPort = InputPorts[ 5 ]; + m_posPort = InputPorts[ 6 ]; + m_scalePort = InputPorts[ 7 ]; + m_tilingPort = InputPorts[ 8 ]; + m_falloffPort = InputPorts[ 9 ]; + + m_scalePort.Visible = false; + m_scalePort.Vector3InternalData = Vector3.one; + m_tilingPort.FloatInternalData = 1; + m_tilingPort.Vector2InternalData = Vector2.one; + m_topIndexPort.FloatInternalData = 1; + m_falloffPort.FloatInternalData = 1; + m_topIndexPort.Visible = false; + m_selectedLocation = PreviewLocation.TopCenter; + m_marginPreviewLeft = 43; + m_drawPreviewAsSphere = true; + m_drawPreviewExpander = false; + m_drawPreview = true; + m_showPreview = true; + m_autoDrawInternalPortData = false; + m_textLabelWidth = 125; + //m_propertyInspectorName = "Triplanar Sampler"; + m_previewShaderGUID = "8723015ec59743143aadfbe480e34391"; + } + + public void ReadPropertiesData() + { + // Top + if( UIUtils.IsUniformNameAvailable( m_tempTopName ) ) + { + UIUtils.ReleaseUniformName( UniqueId, m_topTexture.PropertyName ); + if( !string.IsNullOrEmpty( m_tempTopInspectorName ) ) + { + m_topTexture.SetInspectorName( m_tempTopInspectorName ); + } + if( !string.IsNullOrEmpty( m_tempTopName ) ) + m_topTexture.SetPropertyName( m_tempTopName ); + UIUtils.RegisterUniformName( UniqueId, m_topTexture.PropertyName ); + } + m_topTexture.DefaultTextureValue = m_tempTopDefaultValue; + m_topTexture.OrderIndex = m_tempTopOrderIndex; + m_topTexture.DefaultValue = m_tempTopDefaultTexture; + //m_topTexture.SetMaterialMode( UIUtils.CurrentWindow.CurrentGraph.CurrentMaterial, true ); + + // Mid + if( UIUtils.IsUniformNameAvailable( m_tempMidName ) ) + { + UIUtils.ReleaseUniformName( UniqueId, m_midTexture.PropertyName ); + if( !string.IsNullOrEmpty( m_tempMidInspectorName ) ) + m_midTexture.SetInspectorName( m_tempMidInspectorName ); + if( !string.IsNullOrEmpty( m_tempMidName ) ) + m_midTexture.SetPropertyName( m_tempMidName ); + UIUtils.RegisterUniformName( UniqueId, m_midTexture.PropertyName ); + } + m_midTexture.DefaultTextureValue = m_tempMidDefaultValue; + m_midTexture.OrderIndex = m_tempMidOrderIndex; + m_midTexture.DefaultValue = m_tempMidDefaultTexture; + + // Bot + if( UIUtils.IsUniformNameAvailable( m_tempBotName ) ) + { + UIUtils.ReleaseUniformName( UniqueId, m_botTexture.PropertyName ); + if( !string.IsNullOrEmpty( m_tempBotInspectorName ) ) + m_botTexture.SetInspectorName( m_tempBotInspectorName ); + if( !string.IsNullOrEmpty( m_tempBotName ) ) + m_botTexture.SetPropertyName( m_tempBotName ); + UIUtils.RegisterUniformName( UniqueId, m_botTexture.PropertyName ); + } + m_botTexture.DefaultTextureValue = m_tempBotDefaultValue; + m_botTexture.OrderIndex = m_tempBotOrderIndex; + m_botTexture.DefaultValue = m_tempBotDefaultTexture; + } + + public override void SetMaterialMode( Material mat, bool fetchMaterialValues ) + { + base.SetMaterialMode( mat, fetchMaterialValues ); + + if( !m_texturesInitialize ) + return; + + m_topTexture.SetMaterialMode( mat, fetchMaterialValues ); + m_midTexture.SetMaterialMode( mat, fetchMaterialValues ); + m_botTexture.SetMaterialMode( mat, fetchMaterialValues ); + } + + public void Init() + { + if( m_texturesInitialize ) + return; + else + m_texturesInitialize = true; + + // Top + if( m_topTexture == null ) + { + m_topTexture = ScriptableObject.CreateInstance(); + } + m_topTexture.ContainerGraph = ContainerGraph; + m_topTexture.CustomPrefix = "Top Texture "; + m_topTexture.UniqueId = UniqueId; + m_topTexture.DrawAutocast = false; + m_topTexture.CurrentParameterType = PropertyType.Property; + + // Mid + if( m_midTexture == null ) + { + m_midTexture = ScriptableObject.CreateInstance(); + } + m_midTexture.ContainerGraph = ContainerGraph; + m_midTexture.CustomPrefix = "Mid Texture "; + m_midTexture.UniqueId = UniqueId; + m_midTexture.DrawAutocast = false; + m_midTexture.CurrentParameterType = PropertyType.Property; + + // Bot + if( m_botTexture == null ) + { + m_botTexture = ScriptableObject.CreateInstance(); + } + m_botTexture.ContainerGraph = ContainerGraph; + m_botTexture.CustomPrefix = "Bot Texture "; + m_botTexture.UniqueId = UniqueId; + m_botTexture.DrawAutocast = false; + m_botTexture.CurrentParameterType = PropertyType.Property; + + if( m_materialMode ) + SetDelayedMaterialMode( ContainerGraph.CurrentMaterial ); + + if( m_nodeAttribs != null ) + m_uniqueName = m_nodeAttribs.Name + UniqueId; + + ConfigurePorts(); + + ReRegisterPorts(); + } + + public override void Destroy() + { + base.Destroy(); + + //UIUtils.UnregisterPropertyNode( m_topTexture ); + //UIUtils.UnregisterTexturePropertyNode( m_topTexture ); + + //UIUtils.UnregisterPropertyNode( m_midTexture ); + //UIUtils.UnregisterTexturePropertyNode( m_midTexture ); + + //UIUtils.UnregisterPropertyNode( m_botTexture ); + //UIUtils.UnregisterTexturePropertyNode( m_botTexture ); + if( m_topTexture != null ) + m_topTexture.Destroy(); + m_topTexture = null; + if( m_midTexture != null ) + m_midTexture.Destroy(); + m_midTexture = null; + if( m_botTexture != null ) + m_botTexture.Destroy(); + m_botTexture = null; + + m_tempTopDefaultTexture = null; + m_tempMidDefaultTexture = null; + m_tempBotDefaultTexture = null; + + m_topTexPort = null; + m_midTexPort = null; + m_botTexPort = null; + m_tilingPort = null; + m_falloffPort = null; + m_topIndexPort = null; + m_midIndexPort = null; + m_botIndexPort = null; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + if( m_topTexture == null ) + return; + + + if( m_topTexPort.IsConnected ) + { + PreviewMaterial.SetTexture( "_A", m_topTexPort.InputPreviewTexture( ContainerGraph ) ); + } + else + { + PreviewMaterial.SetTexture( "_A", m_topTexture.Value ); + } + if( m_selectedTriplanarType == TriplanarType.Cylindrical && m_midTexture != null ) + { + if( m_midTexPort.IsConnected ) + PreviewMaterial.SetTexture( "_B", m_midTexPort.InputPreviewTexture( ContainerGraph ) ); + else + PreviewMaterial.SetTexture( "_B", m_midTexture.Value ); + if( m_botTexPort.IsConnected ) + PreviewMaterial.SetTexture( "_C", m_botTexPort.InputPreviewTexture( ContainerGraph ) ); + else + PreviewMaterial.SetTexture( "_C", m_botTexture.Value ); + } + + PreviewMaterial.SetFloat( "_IsNormal", ( m_normalCorrection ? 1 : 0 ) ); + PreviewMaterial.SetFloat( "_IsTangent", ( m_normalSpace == ViewSpace.Tangent ? 1 : 0 ) ); + PreviewMaterial.SetFloat( "_IsSpherical", ( m_selectedTriplanarType == TriplanarType.Spherical ? 1 : 0 ) ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + if( portId == 0 ) + m_topTexPort.MatchPortToConnection(); + + if( portId == 1 ) + m_midTexPort.MatchPortToConnection(); + + if( portId == 2 ) + m_botTexPort.MatchPortToConnection(); + + if( m_texturesInitialize ) + ReRegisterPorts(); + + ConfigurePorts(); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + if( m_texturesInitialize ) + ReRegisterPorts(); + } + + public override void OnConnectedOutputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( portId, otherNodeId, otherPortId, name, type ); + if( portId == 0 ) + { + if( !m_topTexPort.CheckValidType( type ) ) + { + m_topTexPort.FullDeleteConnections(); + UIUtils.ShowMessage( UniqueId, "Triplanar Sampler node only accepts SAMPLER2D and SAMPLER2DARRAY input types.\nTexture Object connected changed to " + type + ", connection was lost, please review and update accordingly.", MessageSeverity.Warning ); + } + else + { + m_topTexPort.MatchPortToConnection(); + } + } + + if( portId == 1 ) + { + if( !m_midTexPort.CheckValidType( type ) ) + { + m_midTexPort.FullDeleteConnections(); + UIUtils.ShowMessage( UniqueId, "Triplanar Sampler node only accepts SAMPLER2D and SAMPLER2DARRAY input types.\nTexture Object connected changed to " + type + ", connection was lost, please review and update accordingly.", MessageSeverity.Warning ); + } + else + { + m_midTexPort.MatchPortToConnection(); + } + } + + if( portId == 2 ) + { + if( !m_botTexPort.CheckValidType( type ) ) + { + m_botTexPort.FullDeleteConnections(); + UIUtils.ShowMessage( UniqueId, "Triplanar Sampler node only accepts SAMPLER2D and SAMPLER2DARRAY input types.\nTexture Object connected changed to " + type + ", connection was lost, please review and update accordingly.", MessageSeverity.Warning ); + } + else + { + m_botTexPort.MatchPortToConnection(); + } + } + + if( m_texturesInitialize ) + ReRegisterPorts(); + + ConfigurePorts(); + } + + public void ReRegisterPorts() + { + if( m_topTexPort.IsConnected ) + { + UIUtils.UnregisterPropertyNode( m_topTexture ); + UIUtils.UnregisterTexturePropertyNode( m_topTexture ); + } + else if( m_topTexPort.Visible ) + { + UIUtils.RegisterPropertyNode( m_topTexture ); + UIUtils.RegisterTexturePropertyNode( m_topTexture ); + } + + if( m_midTexPort.IsConnected || m_selectedTriplanarType == TriplanarType.Spherical ) + { + UIUtils.UnregisterPropertyNode( m_midTexture ); + UIUtils.UnregisterTexturePropertyNode( m_midTexture ); + } + else if( m_midTexPort.Visible && m_selectedTriplanarType == TriplanarType.Cylindrical ) + { + UIUtils.RegisterPropertyNode( m_midTexture ); + UIUtils.RegisterTexturePropertyNode( m_midTexture ); + } + + if( m_botTexPort.IsConnected || m_selectedTriplanarType == TriplanarType.Spherical ) + { + UIUtils.UnregisterPropertyNode( m_botTexture ); + UIUtils.UnregisterTexturePropertyNode( m_botTexture ); + } + else if( m_botTexPort.Visible && m_selectedTriplanarType == TriplanarType.Cylindrical ) + { + UIUtils.RegisterPropertyNode( m_botTexture ); + UIUtils.RegisterTexturePropertyNode( m_botTexture ); + } + } + + public void ConfigurePorts() + { + switch( m_selectedTriplanarType ) + { + case TriplanarType.Spherical: + m_topTexPort.Name = "Tex"; + m_midTexPort.Visible = false; + m_botTexPort.Visible = false; + m_scalePort.ChangeType( WirePortDataType.FLOAT, false ); + break; + case TriplanarType.Cylindrical: + m_topTexPort.Name = "Top"; + m_midTexPort.Visible = true; + m_botTexPort.Visible = true; + m_scalePort.ChangeType( WirePortDataType.FLOAT3, false ); + break; + } + + if( m_normalCorrection ) + { + m_outputPorts[ 0 ].ChangeProperties( "XYZ", WirePortDataType.FLOAT3, false ); + m_outputPorts[ 1 ].ChangeProperties( "X", WirePortDataType.FLOAT, false ); + m_outputPorts[ 2 ].ChangeProperties( "Y", WirePortDataType.FLOAT, false ); + m_outputPorts[ 3 ].ChangeProperties( "Z", WirePortDataType.FLOAT, false ); + + m_outputPorts[ 4 ].Visible = false; + + m_scalePort.Visible = true; + } + else + { + m_outputPorts[ 0 ].ChangeProperties( "RGBA", WirePortDataType.FLOAT4, false ); + m_outputPorts[ 1 ].ChangeProperties( "R", WirePortDataType.FLOAT, false ); + m_outputPorts[ 2 ].ChangeProperties( "G", WirePortDataType.FLOAT, false ); + m_outputPorts[ 3 ].ChangeProperties( "B", WirePortDataType.FLOAT, false ); + m_outputPorts[ 4 ].ChangeProperties( "A", WirePortDataType.FLOAT, false ); + + m_outputPorts[ 4 ].Visible = true; + + m_scalePort.Visible = false; + } + + if( m_topTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) + m_topIndexPort.Visible = true; + else + m_topIndexPort.Visible = false; + + if( m_midTexPort.DataType == WirePortDataType.SAMPLER2DARRAY && m_selectedTriplanarType == TriplanarType.Cylindrical ) + m_midIndexPort.Visible = true; + else + m_midIndexPort.Visible = false; + + if( m_botTexPort.DataType == WirePortDataType.SAMPLER2DARRAY && m_selectedTriplanarType == TriplanarType.Cylindrical ) + m_botIndexPort.Visible = true; + else + m_botIndexPort.Visible = false; + + if( m_selectedTriplanarSpace == TriplanarSpace.World ) + m_posPort.Name = "World Pos"; + else + m_posPort.Name = "Local Pos"; + + m_outputPorts[ 0 ].DirtyLabelSize = true; + m_sizeIsDirty = true; + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + dataCollector.DirtyNormal = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, "Parameters", DrawMainOptions ); + DrawInternalDataGroup(); + if( m_selectedTriplanarType == TriplanarType.Spherical && !m_topTexPort.IsConnected ) + NodeUtils.DrawPropertyGroup( ref m_topTextureFoldout, "Texture", DrawTopTextureOptions ); + else if( !m_topTexPort.IsConnected ) + NodeUtils.DrawPropertyGroup( ref m_topTextureFoldout, "Top Texture", DrawTopTextureOptions ); + + if( m_selectedTriplanarType == TriplanarType.Cylindrical ) + { + if( !m_midTexPort.IsConnected ) + NodeUtils.DrawPropertyGroup( ref m_midTextureFoldout, "Middle Texture", DrawMidTextureOptions ); + if( !m_botTexPort.IsConnected ) + NodeUtils.DrawPropertyGroup( ref m_botTextureFoldout, "Bottom Texture", DrawBotTextureOptions ); + } + } + + void DrawMainOptions() + { + EditorGUI.BeginChangeCheck(); + m_propertyInspectorName = EditorGUILayoutTextField( "Name", m_propertyInspectorName ); + + m_selectedTriplanarType = (TriplanarType)EditorGUILayoutEnumPopup( "Mapping", m_selectedTriplanarType ); + + m_selectedTriplanarSpace = (TriplanarSpace)EditorGUILayoutEnumPopup( "Space", m_selectedTriplanarSpace ); + + m_normalCorrection = EditorGUILayoutToggle( "Normal Map", m_normalCorrection ); + + if( m_normalCorrection ) + m_normalSpace = (ViewSpace)EditorGUILayoutEnumPopup( "Output Normal Space", m_normalSpace ); + + if( EditorGUI.EndChangeCheck() ) + { + SetTitleText( m_propertyInspectorName ); + ConfigurePorts(); + ReRegisterPorts(); + } + } + + void DrawTopTextureOptions() + { + EditorGUI.BeginChangeCheck(); + m_topTexture.ShowPropertyInspectorNameGUI(); + m_topTexture.ShowPropertyNameGUI( true ); + m_topTexture.ShowToolbar(); + if( EditorGUI.EndChangeCheck() ) + { + m_topTexture.BeginPropertyFromInspectorCheck(); + if( m_materialMode ) + m_requireMaterialUpdate = true; + } + + m_topTexture.CheckPropertyFromInspector(); + } + + void DrawMidTextureOptions() + { + if( m_midTexture == null ) + return; + + EditorGUI.BeginChangeCheck(); + m_midTexture.ShowPropertyInspectorNameGUI(); + m_midTexture.ShowPropertyNameGUI( true ); + m_midTexture.ShowToolbar(); + if( EditorGUI.EndChangeCheck() ) + { + m_midTexture.BeginPropertyFromInspectorCheck(); + if( m_materialMode ) + m_requireMaterialUpdate = true; + } + + m_midTexture.CheckPropertyFromInspector(); + } + + void DrawBotTextureOptions() + { + if( m_botTexture == null ) + return; + + EditorGUI.BeginChangeCheck(); + m_botTexture.ShowPropertyInspectorNameGUI(); + m_botTexture.ShowPropertyNameGUI( true ); + m_botTexture.ShowToolbar(); + if( EditorGUI.EndChangeCheck() ) + { + m_botTexture.BeginPropertyFromInspectorCheck(); + if( m_materialMode ) + m_requireMaterialUpdate = true; + } + + m_botTexture.CheckPropertyFromInspector(); + } + + public override void OnEnable() + { + base.OnEnable(); + //if( !m_afterDeserialize ) + //Init(); //Generate texture properties + //else + //m_afterDeserialize = false; + + //if( m_topTexture != null ) + // m_topTexture.ReRegisterName = true; + + //if( m_selectedTriplanarType == TriplanarType.Cylindrical ) + //{ + // if( m_midTexture != null ) + // m_midTexture.ReRegisterName = true; + + // if( m_botTexture != null ) + // m_botTexture.ReRegisterName = true; + //} + } + + //bool m_afterDeserialize = false; + + //public override void OnAfterDeserialize() + //{ + // base.OnAfterDeserialize(); + // m_afterDeserialize = true; + //} + + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + + Init(); + + if( m_topTexture.ReRegisterName ) + { + m_topTexture.ReRegisterName = false; + UIUtils.RegisterUniformName( UniqueId, m_topTexture.PropertyName ); + } + + m_topTexture.CheckDelayedDirtyProperty(); + m_topTexture.CheckPropertyFromInspector(); + m_topTexture.CheckDuplicateProperty(); + + if( m_selectedTriplanarType == TriplanarType.Cylindrical ) + { + if( m_midTexture.ReRegisterName ) + { + m_midTexture.ReRegisterName = false; + UIUtils.RegisterUniformName( UniqueId, m_midTexture.PropertyName ); + } + + m_midTexture.CheckDelayedDirtyProperty(); + m_midTexture.CheckPropertyFromInspector(); + m_midTexture.CheckDuplicateProperty(); + + if( m_botTexture.ReRegisterName ) + { + m_botTexture.ReRegisterName = false; + UIUtils.RegisterUniformName( UniqueId, m_botTexture.PropertyName ); + } + + m_botTexture.CheckDelayedDirtyProperty(); + m_botTexture.CheckPropertyFromInspector(); + m_botTexture.CheckDuplicateProperty(); + } + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_allPicker = m_previewRect; + m_allPicker.x -= 43 * drawInfo.InvertedZoom; + m_allPicker.width = 43 * drawInfo.InvertedZoom; + + m_startPicker = m_previewRect; + m_startPicker.x -= 43 * drawInfo.InvertedZoom; + m_startPicker.width = 43 * drawInfo.InvertedZoom; + m_startPicker.height = 43 * drawInfo.InvertedZoom; + + m_pickerButton = m_startPicker; + m_pickerButton.width = 30 * drawInfo.InvertedZoom; + m_pickerButton.x = m_startPicker.xMax - m_pickerButton.width - 2; + m_pickerButton.height = 10 * drawInfo.InvertedZoom; + m_pickerButton.y = m_startPicker.yMax - m_pickerButton.height - 2; + } + + + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if( !( drawInfo.CurrentEventType == EventType.MouseDown || drawInfo.CurrentEventType == EventType.MouseUp || drawInfo.CurrentEventType == EventType.ExecuteCommand || drawInfo.CurrentEventType == EventType.DragPerform ) ) + return; + + bool insideBox = m_allPicker.Contains( drawInfo.MousePosition ); + + if( insideBox ) + { + m_editing = true; + } + else if( m_editing && !insideBox && drawInfo.CurrentEventType != EventType.ExecuteCommand ) + { + GUI.FocusControl( null ); + m_editing = false; + } + } + private int m_pickId = 0; + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + Rect pickerButtonClone = m_pickerButton; + Rect startPickerClone = m_startPicker; + + if( m_editing ) + { + if( GUI.Button( pickerButtonClone, string.Empty, GUIStyle.none ) ) + { + int controlID = EditorGUIUtility.GetControlID( FocusType.Passive ); + EditorGUIUtility.ShowObjectPicker( m_topTexture.Value, false, "", controlID ); + m_pickId = 0; + } + + if( m_selectedTriplanarType == TriplanarType.Cylindrical ) + { + pickerButtonClone.y += startPickerClone.height; + if( GUI.Button( pickerButtonClone, string.Empty, GUIStyle.none ) ) + { + int controlID = EditorGUIUtility.GetControlID( FocusType.Passive ); + EditorGUIUtility.ShowObjectPicker( m_midTexture.Value, false, "", controlID ); + m_pickId = 1; + } + + pickerButtonClone.y += startPickerClone.height; + if( GUI.Button( pickerButtonClone, string.Empty, GUIStyle.none ) ) + { + int controlID = EditorGUIUtility.GetControlID( FocusType.Passive ); + EditorGUIUtility.ShowObjectPicker( m_botTexture.Value, false, "", controlID ); + m_pickId = 2; + } + } + + string commandName = Event.current.commandName; + UnityEngine.Object newValue = null; + if( commandName.Equals( "ObjectSelectorUpdated" ) || commandName.Equals( "ObjectSelectorClosed" ) ) + { + newValue = EditorGUIUtility.GetObjectPickerObject(); + if( m_pickId == 2 ) + { + if( newValue != (UnityEngine.Object)m_botTexture.Value ) + { + PreviewIsDirty = true; + UndoRecordObject( "Changing value EditorGUIObjectField on node Triplanar Node" ); + m_botTexture.Value = newValue != null ? (Texture2D)newValue : null; + + if( m_materialMode ) + m_requireMaterialUpdate = true; + } + } + else if( m_pickId == 1 ) + { + if( newValue != (UnityEngine.Object)m_midTexture.Value ) + { + PreviewIsDirty = true; + UndoRecordObject( "Changing value EditorGUIObjectField on node Triplanar Node" ); + m_midTexture.Value = newValue != null ? (Texture2D)newValue : null; + + if( m_materialMode ) + m_requireMaterialUpdate = true; + } + } + else + { + if( newValue != (UnityEngine.Object)m_topTexture.Value ) + { + PreviewIsDirty = true; + UndoRecordObject( "Changing value EditorGUIObjectField on node Triplanar Node" ); + m_topTexture.Value = newValue != null ? (Texture2D)newValue : null; + + if( m_materialMode ) + m_requireMaterialUpdate = true; + } + } + + if( commandName.Equals( "ObjectSelectorClosed" ) ) + m_editing = false; + } + + if( GUI.Button( startPickerClone, string.Empty, GUIStyle.none ) ) + { + if( m_topTexPort.IsConnected ) + { + UIUtils.FocusOnNode( m_topTexPort.GetOutputNode( 0 ), 1, true ); + } + else + { + if( m_topTexture.Value != null ) + { + Selection.activeObject = m_topTexture.Value; + EditorGUIUtility.PingObject( Selection.activeObject ); + } + } + m_editing = false; + } + + if( m_selectedTriplanarType == TriplanarType.Cylindrical ) + { + startPickerClone.y += startPickerClone.height; + if( GUI.Button( startPickerClone, string.Empty, GUIStyle.none ) ) + { + if( m_midTexPort.IsConnected ) + { + UIUtils.FocusOnNode( m_midTexPort.GetOutputNode( 0 ), 1, true ); + } + else + { + if( m_midTexture.Value != null ) + { + Selection.activeObject = m_midTexture.Value; + EditorGUIUtility.PingObject( Selection.activeObject ); + } + } + m_editing = false; + } + + startPickerClone.y += startPickerClone.height; + if( GUI.Button( startPickerClone, string.Empty, GUIStyle.none ) ) + { + if( m_botTexPort.IsConnected ) + { + UIUtils.FocusOnNode( m_botTexPort.GetOutputNode( 0 ), 1, true ); + } + else + { + if( m_botTexture.Value != null ) + { + Selection.activeObject = m_botTexture.Value; + EditorGUIUtility.PingObject( Selection.activeObject ); + } + } + m_editing = false; + } + } + } + + pickerButtonClone = m_pickerButton; + startPickerClone = m_startPicker; + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + // Top + if( m_topTexPort.IsConnected ) + { + EditorGUI.DrawPreviewTexture( startPickerClone, m_topTexPort.GetOutputConnection( 0 ).OutputPreviewTexture, null, ScaleMode.ScaleAndCrop ); + } + else if( m_topTexture.Value != null ) + { + EditorGUI.DrawPreviewTexture( startPickerClone, m_topTexture.Value, null, ScaleMode.ScaleAndCrop ); + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + GUI.Label( pickerButtonClone, "Select", UIUtils.MiniSamplerButton ); + } + else + { + GUI.Label( startPickerClone, string.Empty, UIUtils.ObjectFieldThumb ); + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + { + GUI.Label( startPickerClone, "None (Texture2D)", UIUtils.MiniObjectFieldThumbOverlay ); + GUI.Label( pickerButtonClone, "Select", UIUtils.MiniSamplerButton ); + } + } + GUI.Label( startPickerClone, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + + if( m_selectedTriplanarType == TriplanarType.Cylindrical ) + { + // Mid + startPickerClone.y += startPickerClone.height; + pickerButtonClone.y += startPickerClone.height; + if( m_midTexPort.IsConnected ) + { + EditorGUI.DrawPreviewTexture( startPickerClone, m_midTexPort.GetOutputConnection( 0 ).OutputPreviewTexture, null, ScaleMode.ScaleAndCrop ); + } + else if( m_midTexture.Value != null ) + { + EditorGUI.DrawPreviewTexture( startPickerClone, m_midTexture.Value, null, ScaleMode.ScaleAndCrop ); + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + GUI.Label( pickerButtonClone, "Select", UIUtils.MiniSamplerButton ); + } + else + { + GUI.Label( startPickerClone, string.Empty, UIUtils.ObjectFieldThumb ); + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + { + GUI.Label( startPickerClone, "None (Texture2D)", UIUtils.MiniObjectFieldThumbOverlay ); + GUI.Label( pickerButtonClone, "Select", UIUtils.MiniSamplerButton ); + } + } + GUI.Label( startPickerClone, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + + // Bot + startPickerClone.y += startPickerClone.height; + startPickerClone.height = 42 * drawInfo.InvertedZoom; + pickerButtonClone.y += startPickerClone.height; + if( m_botTexPort.IsConnected ) + { + EditorGUI.DrawPreviewTexture( startPickerClone, m_botTexPort.GetOutputConnection( 0 ).OutputPreviewTexture, null, ScaleMode.ScaleAndCrop ); + } + else if( m_botTexture.Value != null ) + { + EditorGUI.DrawPreviewTexture( startPickerClone, m_botTexture.Value, null, ScaleMode.ScaleAndCrop ); + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + GUI.Label( pickerButtonClone, "Select", UIUtils.MiniSamplerButton ); + } + else + { + GUI.Label( startPickerClone, string.Empty, UIUtils.ObjectFieldThumb ); + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + { + GUI.Label( startPickerClone, "None (Texture2D)", UIUtils.MiniObjectFieldThumbOverlay ); + GUI.Label( pickerButtonClone, "Select", UIUtils.MiniSamplerButton ); + } + } + GUI.Label( startPickerClone, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + } + } + } + + public override void OnNodeDoubleClicked( Vector2 currentMousePos2D ) + { + if( currentMousePos2D.y - m_globalPosition.y > Constants.NODE_HEADER_HEIGHT + Constants.NODE_HEADER_EXTRA_HEIGHT ) + { + ContainerGraph.ParentWindow.ParametersWindow.IsMaximized = !ContainerGraph.ParentWindow.ParametersWindow.IsMaximized; + } + else + { + m_editPropertyNameMode = true; + GUI.FocusControl( m_uniqueName ); + TextEditor te = (TextEditor)GUIUtility.GetStateObject( typeof( TextEditor ), GUIUtility.keyboardControl ); + if( te != null ) + { + te.SelectAll(); + } + } + } + + public override void OnNodeSelected( bool value ) + { + base.OnNodeSelected( value ); + if( !value ) + m_editPropertyNameMode = false; + } + + public override void DrawTitle( Rect titlePos ) + { + if( m_editPropertyNameMode ) + { + titlePos.height = Constants.NODE_HEADER_HEIGHT; + EditorGUI.BeginChangeCheck(); + GUI.SetNextControlName( m_uniqueName ); + m_propertyInspectorName = GUITextField( titlePos, m_propertyInspectorName, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + if( EditorGUI.EndChangeCheck() ) + { + SetTitleText( m_propertyInspectorName ); + } + + if( Event.current.isKey && ( Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter ) ) + { + m_editPropertyNameMode = false; + GUIUtility.keyboardControl = 0; + } + } + else + { + base.DrawTitle( titlePos ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputColorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; + + dataCollector.AddPropertyNode( m_topTexture ); + dataCollector.AddPropertyNode( m_midTexture ); + dataCollector.AddPropertyNode( m_botTexture ); + + bool isVertex = ( dataCollector.PortCategory == MasterNodePortCategory.Tessellation || dataCollector.PortCategory == MasterNodePortCategory.Vertex ); + + string texTop = string.Empty; + string texMid = string.Empty; + string texBot = string.Empty; + string ssTop = string.Empty; + string ssMid = string.Empty; + string ssBot = string.Empty; + + if( m_topTexPort.IsConnected ) + { + texTop = m_topTexPort.GeneratePortInstructions( ref dataCollector ); + } + else + { + dataCollector.AddToUniforms( UniqueId, m_topTexture.GetTexture2DUniformValue() ); + dataCollector.AddToProperties( UniqueId, m_topTexture.GetTexture2DPropertyValue(), m_topTexture.OrderIndex ); + texTop = m_topTexture.PropertyName; + } + + if( m_selectedTriplanarType == TriplanarType.Spherical ) + { + texMid = texTop; + texBot = texTop; + +#if UNITY_2018_1_OR_NEWER + if( ( outsideGraph.SamplingMacros || m_topTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) ) +#else + if( ( outsideGraph.SamplingMacros || m_topTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) && !outsideGraph.IsStandardSurface ) +#endif + ssTop = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, texTop , VariableMode.Create ); + } + else + { + if( m_midTexPort.IsConnected ) + { + texMid = m_midTexPort.GeneratePortInstructions( ref dataCollector ); + } + else + { + dataCollector.AddToUniforms( UniqueId, m_midTexture.GetTexture2DUniformValue() ); + dataCollector.AddToProperties( UniqueId, m_midTexture.GetTexture2DPropertyValue(), m_midTexture.OrderIndex ); + texMid = m_midTexture.PropertyName; + } + + if( m_botTexPort.IsConnected ) + { + texBot = m_botTexPort.GeneratePortInstructions( ref dataCollector ); + } + else + { + dataCollector.AddToUniforms( UniqueId, m_botTexture.GetTexture2DUniformValue() ); + dataCollector.AddToProperties( UniqueId, m_botTexture.GetTexture2DPropertyValue(), m_botTexture.OrderIndex ); + texBot = m_botTexture.PropertyName; + } +#if UNITY_2018_1_OR_NEWER + if( ( outsideGraph.SamplingMacros || m_topTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) ) + ssTop = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, texTop , VariableMode.Create ); + if( ( outsideGraph.SamplingMacros || m_midTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) ) + ssMid = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, texMid , VariableMode.Create ); + if( ( outsideGraph.SamplingMacros || m_botTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) ) + ssBot = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, texBot , VariableMode.Create ); +#else + if( ( outsideGraph.SamplingMacros || m_topTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) && !outsideGraph.IsStandardSurface ) + ssTop = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, texTop , VariableMode.Create); + if( ( outsideGraph.SamplingMacros || m_midTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) && !outsideGraph.IsStandardSurface ) + ssMid = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, texMid , VariableMode.Create); + if( ( outsideGraph.SamplingMacros || m_botTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) && !outsideGraph.IsStandardSurface ) + ssBot = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, texBot , VariableMode.Create); +#endif + } + + if( !isVertex ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_POS ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + dataCollector.ForceNormal = true; + } + + string topIndex = "0"; + string midIndex = "0"; + string botIndex = "0"; + if( m_topIndexPort.Visible ) + topIndex = m_topIndexPort.GeneratePortInstructions( ref dataCollector ); + if( m_midIndexPort.Visible ) + midIndex = m_midIndexPort.GeneratePortInstructions( ref dataCollector ); + if( m_botIndexPort.Visible ) + botIndex = m_botIndexPort.GeneratePortInstructions( ref dataCollector ); + + string tiling = m_tilingPort.GeneratePortInstructions( ref dataCollector ); + string falloff = m_falloffPort.GeneratePortInstructions( ref dataCollector ); + + bool scaleNormals = false; + if( m_scalePort.IsConnected || ( m_scalePort.IsConnected && ( m_scalePort.Vector3InternalData == Vector3.one || m_scalePort.FloatInternalData == 1 ) ) ) + scaleNormals = true; + + MipType mip = isVertex ? MipType.MipLevel : MipType.Auto; + string samplingTriplanar = string.Empty; + string headerID = string.Empty; + string header = string.Empty; + string callHeader = string.Empty; + string samplers = string.Empty; + string extraArguments = string.Empty; + List triplanarBody = new List(); + + triplanarBody.AddRange( m_functionSamplingBodyProj ); + headerID += OutputId; + if( m_selectedTriplanarType == TriplanarType.Spherical ) + { + samplers = GeneratorUtils.GetPropertyDeclaraction( "topTexMap", m_topTexPort.DataType, ", " ) + GeneratorUtils.GetSamplerDeclaraction( "samplertopTexMap", m_topTexPort.DataType, ", " ); +#if !UNITY_2018_1_OR_NEWER + if( m_topTexPort.DataType == WirePortDataType.SAMPLER2DARRAY && outsideGraph.IsStandardSurface ) + samplers = "UNITY_ARGS_TEX2DARRAY(topTexMap), "; +#endif + + string array1 = ""; + string array2 = ""; + if( m_topTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) + { + if( outsideGraph.IsSRP ) + { + array1 = ""; + array2 = ", index.x"; + } + else + { + array1 = "float3( "; + array2 = ", index.x )"; + } + } + + triplanarBody.Add( "half4 xNorm; half4 yNorm; half4 zNorm;" ); + triplanarBody.Add( "xNorm = " + GeneratorUtils.GenerateSamplingCall( ref dataCollector, m_topTexPort.DataType, "topTexMap", "samplertopTexMap", string.Format( "{0}tiling * worldPos.zy * float2( nsign.x, 1.0 ){1}", array1, array2 ), mip, "0" ) + ";" ); + triplanarBody.Add( "yNorm = " + GeneratorUtils.GenerateSamplingCall( ref dataCollector, m_topTexPort.DataType, "topTexMap", "samplertopTexMap", string.Format( "{0}tiling * worldPos.xz * float2( nsign.y, 1.0 ){1}", array1, array2 ), mip, "0" ) + ";" ); + triplanarBody.Add( "zNorm = " + GeneratorUtils.GenerateSamplingCall( ref dataCollector, m_topTexPort.DataType, "topTexMap", "samplertopTexMap", string.Format( "{0}tiling * worldPos.xy * float2( -nsign.z, 1.0 ){1}", array1, array2 ), mip, "0" ) + ";" ); + + if( m_normalCorrection ) + { + if( scaleNormals ) + { + ConvertListTo( dataCollector, true, m_functionSamplingBodySignsSphereScale, triplanarBody ); + } + else + { + ConvertListTo( dataCollector, false, m_functionSamplingBodySignsSphere, triplanarBody ); + } + triplanarBody.AddRange( m_functionSamplingBodyReturnSphereNormalize ); + } + else + { + triplanarBody.AddRange( m_functionSamplingBodyReturnSphere ); + } + } + else + { + string topArgs = GeneratorUtils.GetPropertyDeclaraction( "topTexMap", m_topTexPort.DataType, ", " ) + GeneratorUtils.GetSamplerDeclaraction( "samplertopTexMap", m_topTexPort.DataType, ", " ); + string midArgs = GeneratorUtils.GetPropertyDeclaraction( "midTexMap", m_midTexPort.DataType, ", " ) + GeneratorUtils.GetSamplerDeclaraction( "samplermidTexMap", m_midTexPort.DataType, ", " ); + string botArgs = GeneratorUtils.GetPropertyDeclaraction( "botTexMap", m_botTexPort.DataType, ", " ) + GeneratorUtils.GetSamplerDeclaraction( "samplerbotTexMap", m_botTexPort.DataType, ", " ); + +#if !UNITY_2018_1_OR_NEWER + if( m_topTexPort.DataType == WirePortDataType.SAMPLER2DARRAY && outsideGraph.IsStandardSurface ) + topArgs = "UNITY_ARGS_TEX2DARRAY(topTexMap), "; + + if( m_midTexPort.DataType == WirePortDataType.SAMPLER2DARRAY && outsideGraph.IsStandardSurface ) + midArgs = "UNITY_ARGS_TEX2DARRAY(midTexMap), "; + + if( m_botTexPort.DataType == WirePortDataType.SAMPLER2DARRAY && outsideGraph.IsStandardSurface ) + botArgs = "UNITY_ARGS_TEX2DARRAY(botTexMap), "; +#endif + + samplers = topArgs + midArgs + botArgs; + + string uvTop = "tiling * worldPos.xz * float2( nsign.y, 1.0 )"; + if( m_topTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) + uvTop = outsideGraph.IsSRP ? uvTop + ", index.x" : "float3( " + uvTop + ", index.x )"; + + string uvMid = "tiling * worldPos.zy * float2( nsign.x, 1.0 )"; + if( m_midTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) + uvMid = outsideGraph.IsSRP ? uvMid + ", index.y" : "float3( " + uvMid + ", index.y )"; + + string uvMidNeg = "tiling * worldPos.xy * float2( -nsign.z, 1.0 )"; + if( m_midTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) + uvMidNeg = outsideGraph.IsSRP ? uvMidNeg + ", index.y" : "float3( " + uvMidNeg + ", index.y )"; + + string uvBot = "tiling * worldPos.xz * float2( nsign.y, 1.0 )"; + if( m_botTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) + uvBot = outsideGraph.IsSRP ? uvBot + ", index.z" : "float3( " + uvBot + ", index.z )"; + + extraArguments = ", {7}, {8}"; + triplanarBody.AddRange( m_functionSamplingBodyNegProj ); + + triplanarBody.Add( "half4 xNorm; half4 yNorm; half4 yNormN; half4 zNorm;" ); + triplanarBody.Add( "xNorm = " + GeneratorUtils.GenerateSamplingCall( ref dataCollector, m_midTexPort.DataType, "midTexMap", "samplermidTexMap", uvMid, mip, "0" ) + ";" ); + triplanarBody.Add( "yNorm = " + GeneratorUtils.GenerateSamplingCall( ref dataCollector, m_topTexPort.DataType, "topTexMap", "samplertopTexMap", uvTop, mip, "0" ) + ";" ); + triplanarBody.Add( "yNormN = " + GeneratorUtils.GenerateSamplingCall( ref dataCollector, m_botTexPort.DataType, "botTexMap", "samplerbotTexMap", uvBot, mip, "0" ) + ";" ); + triplanarBody.Add( "zNorm = " + GeneratorUtils.GenerateSamplingCall( ref dataCollector, m_midTexPort.DataType, "midTexMap", "samplermidTexMap", uvMidNeg, mip, "0" ) + ";" ); + + if( m_normalCorrection ) + { + if( scaleNormals ) + { + if( !( dataCollector.IsTemplate && dataCollector.IsSRP ) ) + { + dataCollector.AddToIncludes( UniqueId, Constants.UnityStandardUtilsLibFuncs ); + } + + ConvertListTo( dataCollector, true, m_functionSamplingBodySignsSphereScale, triplanarBody ); + ConvertListTo( dataCollector, true, m_functionSamplingBodySignsCylinderScale, triplanarBody ); + } + else + { + ConvertListTo( dataCollector, false, m_functionSamplingBodySignsSphere, triplanarBody ); + ConvertListTo( dataCollector, false, m_functionSamplingBodySignsCylinder, triplanarBody ); + } + triplanarBody.AddRange( m_functionSamplingBodyReturnCylinderNormalize ); + } + else + { + triplanarBody.AddRange( m_functionSamplingBodyReturnCylinder ); + } + } + + string type = UIUtils.WirePortToCgType( m_outputPorts[ 0 ].DataType ); + header = string.Format( m_functionHeader, type, headerID, samplers ); + callHeader = string.Format( m_functionCall, headerID, "{0}, {1}, {2}, {3}, {4}, {5}, {6}" + extraArguments ); + + IOUtils.AddFunctionHeader( ref samplingTriplanar, header ); + foreach( string line in triplanarBody ) + IOUtils.AddFunctionLine( ref samplingTriplanar, line ); + IOUtils.CloseFunctionBody( ref samplingTriplanar ); + + string pos = GeneratorUtils.GenerateWorldPosition( ref dataCollector, UniqueId ); + string norm = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId ); + string worldToTangent = string.Empty; + if( m_normalCorrection && m_normalSpace == ViewSpace.Tangent ) + worldToTangent = GeneratorUtils.GenerateWorldToTangentMatrix( ref dataCollector, UniqueId, CurrentPrecisionType ); + + if( m_selectedTriplanarSpace == TriplanarSpace.Object ) + { + if( m_normalCorrection && m_normalSpace == ViewSpace.Tangent ) + { + string vt = GeneratorUtils.GenerateVertexTangent( ref dataCollector, UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3 ); + string vbt = GeneratorUtils.GenerateVertexBitangent( ref dataCollector, UniqueId, CurrentPrecisionType ); + norm = GeneratorUtils.GenerateVertexNormal( ref dataCollector, UniqueId, CurrentPrecisionType ); + dataCollector.AddLocalVariable( UniqueId, "float3x3 objectToTangent = float3x3("+ vt + ", "+ vbt + ", "+ norm + ");" ); + pos = GeneratorUtils.GenerateVertexPosition( ref dataCollector, UniqueId, WirePortDataType.FLOAT3 ); + worldToTangent = "objectToTangent"; + } + else + { + pos = GeneratorUtils.GenerateVertexPosition( ref dataCollector, UniqueId, WirePortDataType.FLOAT3 ); + norm = GeneratorUtils.GenerateVertexNormal( ref dataCollector, UniqueId, CurrentPrecisionType ); + } + } + + if( m_posPort.IsConnected ) + { + pos = m_posPort.GeneratePortInstructions( ref dataCollector ); + } + +#if !UNITY_2018_1_OR_NEWER + if( outsideGraph.IsStandardSurface && m_topTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) + texTop = "UNITY_PASS_TEX2DARRAY(" + texTop + ")"; + if( outsideGraph.IsStandardSurface && m_midTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) + texMid = "UNITY_PASS_TEX2DARRAY(" + texMid + ")"; + if( outsideGraph.IsStandardSurface && m_botTexPort.DataType == WirePortDataType.SAMPLER2DARRAY ) + texBot = "UNITY_PASS_TEX2DARRAY(" + texBot + ")"; +#endif + + string call = string.Empty; + string normalScale = m_scalePort.GeneratePortInstructions( ref dataCollector ); + + if( !string.IsNullOrEmpty( ssTop ) ) + ssTop = ", " + ssTop; + if( !string.IsNullOrEmpty( ssMid ) ) + ssMid = ", " + ssMid; + if( !string.IsNullOrEmpty( ssBot ) ) + ssBot = ", " + ssBot; + + if( m_selectedTriplanarType == TriplanarType.Spherical ) + call = dataCollector.AddFunctions( callHeader, samplingTriplanar, texTop + ssTop, pos, norm, falloff, tiling, normalScale, topIndex ); + else + call = dataCollector.AddFunctions( callHeader, samplingTriplanar, texTop + ssTop, texMid + ssMid, texBot + ssBot, pos, norm, falloff, tiling, normalScale, "float3(" + topIndex + "," + midIndex + "," + botIndex + ")" ); + string triplanarVarName = "triplanar" + OutputId; + + dataCollector.AddToLocalVariables( dataCollector.PortCategory, UniqueId, type + " "+ triplanarVarName + " = " + call + ";" ); + if( m_normalCorrection && m_normalSpace == ViewSpace.Tangent ) + { + string tanTriplanarVarName = "tanTriplanarNormal" + OutputId; + + dataCollector.AddToLocalVariables( dataCollector.PortCategory, UniqueId, "float3 " + tanTriplanarVarName + " = mul( " + worldToTangent + ", "+ triplanarVarName + " );" ); + + m_outputPorts[ 0 ].SetLocalValue( tanTriplanarVarName, dataCollector.PortCategory ); + + return GetOutputVectorItem( 0, outputId, tanTriplanarVarName ); + } + else + { + m_outputPorts[ 0 ].SetLocalValue( triplanarVarName , dataCollector.PortCategory ); + return GetOutputVectorItem( 0, outputId, triplanarVarName ); + } + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + m_topTexture.OnPropertyNameChanged(); + if( mat.HasProperty( m_topTexture.PropertyName ) && !InsideShaderFunction ) + { + mat.SetTexture( m_topTexture.PropertyName, m_topTexture.MaterialValue ); + } + + m_midTexture.OnPropertyNameChanged(); + if( mat.HasProperty( m_midTexture.PropertyName ) && !InsideShaderFunction ) + { + mat.SetTexture( m_midTexture.PropertyName, m_midTexture.MaterialValue ); + } + + m_botTexture.OnPropertyNameChanged(); + if( mat.HasProperty( m_botTexture.PropertyName ) && !InsideShaderFunction ) + { + mat.SetTexture( m_botTexture.PropertyName, m_botTexture.MaterialValue ); + } + } + + public void SetDelayedMaterialMode( Material mat ) + { + m_topTexture.SetMaterialMode( mat, false ); + if( mat.HasProperty( m_topTexture.PropertyName ) ) + { + m_topTexture.MaterialValue = mat.GetTexture( m_topTexture.PropertyName ); + } + + m_midTexture.SetMaterialMode( mat, false ); + if( mat.HasProperty( m_midTexture.PropertyName ) ) + { + m_midTexture.MaterialValue = mat.GetTexture( m_midTexture.PropertyName ); + } + + m_botTexture.SetMaterialMode( mat, false ); + if( mat.HasProperty( m_botTexture.PropertyName ) ) + { + m_botTexture.MaterialValue = mat.GetTexture( m_botTexture.PropertyName ); + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + base.ForceUpdateFromMaterial( material ); + if( material.HasProperty( m_topTexture.PropertyName ) ) + { + m_topTexture.MaterialValue = material.GetTexture( m_topTexture.PropertyName ); + PreviewIsDirty = true; + } + + if( material.HasProperty( m_midTexture.PropertyName ) ) + { + m_midTexture.MaterialValue = material.GetTexture( m_midTexture.PropertyName ); + PreviewIsDirty = true; + } + + if( material.HasProperty( m_botTexture.PropertyName ) ) + { + m_botTexture.MaterialValue = material.GetTexture( m_botTexture.PropertyName ); + PreviewIsDirty = true; + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedTriplanarType = (TriplanarType)Enum.Parse( typeof( TriplanarType ), GetCurrentParam( ref nodeParams ) ); + m_selectedTriplanarSpace = (TriplanarSpace)Enum.Parse( typeof( TriplanarSpace ), GetCurrentParam( ref nodeParams ) ); + m_normalCorrection = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + + m_tempTopInspectorName = GetCurrentParam( ref nodeParams ); + m_tempTopName = GetCurrentParam( ref nodeParams ); + m_tempTopDefaultValue = (TexturePropertyValues)Enum.Parse( typeof( TexturePropertyValues ), GetCurrentParam( ref nodeParams ) ); + m_tempTopOrderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_tempTopDefaultTexture = AssetDatabase.LoadAssetAtPath( GetCurrentParam( ref nodeParams ) ); + + m_tempMidInspectorName = GetCurrentParam( ref nodeParams ); + m_tempMidName = GetCurrentParam( ref nodeParams ); + m_tempMidDefaultValue = (TexturePropertyValues)Enum.Parse( typeof( TexturePropertyValues ), GetCurrentParam( ref nodeParams ) ); + m_tempMidOrderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_tempMidDefaultTexture = AssetDatabase.LoadAssetAtPath( GetCurrentParam( ref nodeParams ) ); + + m_tempBotInspectorName = GetCurrentParam( ref nodeParams ); + m_tempBotName = GetCurrentParam( ref nodeParams ); + m_tempBotDefaultValue = (TexturePropertyValues)Enum.Parse( typeof( TexturePropertyValues ), GetCurrentParam( ref nodeParams ) ); + m_tempBotOrderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_tempBotDefaultTexture = AssetDatabase.LoadAssetAtPath( GetCurrentParam( ref nodeParams ) ); + + if( UIUtils.CurrentShaderVersion() > 6102 ) + m_propertyInspectorName = GetCurrentParam( ref nodeParams ); + + if( UIUtils.CurrentShaderVersion() <= 18301 ) + Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + + if( UIUtils.CurrentShaderVersion() > 18201 ) + m_normalSpace = (ViewSpace)Enum.Parse( typeof( ViewSpace ), GetCurrentParam( ref nodeParams ) ); + + SetTitleText( m_propertyInspectorName ); + + ConfigurePorts(); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + + Init(); + + ReadPropertiesData(); + + ConfigurePorts(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedTriplanarType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedTriplanarSpace ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalCorrection ); + + IOUtils.AddFieldValueToString( ref nodeInfo, m_topTexture.PropertyInspectorName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_topTexture.PropertyName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_topTexture.DefaultTextureValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_topTexture.OrderIndex.ToString() ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_topTexture.DefaultValue != null ) ? AssetDatabase.GetAssetPath( m_topTexture.DefaultValue ) : Constants.NoStringValue ); + + IOUtils.AddFieldValueToString( ref nodeInfo, m_midTexture.PropertyInspectorName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_midTexture.PropertyName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_midTexture.DefaultTextureValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_midTexture.OrderIndex.ToString() ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_midTexture.DefaultValue != null ) ? AssetDatabase.GetAssetPath( m_midTexture.DefaultValue ) : Constants.NoStringValue ); + + IOUtils.AddFieldValueToString( ref nodeInfo, m_botTexture.PropertyInspectorName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_botTexture.PropertyName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_botTexture.DefaultTextureValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_botTexture.OrderIndex.ToString() ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_botTexture.DefaultValue != null ) ? AssetDatabase.GetAssetPath( m_botTexture.DefaultValue ) : Constants.NoStringValue ); + + IOUtils.AddFieldValueToString( ref nodeInfo, m_propertyInspectorName ); + + //IOUtils.AddFieldValueToString( ref nodeInfo, m_arraySupport ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalSpace ); + } + public override void RefreshOnUndo() + { + base.RefreshOnUndo(); + if( m_topTexture != null ) + { + m_topTexture.BeginPropertyFromInspectorCheck(); + } + + if( m_midTexture != null ) + { + m_midTexture.BeginPropertyFromInspectorCheck(); + } + + if( m_botTexture != null ) + { + m_botTexture.BeginPropertyFromInspectorCheck(); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/TriplanarNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/TriplanarNode.cs.meta new file mode 100644 index 0000000..39ce8da --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/TriplanarNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 396e5bf33f08d3a42a19d7b161f573f2 +timeCreated: 1490358806 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToClipPosHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToClipPosHlpNode.cs new file mode 100644 index 0000000..277effc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToClipPosHlpNode.cs @@ -0,0 +1,34 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Object To Clip Pos", "Object Transform", "Transforms a point from object space to the camera’s clip space in homogeneous coordinates" )] + public sealed class UnityObjToClipPosHlpNode : HelperParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "UnityObjectToClipPos"; + //TODO: revisit this later + m_funcLWFormatOverride = "TransformWorldToHClip(TransformObjectToWorld({0}))"; + m_funcHDFormatOverride = "TransformWorldToHClip(TransformObjectToWorld({0}))"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_outputPorts[ 0 ].Name = "XYZW"; + AddOutputPort( WirePortDataType.FLOAT, "X" ); + AddOutputPort( WirePortDataType.FLOAT, "Y" ); + AddOutputPort( WirePortDataType.FLOAT, "Z" ); + AddOutputPort( WirePortDataType.FLOAT, "W" ); + m_previewShaderGUID = "14ec765a147a53340877b489e73f1c9f"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "unityObjectToClipPos" + OutputId; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToClipPosHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToClipPosHlpNode.cs.meta new file mode 100644 index 0000000..0f62b63 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToClipPosHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c01e190d996825f42bdc81e1fab5e897 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToViewPosHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToViewPosHlpNode.cs new file mode 100644 index 0000000..89258e8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToViewPosHlpNode.cs @@ -0,0 +1,33 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Object To View Pos", "Object Transform", "Transforms a point from object space to view space" )] + public sealed class UnityObjToViewPosHlpNode : HelperParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "UnityObjectToViewPos"; + //TODO: revisit this later + m_funcLWFormatOverride = "TransformWorldToView( TransformObjectToWorld( {0}) )"; + m_funcHDFormatOverride = "TransformWorldToView( TransformObjectToWorld( {0}) )"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_outputPorts[ 0 ].Name = "XYZ"; + AddOutputPort( WirePortDataType.FLOAT, "X" ); + AddOutputPort( WirePortDataType.FLOAT, "Y" ); + AddOutputPort( WirePortDataType.FLOAT, "Z" ); + m_previewShaderGUID = "b790bc1d468a51840a9facef372b4729"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "unityObjectToViewPos" + OutputId; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToViewPosHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToViewPosHlpNode.cs.meta new file mode 100644 index 0000000..c0ea4e5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/UnityObjToViewPosHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5f35cf284cf7d2b47be5a32426fc7a77 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceLightDirHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceLightDirHlpNode.cs new file mode 100644 index 0000000..2848003 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceLightDirHlpNode.cs @@ -0,0 +1,78 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "World Space Light Dir", "Light", "Computes normalized world space light direction" )] + public sealed class WorldSpaceLightDirHlpNode : HelperParentNode + { + private const string NormalizeOptionStr = "Safe Normalize"; + + [SerializeField] + private bool m_safeNormalize = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "UnityWorldSpaceLightDir"; + m_inputPorts[ 0 ].Visible = false; + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_outputPorts[ 0 ].Name = "XYZ"; + + AddOutputPort( WirePortDataType.FLOAT, "X" ); + AddOutputPort( WirePortDataType.FLOAT, "Y" ); + AddOutputPort( WirePortDataType.FLOAT, "Z" ); + + m_useInternalPortData = false; + m_drawPreviewAsSphere = true; + m_autoWrapProperties = true; + m_textLabelWidth = 120; + m_previewShaderGUID = "2e8dc46eb6fb2124d9f0007caf9567e3"; + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + if( m_safeNormalize ) + dataCollector.SafeNormalizeLightDir = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_safeNormalize = EditorGUILayoutToggle( NormalizeOptionStr, m_safeNormalize ); + EditorGUILayout.HelpBox( "Having safe normalize ON makes sure your light vector is not zero even if there's no lights in your scene.", MessageType.None ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate ) + return GetOutputVectorItem( 0, outputId, dataCollector.TemplateDataCollectorInstance.GetWorldSpaceLightDir( CurrentPrecisionType ) ); ; + + dataCollector.AddToIncludes( UniqueId, Constants.UnityCgLibFuncs ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_POS ); + + return GetOutputVectorItem( 0, outputId, GeneratorUtils.GenerateWorldLightDirection( ref dataCollector, UniqueId, CurrentPrecisionType ) ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 15201 ) + { + m_safeNormalize = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_safeNormalize ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceLightDirHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceLightDirHlpNode.cs.meta new file mode 100644 index 0000000..87a3bc3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceLightDirHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2134a58fb8235524d84046a051bce6b5 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceViewDirHlpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceViewDirHlpNode.cs new file mode 100644 index 0000000..27b3dcb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceViewDirHlpNode.cs @@ -0,0 +1,34 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "World Space View Dir", "Object Transform", "World space direction (not normalized) from given object space vertex position towards the camera" )] + public sealed class WorldSpaceViewDirHlpNode : HelperParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_funcType = "WorldSpaceViewDir"; + //TODO: revisit this later + m_funcLWFormatOverride = "( _WorldSpaceCameraPos.xyz - mul(GetObjectToWorldMatrix(), {0} ).xyz )"; + m_funcHDFormatOverride = "( _WorldSpaceCameraPos.xyz - mul(GetObjectToWorldMatrix(), {0} ).xyz )"; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_inputPorts[ 0 ].Vector4InternalData = new UnityEngine.Vector4( 0, 0, 0, 1 ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_outputPorts[ 0 ].Name = "XYZ"; + AddOutputPort( WirePortDataType.FLOAT, "X" ); + AddOutputPort( WirePortDataType.FLOAT, "Y" ); + AddOutputPort( WirePortDataType.FLOAT, "Z" ); + m_previewShaderGUID = "fe0e09756a8a0ba408015b43e66cb8a6"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_localVarName = "worldSpaceViewDir" + OutputId; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceViewDirHlpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceViewDirHlpNode.cs.meta new file mode 100644 index 0000000..4097cec --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/HelperFuncs/WorldSpaceViewDirHlpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 61d7064bd5523634496fa412627603d7 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ISignalGenerator.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ISignalGenerator.cs new file mode 100644 index 0000000..aa64904 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ISignalGenerator.cs @@ -0,0 +1,11 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + interface ISignalGenerator + { + void GenerateSignalPropagation(); + void GenerateSignalInibitor(); + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ISignalGenerator.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ISignalGenerator.cs.meta new file mode 100644 index 0000000..3bfa978 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ISignalGenerator.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cfeab503d3318794ea1af322505320ef +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects.meta new file mode 100644 index 0000000..ba29e65 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2a5d24ae30c4ee74f81a2fa0615e2e95 +folderAsset: yes +timeCreated: 1481126945 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/BlendOpsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/BlendOpsNode.cs new file mode 100644 index 0000000..20ff09a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/BlendOpsNode.cs @@ -0,0 +1,445 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +//https://www.shadertoy.com/view/XdS3RW +//http://www.deepskycolors.com/archivo/2010/04/21/formulas-for-Photoshop-blending-modes.html +//http://www.pegtop.net/delphi/articles/blendmodes/softlight.htm + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + public enum BlendOps + { + ColorBurn, + ColorDodge, + Darken, + Divide, + Difference, + Exclusion, + SoftLight, + HardLight, + HardMix, + Lighten, + LinearBurn, + LinearDodge, + LinearLight, + Multiply, + Overlay, + PinLight, + Subtract, + Screen, + VividLight + } + [Serializable] + [NodeAttributes( "Blend Operations", "Image Effects", "Common layer blending modes" )] + public class BlendOpsNode : ParentNode + { + //private const string ASEHardLightCall = "ASEHardLight({0},{1})"; + //private const string ASEHardLightFunc = + //"inline float ASEHardLight( float srcLocalVar, float dstLocalVar ){" + + //" return ( ( srcLocalVar > 0.5 ) ? ( 1.0 - ( 1.0 - 2.0 * ( srcLocalVar - 0.5 ) ) * ( 1.0 - dstLocalVar ) ) : ( 2.0 * srcLocalVar * dstLocalVar ) ); }"; + + //private const string ASELinearLightCall = "ASELinearLight({0},{1})"; + //private const string ASELinearLightFunc = + //"inline float ASELinearLight( float srcLocalVar, float dstLocalVar ){" + + //" return ( ( srcLocalVar > 0.5 ) ? ( dstLocalVar + 2.0 * srcLocalVar - 1.0 ) : ( dstLocalVar + 2.0 * ( srcLocalVar - 0.5 ) ) ); }"; + + //private const string ASEOverlayCall = "ASEOverlay({0},{1})"; + //private const string ASEOverlayFunc = + //"inline float ASEOverlay( float srcLocalVar, float dstLocalVar ){" + + //" return ( ( dstLocalVar > 0.5 ) ? ( 1.0 - ( 1.0 - 2.0 * ( dstLocalVar - 0.5 ) ) * ( 1.0 - srcLocalVar ) ) : ( 2.0 * dstLocalVar * srcLocalVar ) ); }"; + ////" return (dstLocalVar < 0.5) ? 2.0 * srcLocalVar * dstLocalVar : 1.0 - 2.0 * (1.0 - srcLocalVar) * (1.0 - dstLocalVar); }"; + + //private const string ASEPinLightCall = "ASEPinLight({0},{1})"; + //private const string ASEPinLightFunc = + //"inline float ASEPinLight( float srcLocalVar, float dstLocalVar ){" + + //" return ( ( srcLocalVar > 0.5 ) ? max( dstLocalVar , 2.0 * ( srcLocalVar - 0.5 ) ) : min( dstLocalVar , 2.0 * srcLocalVar ) ); }"; + + //private const string ASEVividLightCall = "ASEVividLight({0},{1})"; + //private const string ASEVividLightFunc = "inline float ASEVividLight( float srcLocalVar, float dstLocalVar ){" + + //" return ( ( srcLocalVar > 0.5 ) ? ( dstLocalVar / ( ( 1.0 - srcLocalVar ) * 2.0 ) ) : ( 1.0 - ( ( ( 1.0 - dstLocalVar ) * 0.5 ) / srcLocalVar ) ) ); }"; + + private const string ASEDarkerColorCall = "ASEDarkerColor{}({0},{1})"; + private const string ASEDarkerColorFunc = "inline float ASEDarkerColor{0}( float srcLocalVar, float dstLocalVar ){" + + " return ({1} < {2}) ? s : d; }"; + + private const string ASELighterColorCall = "ASELighterColor{}({0},{1})"; + private const string ASELighterColorFunc = "inline float ASELighterColor{0}( float srcLocalVar, float dstLocalVar ){" + + " return ({1} > {2}) ? s : d; }"; + + private const string BlendOpsModeStr = "Blend Op"; + private const string SaturateResultStr = "Saturate"; + + [SerializeField] + private BlendOps m_currentBlendOp = BlendOps.ColorBurn; + + [SerializeField] + private WirePortDataType m_mainDataType = WirePortDataType.COLOR; + + [SerializeField] + private bool m_saturate = true; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.COLOR, false, "Source" ); + AddInputPort( WirePortDataType.COLOR, false, "Destiny" ); + AddInputPort( WirePortDataType.FLOAT, false,"Alpha" ); + m_inputPorts[ 2 ].FloatInternalData = 1; + AddOutputPort( WirePortDataType.COLOR, Constants.EmptyPortValue ); + m_inputPorts[ 0 ].AddPortForbiddenTypes( WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4, + WirePortDataType.SAMPLER1D, + WirePortDataType.SAMPLER2D, + WirePortDataType.SAMPLER3D, + WirePortDataType.SAMPLERCUBE, + WirePortDataType.SAMPLER2DARRAY ); + m_inputPorts[ 1 ].AddPortForbiddenTypes( WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4, + WirePortDataType.SAMPLER1D, + WirePortDataType.SAMPLER2D, + WirePortDataType.SAMPLER3D, + WirePortDataType.SAMPLERCUBE, + WirePortDataType.SAMPLER2DARRAY ); + m_textLabelWidth = 75; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_currentBlendOp ) ); + m_useInternalPortData = true; + m_previewShaderGUID = "6d6b3518705b3ba49acdc6e18e480257"; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + m_previewMaterialPassId = (int)m_currentBlendOp; + PreviewMaterial.SetInt( "_Sat", m_saturate ? 1 : 0 ); + int lerpMode = ( m_inputPorts[ 2 ].IsConnected || m_inputPorts[ 2 ].FloatInternalData < 1 ) ? 1 : 0; + PreviewMaterial.SetInt( "_Lerp", lerpMode ); + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnection( portId ); + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + UpdateConnection( inputPortId ); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + UpdateDisconnection( portId ); + } + + void UpdateConnection( int portId ) + { + if( portId == 2 ) + return; + + m_inputPorts[ portId ].MatchPortToConnection(); + int otherPortId = ( portId + 1 ) % 2; + if( m_inputPorts[ otherPortId ].IsConnected ) + { + m_mainDataType = UIUtils.GetPriority( m_inputPorts[ 0 ].DataType ) > UIUtils.GetPriority( m_inputPorts[ 1 ].DataType ) ? m_inputPorts[ 0 ].DataType : m_inputPorts[ 1 ].DataType; + } + else + { + m_mainDataType = m_inputPorts[ portId ].DataType; + m_inputPorts[ otherPortId ].ChangeType( m_mainDataType, false ); + } + m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + } + + void UpdateDisconnection( int portId ) + { + if( portId == 2 ) + return; + + int otherPortId = ( portId + 1 ) % 2; + if( m_inputPorts[ otherPortId ].IsConnected ) + { + m_mainDataType = m_inputPorts[ otherPortId ].DataType; + m_inputPorts[ portId ].ChangeType( m_mainDataType, false ); + m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_currentBlendOp = (BlendOps)EditorGUILayoutEnumPopup( BlendOpsModeStr, m_currentBlendOp ); + if( EditorGUI.EndChangeCheck() ) + { + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_currentBlendOp ) ); + } + m_saturate = EditorGUILayoutToggle( SaturateResultStr, m_saturate ); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + m_upperLeftWidget.DrawWidget( ref m_currentBlendOp, this, OnWidgetUpdate ); + } + + private readonly Action OnWidgetUpdate = ( x ) => + { + x.SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, ( x as BlendOpsNode ).m_currentBlendOp ) ); + }; + + private string CreateMultiChannel( ref MasterNodeDataCollector dataCollector, string function, string srcLocalVar, string dstLocalVar, string varName ) + { + switch( m_outputPorts[ 0 ].DataType ) + { + default: + { + return string.Format( function, srcLocalVar, dstLocalVar ); + } + case WirePortDataType.FLOAT2: + { + string xChannelName = varName + OutputId + "X"; + string xChannelValue = string.Format( function, srcLocalVar + ".x", dstLocalVar + ".x" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, xChannelName, xChannelValue ); + + string yChannelName = varName + OutputId + "Y"; + string yChannelValue = string.Format( function, srcLocalVar + ".y", dstLocalVar + ".y" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, yChannelName, yChannelValue ); + + return string.Format( "float2({0},{1})", xChannelName, yChannelName ); + } + case WirePortDataType.FLOAT3: + { + string xChannelName = varName + OutputId + "X"; + string xChannelValue = string.Format( function, srcLocalVar + ".x", dstLocalVar + ".x" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, xChannelName, xChannelValue ); + + string yChannelName = varName + OutputId + "Y"; + string yChannelValue = string.Format( function, srcLocalVar + ".y", dstLocalVar + ".y" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, yChannelName, yChannelValue ); + + string zChannelName = varName + OutputId + "Z"; + string zChannelValue = string.Format( function, srcLocalVar + ".z", dstLocalVar + ".z" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, zChannelName, zChannelValue ); + + return string.Format( "float3({0},{1},{2})", xChannelName, yChannelName, zChannelName ); + } + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + { + string xChannelName = varName + OutputId + "X"; + string xChannelValue = string.Format( function, srcLocalVar + ".x", dstLocalVar + ".x" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, xChannelName, xChannelValue ); + + string yChannelName = varName + OutputId + "Y"; + string yChannelValue = string.Format( function, srcLocalVar + ".y", dstLocalVar + ".y" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, yChannelName, yChannelValue ); + + string zChannelName = varName + OutputId + "Z"; + string zChannelValue = string.Format( function, srcLocalVar + ".z", dstLocalVar + ".z" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, zChannelName, zChannelValue ); + + string wChannelName = varName + OutputId + "W"; + string wChannelValue = string.Format( function, srcLocalVar + ".w", dstLocalVar + ".w" ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, wChannelName, wChannelValue ); + + return string.Format( "float4({0},{1},{2},{3})", xChannelName, yChannelName, zChannelName, wChannelName ); + } + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string src = m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, m_mainDataType, false, true ); + string dst = m_inputPorts[ 1 ].GenerateShaderForOutput( ref dataCollector, m_mainDataType, false, true ); + + string srcLocalVar = "blendOpSrc" + OutputId; + string dstLocalVar = "blendOpDest" + OutputId; + dataCollector.AddLocalVariable( UniqueId, UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_mainDataType ) + " " + srcLocalVar, src + ";" ); + dataCollector.AddLocalVariable( UniqueId, UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_mainDataType ) + " " + dstLocalVar, dst + ";" ); + + int currIndent = UIUtils.ShaderIndentLevel; + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + UIUtils.ShaderIndentLevel = 0; + } + else + { + UIUtils.ShaderIndentLevel = 1; + UIUtils.ShaderIndentLevel++; + } + + string result = string.Empty; + switch( m_currentBlendOp ) + { + case BlendOps.ColorBurn: + { + result = string.Format( "( 1.0 - ( ( 1.0 - {0}) / max( {1}, 0.00001) ) )", dstLocalVar, srcLocalVar); + } + break; + case BlendOps.ColorDodge: + { + result = string.Format( "( {0}/ max( 1.0 - {1}, 0.00001 ) )", dstLocalVar, srcLocalVar ); + } + break; + case BlendOps.Darken: + { + result = "min( " + srcLocalVar + " , " + dstLocalVar + " )"; + } + break; + case BlendOps.Divide: + { + result = string.Format( "( {0} / max({1},0.00001) )", dstLocalVar, srcLocalVar ); + } + break; + case BlendOps.Difference: + { + result = "abs( " + srcLocalVar + " - " + dstLocalVar + " )"; + } + break; + case BlendOps.Exclusion: + { + result = "( 0.5 - 2.0 * ( " + srcLocalVar + " - 0.5 ) * ( " + dstLocalVar + " - 0.5 ) )"; + } + break; + case BlendOps.SoftLight: + { + result = string.Format( "2.0f*{0}*{1} + {0}*{0}*(1.0f - 2.0f*{1})", dstLocalVar, srcLocalVar ); + } + break; + case BlendOps.HardLight: + { + result = " (( " + srcLocalVar + " > 0.5 ) ? ( 1.0 - ( 1.0 - 2.0 * ( " + srcLocalVar + " - 0.5 ) ) * ( 1.0 - " + dstLocalVar + " ) ) : ( 2.0 * " + srcLocalVar + " * " + dstLocalVar + " ) )"; + //dataCollector.AddFunction( ASEHardLightCall, UIUtils.ShaderIndentTabs + ASEHardLightFunc ); + //result = CreateMultiChannel( ref dataCollector, ASEHardLightCall, srcLocalVar, dstLocalVar, "hardLightBlend" ); + } + break; + case BlendOps.HardMix: + { + result = " round( 0.5 * ( " + srcLocalVar + " + " + dstLocalVar + " ) )"; + } + break; + case BlendOps.Lighten: + { + result = " max( " + srcLocalVar + ", " + dstLocalVar + " )"; + } + break; + case BlendOps.LinearBurn: + { + result = "( " + srcLocalVar + " + " + dstLocalVar + " - 1.0 )"; + } + break; + case BlendOps.LinearDodge: + { + result = "( " + srcLocalVar + " + " + dstLocalVar + " )"; + } + break; + case BlendOps.LinearLight: + { + result = "(( " + srcLocalVar + " > 0.5 )? ( " + dstLocalVar + " + 2.0 * " + srcLocalVar + " - 1.0 ) : ( " + dstLocalVar + " + 2.0 * ( " + srcLocalVar + " - 0.5 ) ) )"; + //dataCollector.AddFunction( ASELinearLightCall, UIUtils.ShaderIndentTabs + ASELinearLightFunc ); + //result = CreateMultiChannel( ref dataCollector, ASELinearLightCall, srcLocalVar, dstLocalVar, "linearLightBlend" ); + } + break; + case BlendOps.Multiply: + { + result = "( " + srcLocalVar + " * " + dstLocalVar + " )"; + } + break; + case BlendOps.Overlay: + { + //result = "(( " + dstLocalVar + " > 0.5 ) ? ( 1.0 - ( 1.0 - 2.0 * ( " + dstLocalVar + " - 0.5 ) ) * ( 1.0 - " + srcLocalVar + " ) ) : ( 2.0 * " + dstLocalVar + " * " + srcLocalVar + " ) )"; + result = "(( " + dstLocalVar + " > 0.5 ) ? ( 1.0 - 2.0 * ( 1.0 - " + dstLocalVar + " ) * ( 1.0 - " + srcLocalVar + " ) ) : ( 2.0 * " + dstLocalVar + " * " + srcLocalVar + " ) )"; + //dataCollector.AddFunction( ASEOverlayCall, UIUtils.ShaderIndentTabs + ASEOverlayFunc ); + //result = CreateMultiChannel( ref dataCollector, ASEOverlayCall, srcLocalVar, dstLocalVar, "overlayBlend" ); + } + break; + case BlendOps.PinLight: + { + result = "(( " + srcLocalVar + " > 0.5 ) ? max( " + dstLocalVar + ", 2.0 * ( " + srcLocalVar + " - 0.5 ) ) : min( " + dstLocalVar + ", 2.0 * " + srcLocalVar + " ) )"; + //dataCollector.AddFunction( ASEPinLightCall, UIUtils.ShaderIndentTabs + ASEPinLightFunc ); + //result = CreateMultiChannel( ref dataCollector, ASEPinLightCall, srcLocalVar, dstLocalVar, "pinLightBlend" ); + } + break; + case BlendOps.Subtract: + { + result = "( " + dstLocalVar + " - " + srcLocalVar + " )"; + } + break; + case BlendOps.Screen: + { + result = "( 1.0 - ( 1.0 - " + srcLocalVar + " ) * ( 1.0 - " + dstLocalVar + " ) )"; + } + break; + case BlendOps.VividLight: + { + result = string.Format( "(( {0} > 0.5 ) ? ( {1} / max( ( 1.0 - {0} ) * 2.0 ,0.00001) ) : ( 1.0 - ( ( ( 1.0 - {1} ) * 0.5 ) / max( {0},0.00001) ) ) )", srcLocalVar, dstLocalVar); + //dataCollector.AddFunction( ASEVividLightCall, UIUtils.ShaderIndentTabs + ASEVividLightFunc ); + //result = CreateMultiChannel( ref dataCollector, ASEVividLightCall, srcLocalVar, dstLocalVar, "vividLightBlend" ); + } + break; + } + + UIUtils.ShaderIndentLevel = currIndent; + if( m_inputPorts[ 2 ].IsConnected || m_inputPorts[ 2 ].FloatInternalData < 1.0 ) + { + string opacity = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + string lerpVar = "lerpBlendMode" + OutputId; + string lerpResult = string.Format( "lerp({0},{1},{2})", dstLocalVar, result, opacity ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_outputPorts[ 0 ].DataType, lerpVar, lerpResult ); + result = lerpVar; + } + + if( m_saturate ) + result = "( saturate( " + result + " ))"; + + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentBlendOp ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_saturate ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_currentBlendOp = (BlendOps)Enum.Parse( typeof( BlendOps ), GetCurrentParam( ref nodeParams ) ); + m_saturate = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_currentBlendOp ) ); + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/BlendOpsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/BlendOpsNode.cs.meta new file mode 100644 index 0000000..3a53cbc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/BlendOpsNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 09fb0867c2a616c488bad8929f4f7ad7 +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/DesaturateOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/DesaturateOpNode.cs new file mode 100644 index 0000000..507c678 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/DesaturateOpNode.cs @@ -0,0 +1,57 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +// http://stackoverflow.com/questions/9320953/what-algorithm-does-photoshop-use-to-desaturate-an-image +// https://www.shadertoy.com/view/lsdXDH + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Desaturate", "Image Effects", "Generic desaturation operation" )] + public sealed class DesaturateOpNode : ParentNode + { + private const string GenericDesaturateOp0 = "dot( {0}, float3( 0.299, 0.587, 0.114 ))"; + private const string GenericDesaturateOp1 = "lerp( {0}, {1}.xxx, {2} )"; + //private const string GenericDesaturateOp = "lerp( {0},dot({0},float3(0.299,0.587,0.114)).xxx,{1})"; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "RGB" ); + AddInputPort( WirePortDataType.FLOAT, false, "Fraction" ); + AddOutputPort( WirePortDataType.FLOAT3, Constants.EmptyPortValue ); + m_useInternalPortData = true; + m_previewShaderGUID = "faabe9efdf44b9648a523f1742abdfd3"; + } + + void UpdatePorts( int portId ) + { + if ( portId == 0 ) + { + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string initalColorValue = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string fraction = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + string initialColorVarName = "desaturateInitialColor" + OutputId; + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, initialColorVarName, initalColorValue ); + + string dotVarName = "desaturateDot" + OutputId; + string dotVarValue = string.Format( GenericDesaturateOp0, initialColorVarName ); + + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, dotVarName, dotVarValue ); + RegisterLocalVariable( 0, string.Format( GenericDesaturateOp1, initialColorVarName, dotVarName,fraction ), ref dataCollector, "desaturateVar" + OutputId ); + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/DesaturateOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/DesaturateOpNode.cs.meta new file mode 100644 index 0000000..c931cbd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/DesaturateOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: eddae0a124877fc47b28ae8853286174 +timeCreated: 1489414268 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/HSVToRGBNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/HSVToRGBNode.cs new file mode 100644 index 0000000..a30c69a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/HSVToRGBNode.cs @@ -0,0 +1,87 @@ +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "HSV to RGB", "Image Effects", "Converts from HSV to RGB color space" )] + public sealed class HSVToRGBNode : ParentNode + { + public static readonly string HSVToRGBHeader = "HSVToRGB( {0}3({1},{2},{3}) )"; + public static readonly string[] HSVToRGBFunction = { "{0}3 HSVToRGB( {0}3 c )\n", + "{\n", + "\t{0}4 K = {0}4( 1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0 );\n", + "\t{0}3 p = abs( frac( c.xxx + K.xyz ) * 6.0 - K.www );\n", + "\treturn c.z * lerp( K.xxx, saturate( p - K.xxx ), c.y );\n", + "}\n"}; + public static readonly bool[] HSVToRGBFlags = { true, + false, + true, + true, + false, + false}; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "Hue" ); + AddInputPort( WirePortDataType.FLOAT, false, "Saturation" ); + AddInputPort( WirePortDataType.FLOAT, false, "Value" ); + AddOutputColorPorts( "RGB", false ); + m_previewShaderGUID = "fab445eb945d63047822a7a6b81b959d"; + m_useInternalPortData = true; + m_autoWrapProperties = true; + m_customPrecision = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + DrawPrecisionProperty(); + } + + public static void AddHSVToRGBFunction( ref MasterNodeDataCollector dataCollector , string precisionString ) + { + if( !dataCollector.HasFunction( HSVToRGBHeader ) ) + { + //Hack to be used util indent is properly used + int currIndent = UIUtils.ShaderIndentLevel; + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + UIUtils.ShaderIndentLevel = 0; + } + else + { + UIUtils.ShaderIndentLevel = 1; + UIUtils.ShaderIndentLevel++; + } + + string finalFunction = string.Empty; + for( int i = 0; i < HSVToRGBFunction.Length; i++ ) + { + finalFunction += UIUtils.ShaderIndentTabs + ( HSVToRGBFlags[ i ] ? string.Format( HSVToRGBFunction[ i ], precisionString ) : HSVToRGBFunction[ i ] ); + } + + UIUtils.ShaderIndentLevel = currIndent; + + dataCollector.AddFunction( HSVToRGBHeader, finalFunction ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + string precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, WirePortDataType.FLOAT ); + + AddHSVToRGBFunction( ref dataCollector , precisionString ); + + string hue = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string saturation = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string value = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + + RegisterLocalVariable( 0, string.Format( HSVToRGBHeader, precisionString, hue, saturation, value ), ref dataCollector, "hsvTorgb" + OutputId ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/HSVToRGBNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/HSVToRGBNode.cs.meta new file mode 100644 index 0000000..5d33d3a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/HSVToRGBNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3d992a68cff329a4a9bd1deb999fe691 +timeCreated: 1494857111 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/LuminanceNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/LuminanceNode.cs new file mode 100644 index 0000000..2582a59 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/LuminanceNode.cs @@ -0,0 +1,32 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Luminance", "Image Effects", "Calculates Luminance value from input")] + public sealed class LuminanceNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "RGB" ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_previewShaderGUID = "81e1d8ffeec8a4b4cabb1094bc981048"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string grayscale = "Luminance(" + value + ")"; + + RegisterLocalVariable( 0, grayscale, ref dataCollector, "luminance" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/LuminanceNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/LuminanceNode.cs.meta new file mode 100644 index 0000000..20c21f3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/LuminanceNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c5f40d01acf184946b8660599f33109f +timeCreated: 1574935849 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/NoiseGeneratorNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/NoiseGeneratorNode.cs new file mode 100644 index 0000000..c6805a4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/NoiseGeneratorNode.cs @@ -0,0 +1,466 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// Based on the work by https://github.com/keijiro/NoiseShader + +using System; +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public enum NoiseGeneratorType + { + Simplex2D, + Simplex3D, + Gradient, + Simple + }; + + [Serializable] + [NodeAttributes( "Noise Generator", "Miscellaneous", "Collection of procedural noise generators", tags: "simplex gradient" )] + public sealed class NoiseGeneratorNode : ParentNode + { + private const string TypeLabelStr = "Type"; + private const string SetTo01RangeOpStr = "{0} = {0}*0.5 + 0.5;"; + private const string SetToMinus1To1RangeOpStr = "{0} = {0}*2 - 1;"; + private const string SetTo01RangeLabel = "0-1 Range"; + private const string SetTo01RangePreviewId = "_To01Range"; + private const string UseUnityVersionLabel = "Use Unity Version"; + + // Simple + private const string SimpleNoiseRandomValueFunc = "inline float noise_randomValue (float2 uv) { return frac(sin(dot(uv, float2(12.9898, 78.233)))*43758.5453); }"; + private const string SimpleNoiseInterpolateFunc = "inline float noise_interpolate (float a, float b, float t) { return (1.0-t)*a + (t*b); }"; + private const string SimpleValueNoiseHeader = "inline float valueNoise (float2 uv)"; + private readonly string[] SimpleValueNoiseBody = { "inline float valueNoise (float2 uv)\n", + "{\n", + "\tfloat2 i = floor(uv);\n", + "\tfloat2 f = frac( uv );\n", + "\tf = f* f * (3.0 - 2.0 * f);\n", + "\tuv = abs( frac(uv) - 0.5);\n", + "\tfloat2 c0 = i + float2( 0.0, 0.0 );\n", + "\tfloat2 c1 = i + float2( 1.0, 0.0 );\n", + "\tfloat2 c2 = i + float2( 0.0, 1.0 );\n", + "\tfloat2 c3 = i + float2( 1.0, 1.0 );\n", + "\tfloat r0 = noise_randomValue( c0 );\n", + "\tfloat r1 = noise_randomValue( c1 );\n", + "\tfloat r2 = noise_randomValue( c2 );\n", + "\tfloat r3 = noise_randomValue( c3 );\n", + "\tfloat bottomOfGrid = noise_interpolate( r0, r1, f.x );\n", + "\tfloat topOfGrid = noise_interpolate( r2, r3, f.x );\n", + "\tfloat t = noise_interpolate( bottomOfGrid, topOfGrid, f.y );\n", + "\treturn t;\n", + "}\n"}; + + private const string SimpleNoiseHeader = "float SimpleNoise(float2 UV, float Scale)"; + private const string SimpleNoiseFunc = "SimpleNoise( {0} )"; + private readonly string[] SimpleNoiseBody = { "float SimpleNoise(float2 UV)\n", + "{\n", + "\tfloat t = 0.0;\n", + "\tfloat freq = pow( 2.0, float( 0 ) );\n", + "\tfloat amp = pow( 0.5, float( 3 - 0 ) );\n", + "\tt += valueNoise( UV/freq )*amp;\n", + "\tfreq = pow(2.0, float(1));\n", + "\tamp = pow(0.5, float(3-1));\n", + "\tt += valueNoise( UV/freq )*amp;\n", + "\tfreq = pow(2.0, float(2));\n", + "\tamp = pow(0.5, float(3-2));\n", + "\tt += valueNoise( UV/freq )*amp;\n", + "\treturn t;\n", + "}\n"}; + + // Simplex 2D + private const string Simplex2DFloat3Mod289Func = "float3 mod2D289( float3 x ) { return x - floor( x * ( 1.0 / 289.0 ) ) * 289.0; }"; + private const string Simplex2DFloat2Mod289Func = "float2 mod2D289( float2 x ) { return x - floor( x * ( 1.0 / 289.0 ) ) * 289.0; }"; + private const string Simplex2DPermuteFunc = "float3 permute( float3 x ) { return mod2D289( ( ( x * 34.0 ) + 1.0 ) * x ); }"; + + private const string SimplexNoise2DHeader = "float snoise( float2 v )"; + private const string SimplexNoise2DFunc = "snoise( {0} )"; + private readonly string[] SimplexNoise2DBody = {"float snoise( float2 v )\n", + "{\n", + "\tconst float4 C = float4( 0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439 );\n", + "\tfloat2 i = floor( v + dot( v, C.yy ) );\n", + "\tfloat2 x0 = v - i + dot( i, C.xx );\n", + "\tfloat2 i1;\n", + "\ti1 = ( x0.x > x0.y ) ? float2( 1.0, 0.0 ) : float2( 0.0, 1.0 );\n", + "\tfloat4 x12 = x0.xyxy + C.xxzz;\n", + "\tx12.xy -= i1;\n", + "\ti = mod2D289( i );\n", + "\tfloat3 p = permute( permute( i.y + float3( 0.0, i1.y, 1.0 ) ) + i.x + float3( 0.0, i1.x, 1.0 ) );\n", + "\tfloat3 m = max( 0.5 - float3( dot( x0, x0 ), dot( x12.xy, x12.xy ), dot( x12.zw, x12.zw ) ), 0.0 );\n", + "\tm = m * m;\n", + "\tm = m * m;\n", + "\tfloat3 x = 2.0 * frac( p * C.www ) - 1.0;\n", + "\tfloat3 h = abs( x ) - 0.5;\n", + "\tfloat3 ox = floor( x + 0.5 );\n", + "\tfloat3 a0 = x - ox;\n", + "\tm *= 1.79284291400159 - 0.85373472095314 * ( a0 * a0 + h * h );\n", + "\tfloat3 g;\n", + "\tg.x = a0.x * x0.x + h.x * x0.y;\n", + "\tg.yz = a0.yz * x12.xz + h.yz * x12.yw;\n", + "\treturn 130.0 * dot( m, g );\n", + "}\n"}; + // Simplex 3D + + + + private const string Simplex3DFloat3Mod289 = "float3 mod3D289( float3 x ) { return x - floor( x / 289.0 ) * 289.0; }"; + private const string Simplex3DFloat4Mod289 = "float4 mod3D289( float4 x ) { return x - floor( x / 289.0 ) * 289.0; }"; + private const string Simplex3DFloat4Permute = "float4 permute( float4 x ) { return mod3D289( ( x * 34.0 + 1.0 ) * x ); }"; + private const string TaylorInvSqrtFunc = "float4 taylorInvSqrt( float4 r ) { return 1.79284291400159 - r * 0.85373472095314; }"; + + private const string SimplexNoise3DHeader = "float snoise( float3 v )"; + private const string SimplexNoise3DFunc = "snoise( {0} )"; + private readonly string[] SimplexNoise3DBody = + { + "float snoise( float3 v )\n", + "{\n", + "\tconst float2 C = float2( 1.0 / 6.0, 1.0 / 3.0 );\n", + "\tfloat3 i = floor( v + dot( v, C.yyy ) );\n", + "\tfloat3 x0 = v - i + dot( i, C.xxx );\n", + "\tfloat3 g = step( x0.yzx, x0.xyz );\n", + "\tfloat3 l = 1.0 - g;\n", + "\tfloat3 i1 = min( g.xyz, l.zxy );\n", + "\tfloat3 i2 = max( g.xyz, l.zxy );\n", + "\tfloat3 x1 = x0 - i1 + C.xxx;\n", + "\tfloat3 x2 = x0 - i2 + C.yyy;\n", + "\tfloat3 x3 = x0 - 0.5;\n", + "\ti = mod3D289( i);\n", + "\tfloat4 p = permute( permute( permute( i.z + float4( 0.0, i1.z, i2.z, 1.0 ) ) + i.y + float4( 0.0, i1.y, i2.y, 1.0 ) ) + i.x + float4( 0.0, i1.x, i2.x, 1.0 ) );\n", + "\tfloat4 j = p - 49.0 * floor( p / 49.0 ); // mod(p,7*7)\n", + "\tfloat4 x_ = floor( j / 7.0 );\n", + "\tfloat4 y_ = floor( j - 7.0 * x_ ); // mod(j,N)\n", + "\tfloat4 x = ( x_ * 2.0 + 0.5 ) / 7.0 - 1.0;\n", + "\tfloat4 y = ( y_ * 2.0 + 0.5 ) / 7.0 - 1.0;\n", + "\tfloat4 h = 1.0 - abs( x ) - abs( y );\n", + "\tfloat4 b0 = float4( x.xy, y.xy );\n", + "\tfloat4 b1 = float4( x.zw, y.zw );\n", + "\tfloat4 s0 = floor( b0 ) * 2.0 + 1.0;\n", + "\tfloat4 s1 = floor( b1 ) * 2.0 + 1.0;\n", + "\tfloat4 sh = -step( h, 0.0 );\n", + "\tfloat4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;\n", + "\tfloat4 a1 = b1.xzyw + s1.xzyw * sh.zzww;\n", + "\tfloat3 g0 = float3( a0.xy, h.x );\n", + "\tfloat3 g1 = float3( a0.zw, h.y );\n", + "\tfloat3 g2 = float3( a1.xy, h.z );\n", + "\tfloat3 g3 = float3( a1.zw, h.w );\n", + "\tfloat4 norm = taylorInvSqrt( float4( dot( g0, g0 ), dot( g1, g1 ), dot( g2, g2 ), dot( g3, g3 ) ) );\n", + "\tg0 *= norm.x;\n", + "\tg1 *= norm.y;\n", + "\tg2 *= norm.z;\n", + "\tg3 *= norm.w;\n", + "\tfloat4 m = max( 0.6 - float4( dot( x0, x0 ), dot( x1, x1 ), dot( x2, x2 ), dot( x3, x3 ) ), 0.0 );\n", + "\tm = m* m;\n", + "\tm = m* m;\n", + "\tfloat4 px = float4( dot( x0, g0 ), dot( x1, g1 ), dot( x2, g2 ), dot( x3, g3 ) );\n", + "\treturn 42.0 * dot( m, px);\n", + "}\n" + }; + + //Gradient Noise + private readonly string UnityGradientNoiseFunc = "UnityGradientNoise({0},{1})"; + private readonly string[] UnityGradientNoiseFunctionsBody = + { + "float2 UnityGradientNoiseDir( float2 p )\n", + "{\n", + "\tp = fmod(p , 289);\n", + "\tfloat x = fmod((34 * p.x + 1) * p.x , 289) + p.y;\n", + "\tx = fmod( (34 * x + 1) * x , 289);\n", + "\tx = frac( x / 41 ) * 2 - 1;\n", + "\treturn normalize( float2(x - floor(x + 0.5 ), abs( x ) - 0.5 ) );\n", + "}\n", + "\n", + "float UnityGradientNoise( float2 UV, float Scale )\n", + "{\n", + "\tfloat2 p = UV * Scale;\n", + "\tfloat2 ip = floor( p );\n", + "\tfloat2 fp = frac( p );\n", + "\tfloat d00 = dot( UnityGradientNoiseDir( ip ), fp );\n", + "\tfloat d01 = dot( UnityGradientNoiseDir( ip + float2( 0, 1 ) ), fp - float2( 0, 1 ) );\n", + "\tfloat d10 = dot( UnityGradientNoiseDir( ip + float2( 1, 0 ) ), fp - float2( 1, 0 ) );\n", + "\tfloat d11 = dot( UnityGradientNoiseDir( ip + float2( 1, 1 ) ), fp - float2( 1, 1 ) );\n", + "\tfp = fp * fp * fp * ( fp * ( fp * 6 - 15 ) + 10 );\n", + "\treturn lerp( lerp( d00, d01, fp.y ), lerp( d10, d11, fp.y ), fp.x ) + 0.5;\n", + "}\n" + }; + private readonly string GradientNoiseFunc = "GradientNoise({0},{1})"; + private readonly string[] GradientNoiseFunctionsBody = + { + "//https://www.shadertoy.com/view/XdXGW8\n", + "float2 GradientNoiseDir( float2 x )\n", + "{\n", + "\tconst float2 k = float2( 0.3183099, 0.3678794 );\n", + "\tx = x * k + k.yx;\n", + "\treturn -1.0 + 2.0 * frac( 16.0 * k * frac( x.x * x.y * ( x.x + x.y ) ) );\n", + "}\n", + "\n", + "float GradientNoise( float2 UV, float Scale )\n", + "{\n", + "\tfloat2 p = UV * Scale;\n", + "\tfloat2 i = floor( p );\n", + "\tfloat2 f = frac( p );\n", + "\tfloat2 u = f * f * ( 3.0 - 2.0 * f );\n", + "\treturn lerp( lerp( dot( GradientNoiseDir( i + float2( 0.0, 0.0 ) ), f - float2( 0.0, 0.0 ) ),\n", + "\t\t\tdot( GradientNoiseDir( i + float2( 1.0, 0.0 ) ), f - float2( 1.0, 0.0 ) ), u.x ),\n", + "\t\t\tlerp( dot( GradientNoiseDir( i + float2( 0.0, 1.0 ) ), f - float2( 0.0, 1.0 ) ),\n", + "\t\t\tdot( GradientNoiseDir( i + float2( 1.0, 1.0 ) ), f - float2( 1.0, 1.0 ) ), u.x ), u.y );\n", + "}\n" + }; + + [SerializeField] + private NoiseGeneratorType m_type = NoiseGeneratorType.Simplex2D; + + [SerializeField] + private bool m_setTo01Range = true; + + [SerializeField] + private bool m_unityVersion = false; + private int m_setTo01RangePreviewId; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT2, false, "UV" ); + AddInputPort( WirePortDataType.FLOAT, false, "Scale" ); + m_inputPorts[ 1 ].FloatInternalData = 1; + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_useInternalPortData = true; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_type ) ); + m_previewShaderGUID = "cd2d37ef5da190b42a91a5a690ba2a7d"; + ConfigurePorts(); + } + + public override void OnEnable() + { + base.OnEnable(); + m_setTo01RangePreviewId = Shader.PropertyToID( SetTo01RangePreviewId ); + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + float range01 = m_setTo01Range ? 1 : 0; + PreviewMaterial.SetFloat( m_setTo01RangePreviewId, range01 ); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + m_upperLeftWidget.DrawWidget( ref m_type, this, OnWidgetUpdate ); + } + + private readonly Action OnWidgetUpdate = ( x ) => + { + ( x as NoiseGeneratorNode ).ConfigurePorts(); + }; + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_type = (NoiseGeneratorType)EditorGUILayoutEnumPopup( TypeLabelStr, m_type ); + if( EditorGUI.EndChangeCheck() ) + { + ConfigurePorts(); + } + + m_setTo01Range = EditorGUILayoutToggle( SetTo01RangeLabel, m_setTo01Range ); + + if( m_type == NoiseGeneratorType.Gradient ) + { + EditorGUI.BeginChangeCheck(); + m_unityVersion = EditorGUILayoutToggle( UseUnityVersionLabel, m_unityVersion ); + if( EditorGUI.EndChangeCheck() ) + { + ConfigurePorts(); + } + } + //EditorGUILayout.HelpBox( "Node still under construction. Use with caution", MessageType.Info ); + } + + private void ConfigurePorts() + { + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_type ) ); + + switch( m_type ) + { + case NoiseGeneratorType.Simplex2D: + { + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT2, false ); + m_previewMaterialPassId = 0; + } + break; + + case NoiseGeneratorType.Simplex3D: + { + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_previewMaterialPassId = 1; + } + break; + case NoiseGeneratorType.Gradient: + { + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT2, false ); + m_previewMaterialPassId = m_unityVersion ? 3 : 2; + } + break; + case NoiseGeneratorType.Simple: + { + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT2, false ); + m_previewMaterialPassId = 4; + } + break; + } + PreviewIsDirty = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ outputId ].IsLocalValue( dataCollector.PortCategory ) ) + { + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + string size = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string scale = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + switch( m_type ) + { + case NoiseGeneratorType.Simplex2D: + { + + string float3Mod289Func = ( dataCollector.IsTemplate ) ? Simplex2DFloat3Mod289Func : "\t\t" + Simplex2DFloat3Mod289Func; + dataCollector.AddFunction( Simplex2DFloat3Mod289Func, float3Mod289Func ); + + string float2Mod289Func = ( dataCollector.IsTemplate ) ? Simplex2DFloat2Mod289Func : "\t\t" + Simplex2DFloat2Mod289Func; + dataCollector.AddFunction( Simplex2DFloat2Mod289Func, float2Mod289Func ); + + string permuteFunc = ( dataCollector.IsTemplate ) ? Simplex2DPermuteFunc : "\t\t" + Simplex2DPermuteFunc; + dataCollector.AddFunction( Simplex2DPermuteFunc, permuteFunc ); + + dataCollector.AddFunction( SimplexNoise2DHeader, SimplexNoise2DBody, false ); + + + if( m_inputPorts[ 1 ].IsConnected || m_inputPorts[ 1 ].FloatInternalData != 1.0f ) + { + size = string.Format( "{0}*{1}", size, scale ); + } + + RegisterLocalVariable( 0, string.Format( SimplexNoise2DFunc, size ), ref dataCollector, ( "simplePerlin2D" + OutputId ) ); + } + break; + case NoiseGeneratorType.Simplex3D: + { + + string float3Mod289Func = ( dataCollector.IsTemplate ) ? Simplex3DFloat3Mod289 : "\t\t" + Simplex3DFloat3Mod289; + dataCollector.AddFunction( Simplex3DFloat3Mod289, float3Mod289Func ); + + string float4Mod289Func = ( dataCollector.IsTemplate ) ? Simplex3DFloat4Mod289 : "\t\t" + Simplex3DFloat4Mod289; + dataCollector.AddFunction( Simplex3DFloat4Mod289, float4Mod289Func ); + + string permuteFunc = ( dataCollector.IsTemplate ) ? Simplex3DFloat4Permute : "\t\t" + Simplex3DFloat4Permute; + dataCollector.AddFunction( Simplex3DFloat4Permute, permuteFunc ); + + string taylorInvSqrtFunc = ( dataCollector.IsTemplate ) ? TaylorInvSqrtFunc : "\t\t" + TaylorInvSqrtFunc; + dataCollector.AddFunction( TaylorInvSqrtFunc, taylorInvSqrtFunc ); + + dataCollector.AddFunction( SimplexNoise3DHeader, SimplexNoise3DBody, false ); + + if( m_inputPorts[ 1 ].IsConnected || m_inputPorts[ 1 ].FloatInternalData != 1.0f ) + { + size = string.Format( "{0}*{1}", size, scale ); + } + + RegisterLocalVariable( 0, string.Format( SimplexNoise3DFunc, size ), ref dataCollector, ( "simplePerlin3D" + OutputId ) ); + } + break; + + case NoiseGeneratorType.Gradient: + { + string[] body = m_unityVersion ? UnityGradientNoiseFunctionsBody : GradientNoiseFunctionsBody; + string func = m_unityVersion ? UnityGradientNoiseFunc : GradientNoiseFunc; + + dataCollector.AddFunction( body[ 0 ], body, false); + RegisterLocalVariable( 0, string.Format( func, size, scale ), ref dataCollector, ( "gradientNoise" + OutputId ) ); + } + break; + + case NoiseGeneratorType.Simple: + { + string randomValue = ( dataCollector.IsTemplate ) ? SimpleNoiseRandomValueFunc : "\t\t" + SimpleNoiseRandomValueFunc; + dataCollector.AddFunction( SimpleNoiseRandomValueFunc, randomValue ); + + string interpolate = ( dataCollector.IsTemplate ) ? SimpleNoiseInterpolateFunc : "\t\t" + SimpleNoiseInterpolateFunc; + dataCollector.AddFunction( SimpleNoiseInterpolateFunc, interpolate ); + + dataCollector.AddFunction( SimpleValueNoiseHeader, SimpleValueNoiseBody, false ); + + dataCollector.AddFunction( SimpleNoiseHeader, SimpleNoiseBody, false ); + + if( m_inputPorts[ 1 ].IsConnected || m_inputPorts[ 1 ].FloatInternalData != 1.0f ) + { + size = string.Format( "{0}*{1}", size, scale ); + } + RegisterLocalVariable( 0, string.Format( SimpleNoiseFunc, size ), ref dataCollector, ( "simpleNoise" + OutputId ) ); + } + break; + } + + if( m_type == NoiseGeneratorType.Simple && !m_setTo01Range ) + { + dataCollector.AddLocalVariable( outputId, string.Format( SetToMinus1To1RangeOpStr, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ) ); + } + + if( m_setTo01Range && m_type != NoiseGeneratorType.Simple ) + { + dataCollector.AddLocalVariable( outputId, string.Format( SetTo01RangeOpStr, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ) ); + } + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_type = (NoiseGeneratorType)Enum.Parse( typeof( NoiseGeneratorType ), GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() < 16903 ) + { + m_setTo01Range = false; + } + else + { + m_setTo01Range = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_unityVersion = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + ConfigurePorts(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_type ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_setTo01Range ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_unityVersion ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/NoiseGeneratorNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/NoiseGeneratorNode.cs.meta new file mode 100644 index 0000000..cb3c00c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/NoiseGeneratorNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6b82a8d1dffe4204fa03a09e2fe783b3 +timeCreated: 1485355115 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/PosterizeNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/PosterizeNode.cs new file mode 100644 index 0000000..9518f64 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/PosterizeNode.cs @@ -0,0 +1,98 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +//https://www.shadertoy.com/view/ldX3D4 +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Posterize", "Image Effects", "Converts a continuous gradation of tones to multiple regions of fewer tones" )] + public sealed class PosterizeNode : ParentNode + { + private const string PosterizationPowerStr = "Power"; + [SerializeField] + private int m_posterizationPower = 1; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.COLOR, false, "RGBA", -1, MasterNodePortCategory.Fragment, 1 ); + AddInputPort( WirePortDataType.INT, false, "Power", -1, MasterNodePortCategory.Fragment, 0 ); + m_inputPorts[ 1 ].AutoDrawInternalData = true; + AddOutputPort( WirePortDataType.COLOR, Constants.EmptyPortValue ); + m_textLabelWidth = 60; + m_autoWrapProperties = true; + m_previewShaderGUID = "ecb3048ef0eec1645bad1d72a98d8279"; + } + + public override void DrawProperties() + { + base.DrawProperties(); + if( !m_inputPorts[ 1 ].IsConnected ) + { + EditorGUILayout.BeginVertical(); + { + EditorGUI.BeginChangeCheck(); + m_posterizationPower = EditorGUILayoutIntSlider( PosterizationPowerStr, m_posterizationPower, 1, 256 ); + if( EditorGUI.EndChangeCheck() ) + { + GetInputPortByUniqueId( 0 ).IntInternalData = m_posterizationPower; + } + } + EditorGUILayout.EndVertical(); + } + else + { + EditorGUILayout.Space(); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string posterizationPower = "1"; + if( m_inputPorts[ 1 ].IsConnected ) + { + posterizationPower = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + } + else + { + posterizationPower = m_posterizationPower.ToString(); + } + + string colorTarget = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + string divVar = "div" + OutputId; + dataCollector.AddLocalVariable( UniqueId, "float " + divVar + "=256.0/float(" + posterizationPower + ");" ); + string result = "( floor( " + colorTarget + " * " + divVar + " ) / " + divVar + " )"; + + RegisterLocalVariable( 0, result, ref dataCollector, "posterize" + OutputId ); + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + m_inputPorts[ 0 ].ChangeType( WirePortDataType.COLOR, false ); + m_inputPorts[ 1 ].ChangeType( WirePortDataType.INT, false ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_posterizationPower ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_posterizationPower = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/PosterizeNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/PosterizeNode.cs.meta new file mode 100644 index 0000000..edceea3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/PosterizeNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7dc4667cd643835489312daa244a03b9 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/RGBToHSVNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/RGBToHSVNode.cs new file mode 100644 index 0000000..6d734a0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/RGBToHSVNode.cs @@ -0,0 +1,93 @@ +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "RGB to HSV", "Image Effects", "Converts from RGB to HSV color space" )] + public sealed class RGBToHSVNode : ParentNode + { + public static readonly string RGBToHSVHeader = "RGBToHSV( {0} )"; + public static readonly string[] RGBToHSVFunction = { "{0}3 RGBToHSV({0}3 c)\n", + "{\n", + "\t{0}4 K = {0}4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n", + "\t{0}4 p = lerp( {0}4( c.bg, K.wz ), {0}4( c.gb, K.xy ), step( c.b, c.g ) );\n", + "\t{0}4 q = lerp( {0}4( p.xyw, c.r ), {0}4( c.r, p.yzx ), step( p.x, c.r ) );\n", + "\t{0} d = q.x - min( q.w, q.y );\n", + "\t{0} e = 1.0e-10;\n", + "\treturn {0}3( abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n", + "}" + }; + + public static readonly bool[] RGBToHSVFlags = { true, + false, + true, + true, + true, + true, + true, + true, + false}; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "RGB" ); + AddOutputPort( WirePortDataType.FLOAT3, "HSV" ); + AddOutputPort( WirePortDataType.FLOAT, "Hue" ); + AddOutputPort( WirePortDataType.FLOAT, "Saturation" ); + AddOutputPort( WirePortDataType.FLOAT, "Value" ); + m_previewShaderGUID = "0f2f09b49bf4954428aafa2dfe1a9a09"; + m_useInternalPortData = true; + m_autoWrapProperties = true; + m_customPrecision = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + DrawPrecisionProperty(); + } + + public static void AddRGBToHSVFunction( ref MasterNodeDataCollector dataCollector, string precisionString ) + { + if( !dataCollector.HasFunction( RGBToHSVHeader ) ) + { + //Hack to be used util indent is properly used + int currIndent = UIUtils.ShaderIndentLevel; + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + UIUtils.ShaderIndentLevel = 0; + } + else + { + UIUtils.ShaderIndentLevel = 1; + UIUtils.ShaderIndentLevel++; + } + + string finalFunction = string.Empty; + for( int i = 0; i < RGBToHSVFunction.Length; i++ ) + { + finalFunction += UIUtils.ShaderIndentTabs + ( RGBToHSVFlags[ i ] ? string.Format( RGBToHSVFunction[ i ], precisionString ) : RGBToHSVFunction[ i ] ); + } + UIUtils.ShaderIndentLevel--; + UIUtils.ShaderIndentLevel = currIndent; + + dataCollector.AddFunction( RGBToHSVHeader, finalFunction ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + string precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, WirePortDataType.FLOAT ); + AddRGBToHSVFunction( ref dataCollector, precisionString ); + + string rgbValue = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + RegisterLocalVariable( 0, string.Format( RGBToHSVHeader, rgbValue ), ref dataCollector, "hsvTorgb" + OutputId ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/RGBToHSVNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/RGBToHSVNode.cs.meta new file mode 100644 index 0000000..b5abf86 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/RGBToHSVNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4d24b838adbc80d4cb63e3fc4f5a1c79 +timeCreated: 1494863846 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimpleContrastOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimpleContrastOpNode.cs new file mode 100644 index 0000000..0131092 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimpleContrastOpNode.cs @@ -0,0 +1,55 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Simple Contrast", "Image Effects", "Simple contrast matrix multiplication" )] + public sealed class SimpleContrastOpNode : ParentNode + { + private const string InputTypeStr = "Contrast"; + private const string FunctionHeader = "CalculateContrast({0},{1})"; + private readonly string[] m_functionBody = { "float4 CalculateContrast( float contrastValue, float4 colorTarget )\n", + "{\n", + "\tfloat t = 0.5 * ( 1.0 - contrastValue );\n", + "\treturn mul( float4x4( contrastValue,0,0,t, 0,contrastValue,0,t, 0,0,contrastValue,t, 0,0,0,1 ), colorTarget );\n", + "}"}; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddPorts(); + m_textLabelWidth = 70; + m_useInternalPortData = true; + m_previewShaderGUID = "8d76799413f9f0547ac9b1de7ba798f1"; + } + + void AddPorts() + { + AddInputPort( WirePortDataType.COLOR, false, "RGBA", -1, MasterNodePortCategory.Fragment, 1 ); + AddInputPort( WirePortDataType.FLOAT, false, "Value", -1, MasterNodePortCategory.Fragment, 0 ); + AddOutputPort( WirePortDataType.COLOR, Constants.EmptyPortValue ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string contrastValue = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string colorTarget = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string result = dataCollector.AddFunctions( FunctionHeader, m_functionBody, false, contrastValue, colorTarget ); + + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() < 5004 ) + { + m_inputPorts[ 1 ].FloatInternalData = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimpleContrastOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimpleContrastOpNode.cs.meta new file mode 100644 index 0000000..a860f21 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimpleContrastOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3f49defa61805f948a04775d391e507a +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimplexNoiseNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimplexNoiseNode.cs new file mode 100644 index 0000000..ec94623 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimplexNoiseNode.cs @@ -0,0 +1,104 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +//https://www.shadertoy.com/view/XsX3zB +using System; +using UnityEngine; +using UnityEditor; + + +namespace AmplifyShaderEditor +{ + public enum NoiseType + { + Simplex3D, + Simplex3DFractal + } + + [Serializable] + [NodeAttributes( "[Deprecated] Simplex Noise", "Image Effects", "Noise generated via the Simplex algorithm",null,KeyCode.None,false,true)] + public sealed class SimplexNoiseNode : ParentNode + { + private string m_randomFuncBody; + private string m_simplex3dFuncBody; + private string m_simplex3dFractalFuncBody; + + private const string RandomfunctionHeader = "Random3({0})"; + private const string Simplex3dfunctionHeader = "Simplex3d({0})"; + private const string Simplex3dFractalfunctionHeader = "Simplex3dFractal( {0})"; + + private const string NoiseTypeStr = "Type"; + + [SerializeField] + private NoiseType m_type = NoiseType.Simplex3D; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + + IOUtils.AddFunctionHeader( ref m_randomFuncBody, "float3 Random3 ( float3 c )" ); + IOUtils.AddFunctionLine( ref m_randomFuncBody, "float fracMul = 512.0;float j = 4096.0*sin ( dot ( c, float3 ( 17.0, 59.4, 15.0 ) ) );float3 r;r.z = frac ( fracMul*j );j *= .125;r.x = frac ( fracMul*j );j *= .125;r.y = frac ( fracMul*j );return r - 0.5;" ); + IOUtils.CloseFunctionBody( ref m_randomFuncBody ); + + IOUtils.AddFunctionHeader( ref m_simplex3dFuncBody, "float3 Simplex3d ( float3 p )" ); + IOUtils.AddFunctionLine( ref m_simplex3dFuncBody, "float F3 = 0.3333333;float G3 = 0.1666667;float3 s = floor ( p + dot ( p, F3.xxx ) );float3 x = p - s + dot ( s, G3.xxx );float3 e = step ( ( 0.0 ).xxx, x - x.yzx );float3 i1 = e*( 1.0 - e.zxy );float3 i2 = 1.0 - e.zxy*( 1.0 - e );float3 x1 = x - i1 + G3;float3 x2 = x - i2 + 2.0*G3;float3 x3 = x - 1.0 + 3.0*G3;float4 w, d;w.x = dot ( x, x );w.y = dot ( x1, x1 );w.z = dot ( x2, x2 );w.w = dot ( x3, x3 );w = max ( 0.6 - w, 0.0 );d.x = dot ( Random3 ( s ), x );d.y = dot ( Random3 ( s + i1 ), x1 );d.z = dot ( Random3 ( s + i2 ), x2 );d.w = dot ( Random3 ( s + 1.0 ), x3 );w *= w;w *= w;d *= w;return dot ( d, ( 52.0 ).xxx ).xxx;" ); + IOUtils.CloseFunctionBody( ref m_simplex3dFuncBody ); + + IOUtils.AddFunctionHeader( ref m_simplex3dFractalFuncBody, "float3 Simplex3dFractal ( float3 m )" ); + IOUtils.AddFunctionLine( ref m_simplex3dFractalFuncBody, "return (0.5333333*Simplex3d ( m ) + 0.2666667*Simplex3d ( 2.0*m ) + 0.1333333*Simplex3d ( 4.0*m ) + 0.0666667*Simplex3d ( 8.0*m )).xxx;" ); + IOUtils.CloseFunctionBody( ref m_simplex3dFractalFuncBody ); + + AddInputPort( WirePortDataType.FLOAT3, false, "Position" ); + AddInputPort( WirePortDataType.FLOAT, false, "Width" ); + AddOutputPort( WirePortDataType.FLOAT3, Constants.EmptyPortValue ); + m_textLabelWidth = 50; + m_useInternalPortData = true; + m_autoWrapProperties = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_type = ( NoiseType ) EditorGUILayoutEnumPopup( NoiseTypeStr, m_type ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + + + string posValue = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string widthValue = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + dataCollector.AddFunctions( RandomfunctionHeader, m_randomFuncBody, "0" ); + string result = string.Empty; + switch ( m_type ) + { + case NoiseType.Simplex3D: + { + string finalValue = dataCollector.AddFunctions( Simplex3dfunctionHeader, m_simplex3dFuncBody, posValue + "*" + widthValue ); + result = finalValue + "* 0.5 + 0.5"; + }break; + + case NoiseType.Simplex3DFractal: + { + dataCollector.AddFunctions( Simplex3dfunctionHeader, m_simplex3dFuncBody, posValue + "*" + widthValue ); + string finalValue = dataCollector.AddFunctions( Simplex3dFractalfunctionHeader, m_simplex3dFractalFuncBody, posValue + "*" + widthValue + "+" + widthValue ); + result = finalValue + "* 0.5 + 0.5"; + }break; + } + + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_type = ( NoiseType ) Enum.Parse( typeof( NoiseType ), GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_type ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimplexNoiseNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimplexNoiseNode.cs.meta new file mode 100644 index 0000000..477f0e3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/SimplexNoiseNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3f888e3dadb5df94199547ab13cb74d2 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/TFHCGrayscale.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/TFHCGrayscale.cs new file mode 100644 index 0000000..5620173 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/TFHCGrayscale.cs @@ -0,0 +1,116 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Grayscale +// Donated by The Four Headed Cat - @fourheadedcat + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Grayscale", "Image Effects", "Convert image colors to grayscale", null, KeyCode.None, true, false, null, null, "The Four Headed Cat - @fourheadedcat", tags:"luminance" )] + public sealed class TFHCGrayscale : ParentNode + { + private const string GrayscaleStyleStr = "Grayscale Style"; + + [SerializeField] + private int m_grayscaleStyle; + + [SerializeField] + private readonly string[] m_GrayscaleStyleValues = { "Luminance", "Natural Classic", "Old School" }; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "RGB" ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_textLabelWidth = 120; + m_useInternalPortData = true; + m_hasLeftDropdown = true; + m_autoWrapProperties = true; + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_GrayscaleStyleValues[ m_grayscaleStyle ] ) ); + m_previewShaderGUID = "56781cd022be9124597f0f396a46a35f"; + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + void UpdateFromSelected() + { + m_previewMaterialPassId = m_grayscaleStyle; + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_GrayscaleStyleValues[ m_grayscaleStyle ] ) ); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_grayscaleStyle = m_upperLeftWidget.DrawWidget( this, m_grayscaleStyle, m_GrayscaleStyleValues ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromSelected(); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_grayscaleStyle = EditorGUILayoutPopup( GrayscaleStyleStr, m_grayscaleStyle, m_GrayscaleStyleValues ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromSelected(); + } + EditorGUILayout.HelpBox( "Grayscale Old:\n\n - In: Image to convert.\n - Grayscale Style: Select the grayscale style.\n\n - Out: Grayscale version of the image.", MessageType.None ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_grayscaleStyle = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + UpdateFromSelected(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_grayscaleStyle ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string i = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string grayscale = string.Empty; + switch( m_grayscaleStyle ) + { + case 1: { grayscale = "dot(" + i + ", float3(0.299,0.587,0.114))"; } break; + case 2: { grayscale = "(" + i + ".r + " + i + ".g + " + i + ".b) / 3"; } break; + default: { grayscale = "Luminance(" + i + ")"; } break; + } + RegisterLocalVariable( 0, grayscale, ref dataCollector, "grayscale" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/TFHCGrayscale.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/TFHCGrayscale.cs.meta new file mode 100644 index 0000000..07f01e0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/TFHCGrayscale.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 32d7b01a9f453d448abf3685a35c4a19 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/VoronoiNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/VoronoiNode.cs new file mode 100644 index 0000000..34d5995 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/VoronoiNode.cs @@ -0,0 +1,618 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Voronoi", "Miscellaneous", "Voronoi", Tags = "noise" )] + public sealed class VoronoiNode : ParentNode + { + // Unity Voronoi + private readonly string UnityVoronoiNoiseFunc = "UnityVoronoi({0},{1},{2},{3})"; + private readonly string[] UnityVoroniNoiseFunctionsBody = + { + "inline float2 UnityVoronoiRandomVector( float2 UV, float offset )\n", + "{\n", + "\tfloat2x2 m = float2x2( 15.27, 47.63, 99.41, 89.98 );\n", + "\tUV = frac( sin(mul(UV, m) ) * 46839.32 );\n", + "\treturn float2( sin(UV.y* +offset ) * 0.5 + 0.5, cos( UV.x* offset ) * 0.5 + 0.5 );\n", + "}\n", + "\n", + "//x - Out y - Cells\n", + "float3 UnityVoronoi( float2 UV, float AngleOffset, float CellDensity, inout float2 mr )\n", + "{\n", + "\tfloat2 g = floor( UV * CellDensity );\n", + "\tfloat2 f = frac( UV * CellDensity );\n", + "\tfloat t = 8.0;\n", + "\tfloat3 res = float3( 8.0, 0.0, 0.0 );\n", + "\n", + "\tfor( int y = -1; y <= 1; y++ )\n", + "\t{\n", + "\t for( int x = -1; x <= 1; x++ )\n", + "\t {\n", + "\t\t\tfloat2 lattice = float2( x, y );\n", + "\t\t\tfloat2 offset = UnityVoronoiRandomVector( lattice + g, AngleOffset );\n", + "\t\t\tfloat d = distance( lattice + offset, f );\n", + "\n", + "\t\t\tif( d < res.x )\n", + "\t\t\t{\n", + "\t\t\t\tmr = f - lattice - offset;\n", + "\t\t\t\tres = float3( d, offset.x, offset.y );\n", + "\t\t\t}\n", + "\t }\n", + "\t}\n", + "\treturn res;\n", + "}\n", + }; + + //////////// + + private const string VoronoiHashHeader = "float2 voronoihash{0}( float2 p )"; + private readonly string[] VoronoiHashBody = { "p = p - 2 * floor( p / 2 );", + "p = float2( dot( p, float2( 127.1, 311.7 ) ), dot( p, float2( 269.5, 183.3 ) ) );", + "return frac( sin( p ) *43758.5453);" }; + + + private const string VoronoiHeader = "float voronoi{0}( float2 v, float time, inout float2 id, inout float2 mr, float smoothness, inout float2 smoothId )"; + private const string VoronoiFunc = "voronoi{0}( {1}, {2}, {3}, {4}, {5}, {6} )"; + private string[] VoronoiBody = + { + "float2 n = floor( v );", + "float2 f = frac( v );", + "float F1 = 8.0;", + "float F2 = 8.0; float2 mg = 0;", + "for ( int j = -1; j <= 1; j++ )", + "{", + " \tfor ( int i = -1; i <= 1; i++ )", + " \t{", + " \t\tfloat2 g = float2( i, j );", + " \t\tfloat2 o = voronoihash{0}( n + g );", + " \t\tfloat2 r = f - g - ( sin( 0 + o * 6.2831 ) * 0.5 + 0.5 );", + " \t\tfloat d = dot( r, r );", + " \t\tif( d + { + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].Visible && m_inputPorts[ i ].AutoDrawInternalData ) + { + m_inputPorts[ i ].ShowInternalData( this ); + } + } + } ); + } + + void ChangeFunction( string scale ) + { + VoronoiBody[ 10 ] = "\t\to = ( sin( time + o * 6.2831 ) * 0.5 + 0.5 ); float2 r = f - g - o;"; + int q = m_searchQuality + 1; + VoronoiBody[ 4 ] = "for ( int j = -" + q + "; j <= " + q + "; j++ )"; + VoronoiBody[ 6 ] = "\tfor ( int i = -" + q + "; i <= " + q + "; i++ )"; + int dFunction = m_distanceFunction; + if( m_functionType == 4 ) + dFunction = 0; + switch( dFunction ) + { + default: + case 0: + VoronoiBody[ 11 ] = "\t\tfloat d = 0.5 * dot( r, r );"; + break; + case 1: + VoronoiBody[ 11 ] = "\t\tfloat d = 0.707 * sqrt(dot( r, r ));"; + break; + case 2: + VoronoiBody[ 11 ] = "\t\tfloat d = 0.5 * ( abs(r.x) + abs(r.y) );"; + break; + case 3: + VoronoiBody[ 11 ] = "\t\tfloat d = max(abs(r.x), abs(r.y));"; + break; + case 4: + VoronoiBody[ 11 ] = "\t\tfloat d = " + ( 1 / Mathf.Pow( 2, 1 / m_minkowskiPower ) ).ToString( "n3" ) + " * pow( ( pow( abs( r.x ), " + m_minkowskiPower + " ) + pow( abs( r.y ), " + m_minkowskiPower + " ) ), " + ( 1 / m_minkowskiPower ).ToString( "n3" ) + " );"; + break; + } + + if( m_functionType == 0 ) + { + if( m_calculateSmoothValue ) + { + VoronoiBody[ 12 ] = " //\t\tif( d 17402 ) + { + m_calculateSmoothValue = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 18902 ) + { + m_applySmoothToIds = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + ChangePorts(); + ChechSmoothPorts(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_searchQuality ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_distanceFunction ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_minkowskiPower ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_functionType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_octaves ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_tileable.ToString() ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_tileScale ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_useUnity ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_calculateSmoothValue ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_applySmoothToIds ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/VoronoiNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/VoronoiNode.cs.meta new file mode 100644 index 0000000..fb9562a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ImageEffects/VoronoiNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a3f99c25e876b164789b7612a63ec748 +timeCreated: 1566897514 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators.meta new file mode 100644 index 0000000..5a304e6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2123282111ea51445b360151bd090f3a +folderAsset: yes +timeCreated: 1481126945 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/Compare.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/Compare.cs new file mode 100644 index 0000000..dab5a15 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/Compare.cs @@ -0,0 +1,293 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.CodeDom; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Compare", "Logical Operators", "Compare A to B given the selected operator. If comparison is true return value of True else return value of False", tags: "If Ternary Compare Less Equal Not Greater" )] + public sealed class Compare : ParentNode + { + private static readonly string[] LabelsSTR = { "Equal", "Not Equal", "Greater", "Greater Or Equal", "Less", "Less Or Equal" }; + + enum Comparision + { + Equal, + NotEqual, + Greater, + GreaterOrEqual, + Less, + LessOrEqual, + } + + private WirePortDataType m_mainInputType = WirePortDataType.FLOAT; + private WirePortDataType m_mainOutputType = WirePortDataType.FLOAT; + + private int m_cachedOperatorId = -1; + + [SerializeField] + private Comparision m_comparision = Comparision.Equal; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "A" ); + AddInputPort( WirePortDataType.FLOAT, false, "B" ); + AddInputPort( WirePortDataType.FLOAT, false, "True" ); + AddInputPort( WirePortDataType.FLOAT, false, "False" ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_inputPorts[ 0 ].AutoDrawInternalData = true; + m_inputPorts[ 1 ].AutoDrawInternalData = true; + m_inputPorts[ 2 ].AutoDrawInternalData = true; + m_inputPorts[ 3 ].AutoDrawInternalData = true; + m_textLabelWidth = 100; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + m_previewShaderGUID = "381937898f0c15747af1da09a751890c"; + UpdateTitle(); + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_comparision = (Comparision)m_upperLeftWidget.DrawWidget( this, (int)m_comparision, LabelsSTR ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateTitle(); + } + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_cachedOperatorId == -1 ) + m_cachedOperatorId = Shader.PropertyToID( "_Operator" ); + + PreviewMaterial.SetInt( m_cachedOperatorId, (int)m_comparision ); + } + + void UpdateTitle() + { + switch( m_comparision ) + { + default: + case Comparision.Equal: + m_additionalContent.text = "( A = B )"; + break; + case Comparision.NotEqual: + m_additionalContent.text = "( A \u2260 B )"; + break; + case Comparision.Greater: + m_additionalContent.text = "( A > B )"; + break; + case Comparision.GreaterOrEqual: + m_additionalContent.text = "( A \u2265 B )"; + break; + case Comparision.Less: + m_additionalContent.text = "( A < B )"; + break; + case Comparision.LessOrEqual: + m_additionalContent.text = "( A \u2264 B )"; + break; + } + m_sizeIsDirty = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_comparision = (Comparision)EditorGUILayoutEnumPopup( "", m_comparision ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateTitle(); + } + + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].Visible ) + { + m_inputPorts[ i ].ShowInternalData( this ); + } + } + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + UpdateConnection( inputPortId ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnection( portId ); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + + int otherPortId = 0; + if( portId < 2 ) + { + otherPortId = ( portId == 0 ) ? 1 : 0; + if( m_inputPorts[ otherPortId ].IsConnected ) + { + m_mainInputType = m_inputPorts[ otherPortId ].DataType; + m_inputPorts[ portId ].ChangeType( m_mainInputType, false ); + } + } + else + { + otherPortId = ( portId == 2 ) ? 3 : 2; + if( m_inputPorts[ otherPortId ].IsConnected ) + { + m_mainOutputType = m_inputPorts[ otherPortId ].DataType; + m_inputPorts[ portId ].ChangeType( m_mainOutputType, false ); + m_outputPorts[ 0 ].ChangeType( m_mainOutputType, false ); + } + } + } + + public void UpdateConnection( int portId ) + { + m_inputPorts[ portId ].MatchPortToConnection(); + int otherPortId = 0; + WirePortDataType otherPortType = WirePortDataType.FLOAT; + if( portId < 2 ) + { + otherPortId = ( portId == 0 ) ? 1 : 0; + otherPortType = m_inputPorts[ otherPortId ].IsConnected ? m_inputPorts[ otherPortId ].DataType : WirePortDataType.FLOAT; + m_mainInputType = UIUtils.GetPriority( m_inputPorts[ portId ].DataType ) > UIUtils.GetPriority( otherPortType ) ? m_inputPorts[ portId ].DataType : otherPortType; + if( !m_inputPorts[ otherPortId ].IsConnected ) + { + m_inputPorts[ otherPortId ].ChangeType( m_mainInputType, false ); + } + } + else + { + otherPortId = ( portId == 2 ) ? 3 : 2; + otherPortType = m_inputPorts[ otherPortId ].IsConnected ? m_inputPorts[ otherPortId ].DataType : WirePortDataType.FLOAT; + m_mainOutputType = UIUtils.GetPriority( m_inputPorts[ portId ].DataType ) > UIUtils.GetPriority( otherPortType ) ? m_inputPorts[ portId ].DataType : otherPortType; + + m_outputPorts[ 0 ].ChangeType( m_mainOutputType, false ); + + if( !m_inputPorts[ otherPortId ].IsConnected ) + { + m_inputPorts[ otherPortId ].ChangeType( m_mainOutputType, false ); + } + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + //Conditional Operator ?: has some shenanigans + //If the first operand is of type bool, one of the following must hold for the second and third operands: + //Both operands have compatible structure types. + //Both operands are scalars with numeric or bool type. + //Both operands are vectors with numeric or bool type, where the two vectors are of the same size, which is less than or equal to four. + //If the first operand is a packed vector of bool, then the conditional selection is performed on an elementwise basis.Both the second and third operands must be numeric vectors of the same size as the first operand. + WirePortDataType compatibleInputType = m_mainInputType; + if( m_mainInputType != WirePortDataType.FLOAT && m_mainInputType != WirePortDataType.INT && m_mainInputType != m_mainOutputType ) + { + compatibleInputType = m_mainOutputType; + } + + string a = m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, compatibleInputType, ignoreLocalvar, true ); + string b = m_inputPorts[ 1 ].GenerateShaderForOutput( ref dataCollector, compatibleInputType, ignoreLocalvar, true ); + string op = string.Empty; + switch( m_comparision ) + { + default: + case Comparision.Equal: + op = "=="; + break; + case Comparision.NotEqual: + op = "!="; + break; + case Comparision.Greater: + op = ">"; + break; + case Comparision.GreaterOrEqual: + op = ">="; + break; + case Comparision.Less: + op = "<"; + break; + case Comparision.LessOrEqual: + op = "<="; + break; + } + string T = m_inputPorts[ 2 ].GenerateShaderForOutput( ref dataCollector, m_mainOutputType, ignoreLocalvar, true ); + string F = m_inputPorts[ 3 ].GenerateShaderForOutput( ref dataCollector, m_mainOutputType, ignoreLocalvar, true ); + return CreateOutputLocalVariable( 0, string.Format( "( {0} {2} {1} ? {3} : {4} )", a, b, op, T, F ), ref dataCollector ); + } + + public override void ReadFromDeprecated( ref string[] nodeParams, Type oldType = null ) + { + base.ReadFromDeprecated( ref nodeParams, oldType ); + + if( oldType == typeof( TFHCCompareEqual ) ) + { + m_comparision = Comparision.Equal; + } + else + if( oldType == typeof( TFHCCompareNotEqual ) ) + { + m_comparision = Comparision.NotEqual; + } + else + if( oldType == typeof( TFHCCompareGreater ) ) + { + m_comparision = Comparision.Greater; + } + else + if( oldType == typeof( TFHCCompareGreaterEqual ) ) + { + m_comparision = Comparision.GreaterOrEqual; + } + else + if( oldType == typeof( TFHCCompareLower ) ) + { + m_comparision = Comparision.Less; + } + else + if( oldType == typeof( TFHCCompareLowerEqual ) ) + { + m_comparision = Comparision.LessOrEqual; + } + + UpdateTitle(); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + + m_comparision = (Comparision)Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + UpdateTitle(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + + IOUtils.AddFieldValueToString( ref nodeInfo, (int)m_comparision ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/Compare.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/Compare.cs.meta new file mode 100644 index 0000000..b8307fa --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/Compare.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ab308ada4f120144b8d44aef5c834fe6 +timeCreated: 1588859716 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/ConditionalIfNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/ConditionalIfNode.cs new file mode 100644 index 0000000..d42d970 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/ConditionalIfNode.cs @@ -0,0 +1,297 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; +//using System.Collections.Generic; +//using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "If", "Logical Operators", "Conditional comparison between A with B." )] + public sealed class ConditionalIfNode : ParentNode + { + private const string UseUnityBranchesStr = "Dynamic Branching"; + private const string UnityBranchStr = "UNITY_BRANCH "; + + private readonly string[] IfOps = { "if( {0} > {1} )", + "if( {0} == {1} )", + "if( {0} < {1} )", + "if( {0} >= {1} )", + "if( {0} <= {1} )", + "if( {0} != {1} )" }; + + //private WirePortDataType m_inputMainDataType = WirePortDataType.FLOAT; + private WirePortDataType m_outputMainDataType = WirePortDataType.FLOAT; + private string[] m_results = { string.Empty, string.Empty, string.Empty }; + + [SerializeField] + private bool m_useUnityBranch = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "A" ); + AddInputPort( WirePortDataType.FLOAT, false, "B" ); + m_inputPorts[ 0 ].AddPortRestrictions( WirePortDataType.FLOAT, WirePortDataType.INT ); + m_inputPorts[ 1 ].AddPortRestrictions( WirePortDataType.FLOAT, WirePortDataType.INT ); + + AddInputPort( WirePortDataType.FLOAT, false, "A > B" ); + AddInputPort( WirePortDataType.FLOAT, false, "A == B" ); + AddInputPort( WirePortDataType.FLOAT, false, "A < B" ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_inputPorts[ 0 ].AutoDrawInternalData = true; + m_inputPorts[ 1 ].AutoDrawInternalData = true; + m_textLabelWidth = 131; + //m_useInternalPortData = true; + m_autoWrapProperties = true; + m_previewShaderGUID = "f6fb4d46bddf29e45a8a3ddfed75d0c0"; + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + UpdateConnection( inputPortId ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnection( portId ); + } + + public override void DrawProperties() + { + base.DrawProperties(); + if( !m_inputPorts[ 0 ].IsConnected ) + m_inputPorts[ 0 ].FloatInternalData = EditorGUILayoutFloatField( m_inputPorts[ 0 ].Name, m_inputPorts[ 0 ].FloatInternalData ); + if( !m_inputPorts[ 1 ].IsConnected ) + m_inputPorts[ 1 ].FloatInternalData = EditorGUILayoutFloatField( m_inputPorts[ 1 ].Name, m_inputPorts[ 1 ].FloatInternalData ); + m_useUnityBranch = EditorGUILayoutToggle( UseUnityBranchesStr, m_useUnityBranch ); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + UpdateConnection( portId ); + } + + //void TestMainInputDataType() + //{ + // WirePortDataType newType = WirePortDataType.FLOAT; + // if ( m_inputPorts[ 0 ].IsConnected && UIUtils.GetPriority( m_inputPorts[ 0 ].DataType ) > UIUtils.GetPriority( newType ) ) + // { + // newType = m_inputPorts[ 0 ].DataType; + // } + + // if ( m_inputPorts[ 1 ].IsConnected && ( UIUtils.GetPriority( m_inputPorts[ 1 ].DataType ) > UIUtils.GetPriority( newType ) ) ) + // { + // newType = m_inputPorts[ 1 ].DataType; + // } + + // m_inputMainDataType = newType; + //} + + void TestMainOutputDataType() + { + WirePortDataType newType = WirePortDataType.FLOAT; + for( int i = 2; i < 5; i++ ) + { + if( m_inputPorts[ i ].IsConnected && ( UIUtils.GetPriority( m_inputPorts[ i ].DataType ) > UIUtils.GetPriority( newType ) ) ) + { + newType = m_inputPorts[ i ].DataType; + } + } + + if( newType != m_outputMainDataType ) + { + m_outputMainDataType = newType; + } + m_outputPorts[ 0 ].ChangeType( m_outputMainDataType, false ); + } + + public void UpdateConnection( int portId ) + { + m_inputPorts[ portId ].MatchPortToConnection(); + switch( portId ) + { + //case 0: + //case 1: + //{ + // TestMainInputDataType(); + //} + //break; + case 2: + case 3: + case 4: + { + TestMainOutputDataType(); + } + break; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string AValue = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector); + string BValue = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + m_results[ 0 ] = m_inputPorts[ 2 ].GenerateShaderForOutput( ref dataCollector, m_outputMainDataType, ignoreLocalvar, true ); + m_results[ 1 ] = m_inputPorts[ 3 ].GenerateShaderForOutput( ref dataCollector, m_outputMainDataType, ignoreLocalvar, true ); + m_results[ 2 ] = m_inputPorts[ 4 ].GenerateShaderForOutput( ref dataCollector, m_outputMainDataType, ignoreLocalvar, true ); + + string localVarName = "ifLocalVar" + OutputId; + string localVarDec = string.Format( "{0} {1} = 0;", UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ), localVarName ); + + bool lequal = false; + bool greater = false; + bool lesser = false; + bool gequal = false; + bool equal = false; + bool nequal = false; + bool welse = false; + bool midCon = false; + + if( m_inputPorts[ 2 ].IsConnected ) + { + greater = true; + } + + if( m_inputPorts[ 4 ].IsConnected ) + { + lesser = true; + } + + if( greater && m_inputPorts[ 2 ].GetOutputConnection() == m_inputPorts[ 3 ].GetOutputConnection() ) + { + gequal = true; + } + + if( lesser && m_inputPorts[ 4 ].GetOutputConnection() == m_inputPorts[ 3 ].GetOutputConnection() ) + { + lequal = true; + } + + if( m_inputPorts[ 2 ].GetOutputConnection() == m_inputPorts[ 4 ].GetOutputConnection() ) + { + if( m_inputPorts[ 3 ].IsConnected ) + equal = true; + else if( m_inputPorts[ 2 ].IsConnected ) + nequal = true; + } + + if( m_inputPorts[ 3 ].IsConnected ) + { + midCon = true; + + if( greater && lesser ) + welse = true; + } + + dataCollector.AddLocalVariable( UniqueId, localVarDec, true ); + if ( m_useUnityBranch && !( lequal && gequal ) && !( !greater && !midCon && !lesser ) ) + dataCollector.AddLocalVariable( UniqueId, UnityBranchStr, true ); + + if( lequal && gequal ) // all equal + { + dataCollector.AddLocalVariable( UniqueId, string.Format( "{0} = {1};", localVarName, m_results[ 1 ] ), true ); + } + else if( !lequal && gequal ) // greater or equal + { + dataCollector.AddLocalVariable( UniqueId, string.Format( IfOps[ 3 ], AValue, BValue ), true ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "\t{0} = {1};", localVarName, m_results[ 0 ] ), true ); + + if( welse ) + { + dataCollector.AddLocalVariable( UniqueId, "else", true ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "\t{0} = {1};", localVarName, m_results[ 2 ] ), true ); + } + } + else if( lequal && !gequal )// lesser or equal + { + dataCollector.AddLocalVariable( UniqueId, string.Format( IfOps[ 4 ], AValue, BValue ), true ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "\t{0} = {1};", localVarName, m_results[ 2 ] ), true ); + + if( welse ) + { + dataCollector.AddLocalVariable( UniqueId, "else", true ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "\t{0} = {1};", localVarName, m_results[ 0 ] ), true ); + } + } + else if( nequal )// not equal + { + dataCollector.AddLocalVariable( UniqueId, string.Format( IfOps[ 5 ], AValue, BValue ), true ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "\t{0} = {1};", localVarName, m_results[ 0 ] ), true ); + } + else if( equal )// equal + { + dataCollector.AddLocalVariable( UniqueId, string.Format( IfOps[ 1 ], AValue, BValue ), true ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "\t{0} = {1};", localVarName, m_results[ 1 ] ), true ); + + if( welse ) + { + dataCollector.AddLocalVariable( UniqueId, "else", true ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "\t{0} = {1};", localVarName, m_results[ 0 ] ), true ); + } + } + else if( lesser && !midCon && !greater ) // lesser + { + dataCollector.AddLocalVariable( UniqueId, string.Format( IfOps[ 2 ], AValue, BValue ), true ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "\t{0} = {1};", localVarName, m_results[ 2 ] ), true ); + } + else if( greater && !midCon && !lesser ) // greater + { + dataCollector.AddLocalVariable( UniqueId, string.Format( IfOps[ 0 ], AValue, BValue ), true ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "\t{0} = {1};", localVarName, m_results[ 0 ] ), true ); + } + else if( !greater && !midCon && !lesser ) // none + { + //dataCollector.AddLocalVariable( UniqueId, localVarDec ); + } + else // all different + { + bool ifStarted = false; + if( greater ) + { + dataCollector.AddLocalVariable( UniqueId, string.Format( IfOps[ 0 ], AValue, BValue ), true ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "\t{0} = {1};", localVarName, m_results[ 0 ] ), true ); + ifStarted = true; + } + + if( midCon ) + { + dataCollector.AddLocalVariable( UniqueId, ( ifStarted ? "else " : string.Empty ) +string.Format( IfOps[ 1 ], AValue, BValue ), true ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "\t{0} = {1};", localVarName, m_results[ 1 ] ), true ); + ifStarted = true; + } + + if( lesser ) + { + dataCollector.AddLocalVariable( UniqueId, "else " + string.Format( IfOps[ 2 ], AValue, BValue ), true ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "\t{0} = {1};", localVarName, m_results[ 2 ] ), true ); + } + } + + m_outputPorts[ 0 ].SetLocalValue( localVarName, dataCollector.PortCategory ); + return localVarName; + } + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 4103 ) + { + m_useUnityBranch = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_useUnityBranch ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/ConditionalIfNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/ConditionalIfNode.cs.meta new file mode 100644 index 0000000..930b353 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/ConditionalIfNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3deb719c04d269e49bcd2a2c365da6fb +timeCreated: 1486405023 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/KeywordSwitchNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/KeywordSwitchNode.cs new file mode 100644 index 0000000..2365036 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/KeywordSwitchNode.cs @@ -0,0 +1,133 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Keyword Switch", "Logical Operators", "Attributes a value according to the existance of a selected keyword", Deprecated = true, DeprecatedAlternativeType = typeof(StaticSwitch), DeprecatedAlternative = "Static Switch" )] + public sealed class KeywordSwitchNode : ParentNode + { + private const string KeywordStr = "Keyword"; + private const string CustomStr = "Custom"; + + [SerializeField] + private string m_currentKeyword = string.Empty; + + [SerializeField] + private int m_currentKeywordId = 0; + + [SerializeField] + private WirePortDataType m_mainPortType = WirePortDataType.FLOAT; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "True" ); + AddInputPort( WirePortDataType.FLOAT, false, "False" ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_textLabelWidth = 65; + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_currentKeywordId = EditorGUILayoutPopup( KeywordStr, m_currentKeywordId, UIUtils.AvailableKeywords ); + if ( EditorGUI.EndChangeCheck() ) + { + if ( m_currentKeywordId != 0 ) + { + m_currentKeyword = UIUtils.AvailableKeywords[ m_currentKeywordId ]; + } + } + if ( m_currentKeywordId == 0 ) + { + m_currentKeyword = EditorGUILayoutTextField( CustomStr, m_currentKeyword ); + } + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnected( portId ); + } + + public override void OnConnectedOutputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( portId, otherNodeId, otherPortId, name, type ); + UpdateConnected( portId ); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + UpdateDisconnected( portId ); + } + + void UpdateConnected( int portId ) + { + m_inputPorts[ portId ].MatchPortToConnection(); + int otherPortId = ( portId + 1 ) % 2; + if ( m_inputPorts[ otherPortId ].IsConnected ) + { + m_mainPortType = ( UIUtils.GetPriority( m_inputPorts[ portId ].DataType ) > UIUtils.GetPriority( m_inputPorts[ otherPortId ].DataType ) ) ? + m_inputPorts[ portId ].DataType : + m_inputPorts[ otherPortId ].DataType; + } + else + { + m_mainPortType = m_inputPorts[ portId ].DataType; + m_inputPorts[ otherPortId ].ChangeType( m_mainPortType, false ); + } + m_outputPorts[ 0 ].ChangeType( m_mainPortType, false ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string trueCode = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string falseCode = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + string localVarName = "simpleKeywordVar"+OutputId; + string outType = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ); + dataCollector.AddLocalVariable( UniqueId, "#ifdef " + m_currentKeyword, true ); + dataCollector.AddLocalVariable( UniqueId, outType + " " + localVarName + " = " + trueCode + ";", true ); + dataCollector.AddLocalVariable( UniqueId, "#else", true ); + dataCollector.AddLocalVariable( UniqueId, outType + " " + localVarName + " = " + falseCode + ";", true ); + dataCollector.AddLocalVariable( UniqueId, "#endif", true ); + m_outputPorts[ 0 ].SetLocalValue( localVarName, dataCollector.PortCategory ); + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + void UpdateDisconnected( int portId ) + { + int otherPortId = ( portId + 1 ) % 2; + if ( m_inputPorts[ otherPortId ].IsConnected ) + { + m_mainPortType = m_inputPorts[ otherPortId ].DataType; + m_inputPorts[ portId ].ChangeType( m_mainPortType, false ); + } + m_outputPorts[ 0 ].ChangeType( m_mainPortType, false ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_currentKeyword = GetCurrentParam( ref nodeParams ); + m_currentKeywordId = UIUtils.GetKeywordId( m_currentKeyword ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentKeyword ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/KeywordSwitchNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/KeywordSwitchNode.cs.meta new file mode 100644 index 0000000..7549755 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/KeywordSwitchNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 04eb50f45d1416e4bb61902a49f06d58 +timeCreated: 1500648134 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareEqual.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareEqual.cs new file mode 100644 index 0000000..dea9b14 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareEqual.cs @@ -0,0 +1,35 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Compare (A == B) +// Donated by The Four Headed Cat - @fourheadedcat + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Compare (A = B)", "Logical Operators", "Check if A is equal to B. If true return value of True else return value of False", null, KeyCode.None, true, true, "Compare", typeof( Compare ), "The Four Headed Cat - @fourheadedcat" )] + public sealed class TFHCCompareEqual : TFHCStub + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].Name = "A"; + m_inputPorts[ 1 ].Name = "B"; + AddInputPort( WirePortDataType.FLOAT, false, "True" ); + AddInputPort( WirePortDataType.FLOAT, false, "False" ); + m_textLabelWidth = 100; + m_useInternalPortData = true; + m_previewShaderGUID = "6904de6cf8c08e7439672390b425ab50"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + GetInputData( ref dataCollector, ignoreLocalvar ); + string strout = "(( " + m_inputDataPort0 + " == " + m_inputDataPort1 + " ) ? " + m_inputDataPort2 + " : " + m_inputDataPort3 + " )"; + return CreateOutputLocalVariable( 0, strout, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareEqual.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareEqual.cs.meta new file mode 100644 index 0000000..d8255b8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareEqual.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d6d04219b3c5c5a4282aa9a763b9ad3c +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreater.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreater.cs new file mode 100644 index 0000000..3d6db6a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreater.cs @@ -0,0 +1,36 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Compare (A > B) +// Donated by The Four Headed Cat - @fourheadedcat + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes("Compare (A > B)", "Logical Operators", "Check if A is greater than B. If true return value of True else return value of False", null, KeyCode.None, true, true, "Compare", typeof( Compare ), "The Four Headed Cat - @fourheadedcat" )] + public sealed class TFHCCompareGreater : TFHCStub + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].Name = "A"; + m_inputPorts[ 1 ].Name = "B"; + AddInputPort( WirePortDataType.FLOAT, false, "True" ); + AddInputPort( WirePortDataType.FLOAT, false, "False" ); + m_textLabelWidth = 100; + m_useInternalPortData = true; + m_previewShaderGUID = "363192dbd019ad2478f2fe6c277b7e48"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + GetInputData( ref dataCollector, ignoreLocalvar ); + string strout = "(( " + m_inputDataPort0 + " > " + m_inputDataPort1 + " ) ? " + m_inputDataPort2 + " : " + m_inputDataPort3 + " )"; + //Debug.Log(strout); + return CreateOutputLocalVariable( 0, strout, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreater.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreater.cs.meta new file mode 100644 index 0000000..7d1c572 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreater.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ff04934859005cd41ac644f2a9349e8b +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreaterEqual.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreaterEqual.cs new file mode 100644 index 0000000..5dc0fe6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreaterEqual.cs @@ -0,0 +1,37 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Compare (A >= B) +// Donated by The Four Headed Cat - @fourheadedcat + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes("Compare (A \u2265 B)", "Logical Operators", "Check if A is greater than or equal to B. If true return value of True else return value of False", null, KeyCode.None, true, true, "Compare", typeof(Compare), "The Four Headed Cat - @fourheadedcat" )] + public sealed class TFHCCompareGreaterEqual : TFHCStub + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].Name = "A"; + m_inputPorts[ 1 ].Name = "B"; + AddInputPort( WirePortDataType.FLOAT, false, "True" ); + AddInputPort( WirePortDataType.FLOAT, false, "False" ); + m_textLabelWidth = 100; + m_useInternalPortData = true; + m_previewShaderGUID = "f4ff76282a117c2429a1bcd8ba3a9112"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + GetInputData( ref dataCollector, ignoreLocalvar ); + string strout = "(( " + m_inputDataPort0 + " >= " + m_inputDataPort1 + " ) ? " + m_inputDataPort2 + " : " + m_inputDataPort3 + " )"; + //Debug.Log(strout); + return CreateOutputLocalVariable( 0, strout, ref dataCollector ); + + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreaterEqual.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreaterEqual.cs.meta new file mode 100644 index 0000000..d871371 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareGreaterEqual.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b2792c240940c3349bdef401f5683f70 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLower.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLower.cs new file mode 100644 index 0000000..8f98947 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLower.cs @@ -0,0 +1,35 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Compare (A < B) +// Donated by The Four Headed Cat - @fourheadedcat + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes("Compare (A < B)", "Logical Operators", "Check if A is lower than B. If true return value of True else return value of False", null, KeyCode.None, true, true, "Compare", typeof( Compare ), "The Four Headed Cat - @fourheadedcat" )] + public sealed class TFHCCompareLower : TFHCStub + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].Name = "A"; + m_inputPorts[ 1 ].Name = "B"; + AddInputPort( WirePortDataType.FLOAT, false, "True" ); + AddInputPort( WirePortDataType.FLOAT, false, "False" ); + m_textLabelWidth = 100; + m_useInternalPortData = true; + m_previewShaderGUID = "8024509244392ed44b37c28473e66a8a"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + GetInputData( ref dataCollector, ignoreLocalvar ); + string strout = "(( " + m_inputDataPort0 + " < " + m_inputDataPort1 + " ) ? " + m_inputDataPort2 + " : " + m_inputDataPort3 + " )"; + return CreateOutputLocalVariable( 0, strout, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLower.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLower.cs.meta new file mode 100644 index 0000000..e5abcf6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLower.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1a70dcf76fe65a64ca70400d6d08563d +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLowerEqual.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLowerEqual.cs new file mode 100644 index 0000000..d9bcafd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLowerEqual.cs @@ -0,0 +1,35 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Compare (A <= B) +// Donated by The Four Headed Cat - @fourheadedcat + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes("Compare (A \u2264 B)", "Logical Operators", "Check if A is lower than or equal to B. If true return value of True else return value of False", null, KeyCode.None, true, true, "Compare", typeof( Compare ), "The Four Headed Cat - @fourheadedcat" )] + public sealed class TFHCCompareLowerEqual : TFHCStub + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].Name = "A"; + m_inputPorts[ 1 ].Name = "B"; + AddInputPort( WirePortDataType.FLOAT, false, "True" ); + AddInputPort( WirePortDataType.FLOAT, false, "False" ); + m_textLabelWidth = 100; + m_useInternalPortData = true; + m_previewShaderGUID = "9a3e17508793b9d42b1efaaf5bcd2554"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + GetInputData( ref dataCollector, ignoreLocalvar ); + string strout = "(( " + m_inputDataPort0 + " <= " + m_inputDataPort1 + " ) ? " + m_inputDataPort2 + " : " + m_inputDataPort3 + " )"; + return CreateOutputLocalVariable( 0, strout, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLowerEqual.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLowerEqual.cs.meta new file mode 100644 index 0000000..4fd5bee --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareLowerEqual.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e1e66ddf48770134b806dd1f397e4ac3 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareNotEqual.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareNotEqual.cs new file mode 100644 index 0000000..98ec281 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareNotEqual.cs @@ -0,0 +1,35 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Compare (A != B) +// Donated by The Four Headed Cat - @fourheadedcat + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes("Compare (A \u2260 B)", "Logical Operators", "Check if A is not equal to B. If true return value of True else return value of False", null, KeyCode.None, true, true, "Compare", typeof( Compare ), "The Four Headed Cat - @fourheadedcat" )] + public sealed class TFHCCompareNotEqual : TFHCStub + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].Name = "A"; + m_inputPorts[ 1 ].Name = "B"; + AddInputPort( WirePortDataType.FLOAT, false, "True" ); + AddInputPort( WirePortDataType.FLOAT, false, "False" ); + m_textLabelWidth = 100; + m_useInternalPortData = true; + m_previewShaderGUID = "75f433376eef1ad4a881d99124e08008"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + GetInputData( ref dataCollector, ignoreLocalvar ); + string strout = "(( " + m_inputDataPort0 + " != " + m_inputDataPort1 + " ) ? " + m_inputDataPort2 + " : " + m_inputDataPort3 + " )"; + return CreateOutputLocalVariable( 0, strout, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareNotEqual.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareNotEqual.cs.meta new file mode 100644 index 0000000..77f259d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareNotEqual.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 48f885e2f5fa775409b9f50be6aaf80a +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareWithRange.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareWithRange.cs new file mode 100644 index 0000000..efd0d40 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareWithRange.cs @@ -0,0 +1,122 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Compare With Range +// Donated by The Four Headed Cat - @fourheadedcat + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Compare With Range", "Logical Operators", "Check if A is in the range between Range Min and Range Max. If true return value of True else return value of False", null, KeyCode.None, true, false, null, null, "The Four Headed Cat - @fourheadedcat" )] + public sealed class TFHCCompareWithRange : DynamicTypeNode + { + private WirePortDataType m_mainInputType = WirePortDataType.FLOAT; + private WirePortDataType m_mainOutputType = WirePortDataType.FLOAT; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].Name = "Value"; + m_inputPorts[ 1 ].Name = "Range Min"; + AddInputPort( WirePortDataType.FLOAT, false, "Range Max" ); + AddInputPort( WirePortDataType.FLOAT, false, "True" ); + AddInputPort( WirePortDataType.FLOAT, false, "False" ); + m_textLabelWidth = 100; + m_useInternalPortData = true; + m_previewShaderGUID = "127d114eed178d7409f900134a6c00d1"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + UpdateConnections( portId ); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + UpdateConnections( outputPortId ); + } + + public override void OnInputPortDisconnected( int portId ) + { + if ( portId < 3 ) + { + if ( portId > 0 ) + { + m_inputPorts[ portId ].ChangeType( m_mainInputType, false ); + } + } + else + { + int otherPortId = ( portId == 3 ) ? 4 : 3; + if ( m_inputPorts[ otherPortId ].IsConnected ) + { + m_mainOutputType = m_inputPorts[ otherPortId ].DataType; + m_inputPorts[ portId ].ChangeType( m_mainOutputType, false ); + m_outputPorts[ 0 ].ChangeType( m_mainOutputType, false ); + } + } + } + + void UpdateConnections( int portId ) + { + m_inputPorts[ portId ].MatchPortToConnection(); + int otherPortId = 0; + WirePortDataType otherPortType = WirePortDataType.FLOAT; + if ( portId < 3 ) + { + if ( portId == 0 ) + { + m_mainInputType = m_inputPorts[ 0 ].DataType; + for ( int i = 1; i < 3; i++ ) + { + if ( !m_inputPorts[ i ].IsConnected ) + { + m_inputPorts[ i ].ChangeType( m_mainInputType, false ); + } + } + } + } + else + { + otherPortId = ( portId == 3 ) ? 4 : 3; + otherPortType = m_inputPorts[ otherPortId ].IsConnected ? m_inputPorts[ otherPortId ].DataType : WirePortDataType.FLOAT; + m_mainOutputType = UIUtils.GetPriority( m_inputPorts[ portId ].DataType ) > UIUtils.GetPriority( otherPortType ) ? m_inputPorts[ portId ].DataType : otherPortType; + + m_outputPorts[ 0 ].ChangeType( m_mainOutputType, false ); + + if ( !m_inputPorts[ otherPortId ].IsConnected ) + { + m_inputPorts[ otherPortId ].ChangeType( m_mainOutputType, false ); + } + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + //Conditional Operator ?: has some shenanigans + //If the first operand is of type bool, one of the following must hold for the second and third operands: + //Both operands have compatible structure types. + //Both operands are scalars with numeric or bool type. + //Both operands are vectors with numeric or bool type, where the two vectors are of the same size, which is less than or equal to four. + //If the first operand is a packed vector of bool, then the conditional selection is performed on an elementwise basis.Both the second and third operands must be numeric vectors of the same size as the first operand. + WirePortDataType compatibleInputType = m_mainInputType; + if ( m_mainInputType != WirePortDataType.FLOAT && m_mainInputType != WirePortDataType.INT && m_mainInputType != m_mainOutputType ) + { + compatibleInputType = m_mainOutputType; + } + + //Check if VALUE is in range between MIN and MAX. If true return VALUE IF TRUE else VALUE IF FALSE" + string a = m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, compatibleInputType, ignoreLocalvar, true ); + string b = m_inputPorts[ 1 ].GenerateShaderForOutput( ref dataCollector, compatibleInputType, ignoreLocalvar, true ); + string c = m_inputPorts[ 2 ].GenerateShaderForOutput( ref dataCollector, compatibleInputType, ignoreLocalvar, true ); + string d = m_inputPorts[ 3 ].GenerateShaderForOutput( ref dataCollector, m_mainOutputType, ignoreLocalvar, true ); + string e = m_inputPorts[ 4 ].GenerateShaderForOutput( ref dataCollector, m_mainOutputType, ignoreLocalvar, true ); + string strout = "(( " + a + " >= " + b + " && " + a + " <= " + c + " ) ? " + d + " : " + e + " )"; + //Debug.Log(strout); + return CreateOutputLocalVariable( 0, strout, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareWithRange.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareWithRange.cs.meta new file mode 100644 index 0000000..9cef3a3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCCompareWithRange.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e7d30ad11b781804ebd54834781a32d9 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCIf.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCIf.cs new file mode 100644 index 0000000..7ed7272 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCIf.cs @@ -0,0 +1,133 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node If +// Donated by The Four Headed Cat - @fourheadedcat + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "If [Community]", "Logical Operators", "Compare A with B. If A is greater than B output the value of A > B port. If A is equal to B output the value of A == B port. If A is lower than B output the value of A < B port. Equal Threshold parameter will be used to check A == B adding and subtracting this value to A.", null, KeyCode.None, true, false, null, null, "The Four Headed Cat - @fourheadedcat" )] + public sealed class TFHCIf : ParentNode + { + private WirePortDataType m_inputMainDataType = WirePortDataType.FLOAT; + private WirePortDataType m_outputMainDataType = WirePortDataType.FLOAT; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "A" ); + AddInputPort( WirePortDataType.FLOAT, false, "B" ); + AddInputPort( WirePortDataType.FLOAT, false, "A > B" ); + AddInputPort( WirePortDataType.FLOAT, false, "A == B" ); + AddInputPort( WirePortDataType.FLOAT, false, "A < B" ); + AddInputPort( WirePortDataType.FLOAT, false, "Equal Threshold" ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_textLabelWidth = 110; + m_useInternalPortData = true; + m_previewShaderGUID = "5c7bc7e3cab81da499e4864ace0d86c5"; + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + UpdateConnection( inputPortId ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnection( portId ); + } + + public override void OnInputPortDisconnected( int portId ) + { + UpdateConnection( portId ); + } + + void TestMainInputDataType() + { + WirePortDataType newType = WirePortDataType.FLOAT; + if( m_inputPorts[ 0 ].IsConnected && UIUtils.GetPriority( m_inputPorts[ 0 ].DataType ) > UIUtils.GetPriority( newType ) ) + { + newType = m_inputPorts[ 0 ].DataType; + } + + if( m_inputPorts[ 1 ].IsConnected && ( UIUtils.GetPriority( m_inputPorts[ 1 ].DataType ) > UIUtils.GetPriority( newType ) ) ) + { + newType = m_inputPorts[ 1 ].DataType; + } + + if( m_inputPorts[ 5 ].IsConnected && ( UIUtils.GetPriority( m_inputPorts[ 5 ].DataType ) > UIUtils.GetPriority( newType ) ) ) + { + newType = m_inputPorts[ 5 ].DataType; + } + + m_inputMainDataType = newType; + } + + void TestMainOutputDataType() + { + WirePortDataType newType = WirePortDataType.FLOAT; + for( int i = 2; i < 5; i++ ) + { + if( m_inputPorts[ i ].IsConnected && ( UIUtils.GetPriority( m_inputPorts[ i ].DataType ) > UIUtils.GetPriority( newType ) ) ) + { + newType = m_inputPorts[ i ].DataType; + } + } + + if( newType != m_outputMainDataType ) + { + m_outputMainDataType = newType; + m_outputPorts[ 0 ].ChangeType( m_outputMainDataType, false ); + } + } + + public void UpdateConnection( int portId ) + { + m_inputPorts[ portId ].MatchPortToConnection(); + switch( portId ) + { + case 0: + case 1: + case 5: + { + TestMainInputDataType(); + } + break; + case 2: + case 3: + case 4: + { + TestMainOutputDataType(); + } + break; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + string a = m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, m_inputMainDataType, ignoreLocalvar, true ); + string b = m_inputPorts[ 1 ].GenerateShaderForOutput( ref dataCollector, m_inputMainDataType, ignoreLocalvar, true ); + string r1 = m_inputPorts[ 2 ].GenerateShaderForOutput( ref dataCollector, m_outputMainDataType, ignoreLocalvar, true ); + string r2 = m_inputPorts[ 3 ].GenerateShaderForOutput( ref dataCollector, m_outputMainDataType, ignoreLocalvar, true ); + string r3 = m_inputPorts[ 4 ].GenerateShaderForOutput( ref dataCollector, m_outputMainDataType, ignoreLocalvar, true ); + string tr = m_inputPorts[ 5 ].GenerateShaderForOutput( ref dataCollector, m_inputMainDataType, ignoreLocalvar, true ); + + // No Equal Threshold parameter + //(a > b ? r1 : a == b ? r2 : r3 ) + //string strout = " ( " + a + " > " + b + " ? " + r1 + " : " + a + " == " + b + " ? " + r2 + " : " + r3 + " ) "; + + // With Equal Threshold parameter + // ( a - tr > b ? r1 : a - tr <= b && a + tr >= b ? r2 : r3 ) + string strout = " ( " + a + " - " + tr + " > " + b + " ? " + r1 + " : " + a + " - " + tr + " <= " + b + " && " + a + " + " + tr + " >= " + b + " ? " + r2 + " : " + r3 + " ) "; + + //Debug.Log( strout ); + return CreateOutputLocalVariable( 0, strout, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCIf.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCIf.cs.meta new file mode 100644 index 0000000..8d6fe58 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCIf.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1a3d561a45c21114c99f52c5432b25e9 +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCStub.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCStub.cs new file mode 100644 index 0000000..38dd405 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCStub.cs @@ -0,0 +1,103 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + + +namespace AmplifyShaderEditor +{ + [System.Serializable] + public class TFHCStub : DynamicTypeNode + { + protected WirePortDataType m_mainInputType = WirePortDataType.FLOAT; + protected WirePortDataType m_mainOutputType = WirePortDataType.FLOAT; + protected string m_inputDataPort0 = string.Empty; + protected string m_inputDataPort1 = string.Empty; + protected string m_inputDataPort2 = string.Empty; + protected string m_inputDataPort3 = string.Empty; + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + UpdateConnections( portId ); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + UpdateConnections( outputPortId ); + } + + public override void OnInputPortDisconnected( int portId ) + { + int otherPortId = 0; + if ( portId < 2 ) + { + otherPortId = ( portId == 0 ) ? 1 : 0; + if ( m_inputPorts[ otherPortId ].IsConnected ) + { + m_mainInputType = m_inputPorts[ otherPortId ].DataType; + m_inputPorts[ portId ].ChangeType( m_mainInputType, false ); + } + } + else + { + otherPortId = ( portId == 2 ) ? 3 : 2; + if ( m_inputPorts[ otherPortId ].IsConnected ) + { + m_mainOutputType = m_inputPorts[ otherPortId ].DataType; + m_inputPorts[ portId ].ChangeType( m_mainOutputType, false ); + m_outputPorts[ 0 ].ChangeType( m_mainOutputType, false ); + } + } + } + + public void GetInputData( ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + //Conditional Operator ?: has some shenanigans + //If the first operand is of type bool, one of the following must hold for the second and third operands: + //Both operands have compatible structure types. + //Both operands are scalars with numeric or bool type. + //Both operands are vectors with numeric or bool type, where the two vectors are of the same size, which is less than or equal to four. + //If the first operand is a packed vector of bool, then the conditional selection is performed on an elementwise basis.Both the second and third operands must be numeric vectors of the same size as the first operand. + WirePortDataType compatibleInputType = m_mainInputType; + if ( m_mainInputType != WirePortDataType.FLOAT && m_mainInputType != WirePortDataType.INT && m_mainInputType != m_mainOutputType ) + { + compatibleInputType = m_mainOutputType; + } + + m_inputDataPort0 = m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, compatibleInputType, ignoreLocalvar, true ); + m_inputDataPort1 = m_inputPorts[ 1 ].GenerateShaderForOutput( ref dataCollector, compatibleInputType, ignoreLocalvar, true ); + + + m_inputDataPort2 = m_inputPorts[ 2 ].GenerateShaderForOutput( ref dataCollector, m_mainOutputType, ignoreLocalvar, true ); + m_inputDataPort3 = m_inputPorts[ 3 ].GenerateShaderForOutput( ref dataCollector, m_mainOutputType, ignoreLocalvar, true ); + } + + void UpdateConnections( int portId ) + { + m_inputPorts[ portId ].MatchPortToConnection(); + int otherPortId = 0; + WirePortDataType otherPortType = WirePortDataType.FLOAT; + if ( portId < 2 ) + { + otherPortId = ( portId == 0 ) ? 1 : 0; + otherPortType = m_inputPorts[ otherPortId ].IsConnected ? m_inputPorts[ otherPortId ].DataType : WirePortDataType.FLOAT; + m_mainInputType = UIUtils.GetPriority( m_inputPorts[ portId ].DataType ) > UIUtils.GetPriority( otherPortType ) ? m_inputPorts[ portId ].DataType : otherPortType; + if ( !m_inputPorts[ otherPortId ].IsConnected ) + { + m_inputPorts[ otherPortId ].ChangeType( m_mainInputType, false ); + } + } + else + { + otherPortId = ( portId == 2 ) ? 3 : 2; + otherPortType = m_inputPorts[ otherPortId ].IsConnected ? m_inputPorts[ otherPortId ].DataType : WirePortDataType.FLOAT; + m_mainOutputType = UIUtils.GetPriority( m_inputPorts[ portId ].DataType ) > UIUtils.GetPriority( otherPortType ) ? m_inputPorts[ portId ].DataType : otherPortType; + + m_outputPorts[ 0 ].ChangeType( m_mainOutputType, false ); + + if ( !m_inputPorts[ otherPortId ].IsConnected ) + { + m_inputPorts[ otherPortId ].ChangeType( m_mainOutputType, false ); + } + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCStub.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCStub.cs.meta new file mode 100644 index 0000000..ca618e7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/LogicalOperators/TFHCStub.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 67238b98f61049c45b496af625863edf +timeCreated: 1481646118 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master.meta new file mode 100644 index 0000000..e014e2d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7787d08c0679d324c99a7ca9a1a3e6a4 +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalDefinesHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalDefinesHelper.cs new file mode 100644 index 0000000..7aa08d9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalDefinesHelper.cs @@ -0,0 +1,140 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class AdditionalDefinesHelper + { + private const string AdditionalDefinesStr = " Additional Defines"; + private const float ShaderKeywordButtonLayoutWidth = 15; + private ParentNode m_currentOwner; + + [SerializeField] + private List m_additionalDefines = new List(); + public List DefineList { get { return m_additionalDefines; } set { m_additionalDefines = value; } } + + [SerializeField] + private List m_outsideDefines = new List(); + public List OutsideList { get { return m_outsideDefines; } set { m_outsideDefines = value; } } + + public void Draw( ParentNode owner ) + { + m_currentOwner = owner; + bool value = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalDefines; + NodeUtils.DrawPropertyGroup( ref value, AdditionalDefinesStr, DrawMainBody, DrawButtons ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalDefines = value; + } + + void DrawButtons() + { + EditorGUILayout.Separator(); + + // Add keyword + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_additionalDefines.Add( string.Empty ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove keyword + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + if( m_additionalDefines.Count > 0 ) + { + m_additionalDefines.RemoveAt( m_additionalDefines.Count - 1 ); + EditorGUI.FocusTextInControl( null ); + } + } + } + + void DrawMainBody() + { + EditorGUILayout.Separator(); + int itemCount = m_additionalDefines.Count; + int markedToDelete = -1; + for( int i = 0; i < itemCount; i++ ) + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUI.BeginChangeCheck(); + m_additionalDefines[ i ] = EditorGUILayout.TextField( m_additionalDefines[ i ] ); + if( EditorGUI.EndChangeCheck() ) + { + m_additionalDefines[ i ] = UIUtils.RemoveShaderInvalidCharacters( m_additionalDefines[ i ] ); + } + + // Add new port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_additionalDefines.Insert( i + 1, string.Empty ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + markedToDelete = i; + } + } + EditorGUILayout.EndHorizontal(); + } + + if( markedToDelete > -1 ) + { + if( m_additionalDefines.Count > markedToDelete ) + { + m_additionalDefines.RemoveAt( markedToDelete ); + EditorGUI.FocusTextInControl( null ); + } + } + EditorGUILayout.Separator(); + EditorGUILayout.HelpBox( "Please add your defines without the #define keywords", MessageType.Info ); + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + int count = Convert.ToInt32( nodeParams[ index++ ] ); + for( int i = 0; i < count; i++ ) + { + m_additionalDefines.Add( nodeParams[ index++ ] ); + } + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDefines.Count ); + for( int i = 0; i < m_additionalDefines.Count; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDefines[ i ] ); + } + } + + public void AddToDataCollector( ref MasterNodeDataCollector dataCollector ) + { + for( int i = 0; i < m_additionalDefines.Count; i++ ) + { + if( !string.IsNullOrEmpty( m_additionalDefines[ i ] ) ) + dataCollector.AddToDefines( -1, m_additionalDefines[ i ] ); + } + + for( int i = 0; i < m_outsideDefines.Count; i++ ) + { + if( !string.IsNullOrEmpty( m_outsideDefines[ i ] ) ) + dataCollector.AddToDefines( -1, m_outsideDefines[ i ] ); + } + } + + public void Destroy() + { + m_additionalDefines.Clear(); + m_additionalDefines = null; + m_currentOwner = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalDefinesHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalDefinesHelper.cs.meta new file mode 100644 index 0000000..6839c0e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalDefinesHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0801a5994efb46142ad8dcc0fe3c47f8 +timeCreated: 1513252939 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalIncludesHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalIncludesHelper.cs new file mode 100644 index 0000000..542b586 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalIncludesHelper.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class AdditionalIncludesHelper + { + private const string AdditionalIncludesStr = " Additional Includes"; + private const float ShaderKeywordButtonLayoutWidth = 15; + private ParentNode m_currentOwner; + + [SerializeField] + private List m_additionalIncludes = new List(); + public List IncludeList { get { return m_additionalIncludes; } set { m_additionalIncludes = value; } } + + [SerializeField] + private List m_outsideIncludes = new List(); + public List OutsideList { get { return m_outsideIncludes; } set { m_outsideIncludes = value; } } + + public void Draw( ParentNode owner ) + { + m_currentOwner = owner; + bool value = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalIncludes; + NodeUtils.DrawPropertyGroup( ref value, AdditionalIncludesStr, DrawMainBody, DrawButtons ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalIncludes = value; + + } + + void DrawButtons() + { + EditorGUILayout.Separator(); + + // Add keyword + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_additionalIncludes.Add( string.Empty ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove keyword + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + if( m_additionalIncludes.Count > 0 ) + { + m_additionalIncludes.RemoveAt( m_additionalIncludes.Count - 1 ); + EditorGUI.FocusTextInControl( null ); + } + } + } + + void DrawMainBody() + { + EditorGUILayout.Separator(); + //if( OutsideList != null && OutsideList.Count > 0 ) + //{ + // m_drawElements.Clear(); + // EditorGUI.BeginDisabledGroup( true ); + // int outsideCount = OutsideList.Count; + // for( int i = 0; i < outsideCount; i++ ) + // { + // if( !m_drawElements.Contains( OutsideList[ i ] ) ) + // { + // m_drawElements.Add( OutsideList[ i ] ); + // EditorGUILayout.TextField( OutsideList[ i ] ); + // } + // } + // EditorGUI.EndDisabledGroup(); + // EditorGUILayout.Separator(); + //} + int itemCount = m_additionalIncludes.Count; + int markedToDelete = -1; + for( int i = 0; i < itemCount; i++ ) + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUI.BeginChangeCheck(); + m_additionalIncludes[ i ] = EditorGUILayout.TextField( m_additionalIncludes[ i ] ); + if( EditorGUI.EndChangeCheck() ) + { + m_additionalIncludes[ i ] = UIUtils.RemoveShaderInvalidCharacters( m_additionalIncludes[ i ] ); + } + + // Add new port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_additionalIncludes.Insert( i + 1, string.Empty ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + markedToDelete = i; + } + } + EditorGUILayout.EndHorizontal(); + } + + if( markedToDelete > -1 ) + { + if( m_additionalIncludes.Count > markedToDelete ) + { + m_additionalIncludes.RemoveAt( markedToDelete ); + EditorGUI.FocusTextInControl( null ); + } + } + EditorGUILayout.Separator(); + EditorGUILayout.HelpBox( "Please add your includes without the #include \"\" keywords", MessageType.Info ); + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + int count = Convert.ToInt32( nodeParams[ index++ ] ); + for( int i = 0; i < count; i++ ) + { + m_additionalIncludes.Add( nodeParams[ index++ ] ); + } + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalIncludes.Count ); + for( int i = 0; i < m_additionalIncludes.Count; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalIncludes[ i ] ); + } + } + + public void AddToDataCollector( ref MasterNodeDataCollector dataCollector ) + { + for( int i = 0; i < m_additionalIncludes.Count; i++ ) + { + if( !string.IsNullOrEmpty( m_additionalIncludes[ i ] ) ) + dataCollector.AddToIncludes( -1, m_additionalIncludes[ i ] ); + } + + for( int i = 0; i < m_outsideIncludes.Count; i++ ) + { + if( !string.IsNullOrEmpty( m_outsideIncludes[ i ] ) ) + dataCollector.AddToIncludes( -1, m_outsideIncludes[ i ] ); + } + } + + public void Destroy() + { + m_additionalIncludes.Clear(); + m_additionalIncludes = null; + m_currentOwner = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalIncludesHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalIncludesHelper.cs.meta new file mode 100644 index 0000000..0997164 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalIncludesHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 74ff3d342e013f64198aaf767e623962 +timeCreated: 1498123240 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalPragmasHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalPragmasHelper.cs new file mode 100644 index 0000000..a7e8970 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalPragmasHelper.cs @@ -0,0 +1,141 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class AdditionalPragmasHelper + { + private const string AdditionalPragmasStr = " Additional Pragmas"; + private const float ShaderKeywordButtonLayoutWidth = 15; + private ParentNode m_currentOwner; + + [SerializeField] + private List m_additionalPragmas = new List(); + public List PragmaList { get { return m_additionalPragmas; } set { m_additionalPragmas = value; } } + + [SerializeField] + private List m_outsidePragmas = new List(); + public List OutsideList { get { return m_outsidePragmas; } set { m_outsidePragmas = value; } } + + public void Draw( ParentNode owner ) + { + m_currentOwner = owner; + bool value = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalPragmas; + NodeUtils.DrawPropertyGroup( ref value, AdditionalPragmasStr, DrawMainBody, DrawButtons ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalPragmas = value; + + } + + void DrawButtons() + { + EditorGUILayout.Separator(); + + // Add keyword + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_additionalPragmas.Add( string.Empty ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove keyword + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + if( m_additionalPragmas.Count > 0 ) + { + m_additionalPragmas.RemoveAt( m_additionalPragmas.Count - 1 ); + EditorGUI.FocusTextInControl( null ); + } + } + } + + void DrawMainBody() + { + EditorGUILayout.Separator(); + int itemCount = m_additionalPragmas.Count; + int markedToDelete = -1; + for( int i = 0; i < itemCount; i++ ) + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUI.BeginChangeCheck(); + m_additionalPragmas[ i ] = EditorGUILayout.TextField( m_additionalPragmas[ i ] ); + if( EditorGUI.EndChangeCheck() ) + { + m_additionalPragmas[ i ] = UIUtils.RemoveShaderInvalidCharacters( m_additionalPragmas[ i ] ); + } + + // Add new port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_additionalPragmas.Insert( i + 1, string.Empty ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + markedToDelete = i; + } + } + EditorGUILayout.EndHorizontal(); + } + + if( markedToDelete > -1 ) + { + if( m_additionalPragmas.Count > markedToDelete ) + { + m_additionalPragmas.RemoveAt( markedToDelete ); + EditorGUI.FocusTextInControl( null ); + } + } + EditorGUILayout.Separator(); + EditorGUILayout.HelpBox( "Please add your pragmas without the #pragma keywords", MessageType.Info ); + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + int count = Convert.ToInt32( nodeParams[ index++ ] ); + for( int i = 0; i < count; i++ ) + { + m_additionalPragmas.Add( nodeParams[ index++ ] ); + } + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalPragmas.Count ); + for( int i = 0; i < m_additionalPragmas.Count; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalPragmas[ i ] ); + } + } + + public void AddToDataCollector( ref MasterNodeDataCollector dataCollector ) + { + for( int i = 0; i < m_additionalPragmas.Count; i++ ) + { + if( !string.IsNullOrEmpty( m_additionalPragmas[ i ] ) ) + dataCollector.AddToPragmas( -1, m_additionalPragmas[ i ] ); + } + + for( int i = 0; i < m_outsidePragmas.Count; i++ ) + { + if( !string.IsNullOrEmpty( m_outsidePragmas[ i ] ) ) + dataCollector.AddToPragmas( -1, m_outsidePragmas[ i ] ); + } + } + + public void Destroy() + { + m_additionalPragmas.Clear(); + m_additionalPragmas = null; + m_currentOwner = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalPragmasHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalPragmasHelper.cs.meta new file mode 100644 index 0000000..3f245aa --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalPragmasHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3153b4d10effd174988d75b84b12d281 +timeCreated: 1504515475 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalSurfaceOptionsHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalSurfaceOptionsHelper.cs new file mode 100644 index 0000000..cd3efae --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalSurfaceOptionsHelper.cs @@ -0,0 +1,153 @@ +using System; +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + + [Serializable] + public class AdditionalSurfaceOptionsHelper + { + private const string AdditionalOptionsStr = " Additional Surface Options"; + + + private const float ShaderKeywordButtonLayoutWidth = 15; + private ParentNode m_currentOwner; + + [SerializeField] + private List m_availableOptions = new List(); + + public void Draw( ParentNode owner ) + { + m_currentOwner = owner; + bool value = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalSurfaceOptions; + NodeUtils.DrawPropertyGroup( ref value, AdditionalOptionsStr, DrawMainBody, DrawButtons ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalSurfaceOptions = value; + } + + void DrawButtons() + { + EditorGUILayout.Separator(); + + // Add tag + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_availableOptions.Add( string.Empty ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove tag + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + if( m_availableOptions.Count > 0 ) + { + m_availableOptions.RemoveAt( m_availableOptions.Count - 1 ); + EditorGUI.FocusTextInControl( null ); + } + } + } + + void DrawMainBody() + { + EditorGUILayout.Separator(); + int itemCount = m_availableOptions.Count; + + if( itemCount == 0 ) + { + EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one.", MessageType.Info ); + } + + int markedToDelete = -1; + float originalLabelWidth = EditorGUIUtility.labelWidth; + for( int i = 0; i < itemCount; i++ ) + { + + EditorGUI.indentLevel += 1; + EditorGUIUtility.labelWidth = 62; + EditorGUILayout.BeginHorizontal(); + //Option + EditorGUI.BeginChangeCheck(); + m_availableOptions[ i ] = EditorGUILayout.TextField( "["+i+"] -", m_availableOptions[ i ] ); + if( EditorGUI.EndChangeCheck() ) + { + m_availableOptions[ i ] = UIUtils.RemoveShaderInvalidCharacters( m_availableOptions[ i ] ); + } + + EditorGUIUtility.labelWidth = originalLabelWidth; + + { + // Add new port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_availableOptions.Insert( i + 1, string.Empty ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + markedToDelete = i; + } + } + EditorGUILayout.EndHorizontal(); + EditorGUI.indentLevel -= 1; + } + + if( markedToDelete > -1 ) + { + if( m_availableOptions.Count > markedToDelete ) + { + m_availableOptions.RemoveAt( markedToDelete ); + EditorGUI.FocusTextInControl( null ); + } + } + EditorGUILayout.Separator(); + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + int count = Convert.ToInt32( nodeParams[ index++ ] ); + for( int i = 0; i < count; i++ ) + { + m_availableOptions.Add( nodeParams[ index++ ] ); + } + } + + public void WriteToString( ref string nodeInfo ) + { + int optionsCount = m_availableOptions.Count; + IOUtils.AddFieldValueToString( ref nodeInfo, optionsCount ); + for( int i = 0; i < optionsCount; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_availableOptions[ i ].ToString() ); + } + } + + public void WriteToOptionalSurfaceOptions( ref string currentOptions ) + { + int tagsCount = m_availableOptions.Count; + if( tagsCount == 0 ) + return; + + string result = " "; + + for( int i = 0; i < tagsCount; i++ ) + { + result += m_availableOptions[ i ]; + if( i < tagsCount - 1 ) + { + result += " "; + } + } + currentOptions = currentOptions + result; + } + + public void Destroy() + { + m_availableOptions.Clear(); + m_availableOptions = null; + m_currentOwner = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalSurfaceOptionsHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalSurfaceOptionsHelper.cs.meta new file mode 100644 index 0000000..ccd630e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/AdditionalSurfaceOptionsHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d830b2cc8bc5e174485077319135fc1e +timeCreated: 1528881842 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs new file mode 100644 index 0000000..7dbb476 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs @@ -0,0 +1,273 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +// Billboard based on: +// https://gist.github.com/renaudbedard/7a90ec4a5a7359712202 +using System; +using UnityEngine; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public enum BillboardType + { + Cylindrical, + Spherical + } + + [Serializable] + public class BillboardOpHelper + { + public static readonly string BillboardTitleStr = " Billboard"; + public static readonly string BillboardTypeStr = "Type"; + public static readonly string BillboardRotIndStr = "Ignore Rotation"; + + public static readonly string[] BillboardCylindricalInstructions = { "//Calculate new billboard vertex position and normal", + "float3 upCamVec = float3( 0, 1, 0 )"}; + + public static readonly string[] BillboardSphericalInstructions = { "//Calculate new billboard vertex position and normal", + "float3 upCamVec = normalize ( UNITY_MATRIX_V._m10_m11_m12 )"}; + + + public static readonly string[] BillboardCommonInstructions = { "float3 forwardCamVec = -normalize ( UNITY_MATRIX_V._m20_m21_m22 )", + "float3 rightCamVec = normalize( UNITY_MATRIX_V._m00_m01_m02 )", + "float4x4 rotationCamMatrix = float4x4( rightCamVec, 0, upCamVec, 0, forwardCamVec, 0, 0, 0, 0, 1 )", + "{0} = normalize( mul( float4( {0} , 0 ), rotationCamMatrix )).xyz"}; + + public static readonly string[] BillboardRotDependent = { "//This unfortunately must be made to take non-uniform scaling into account", + "//Transform to world coords, apply rotation and transform back to local", + "{0} = mul( {1} , unity_ObjectToWorld ){2}", + "{0} = mul( {1} , rotationCamMatrix ){2}", + "{0} = mul( {1} , unity_WorldToObject ){2}"}; + + + public static readonly string[] BillboardRotIndependent = { "{0}.x *= length( unity_ObjectToWorld._m00_m10_m20 )", + "{0}.y *= length( unity_ObjectToWorld._m01_m11_m21 )", + "{0}.z *= length( unity_ObjectToWorld._m02_m12_m22 )", + "{0} = mul( {0}, rotationCamMatrix )", + "{0}.xyz += unity_ObjectToWorld._m03_m13_m23", + "//Need to nullify rotation inserted by generated surface shader", + "{0} = mul( unity_WorldToObject, {0} )"}; + + + + public static readonly string[] BillboardHDRotDependent = { "//This unfortunately must be made to take non-uniform scaling into account", + "//Transform to world coords, apply rotation and transform back to local", + "{0} = mul( {1} , GetObjectToWorldMatrix() ){2}", + "{0} = mul( {1} , rotationCamMatrix ){2}", + "{0} = mul( {1} , GetWorldToObjectMatrix() ){2}"}; + + + public static readonly string[] BillboardHDRotIndependent = { "{0}.x *= length( GetObjectToWorldMatrix()._m00_m10_m20 )", + "{0}.y *= length( GetObjectToWorldMatrix()._m01_m11_m21 )", + "{0}.z *= length( GetObjectToWorldMatrix()._m02_m12_m22 )", + "{0} = mul( {0}, rotationCamMatrix )", + //Comment this next one out in HDRP since it was moving the vertices to incorrect locations + // Over HDRP the correct results are achievied without having to do this operation + //This is because the vertex position variable is a float3 and an implicit cast is done to float4 + //with w set to 0, this makes the multiplication below only affects rotation and not translation + //thus no adding the world translation is needed to counter the GetObjectToWorldMatrix() operation + "{0}.xyz += GetObjectToWorldMatrix()._m03_m13_m23", + "//Need to nullify rotation inserted by generated surface shader", + "{0} = mul( GetWorldToObjectMatrix(), {0} )"}; + + + [SerializeField] + private bool m_isBillboard = false; + + [SerializeField] + private BillboardType m_billboardType = BillboardType.Cylindrical; + + [SerializeField] + private bool m_rotationIndependent = false; + + public void Draw( ParentNode owner ) + { + bool visible = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedVertexOptions; + bool enabled = m_isBillboard; + NodeUtils.DrawPropertyGroup( owner, ref visible, ref m_isBillboard, BillboardTitleStr, () => + { + m_billboardType = (BillboardType)owner.EditorGUILayoutEnumPopup( BillboardTypeStr, m_billboardType ); + m_rotationIndependent = owner.EditorGUILayoutToggle( BillboardRotIndStr, m_rotationIndependent ); + } ); + + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedVertexOptions = visible; + if( m_isBillboard != enabled ) + { + UIUtils.RequestSave(); + } + } + public void FillDataCollectorWithInternalData( ref MasterNodeDataCollector dataCollector ) + { + if( m_isBillboard ) + { + FillDataCollector( ref dataCollector, m_billboardType, m_rotationIndependent, "v.vertex", "v.normal", false ); + } + } + + public static void CheckVertexPosition( ref string value , ref MasterNodeDataCollector dataCollector ) + { + if( dataCollector.IsTemplate ) + { + WirePortDataType vertexSize = dataCollector.TemplateDataCollectorInstance.GetVertexPositionDataType(); + if( vertexSize != WirePortDataType.FLOAT4 ) + { + // the {0}.xyz += GetObjectToWorldMatrix()._m03_m13_m23 must only be done over float4 vertices for the reason stated above for HDRP + // on all others can be commented out + value = "//" + value; + } + } + } + + // This should be called after the Vertex Offset and Vertex Normal ports are analised + public static void FillDataCollector( ref MasterNodeDataCollector dataCollector, BillboardType billboardType, bool rotationIndependent, string vertexPosValue, string vertexNormalValue, bool vertexIsFloat3 ) + { + switch( billboardType ) + { + case BillboardType.Cylindrical: + { + for( int i = 0; i < BillboardCylindricalInstructions.Length; i++ ) + { + dataCollector.AddVertexInstruction( BillboardCylindricalInstructions[ i ] + ( dataCollector.IsTemplate ? ";" : string.Empty ), -1, true ); + } + } + break; + + case BillboardType.Spherical: + { + for( int i = 0; i < BillboardCylindricalInstructions.Length; i++ ) + { + dataCollector.AddVertexInstruction( BillboardSphericalInstructions[ i ] + ( dataCollector.IsTemplate ? ";" : string.Empty ), -1, true ); + } + } + break; + } + + for( int i = 0; i < BillboardCommonInstructions.Length; i++ ) + { + string value = ( i == 3 ) ? string.Format( BillboardCommonInstructions[ i ], vertexNormalValue ) : BillboardCommonInstructions[ i ]; + dataCollector.AddVertexInstruction( value + ( dataCollector.IsTemplate ? ";" : string.Empty ), -1, true ); + } + + if( rotationIndependent ) + { + + + for( int i = 0; i < BillboardRotIndependent.Length; i++ ) + { + string value = string.Empty; + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType != TemplateSRPType.BuiltIn ) + { + value = ( i != 5 ) ? string.Format( BillboardHDRotIndependent[ i ], vertexPosValue ) : BillboardHDRotIndependent[ i ]; + if( i == 4 ) + { + CheckVertexPosition( ref value , ref dataCollector ); + } + + } + else + { + value = ( i != 5 ) ? string.Format( BillboardRotIndependent[ i ], vertexPosValue ) : BillboardRotIndependent[ i ]; + if( i == 4 ) + { + CheckVertexPosition( ref value , ref dataCollector ); + } + } + dataCollector.AddVertexInstruction( value + ( dataCollector.IsTemplate ? ";" : string.Empty ), -1, true ); + } + } + else + { + string vertexPosConverted = vertexIsFloat3 ? string.Format( "float4({0},0)", vertexPosValue ) : vertexPosValue; + for( int i = 0; i < BillboardRotDependent.Length; i++ ) + { + string value = string.Empty; + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + { + value = ( i > 1 ) ? string.Format( BillboardHDRotDependent[ i ], vertexPosValue, vertexPosConverted, ( vertexIsFloat3 ? ".xyz" : string.Empty ) ) : BillboardHDRotDependent[ i ]; + } + else + { + value = ( i > 1 ) ? string.Format( BillboardRotDependent[ i ], vertexPosValue, vertexPosConverted, ( vertexIsFloat3 ? ".xyz" : string.Empty ) ) : BillboardRotDependent[ i ]; + } + dataCollector.AddVertexInstruction( value + ( dataCollector.IsTemplate ? ";" : string.Empty ), -1, true ); + } + } + } + + public string[] GetInternalMultilineInstructions() + { + // This method is only used on Surface ... no HD variation is needed + return GetMultilineInstructions( m_billboardType, m_rotationIndependent, "v.vertex", "v.normal" ); + } + + public static string[] GetMultilineInstructions( BillboardType billboardType, bool rotationIndependent, string vertexPosValue, string vertexNormalValue ) + { + // This method is only used on Surface ... no HD variation is needed + List body = new List(); + switch( billboardType ) + { + case BillboardType.Cylindrical: + { + for( int i = 0; i < BillboardCylindricalInstructions.Length; i++ ) + { + body.Add( BillboardCylindricalInstructions[ i ] ); + } + } + break; + + case BillboardType.Spherical: + { + for( int i = 0; i < BillboardCylindricalInstructions.Length; i++ ) + { + body.Add( BillboardSphericalInstructions[ i ] ); + } + } + break; + } + + for( int i = 0; i < BillboardCommonInstructions.Length; i++ ) + { + string value = ( i == 3 ) ? string.Format( BillboardCommonInstructions[ i ], vertexNormalValue ) : BillboardCommonInstructions[ i ]; + body.Add( value ); + } + + if( rotationIndependent ) + { + for( int i = 0; i < BillboardRotIndependent.Length; i++ ) + { + string value = ( i != 5 ) ? string.Format( BillboardRotIndependent[ i ], vertexPosValue ) : BillboardRotIndependent[ i ]; + body.Add( value ); + } + } + else + { + for( int i = 0; i < BillboardRotDependent.Length; i++ ) + { + string value = ( i > 1 ) ? string.Format( BillboardRotDependent[ i ], vertexPosValue ) : BillboardRotDependent[ i ]; + body.Add( value ); + } + } + return body.ToArray(); + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + m_isBillboard = Convert.ToBoolean( nodeParams[ index++ ] ); + m_billboardType = (BillboardType)Enum.Parse( typeof( BillboardType ), nodeParams[ index++ ] ); + if( UIUtils.CurrentShaderVersion() > 11007 ) + { + m_rotationIndependent = Convert.ToBoolean( nodeParams[ index++ ] ); + } + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_isBillboard ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_billboardType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_rotationIndependent ); + } + + public bool IsBillboard { get { return m_isBillboard; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs.meta new file mode 100644 index 0000000..812475f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BillboardOpHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 837b906a268babc49ac733573c5b3394 +timeCreated: 1489159407 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BlendOpsHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BlendOpsHelper.cs new file mode 100644 index 0000000..989ace5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BlendOpsHelper.cs @@ -0,0 +1,447 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public enum AvailableBlendFactor + { + One = 1, + Zero = 0, + SrcColor = 3, + SrcAlpha = 5, + DstColor = 2, + DstAlpha = 7, + OneMinusSrcColor = 6, + OneMinusSrcAlpha = 10, + OneMinusDstColor = 4, + OneMinusDstAlpha = 8, + SrcAlphaSaturate = 9 + }; + + public enum AvailableBlendOps + { + OFF = 0, + Add, + Sub, + RevSub, + Min, + Max, + //Direct X11 only + LogicalClear, + LogicalSet, + LogicalCopy, + LogicalCopyInverted, + LogicalNoop, + LogicalInvert, + LogicalAnd, + LogicalNand, + LogicalOr, + LogicalNor, + LogicalXor, + LogicalEquiv, + LogicalAndReverse, + LogicalAndInverted, + LogicalOrReverse, + LogicalOrInverted + }; + + public class CommonBlendTypes + { + public string Name; + public AvailableBlendFactor SourceFactor; + public AvailableBlendFactor DestFactor; + public CommonBlendTypes( string name, AvailableBlendFactor sourceFactor, AvailableBlendFactor destFactor ) + { + Name = name; + SourceFactor = sourceFactor; + DestFactor = destFactor; + } + } + + [Serializable] + public class BlendOpsHelper + { + public static readonly string[] BlendOpsLabels = + { + "", + "Add", + "Sub", + "RevSub", + "Min", + "Max", + "LogicalClear ( DX11.1 Only )", + "LogicalSet ( DX11.1 Only )", + "LogicalCopy ( DX11.1 Only )", + "LogicalCopyInverted ( DX11.1 Only )", + "LogicalNoop ( DX11.1 Only )", + "LogicalInvert ( DX11.1 Only )", + "LogicalAnd ( DX11.1 Only )", + "LogicalNand ( DX11.1 Only )", + "LogicalOr ( DX11.1 Only )", + "LogicalNor ( DX11.1 Only )", + "LogicalXor ( DX11.1 Only )", + "LogicalEquiv ( DX11.1 Only )", + "LogicalAndReverse ( DX11.1 Only )", + "LogicalAndInverted ( DX11.1 Only )", + "LogicalOrReverse ( DX11.1 Only )", + "LogicalOrInverted ( DX11.1 Only )" + }; + + private const string BlendModesRGBStr = "Blend RGB"; + private const string BlendModesAlphaStr = "Blend Alpha"; + + private const string BlendOpsRGBStr = "Blend Op RGB"; + private const string BlendOpsAlphaStr = "Blend Op Alpha"; + + private const string SourceFactorStr = "Src"; + private const string DstFactorStr = "Dst"; + + private const string SingleBlendFactorStr = "Blend {0} {1}"; + private const string SeparateBlendFactorStr = "Blend {0} {1} , {2} {3}"; + + private const string SingleBlendOpStr = "BlendOp {0}"; + private const string SeparateBlendOpStr = "BlendOp {0} , {1}"; + + private string[] m_commonBlendTypesArr; + private List m_commonBlendTypes = new List { new CommonBlendTypes("", AvailableBlendFactor.Zero, AvailableBlendFactor.Zero ), + new CommonBlendTypes("Custom", AvailableBlendFactor.Zero, AvailableBlendFactor.Zero ) , + new CommonBlendTypes("Alpha Blend", AvailableBlendFactor.SrcAlpha, AvailableBlendFactor.OneMinusSrcAlpha ) , + new CommonBlendTypes("Premultiplied", AvailableBlendFactor.One, AvailableBlendFactor.OneMinusSrcAlpha ), + new CommonBlendTypes("Additive", AvailableBlendFactor.One, AvailableBlendFactor.One ), + new CommonBlendTypes("Soft Additive", AvailableBlendFactor.OneMinusDstColor, AvailableBlendFactor.One ), + new CommonBlendTypes("Multiplicative", AvailableBlendFactor.DstColor, AvailableBlendFactor.Zero ), + new CommonBlendTypes("2x Multiplicative", AvailableBlendFactor.DstColor, AvailableBlendFactor.SrcColor ), + new CommonBlendTypes("Particle Additive", AvailableBlendFactor.SrcAlpha, AvailableBlendFactor.One ),}; + + [SerializeField] + private bool m_enabled = false; + + // Blend Factor + // RGB + [SerializeField] + private int m_currentIndex = 0; + + + [SerializeField] + private InlineProperty m_sourceFactorRGB = new InlineProperty( 0 ); + + [SerializeField] + private InlineProperty m_destFactorRGB = new InlineProperty( 0 ); + + // Alpha + [SerializeField] + private int m_currentAlphaIndex = 0; + + [SerializeField] + private InlineProperty m_sourceFactorAlpha = new InlineProperty( 0 ); + + [SerializeField] + private InlineProperty m_destFactorAlpha = new InlineProperty( 0 ); + + //Blend Ops + [SerializeField] + private bool m_blendOpEnabled = false; + + [SerializeField] + private InlineProperty m_blendOpRGB = new InlineProperty( 0 ); + + [SerializeField] + private InlineProperty m_blendOpAlpha = new InlineProperty( 0 ); + + public BlendOpsHelper() + { + m_commonBlendTypesArr = new string[ m_commonBlendTypes.Count ]; + for( int i = 0; i < m_commonBlendTypesArr.Length; i++ ) + { + m_commonBlendTypesArr[ i ] = m_commonBlendTypes[ i ].Name; + } + } + + public void Draw( UndoParentNode owner, bool customBlendAvailable ) + { + m_enabled = customBlendAvailable; + + // RGB + EditorGUI.BeginChangeCheck(); + m_currentIndex = owner.EditorGUILayoutPopup( BlendModesRGBStr, m_currentIndex, m_commonBlendTypesArr ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_currentIndex > 1 ) + { + m_sourceFactorRGB.IntValue = (int)m_commonBlendTypes[ m_currentIndex ].SourceFactor; + m_sourceFactorRGB.SetInlineNodeValue(); + + m_destFactorRGB.IntValue = (int)m_commonBlendTypes[ m_currentIndex ].DestFactor; + m_destFactorRGB.SetInlineNodeValue(); + } + } + EditorGUI.BeginDisabledGroup( m_currentIndex == 0 ); + + EditorGUI.BeginChangeCheck(); + float cached = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 40; + + EditorGUILayout.BeginHorizontal(); + AvailableBlendFactor tempCast = (AvailableBlendFactor)m_sourceFactorRGB.IntValue; + m_sourceFactorRGB.CustomDrawer( ref owner, ( x ) => { tempCast = (AvailableBlendFactor)x.EditorGUILayoutEnumPopup( SourceFactorStr, tempCast ); }, SourceFactorStr ); + m_sourceFactorRGB.IntValue = (int)tempCast; + EditorGUI.indentLevel--; + EditorGUIUtility.labelWidth = 25; + tempCast = (AvailableBlendFactor)m_destFactorRGB.IntValue; + m_destFactorRGB.CustomDrawer( ref owner, ( x ) => { tempCast = (AvailableBlendFactor)x.EditorGUILayoutEnumPopup( DstFactorStr, tempCast ); }, DstFactorStr ); + m_destFactorRGB.IntValue = (int)tempCast; + EditorGUI.indentLevel++; + EditorGUILayout.EndHorizontal(); + + EditorGUIUtility.labelWidth = cached; + if( EditorGUI.EndChangeCheck() ) + { + CheckRGBIndex(); + } + + // Both these tests should be removed on a later stage + // ASE v154dev004 changed AvailableBlendOps.OFF value from -1 to 0 + // If importing the new package into an already opened ASE window makes + // hotcode to preserve the -1 value on these variables + if( m_blendOpRGB.FloatValue < 0 ) + m_blendOpRGB.FloatValue = 0; + + if( m_blendOpAlpha.FloatValue < 0 ) + m_blendOpAlpha.FloatValue = 0; + + EditorGUI.BeginChangeCheck(); + //AvailableBlendOps tempOpCast = (AvailableBlendOps)m_blendOpRGB.IntValue; + m_blendOpRGB.CustomDrawer( ref owner, ( x ) => { m_blendOpRGB.IntValue = x.EditorGUILayoutPopup( BlendOpsRGBStr, m_blendOpRGB.IntValue, BlendOpsLabels ); }, BlendOpsRGBStr ); + //m_blendOpRGB.IntValue = (int)tempOpCast; + if( EditorGUI.EndChangeCheck() ) + { + m_blendOpEnabled = ( !m_blendOpRGB.Active && m_blendOpRGB.IntValue > -1 ) || ( m_blendOpRGB.Active && m_blendOpRGB.NodeId > -1 );//AvailableBlendOps.OFF; + m_blendOpRGB.SetInlineNodeValue(); + } + + EditorGUI.EndDisabledGroup(); + + // Alpha + EditorGUILayout.Separator(); + + EditorGUI.BeginChangeCheck(); + m_currentAlphaIndex = owner.EditorGUILayoutPopup( BlendModesAlphaStr, m_currentAlphaIndex, m_commonBlendTypesArr ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_currentAlphaIndex > 0 ) + { + m_sourceFactorAlpha.IntValue = (int)m_commonBlendTypes[ m_currentAlphaIndex ].SourceFactor; + m_sourceFactorAlpha.SetInlineNodeValue(); + + m_destFactorAlpha.IntValue = (int)m_commonBlendTypes[ m_currentAlphaIndex ].DestFactor; + m_destFactorAlpha.SetInlineNodeValue(); + } + } + EditorGUI.BeginDisabledGroup( m_currentAlphaIndex == 0 ); + + EditorGUI.BeginChangeCheck(); + cached = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 40; + EditorGUILayout.BeginHorizontal(); + tempCast = (AvailableBlendFactor)m_sourceFactorAlpha.IntValue; + m_sourceFactorAlpha.CustomDrawer( ref owner, ( x ) => { tempCast = (AvailableBlendFactor)x.EditorGUILayoutEnumPopup( SourceFactorStr, tempCast ); }, SourceFactorStr ); + m_sourceFactorAlpha.IntValue = (int)tempCast; + EditorGUI.indentLevel--; + EditorGUIUtility.labelWidth = 25; + tempCast = (AvailableBlendFactor)m_destFactorAlpha.IntValue; + m_destFactorAlpha.CustomDrawer( ref owner, ( x ) => { tempCast = (AvailableBlendFactor)x.EditorGUILayoutEnumPopup( DstFactorStr, tempCast ); }, DstFactorStr ); + m_destFactorAlpha.IntValue = (int)tempCast; + EditorGUI.indentLevel++; + EditorGUILayout.EndHorizontal(); + EditorGUIUtility.labelWidth = cached; + + if( EditorGUI.EndChangeCheck() ) + { + CheckAlphaIndex(); + } + EditorGUI.BeginChangeCheck(); + //tempOpCast = (AvailableBlendOps)m_blendOpAlpha.IntValue; + m_blendOpAlpha.CustomDrawer( ref owner, ( x ) => { m_blendOpAlpha.IntValue = x.EditorGUILayoutPopup( BlendOpsAlphaStr, m_blendOpAlpha.IntValue, BlendOpsLabels ); }, BlendOpsAlphaStr ); + //m_blendOpAlpha.IntValue = (int)tempOpCast; + if( EditorGUI.EndChangeCheck() ) + { + m_blendOpAlpha.SetInlineNodeValue(); + } + EditorGUI.EndDisabledGroup(); + EditorGUILayout.Separator(); + } + + void CheckRGBIndex() + { + int count = m_commonBlendTypes.Count; + m_currentIndex = 1; + for( int i = 1; i < count; i++ ) + { + if( m_commonBlendTypes[ i ].SourceFactor == (AvailableBlendFactor)m_sourceFactorRGB.IntValue && m_commonBlendTypes[ i ].DestFactor == (AvailableBlendFactor)m_destFactorRGB.IntValue ) + { + m_currentIndex = i; + return; + } + } + + } + + void CheckAlphaIndex() + { + int count = m_commonBlendTypes.Count; + m_currentAlphaIndex = 1; + for( int i = 1; i < count; i++ ) + { + if( m_commonBlendTypes[ i ].SourceFactor == (AvailableBlendFactor)m_sourceFactorAlpha.IntValue && m_commonBlendTypes[ i ].DestFactor == (AvailableBlendFactor)m_destFactorAlpha.IntValue ) + { + m_currentAlphaIndex = i; + if( m_currentAlphaIndex > 0 && m_currentIndex == 0 ) + m_currentIndex = 1; + return; + } + } + + if( m_currentAlphaIndex > 0 && m_currentIndex == 0 ) + m_currentIndex = 1; + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + m_currentIndex = Convert.ToInt32( nodeParams[ index++ ] ); + if( UIUtils.CurrentShaderVersion() > 15103 ) + { + m_sourceFactorRGB.ReadFromString( ref index, ref nodeParams ); + m_destFactorRGB.ReadFromString( ref index, ref nodeParams ); + } + else + { + m_sourceFactorRGB.IntValue = (int)(AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), nodeParams[ index++ ] ); + m_destFactorRGB.IntValue = (int)(AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), nodeParams[ index++ ] ); + } + + m_currentAlphaIndex = Convert.ToInt32( nodeParams[ index++ ] ); + if( UIUtils.CurrentShaderVersion() > 15103 ) + { + m_sourceFactorAlpha.ReadFromString( ref index, ref nodeParams ); + m_destFactorAlpha.ReadFromString( ref index, ref nodeParams ); + + m_blendOpRGB.ReadFromString( ref index, ref nodeParams ); + m_blendOpAlpha.ReadFromString( ref index, ref nodeParams ); + if( UIUtils.CurrentShaderVersion() < 15404 ) + { + // Now BlendOps enum starts at 0 and not -1 + m_blendOpRGB.FloatValue += 1; + m_blendOpAlpha.FloatValue += 1; + } + } + else + { + m_sourceFactorAlpha.IntValue = (int)(AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), nodeParams[ index++ ] ); + m_destFactorAlpha.IntValue = (int)(AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), nodeParams[ index++ ] ); + m_blendOpRGB.IntValue = (int)(AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), nodeParams[ index++ ] ); + m_blendOpAlpha.IntValue = (int)(AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), nodeParams[ index++ ] ); + } + + m_enabled = ( m_currentIndex > 0 || m_currentAlphaIndex > 0 ); + m_blendOpEnabled = ( !m_blendOpRGB.Active && m_blendOpRGB.IntValue > -1 ) || ( m_blendOpRGB.Active && m_blendOpRGB.NodeId > -1 ); + } + + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentIndex ); + m_sourceFactorRGB.WriteToString( ref nodeInfo ); + m_destFactorRGB.WriteToString( ref nodeInfo ); + + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentAlphaIndex ); + m_sourceFactorAlpha.WriteToString( ref nodeInfo ); + m_destFactorAlpha.WriteToString( ref nodeInfo ); + + m_blendOpRGB.WriteToString( ref nodeInfo ); + m_blendOpAlpha.WriteToString( ref nodeInfo ); + } + + public void SetBlendOpsFromBlendMode( AlphaMode mode, bool customBlendAvailable ) + { + switch( mode ) + { + case AlphaMode.Transparent: + m_currentIndex = 2; + m_sourceFactorRGB.IntValue = (int)m_commonBlendTypes[ m_currentIndex ].SourceFactor; + m_destFactorRGB.IntValue = (int)m_commonBlendTypes[ m_currentIndex ].DestFactor; + break; + case AlphaMode.Masked: + case AlphaMode.Translucent: + m_currentIndex = 0; + break; + case AlphaMode.Premultiply: + m_currentIndex = 3; + m_sourceFactorRGB.IntValue = (int)m_commonBlendTypes[ m_currentIndex ].SourceFactor; + m_destFactorRGB.IntValue = (int)m_commonBlendTypes[ m_currentIndex ].DestFactor; + break; + } + m_enabled = customBlendAvailable; + } + + public string CreateBlendOps() + { + + string result = "\t\t" + CurrentBlendFactor + "\n"; + if( m_blendOpEnabled ) + { + result += "\t\t" + CurrentBlendOp + "\n"; + } + return result; + } + + public string CurrentBlendRGB { get { return m_commonBlendTypes[ m_currentIndex ].Name; } } + + public string CurrentBlendFactorSingle { get { return string.Format( SingleBlendFactorStr, m_sourceFactorRGB.GetValueOrProperty( ( (AvailableBlendFactor)m_sourceFactorRGB.IntValue ).ToString() ), m_destFactorRGB.GetValueOrProperty( ( (AvailableBlendFactor)m_destFactorRGB.IntValue ).ToString() ) ); } } + //public string CurrentBlendFactorSingleAlpha { get { return string.Format(SeparateBlendFactorStr, m_sourceFactorRGB, m_destFactorRGB, m_sourceFactorAlpha, m_destFactorAlpha); } } + public string CurrentBlendFactorSeparate + { + get + { + string src = ( m_currentIndex > 0 ? m_sourceFactorRGB.GetValueOrProperty( ( (AvailableBlendFactor)m_sourceFactorRGB.IntValue ).ToString() ) : AvailableBlendFactor.One.ToString() ); + string dst = ( m_currentIndex > 0 ? m_destFactorRGB.GetValueOrProperty( ( (AvailableBlendFactor)m_destFactorRGB.IntValue ).ToString() ) : AvailableBlendFactor.Zero.ToString() ); + string srca = m_sourceFactorAlpha.GetValueOrProperty( ( (AvailableBlendFactor)m_sourceFactorAlpha.IntValue ).ToString() ); + string dsta = m_destFactorAlpha.GetValueOrProperty( ( (AvailableBlendFactor)m_destFactorAlpha.IntValue ).ToString() ); + return string.Format( SeparateBlendFactorStr, src, dst, srca, dsta ); + } + } + public string CurrentBlendFactor { get { return ( ( m_currentAlphaIndex > 0 ) ? CurrentBlendFactorSeparate : CurrentBlendFactorSingle ); } } + + public string CurrentBlendOpSingle + { + get + { + string value = m_blendOpRGB.GetValueOrProperty( ( (AvailableBlendOps)m_blendOpRGB.IntValue ).ToString() ); + if( value.Equals( ( AvailableBlendOps.OFF ).ToString() ) ) + return string.Empty; + + return string.Format( SingleBlendOpStr, value ); + } + } + public string CurrentBlendOpSeparate + { + get + { + string rgbValue = m_blendOpRGB.GetValueOrProperty( ( (AvailableBlendOps)m_blendOpRGB.IntValue ).ToString() ); + + if( rgbValue.Equals( ( AvailableBlendOps.OFF ).ToString() )) + rgbValue = "Add"; + + string alphaValue = m_blendOpAlpha.GetValueOrProperty( ( (AvailableBlendOps)m_blendOpAlpha.IntValue ).ToString() ); + return string.Format( SeparateBlendOpStr, ( m_currentIndex > 0 ? rgbValue : AvailableBlendOps.Add.ToString() ), alphaValue ); + } + } + public string CurrentBlendOp { get { return ( ( m_currentAlphaIndex > 0 && m_blendOpAlpha.GetValueOrProperty( ( (AvailableBlendOps)m_blendOpAlpha.IntValue ).ToString() ) != AvailableBlendOps.OFF.ToString() ) ? CurrentBlendOpSeparate : CurrentBlendOpSingle ); } } + + public bool Active { get { return m_enabled && ( m_currentIndex > 0 || m_currentAlphaIndex > 0 ); } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BlendOpsHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BlendOpsHelper.cs.meta new file mode 100644 index 0000000..95ea7b5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/BlendOpsHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8b59649a5f829e24cb4de8c1a715f8b4 +timeCreated: 1485530925 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CodeGenerationData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CodeGenerationData.cs new file mode 100644 index 0000000..5245c9f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CodeGenerationData.cs @@ -0,0 +1,24 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +namespace AmplifyShaderEditor +{ + [System.Serializable] + public class CodeGenerationData + { + [SerializeField] + public bool IsActive; + [SerializeField] + public string Name; + [SerializeField] + public string Value; + + public CodeGenerationData( string name, string value ) + { + IsActive = false; + Name = name; + Value = value; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CodeGenerationData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CodeGenerationData.cs.meta new file mode 100644 index 0000000..2c5d759 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CodeGenerationData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7a47d8101acb2e94d95016b69a1c2e41 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ColorMaskHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ColorMaskHelper.cs new file mode 100644 index 0000000..2280c9f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ColorMaskHelper.cs @@ -0,0 +1,107 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + class ColorMaskHelper + { + private GUIContent ColorMaskContent = new GUIContent( "Color Mask", "Sets color channel writing mask, turning all off makes the object completely invisible\nDefault: RGBA" ); + private readonly char[] m_colorMaskChar = { 'R', 'G', 'B', 'A' }; + + private GUIStyle m_leftToggleColorMask; + private GUIStyle m_middleToggleColorMask; + private GUIStyle m_rightToggleColorMask; + + + [SerializeField] + private bool[] m_colorMask = { true, true, true, true }; + + [SerializeField] + private InlineProperty m_inlineMask = new InlineProperty(); + + public void Draw( UndoParentNode owner ) + { + m_inlineMask.CustomDrawer( ref owner, DrawColorMaskControls, ColorMaskContent.text ); + } + + private void DrawColorMaskControls( UndoParentNode owner ) + { + if( m_leftToggleColorMask == null || m_leftToggleColorMask.normal.background == null ) + { + m_leftToggleColorMask = GUI.skin.GetStyle( "miniButtonLeft" ); + } + + if( m_middleToggleColorMask == null || m_middleToggleColorMask.normal.background == null ) + { + m_middleToggleColorMask = GUI.skin.GetStyle( "miniButtonMid" ); + } + + if( m_rightToggleColorMask == null || m_rightToggleColorMask.normal.background == null ) + { + m_rightToggleColorMask = GUI.skin.GetStyle( "miniButtonRight" ); + } + + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField( ColorMaskContent, GUILayout.Width( 90 ) ); + + m_colorMask[ 0 ] = owner.GUILayoutToggle( m_colorMask[ 0 ], "R", m_leftToggleColorMask ); + m_colorMask[ 1 ] = owner.GUILayoutToggle( m_colorMask[ 1 ], "G", m_middleToggleColorMask ); + m_colorMask[ 2 ] = owner.GUILayoutToggle( m_colorMask[ 2 ], "B", m_middleToggleColorMask ); + m_colorMask[ 3 ] = owner.GUILayoutToggle( m_colorMask[ 3 ], "A", m_rightToggleColorMask ); + + EditorGUILayout.EndHorizontal(); + } + + public void BuildColorMask( ref string ShaderBody, bool customBlendAvailable ) + { + int count = 0; + string colorMask = string.Empty; + for( int i = 0; i < m_colorMask.Length; i++ ) + { + if( m_colorMask[ i ] ) + { + count++; + colorMask += m_colorMaskChar[ i ]; + } + } + + if( ( count != m_colorMask.Length && customBlendAvailable ) || m_inlineMask.Active ) + { + MasterNode.AddRenderState( ref ShaderBody, "ColorMask", m_inlineMask.GetValueOrProperty( ( ( count == 0 ) ? "0" : colorMask ) ) ); + } + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + for( int i = 0; i < m_colorMask.Length; i++ ) + { + m_colorMask[ i ] = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( UIUtils.CurrentShaderVersion() > 14501 ) + m_inlineMask.ReadFromString( ref index, ref nodeParams ); + } + + public void WriteToString( ref string nodeInfo ) + { + for( int i = 0; i < m_colorMask.Length; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_colorMask[ i ] ); + } + + m_inlineMask.WriteToString( ref nodeInfo ); + } + + public void Destroy() + { + m_leftToggleColorMask = null; + m_middleToggleColorMask = null; + m_rightToggleColorMask = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ColorMaskHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ColorMaskHelper.cs.meta new file mode 100644 index 0000000..69c24b0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ColorMaskHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bf65efd881afd1b4cbd2b27f3f17251b +timeCreated: 1488903773 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CustomTagsHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CustomTagsHelper.cs new file mode 100644 index 0000000..89a450c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CustomTagsHelper.cs @@ -0,0 +1,482 @@ +using System; +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class CustomTagData + { + private const string TagFormat = "\"{0}\"=\"{1}\""; + public string TagName; + public string TagValue; + public int TagId = -1; + public bool TagFoldout = true; + + [SerializeField] + private TemplateSpecialTags m_specialTag = TemplateSpecialTags.None; + [SerializeField] + private DisableBatching m_disableBatching = DisableBatching.False; + [SerializeField] + private RenderType m_renderType = RenderType.Opaque; + [SerializeField] + private RenderQueue m_renderQueue = RenderQueue.Geometry; + [SerializeField] + private int m_renderQueueOffset = 0; + + public CustomTagData() + { + TagName = string.Empty; + TagValue = string.Empty; + m_specialTag = TemplateSpecialTags.None; + m_disableBatching = DisableBatching.False; + m_renderType = RenderType.Opaque; + m_renderQueue = RenderQueue.Geometry; + m_renderQueueOffset = 0; + } + + public CustomTagData( CustomTagData other ) + { + TagName = other.TagName; + TagValue = other.TagValue; + TagId = other.TagId; + TagFoldout = other.TagFoldout; + + m_specialTag = other.m_specialTag; + m_disableBatching = other.m_disableBatching; + m_renderType = other.m_renderType; + m_renderQueue = other.m_renderQueue; + m_renderQueueOffset = other.m_renderQueueOffset; + } + + public void SetTagValue( params string[] value ) + { + TagValue = value[ 0 ]; + switch( m_specialTag ) + { + case TemplateSpecialTags.RenderType: + { + if( !TemplateHelperFunctions.StringToRenderType.TryGetValue( value[ 0 ], out m_renderType ) ) + { + m_renderType = RenderType.Custom; + TagValue = value[ 0 ]; + } + } + break; + case TemplateSpecialTags.Queue: + { + if( value.Length == 2 ) + { + m_renderQueue = TemplateHelperFunctions.StringToRenderQueue[ value[ 0 ] ]; + int.TryParse( value[ 1 ], out m_renderQueueOffset ); + } + else + { + int indexPlus = value[ 0 ].IndexOf( '+' ); + if( indexPlus > 0 ) + { + string[] args = value[ 0 ].Split( '+' ); + m_renderQueue = TemplateHelperFunctions.StringToRenderQueue[ args[ 0 ] ]; + int.TryParse( args[ 1 ], out m_renderQueueOffset ); + } + else + { + int indexMinus = value[ 0 ].IndexOf( '-' ); + if( indexMinus > 0 ) + { + string[] args = value[ 0 ].Split( '-' ); + m_renderQueue = TemplateHelperFunctions.StringToRenderQueue[ args[ 0 ] ]; + int.TryParse( args[ 1 ], out m_renderQueueOffset ); + m_renderQueueOffset *= -1; + } + else + { + m_renderQueue = TemplateHelperFunctions.StringToRenderQueue[ value[ 0 ] ]; + m_renderQueueOffset = 0; + } + } + } + BuildQueueTagValue(); + } + break; + case TemplateSpecialTags.DisableBatching: + { + if( !TemplateHelperFunctions.StringToDisableBatching.TryGetValue( value[ 0 ], out m_disableBatching ) ) + { + m_disableBatching = DisableBatching.False; + TagValue = value[ 0 ]; + } + } + break; + } + } + + void CheckSpecialTag() + { + if( TagName.Equals( Constants.RenderTypeHelperStr ) ) + { + m_specialTag = TemplateSpecialTags.RenderType; + if( !TemplateHelperFunctions.StringToRenderType.TryGetValue( TagValue, out m_renderType )) + { + m_renderType = RenderType.Custom; + } + } + else if( TagName.Equals( Constants.RenderQueueHelperStr ) ) + { + m_specialTag = TemplateSpecialTags.Queue; + SetTagValue( TagValue ); + } + else if( TagName.Equals( Constants.DisableBatchingHelperStr ) ) + { + m_specialTag = TemplateSpecialTags.DisableBatching; + if( !TemplateHelperFunctions.StringToDisableBatching.TryGetValue( TagValue, out m_disableBatching ) ) + { + m_disableBatching = DisableBatching.False; + } + } + else + { + m_specialTag = TemplateSpecialTags.None; + } + } + + public CustomTagData( string name, string value, int id ) + { + TagName = name; + TagValue = value; + TagId = id; + CheckSpecialTag(); + } + + //Used on Template based shaders loading + public CustomTagData( string data, int id ) + { + TagId = id; + string[] arr = data.Split( IOUtils.VALUE_SEPARATOR ); + if( arr.Length > 1 ) + { + TagName = arr[ 0 ]; + TagValue = arr[ 1 ]; + } + + if( arr.Length > 2 ) + { + m_specialTag = (TemplateSpecialTags)Enum.Parse( typeof( TemplateSpecialTags ), arr[ 2 ] ); + switch( m_specialTag ) + { + case TemplateSpecialTags.RenderType: + { + if( !TemplateHelperFunctions.StringToRenderType.TryGetValue( TagValue, out m_renderType ) ) + { + m_renderType = RenderType.Custom; + } + } + break; + case TemplateSpecialTags.Queue: + { + if( arr.Length == 4 ) + { + m_renderQueue = (RenderQueue)Enum.Parse( typeof( RenderQueue ), TagValue ); + int.TryParse( arr[ 3 ], out m_renderQueueOffset ); + } + BuildQueueTagValue(); + } + break; + case TemplateSpecialTags.DisableBatching: + { + if( !TemplateHelperFunctions.StringToDisableBatching.TryGetValue( TagValue, out m_disableBatching ) ) + { + m_disableBatching = DisableBatching.False; + } + } + break; + } + } + else if( UIUtils.CurrentShaderVersion() < 15600 ) + { + CheckSpecialTag(); + } + } + + //Used on Standard Surface shaders loading + public CustomTagData( string data ) + { + string[] arr = data.Split( IOUtils.VALUE_SEPARATOR ); + if( arr.Length > 1 ) + { + TagName = arr[ 0 ]; + TagValue = arr[ 1 ]; + } + } + + public override string ToString() + { + switch( m_specialTag ) + { + case TemplateSpecialTags.RenderType: + return TagName + IOUtils.VALUE_SEPARATOR + + ( RenderType != RenderType.Custom? RenderType.ToString(): TagValue ) + IOUtils.VALUE_SEPARATOR + + m_specialTag; + case TemplateSpecialTags.Queue: + return TagName + IOUtils.VALUE_SEPARATOR + + m_renderQueue.ToString() + IOUtils.VALUE_SEPARATOR + + m_specialTag + IOUtils.VALUE_SEPARATOR + + m_renderQueueOffset; + case TemplateSpecialTags.DisableBatching: + return TagName + IOUtils.VALUE_SEPARATOR + + Batching.ToString() + IOUtils.VALUE_SEPARATOR + + m_specialTag; + } + + return TagName + IOUtils.VALUE_SEPARATOR + TagValue; + } + + public string GenerateTag() + { + switch( m_specialTag ) + { + case TemplateSpecialTags.RenderType: + return string.Format( TagFormat, TagName, ( RenderType != RenderType.Custom ? RenderType.ToString() : TagValue ) ); + case TemplateSpecialTags.DisableBatching: + case TemplateSpecialTags.Queue: + case TemplateSpecialTags.None: + default: + return string.Format( TagFormat, TagName, TagValue ); + } + } + + public void BuildQueueTagValue() + { + TagValue = m_renderQueue.ToString(); + if( m_renderQueueOffset > 0 ) + { + TagValue += "+" + m_renderQueueOffset; + } + else if( m_renderQueueOffset < 0 ) + { + TagValue += m_renderQueueOffset; + } + } + + public TemplateSpecialTags SpecialTag + { + get { return m_specialTag; } + set + { + m_specialTag = value; + switch( value ) + { + case TemplateSpecialTags.DisableBatching: + { + TagValue = m_disableBatching.ToString(); + } + break; + case TemplateSpecialTags.RenderType: + { + //if( m_renderType != RenderType.Custom ) + // TagValue = m_renderType.ToString(); + } + break; + case TemplateSpecialTags.Queue: + { + BuildQueueTagValue(); + } + break; + } + } + } + + public DisableBatching Batching + { + get { return m_disableBatching; } + set { m_disableBatching = value; + TagValue = value.ToString(); + } + } + + public RenderType RenderType + { + get { return m_renderType; } + set + { + m_renderType = value; + //if( m_renderType != RenderType.Custom ) + // TagValue = value.ToString(); + } + } + + public RenderQueue RenderQueue + { + get { return m_renderQueue; } + set { m_renderQueue = value; } + } + public int RenderQueueOffset + { + get { return m_renderQueueOffset; } + set { m_renderQueueOffset = value; } + } + + public bool IsValid { get { return ( !string.IsNullOrEmpty( TagValue ) && !string.IsNullOrEmpty( TagName ) ); } } + } + + [Serializable] + public class CustomTagsHelper + { + private const string CustomTagsStr = " Custom SubShader Tags"; + private const string TagNameStr = "Name"; + private const string TagValueStr = "Value"; + + private const float ShaderKeywordButtonLayoutWidth = 15; + private ParentNode m_currentOwner; + + [SerializeField] + private List m_availableTags = new List(); + + public void Draw( ParentNode owner ) + { + m_currentOwner = owner; + bool value = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedCustomTags; + NodeUtils.DrawPropertyGroup( ref value, CustomTagsStr, DrawMainBody, DrawButtons ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedCustomTags = value; + } + + void DrawButtons() + { + EditorGUILayout.Separator(); + + // Add tag + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_availableTags.Add( new CustomTagData() ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove tag + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + if( m_availableTags.Count > 0 ) + { + m_availableTags.RemoveAt( m_availableTags.Count - 1 ); + EditorGUI.FocusTextInControl( null ); + } + } + } + + void DrawMainBody() + { + EditorGUILayout.Separator(); + int itemCount = m_availableTags.Count; + + if( itemCount == 0 ) + { + EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one.", MessageType.Info ); + } + + int markedToDelete = -1; + float originalLabelWidth = EditorGUIUtility.labelWidth; + for( int i = 0; i < itemCount; i++ ) + { + m_availableTags[ i ].TagFoldout = m_currentOwner.EditorGUILayoutFoldout( m_availableTags[ i ].TagFoldout, string.Format( "[{0}] - {1}", i, m_availableTags[ i ].TagName ) ); + if( m_availableTags[ i ].TagFoldout ) + { + EditorGUI.indentLevel += 1; + EditorGUIUtility.labelWidth = 70; + //Tag Name + EditorGUI.BeginChangeCheck(); + m_availableTags[ i ].TagName = EditorGUILayout.TextField( TagNameStr, m_availableTags[ i ].TagName ); + if( EditorGUI.EndChangeCheck() ) + { + m_availableTags[ i ].TagName = UIUtils.RemoveShaderInvalidCharacters( m_availableTags[ i ].TagName ); + } + + //Tag Value + EditorGUI.BeginChangeCheck(); + m_availableTags[ i ].TagValue = EditorGUILayout.TextField( TagValueStr, m_availableTags[ i ].TagValue ); + if( EditorGUI.EndChangeCheck() ) + { + m_availableTags[ i ].TagValue = UIUtils.RemoveShaderInvalidCharacters( m_availableTags[ i ].TagValue ); + } + + EditorGUIUtility.labelWidth = originalLabelWidth; + + EditorGUILayout.BeginHorizontal(); + { + GUILayout.Label( " " ); + // Add new port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_availableTags.Insert( i + 1, new CustomTagData() ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + markedToDelete = i; + } + } + EditorGUILayout.EndHorizontal(); + + EditorGUI.indentLevel -= 1; + } + + } + if( markedToDelete > -1 ) + { + if( m_availableTags.Count > markedToDelete ) + { + m_availableTags.RemoveAt( markedToDelete ); + EditorGUI.FocusTextInControl( null ); + } + } + EditorGUILayout.Separator(); + } + + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + int count = Convert.ToInt32( nodeParams[ index++ ] ); + for( int i = 0; i < count; i++ ) + { + m_availableTags.Add( new CustomTagData( nodeParams[ index++ ] ) ); + } + } + + public void WriteToString( ref string nodeInfo ) + { + int tagsCount = m_availableTags.Count; + IOUtils.AddFieldValueToString( ref nodeInfo, tagsCount ); + for( int i = 0; i < tagsCount; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_availableTags[ i ].ToString() ); + } + } + + public string GenerateCustomTags() + { + int tagsCount = m_availableTags.Count; + string result = tagsCount == 0 ? string.Empty : " "; + + for( int i = 0; i < tagsCount; i++ ) + { + if( m_availableTags[ i ].IsValid ) + { + result += m_availableTags[ i ].GenerateTag(); + if( i < tagsCount - 1 ) + { + result += " "; + } + } + } + return result; + } + + public void Destroy() + { + m_availableTags.Clear(); + m_availableTags = null; + m_currentOwner = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CustomTagsHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CustomTagsHelper.cs.meta new file mode 100644 index 0000000..de6b426 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/CustomTagsHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5ed32be99aefda24483c9e3499a5cd23 +timeCreated: 1500400244 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/DependenciesHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/DependenciesHelper.cs new file mode 100644 index 0000000..915f173 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/DependenciesHelper.cs @@ -0,0 +1,210 @@ +using System; +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class DependenciesData + { + private string DependencyFormat = "Dependency \"{0}\"=\"{1}\"\n"; + public string DependencyName; + public string DependencyValue; + public bool DependencyFoldout = true; + + public DependenciesData() + { + DependencyName = string.Empty; + DependencyValue = string.Empty; + } + + public DependenciesData( string data ) + { + string[] arr = data.Split( IOUtils.VALUE_SEPARATOR ); + if( arr.Length > 1 ) + { + DependencyName = arr[ 0 ]; + DependencyValue = arr[ 1 ]; + } + } + + public override string ToString() + { + return DependencyName + IOUtils.VALUE_SEPARATOR + DependencyValue; + } + + public string GenerateDependency() + { + return string.Format( DependencyFormat, DependencyName, DependencyValue ); + } + + public bool IsValid { get { return ( !string.IsNullOrEmpty( DependencyValue ) && !string.IsNullOrEmpty( DependencyName ) ); } } + } + + [Serializable] + public class DependenciesHelper + { + private const string CustomDependencysStr = " Dependencies"; + private const string DependencyNameStr = "Name"; + private const string DependencyValueStr = "Value"; + + private const float ShaderKeywordButtonLayoutWidth = 15; + private ParentNode m_currentOwner; + + [SerializeField] + private List m_availableDependencies = new List(); + + public void Draw( ParentNode owner, bool isNested = false ) + { + m_currentOwner = owner; + bool value = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDependencies; + if( isNested ) + { + NodeUtils.DrawNestedPropertyGroup( ref value, CustomDependencysStr, DrawMainBody, DrawButtons ); + } + else + { + NodeUtils.DrawPropertyGroup( ref value, CustomDependencysStr, DrawMainBody, DrawButtons ); + } + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDependencies = value; + } + + void DrawButtons() + { + EditorGUILayout.Separator(); + + // Add Dependency + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_availableDependencies.Add( new DependenciesData() ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove Dependency + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + if( m_availableDependencies.Count > 0 ) + { + m_availableDependencies.RemoveAt( m_availableDependencies.Count - 1 ); + EditorGUI.FocusTextInControl( null ); + } + } + } + + void DrawMainBody() + { + EditorGUILayout.Separator(); + int itemCount = m_availableDependencies.Count; + + if( itemCount == 0 ) + { + EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one.", MessageType.Info ); + } + + int markedToDelete = -1; + float originalLabelWidth = EditorGUIUtility.labelWidth; + for( int i = 0; i < itemCount; i++ ) + { + m_availableDependencies[ i ].DependencyFoldout = m_currentOwner.EditorGUILayoutFoldout( m_availableDependencies[ i ].DependencyFoldout, string.Format( "[{0}] - {1}", i, m_availableDependencies[ i ].DependencyName ) ); + if( m_availableDependencies[ i ].DependencyFoldout ) + { + EditorGUI.indentLevel += 1; + EditorGUIUtility.labelWidth = 70; + //Dependency Name + EditorGUI.BeginChangeCheck(); + m_availableDependencies[ i ].DependencyName = EditorGUILayout.TextField( DependencyNameStr, m_availableDependencies[ i ].DependencyName ); + if( EditorGUI.EndChangeCheck() ) + { + m_availableDependencies[ i ].DependencyName = UIUtils.RemoveShaderInvalidCharacters( m_availableDependencies[ i ].DependencyName ); + } + + //Dependency Value + EditorGUI.BeginChangeCheck(); + m_availableDependencies[ i ].DependencyValue = EditorGUILayout.TextField( DependencyValueStr, m_availableDependencies[ i ].DependencyValue ); + if( EditorGUI.EndChangeCheck() ) + { + m_availableDependencies[ i ].DependencyValue = UIUtils.RemoveShaderInvalidCharacters( m_availableDependencies[ i ].DependencyValue ); + } + + EditorGUIUtility.labelWidth = originalLabelWidth; + + EditorGUILayout.BeginHorizontal(); + { + GUILayout.Label( " " ); + // Add new port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_availableDependencies.Insert( i + 1, new DependenciesData() ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + markedToDelete = i; + } + } + EditorGUILayout.EndHorizontal(); + + EditorGUI.indentLevel -= 1; + } + + } + if( markedToDelete > -1 ) + { + if( m_availableDependencies.Count > markedToDelete ) + { + m_availableDependencies.RemoveAt( markedToDelete ); + EditorGUI.FocusTextInControl( null ); + } + } + EditorGUILayout.Separator(); + } + + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + int count = Convert.ToInt32( nodeParams[ index++ ] ); + for( int i = 0; i < count; i++ ) + { + m_availableDependencies.Add( new DependenciesData( nodeParams[ index++ ] ) ); + } + } + + public void WriteToString( ref string nodeInfo ) + { + int dependencyCount = m_availableDependencies.Count; + IOUtils.AddFieldValueToString( ref nodeInfo, dependencyCount ); + for( int i = 0; i < dependencyCount; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_availableDependencies[ i ].ToString() ); + } + } + + public string GenerateDependencies() + { + int dependencyCount = m_availableDependencies.Count; + string result = dependencyCount == 0 ? string.Empty : "\n"; + UIUtils.ShaderIndentLevel++; + for( int i = 0; i < dependencyCount; i++ ) + { + if( m_availableDependencies[ i ].IsValid ) + { + result += UIUtils.ShaderIndentTabs + m_availableDependencies[ i ].GenerateDependency(); + } + } + UIUtils.ShaderIndentLevel--; + return result; + } + + public void Destroy() + { + m_availableDependencies.Clear(); + m_availableDependencies = null; + m_currentOwner = null; + } + + public bool HasDependencies { get { return m_availableDependencies.Count > 0; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/DependenciesHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/DependenciesHelper.cs.meta new file mode 100644 index 0000000..92e4d81 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/DependenciesHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2daff2983fe91ac43953017a8be984a7 +timeCreated: 1512404972 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FallbackPickerHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FallbackPickerHelper.cs new file mode 100644 index 0000000..6d006a9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FallbackPickerHelper.cs @@ -0,0 +1,119 @@ +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class FallbackPickerHelper : ScriptableObject + { + private const string FallbackFormat = "Fallback \"{0}\""; + private const string FallbackShaderStr = "Fallback"; + private const string ShaderPoputContext = "CONTEXT/ShaderPopup"; + + private Material m_dummyMaterial; + private MenuCommand m_dummyCommand; + + [SerializeField] + private string m_fallbackShader = string.Empty; + + public void Init() + { + hideFlags = HideFlags.HideAndDontSave; + m_dummyMaterial = null; + m_dummyCommand = null; + } + + public void Draw( ParentNode owner ) + { + EditorGUILayout.BeginHorizontal(); + m_fallbackShader = owner.EditorGUILayoutTextField( FallbackShaderStr, m_fallbackShader ); + if ( GUILayout.Button( string.Empty, UIUtils.InspectorPopdropdownFallback, GUILayout.Width( 17 ), GUILayout.Height( 19 ) ) ) + { + EditorGUI.FocusTextInControl( null ); + GUI.FocusControl( null ); + DisplayShaderContext( owner, GUILayoutUtility.GetRect( GUIContent.none, EditorStyles.popup ) ); + } + EditorGUILayout.EndHorizontal(); + } + + private void DisplayShaderContext( ParentNode node, Rect r ) + { + if ( m_dummyCommand == null ) + m_dummyCommand = new MenuCommand( this, 0 ); + + if ( m_dummyMaterial == null ) + m_dummyMaterial = new Material( Shader.Find( "Hidden/ASESShaderSelectorUnlit" ) ); + +#pragma warning disable 0618 + UnityEditorInternal.InternalEditorUtility.SetupShaderMenu( m_dummyMaterial ); +#pragma warning restore 0618 + EditorUtility.DisplayPopupMenu( r, ShaderPoputContext, m_dummyCommand ); + } + + private void OnSelectedShaderPopup( string command, Shader shader ) + { + if ( shader != null ) + { + UIUtils.MarkUndoAction(); + Undo.RecordObject( this, "Selected fallback shader" ); + m_fallbackShader = shader.name; + } + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + m_fallbackShader = nodeParams[ index++ ]; + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_fallbackShader ); + } + + public void Destroy() + { + GameObject.DestroyImmediate( m_dummyMaterial ); + m_dummyMaterial = null; + m_dummyCommand = null; + } + + public string TabbedFallbackShader + { + get + { + if( string.IsNullOrEmpty( m_fallbackShader ) ) + return string.Empty; + + return "\t" + string.Format( FallbackFormat, m_fallbackShader ) + "\n"; + } + } + + public string FallbackShader + { + get + { + if( string.IsNullOrEmpty( m_fallbackShader ) ) + return string.Empty; + + return string.Format( FallbackFormat, m_fallbackShader ); + } + } + + public string RawFallbackShader + { + get + { + return m_fallbackShader; + } + set + { + m_fallbackShader = value; + } + } + + + public bool Active { get { return !string.IsNullOrEmpty( m_fallbackShader ); } } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FallbackPickerHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FallbackPickerHelper.cs.meta new file mode 100644 index 0000000..2336aa8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FallbackPickerHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cd5a03cee1255ba438e2062d215b70b6 +timeCreated: 1490378537 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionInput.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionInput.cs new file mode 100644 index 0000000..155d200 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionInput.cs @@ -0,0 +1,527 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Function Input", "Functions", "Function Input adds an input port to the shader function", NodeAvailabilityFlags = (int)NodeAvailability.ShaderFunction )] + public sealed class FunctionInput : ParentNode + { + private const string InputTypeStr = "Input Type"; + private readonly string[] m_inputValueTypes ={ "Int", + "Float", + "Vector2", + "Vector3", + "Vector4", + "Color", + "Matrix 3x3", + "Matrix 4x4", + "Sampler 1D", + "Sampler 2D", + "Sampler 3D", + "Sampler Cube", + "Sampler 2D Array", + "Sampler State", + "Custom"}; + + [SerializeField] + private int m_selectedInputTypeInt = 1; + + private WirePortDataType m_selectedInputType = WirePortDataType.FLOAT; + + [SerializeField] + private FunctionNode m_functionNode; + + [SerializeField] + private string m_inputName = "Input"; + + [SerializeField] + private bool m_autoCast = false; + + [SerializeField] + private int m_orderIndex = -1; + + private int m_typeId = -1; + + public bool m_ignoreConnection = false; + + public delegate string PortGeneration( ref MasterNodeDataCollector dataCollector, int index, ParentGraph graph ); + public PortGeneration OnPortGeneration = null; + + //Title editing + [SerializeField] + private string m_uniqueName; + + private bool m_isEditing; + private bool m_stopEditing; + private bool m_startEditing; + private double m_clickTime; + private double m_doubleClickTime = 0.3; + private Rect m_titleClickArea; + private bool m_showTitleWhenNotEditing = true; + + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + m_inputPorts[ 0 ].AutoDrawInternalData = true; + //m_inputPorts[ 0 ].Visible = false; + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_autoWrapProperties = true; + m_textLabelWidth = 100; + SetTitleText( m_inputName ); + UpdatePorts(); + SetAdditonalTitleText( "( " + m_inputValueTypes[ m_selectedInputTypeInt ] + " )" ); + m_previewShaderGUID = "04bc8e7b317dccb4d8da601680dd8140"; + } + + public override void SetPreviewInputs() + { + if( Fnode == null ) + { + m_ignoreConnection = false; + CheckSpherePreview(); + } + else + { + var input = Fnode.GetInput( this ); + if( input != null && ( !InputPorts[ 0 ].IsConnected || input.IsConnected ) ) + { + m_ignoreConnection = true; + InputPorts[ 0 ].PreparePortCacheID(); + Fnode.SetPreviewInput( input ); + if( input.ExternalReferences.Count > 0 ) + { + SpherePreview = Fnode.ContainerGraph.GetNode( input.ExternalReferences[ 0 ].NodeId ).SpherePreview; + } + else + { + SpherePreview = false; + } + PreviewMaterial.SetTexture( InputPorts[ 0 ].CachedPropertyId, input.InputPreviewTexture( Fnode.ContainerGraph ) ); + } + else + { + m_ignoreConnection = false; + CheckSpherePreview(); + } + } + + if( !m_ignoreConnection ) + base.SetPreviewInputs(); + + for( int i = 0; i < OutputPorts[ 0 ].ExternalReferences.Count; i++ ) + { + ContainerGraph.GetNode( OutputPorts[ 0 ].ExternalReferences[ i ].NodeId ).OnNodeChange(); + } + + if( m_typeId == -1 ) + m_typeId = Shader.PropertyToID( "_Type" ); + + if( m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT || m_inputPorts[ 0 ].DataType == WirePortDataType.INT ) + PreviewMaterial.SetInt( m_typeId, 1 ); + else if( m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT2 ) + PreviewMaterial.SetInt( m_typeId, 2 ); + else if( m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT3 ) + PreviewMaterial.SetInt( m_typeId, 3 ); + else + PreviewMaterial.SetInt( m_typeId, 0 ); + + } + + public override bool RecursivePreviewUpdate( Dictionary duplicatesDict = null ) + { + if( duplicatesDict == null ) + { + duplicatesDict = ContainerGraph.ParentWindow.VisitedChanged; + } + + for( int i = 0; i < InputPorts.Count; i++ ) + { + ParentNode outNode = null; + if( Fnode != null ) + { + var input = Fnode.GetInput( this ); + if( input.ExternalReferences.Count > 0 ) + { + outNode = Fnode.ContainerGraph.GetNode( input.ExternalReferences[ 0 ].NodeId ); + } + else if( InputPorts[ i ].ExternalReferences.Count > 0 ) + { + outNode = ContainerGraph.GetNode( InputPorts[ i ].ExternalReferences[ 0 ].NodeId ); + } + } + else + { + if( InputPorts[ i ].ExternalReferences.Count > 0 ) + { + outNode = ContainerGraph.GetNode( InputPorts[ i ].ExternalReferences[ 0 ].NodeId ); + } + } + if( outNode != null ) + { + if( !duplicatesDict.ContainsKey( outNode.OutputId ) ) + { + bool result = outNode.RecursivePreviewUpdate(); + if( result ) + PreviewIsDirty = true; + } + else if( duplicatesDict[ outNode.OutputId ] ) + { + PreviewIsDirty = true; + } + } + } + + bool needsUpdate = PreviewIsDirty; + RenderNodePreview(); + if( !duplicatesDict.ContainsKey( OutputId ) ) + duplicatesDict.Add( OutputId, needsUpdate ); + return needsUpdate; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + UIUtils.RegisterFunctionInputNode( this ); + if( m_nodeAttribs != null ) + m_uniqueName = m_nodeAttribs.Name + UniqueId; + } + + public override void Destroy() + { + base.Destroy(); + OnPortGeneration = null; + UIUtils.UnregisterFunctionInputNode( this ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + if( AutoCast ) + { + m_inputPorts[ 0 ].MatchPortToConnection(); + SetIntTypeFromPort(); + UpdatePorts(); + SetAdditonalTitleText( "( " + m_inputValueTypes[ m_selectedInputTypeInt ] + " )" ); + } + } + + public override void OnConnectedOutputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( portId, otherNodeId, otherPortId, name, type ); + if( AutoCast ) + { + m_inputPorts[ 0 ].MatchPortToConnection(); + SetIntTypeFromPort(); + UpdatePorts(); + SetAdditonalTitleText( "( " + m_inputValueTypes[ m_selectedInputTypeInt ] + " )" ); + } + } + + public void SetIntTypeFromPort() + { + switch( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.INT: m_selectedInputTypeInt = 0; break; + default: + case WirePortDataType.FLOAT: m_selectedInputTypeInt = 1; break; + case WirePortDataType.FLOAT2: m_selectedInputTypeInt = 2; break; + case WirePortDataType.FLOAT3: m_selectedInputTypeInt = 3; break; + case WirePortDataType.FLOAT4: m_selectedInputTypeInt = 4; break; + case WirePortDataType.COLOR: m_selectedInputTypeInt = 5; break; + case WirePortDataType.FLOAT3x3: m_selectedInputTypeInt = 6; break; + case WirePortDataType.FLOAT4x4: m_selectedInputTypeInt = 7; break; + case WirePortDataType.SAMPLER1D: m_selectedInputTypeInt = 8; break; + case WirePortDataType.SAMPLER2D: m_selectedInputTypeInt = 9; break; + case WirePortDataType.SAMPLER3D: m_selectedInputTypeInt = 10; break; + case WirePortDataType.SAMPLERCUBE: m_selectedInputTypeInt = 11; break; + case WirePortDataType.SAMPLER2DARRAY: m_selectedInputTypeInt = 12; break; + case WirePortDataType.SAMPLERSTATE: m_selectedInputTypeInt = 13; break; + case WirePortDataType.OBJECT: m_selectedInputTypeInt = 14; break; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + // Custom Editable Title + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + if( !m_isEditing && ( ( !ContainerGraph.ParentWindow.MouseInteracted && drawInfo.CurrentEventType == EventType.MouseDown && m_titleClickArea.Contains( drawInfo.MousePosition ) ) ) ) + { + if( ( EditorApplication.timeSinceStartup - m_clickTime ) < m_doubleClickTime ) + m_startEditing = true; + else + GUI.FocusControl( null ); + m_clickTime = EditorApplication.timeSinceStartup; + } + else if( m_isEditing && ( ( drawInfo.CurrentEventType == EventType.MouseDown && !m_titleClickArea.Contains( drawInfo.MousePosition ) ) || !EditorGUIUtility.editingTextField ) ) + { + m_stopEditing = true; + } + + if( m_isEditing || m_startEditing ) + { + EditorGUI.BeginChangeCheck(); + GUI.SetNextControlName( m_uniqueName ); + m_inputName = EditorGUITextField( m_titleClickArea, string.Empty, m_inputName, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + if( EditorGUI.EndChangeCheck() ) + { + SetTitleText( m_inputName ); + UIUtils.UpdateFunctionInputData( UniqueId, m_inputName ); + } + + if( m_startEditing ) + EditorGUI.FocusTextInControl( m_uniqueName ); + + } + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + if( m_startEditing ) + { + m_startEditing = false; + m_isEditing = true; + } + + if( m_stopEditing ) + { + m_stopEditing = false; + m_isEditing = false; + GUI.FocusControl( null ); + } + } + + + } + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + // RUN LAYOUT CHANGES AFTER TITLES CHANGE + base.OnNodeLayout( drawInfo ); + m_titleClickArea = m_titlePos; + m_titleClickArea.height = Constants.NODE_HEADER_HEIGHT; + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + + if( !m_isVisible ) + return; + + // Fixed Title ( only renders when not editing ) + if( m_showTitleWhenNotEditing && !m_isEditing && !m_startEditing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + GUI.Label( m_titleClickArea, m_content, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + } + } + + public override void OnNodeDoubleClicked( Vector2 currentMousePos2D ) + { + if( currentMousePos2D.y - m_globalPosition.y > ( Constants.NODE_HEADER_HEIGHT + Constants.NODE_HEADER_EXTRA_HEIGHT ) * ContainerGraph.ParentWindow.CameraDrawInfo.InvertedZoom ) + { + ContainerGraph.ParentWindow.ParametersWindow.IsMaximized = !ContainerGraph.ParentWindow.ParametersWindow.IsMaximized; + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUILayout.BeginVertical(); + EditorGUI.BeginChangeCheck(); + m_inputName = EditorGUILayoutTextField( "Name", m_inputName ); + if( EditorGUI.EndChangeCheck() ) + { + SetTitleText( m_inputName ); + UIUtils.UpdateFunctionInputData( UniqueId, m_inputName ); + } + EditorGUI.BeginChangeCheck(); + m_selectedInputTypeInt = EditorGUILayoutPopup( InputTypeStr, m_selectedInputTypeInt, m_inputValueTypes ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePorts(); + SetAdditonalTitleText( "( " + m_inputValueTypes[ m_selectedInputTypeInt ] + " )" ); + } + + m_autoCast = EditorGUILayoutToggle( "Auto Cast", m_autoCast ); + + EditorGUILayout.Separator(); + if( !m_inputPorts[ 0 ].IsConnected && m_inputPorts[ 0 ].ValidInternalData ) + { + m_inputPorts[ 0 ].ShowInternalData( this, true, "Default Value" ); + } + + + EditorGUILayout.EndVertical(); + } + + void UpdatePorts() + { + switch( m_selectedInputTypeInt ) + { + case 0: m_selectedInputType = WirePortDataType.INT; break; + default: + case 1: m_selectedInputType = WirePortDataType.FLOAT; break; + case 2: m_selectedInputType = WirePortDataType.FLOAT2; break; + case 3: m_selectedInputType = WirePortDataType.FLOAT3; break; + case 4: m_selectedInputType = WirePortDataType.FLOAT4; break; + case 5: m_selectedInputType = WirePortDataType.COLOR; break; + case 6: m_selectedInputType = WirePortDataType.FLOAT3x3; break; + case 7: m_selectedInputType = WirePortDataType.FLOAT4x4; break; + case 8: m_selectedInputType = WirePortDataType.SAMPLER1D; break; + case 9: m_selectedInputType = WirePortDataType.SAMPLER2D; break; + case 10: m_selectedInputType = WirePortDataType.SAMPLER3D; break; + case 11: m_selectedInputType = WirePortDataType.SAMPLERCUBE; break; + case 12: m_selectedInputType = WirePortDataType.SAMPLER2DARRAY; break; + case 13: m_selectedInputType = WirePortDataType.SAMPLERSTATE; break; + case 14: m_selectedInputType = WirePortDataType.OBJECT; break; + } + + ChangeInputType( m_selectedInputType, false ); + + //This node doesn't have any restrictions but changing types should be restricted to prevent invalid connections + m_outputPorts[ 0 ].ChangeTypeWithRestrictions( m_selectedInputType, PortCreateRestriction( m_selectedInputType ) ); + m_sizeIsDirty = true; + } + + public int PortCreateRestriction( WirePortDataType dataType ) + { + int restrictions = 0; + WirePortDataType[] types = null; + switch( dataType ) + { + case WirePortDataType.OBJECT: + break; + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + case WirePortDataType.INT: + { + types = new WirePortDataType[] { WirePortDataType.FLOAT, WirePortDataType.FLOAT2, WirePortDataType.FLOAT3, WirePortDataType.FLOAT4, WirePortDataType.COLOR, WirePortDataType.INT, WirePortDataType.OBJECT }; + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + types = new WirePortDataType[] { WirePortDataType.FLOAT3x3, WirePortDataType.FLOAT4x4, WirePortDataType.OBJECT }; + } + break; + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + { + types = new WirePortDataType[] { WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.SAMPLER2DARRAY, WirePortDataType.OBJECT }; + } + break; + case WirePortDataType.SAMPLERSTATE: + { + types = new WirePortDataType[] { WirePortDataType.SAMPLERSTATE }; + } + break; + default: + break; + } + + if( types != null ) + { + for( int i = 0; i < types.Length; i++ ) + { + restrictions = restrictions | (int)types[ i ]; + } + } + + return restrictions; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ outputId ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + + string result = string.Empty; + if( OnPortGeneration != null ) + result = OnPortGeneration( ref dataCollector, m_orderIndex, ContainerGraph.ParentWindow.CustomGraph ); + else + result = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + if( m_outputPorts[ outputId ].ConnectionCount > 1 ) + RegisterLocalVariable( outputId, result, ref dataCollector ); + else + m_outputPorts[ outputId ].SetLocalValue( result, dataCollector.PortCategory ); + + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_inputName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedInputTypeInt ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_orderIndex ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_autoCast ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_inputName = GetCurrentParam( ref nodeParams ); + m_selectedInputTypeInt = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_orderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_autoCast = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + + SetTitleText( m_inputName ); + UpdatePorts(); + SetAdditonalTitleText( "( " + m_inputValueTypes[ m_selectedInputTypeInt ] + " )" ); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + + SetTitleText( m_inputName ); + UpdatePorts(); + SetAdditonalTitleText( "( " + m_inputValueTypes[ m_selectedInputTypeInt ] + " )" ); + } + + public WirePortDataType SelectedInputType + { + get { return m_selectedInputType; } + } + + public string InputName + { + get { return m_inputName; } + } + + public int OrderIndex + { + get { return m_orderIndex; } + set { m_orderIndex = value; } + } + + public bool AutoCast + { + get { return m_autoCast; } + set { m_autoCast = value; } + } + + public FunctionNode Fnode + { + get { return m_functionNode; } + set { m_functionNode = value; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionInput.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionInput.cs.meta new file mode 100644 index 0000000..c5aa550 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionInput.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 64064ea01705e084cbe00a3bbeef2c3d +timeCreated: 1491927259 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs new file mode 100644 index 0000000..d6fa21e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs @@ -0,0 +1,1246 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +//#define ADD_SHADER_FUNCTION_HEADERS + +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Function Node", "Functions", "Function Node", KeyCode.None, false, 0, int.MaxValue, typeof( AmplifyShaderFunction ) )] + public class FunctionNode : ParentNode + { + [SerializeField] + private AmplifyShaderFunction m_function; + + [SerializeField] + private ParentGraph m_functionGraph; + + [SerializeField] + private int m_functionGraphId = -1; + + [SerializeField] + private List m_allFunctionInputs; + private Dictionary m_allFunctionInputsDict = new Dictionary(); + + [SerializeField] + private List m_allFunctionOutputs; + private Dictionary m_allFunctionOutputsDict = new Dictionary(); + + [SerializeField] + private List m_allFunctionSwitches; + private Dictionary m_allFunctionSwitchesDict = new Dictionary(); + + [SerializeField] + private ReordenatorNode m_reordenator; + + [SerializeField] + private string m_filename; + + [SerializeField] + private string m_headerTitle = string.Empty; + + [SerializeField] + private int m_orderIndex; + + [SerializeField] + private string m_functionCheckSum; + + [SerializeField] + private string m_functionGUID = string.Empty; + + //[SerializeField] + //private List m_includes = new List(); + + //[SerializeField] + //private List m_pragmas = new List(); + + [SerializeField] + private List m_directives = new List(); + + private bool m_parametersFoldout = true; + [SerializeField] + private ParentGraph m_outsideGraph = null; + + [SerializeField] + private FunctionOutput m_mainPreviewNode; + + bool m_portsChanged = false; + //[SerializeField] + bool m_initialGraphDraw = false; + + private bool m_refreshIdsRequired = false; + + public string[] ReadOptionsHelper = new string[] { }; + + private bool m_lateRefresh = false; + + private Dictionary m_duplicatesBuffer = new Dictionary(); + string LastLine( string text ) + { + string[] lines = text.Replace( "\r", "" ).Split( '\n' ); + return lines[ lines.Length - 1 ]; + } + + public void CommonInit( AmplifyShaderFunction function, int uniqueId ) + { + SetBaseUniqueId( uniqueId ); + + if( function == null ) + return; + + m_refreshIdsRequired = UIUtils.IsLoading && ( UIUtils.CurrentShaderVersion() < 14004 ); + + m_function = function; + + if( Function.FunctionName.Length > 1 ) + { + SetTitleText( GraphContextMenu.AddSpacesToSentence( Function.FunctionName ) ); + } + else + { + SetTitleText( Function.FunctionName ); + } + m_tooltipText = Function.Description; + m_hasTooltipLink = false; + if( m_functionGraph == null ) + { + //m_functionGraph = new ParentGraph(); + m_functionGraph = CreateInstance(); + m_functionGraph.Init(); + m_functionGraph.ParentWindow = ContainerGraph.ParentWindow; + } + + if( string.IsNullOrEmpty( m_functionGUID ) ) + { + m_functionGUID = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_function ) ); + } + + m_functionGraphId = Mathf.Max( m_functionGraphId, ContainerGraph.ParentWindow.GraphCount ); + ContainerGraph.ParentWindow.GraphCount = m_functionGraphId + 1; + m_functionGraph.SetGraphId( m_functionGraphId ); + + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + + AmplifyShaderEditorWindow.LoadFromMeta( ref m_functionGraph, ContainerGraph.ParentWindow.ContextMenuInstance, Function.FunctionInfo ); + //m_functionCheckSum = LastLine( m_function.FunctionInfo ); + m_functionCheckSum = AssetDatabase.GetAssetDependencyHash( AssetDatabase.GetAssetPath( m_function ) ).ToString(); + List propertyList = UIUtils.PropertyNodesList(); + m_allFunctionInputs = UIUtils.FunctionInputList(); + m_allFunctionOutputs = UIUtils.FunctionOutputList(); + m_allFunctionSwitches = UIUtils.FunctionSwitchList(); + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + m_allFunctionInputs.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + m_allFunctionOutputs.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + m_allFunctionSwitches.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + + int inputCount = m_allFunctionInputs.Count; + for( int i = 0; i < inputCount; i++ ) + { + if( m_refreshIdsRequired ) + { + AddInputPort( m_allFunctionInputs[ i ].SelectedInputType, false, m_allFunctionInputs[ i ].InputName ); + } + else + { + AddInputPort( m_allFunctionInputs[ i ].SelectedInputType, false, m_allFunctionInputs[ i ].InputName, -1, MasterNodePortCategory.Fragment, m_allFunctionInputs[ i ].UniqueId ); + } + InputPortSwitchRestriction( m_inputPorts[ i ] ); + + if( !m_allFunctionInputs[ i ].InputPorts[ 0 ].IsConnected ) + { + m_inputPorts[ i ].AutoDrawInternalData = true; + m_inputPorts[ i ].InternalData = m_allFunctionInputs[ i ].InputPorts[ 0 ].InternalData; + } + m_allFunctionInputs[ i ].Fnode = this; + } + + int outputCount = m_allFunctionOutputs.Count; + FunctionOutput first = null; + for( int i = 0; i < outputCount; i++ ) + { + if( i == 0 ) + first = m_allFunctionOutputs[ i ]; + + if( m_allFunctionOutputs[ i ].PreviewNode ) + { + m_mainPreviewNode = m_allFunctionOutputs[ i ]; + } + + if( m_refreshIdsRequired ) + { + AddOutputPort( m_allFunctionOutputs[ i ].AutoOutputType, m_allFunctionOutputs[ i ].OutputName ); + } + else + { + AddOutputPort( m_allFunctionOutputs[ i ].AutoOutputType, m_allFunctionOutputs[ i ].OutputName, m_allFunctionOutputs[ i ].UniqueId ); + } + OutputPortSwitchRestriction( m_outputPorts[ i ] ); + } + + // make sure to hide the ports properly + CheckPortVisibility(); + + if( m_mainPreviewNode == null ) + m_mainPreviewNode = first; + + //create reordenator to main graph + bool inside = false; + if( ContainerGraph.ParentWindow.CustomGraph != null ) + inside = true; + + if( /*hasConnectedProperties*/propertyList.Count > 0 ) + { + m_reordenator = ScriptableObject.CreateInstance(); + m_reordenator.Init( "_" + Function.FunctionName, Function.FunctionName, propertyList, false ); + m_reordenator.OrderIndex = m_orderIndex; + m_reordenator.HeaderTitle = Function.FunctionName; + m_reordenator.IsInside = inside; + } + + if( m_reordenator != null ) + { + cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = null; + UIUtils.RegisterPropertyNode( m_reordenator ); + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + if( inside ) + { + UIUtils.RegisterPropertyNode( m_reordenator ); + } + } + + UIUtils.RegisterFunctionNode( this ); + + m_previewShaderGUID = "aca70c900c50c004e8ef0b47c4fac4d4"; + m_useInternalPortData = false; + m_selectedLocation = function.PreviewPosition; + UIUtils.CurrentWindow.OutsideGraph.OnLODMasterNodesAddedEvent += OnLODMasterNodesAddedEvent; + } + + public InputPort GetInput( FunctionInput input ) + { + int index = m_allFunctionInputs.FindIndex( ( x ) => { return x.Equals( input ); } ); + if( index >= 0 ) + return InputPorts[ index ]; + else + return null; + } + + private void OnLODMasterNodesAddedEvent( int lod ) + { + AddShaderFunctionDirectivesInternal( lod ); + } + + public void SetPreviewInput( InputPort input ) + { + if( !HasPreviewShader || !m_initialized ) + return; + + if( input.IsConnected && input.InputNodeHasPreview( ContainerGraph ) ) + { + input.SetPreviewInputTexture( ContainerGraph ); + } + else + { + input.SetPreviewInputValue( ContainerGraph ); + } + } + + public override bool RecursivePreviewUpdate( Dictionary duplicatesDict = null ) + { + if( duplicatesDict == null ) + { + duplicatesDict = ContainerGraph.ParentWindow.VisitedChanged; + } + + if( m_allFunctionOutputs == null || m_allFunctionOutputs.Count == 0 ) + return false; + + for( int i = 0; i < m_allFunctionOutputs.Count; i++ ) + { + ParentNode outNode = m_allFunctionOutputs[ i ]; + if( outNode != null ) + { + if( !duplicatesDict.ContainsKey( outNode.OutputId ) ) + { + bool result = outNode.RecursivePreviewUpdate(); + if( result ) + PreviewIsDirty = true; + } + else if( duplicatesDict[ outNode.OutputId ] ) + { + PreviewIsDirty = true; + } + } + } + + bool needsUpdate = PreviewIsDirty; + RenderNodePreview(); + if( !duplicatesDict.ContainsKey( OutputId ) ) + duplicatesDict.Add( OutputId, needsUpdate ); + return needsUpdate; + } + + public override void RenderNodePreview() + { + if( m_outputPorts == null ) + return; + + if( !PreviewIsDirty && !m_continuousPreviewRefresh ) + return; + + // this is in the wrong place?? + if( m_drawPreviewAsSphere != m_mainPreviewNode.SpherePreview ) + { + m_drawPreviewAsSphere = m_mainPreviewNode.SpherePreview; + OnNodeChange(); + } + + int count = m_outputPorts.Count; + for( int i = 0; i < count; i++ ) + { + m_outputPorts[ i ].OutputPreviewTexture = m_allFunctionOutputs[ i ].PreviewTexture; + } + + if( PreviewIsDirty ) + FinishPreviewRender = true; + + PreviewIsDirty = false; + } + + public override RenderTexture PreviewTexture + { + get + { + if( m_mainPreviewNode != null ) + return m_mainPreviewNode.PreviewTexture; + else + return base.PreviewTexture; + } + } + + private void AddShaderFunctionDirectivesInternal( int lod ) + { + List nodes = ContainerGraph.ParentWindow.OutsideGraph.GetMultiPassMasterNodes( lod ); + int count = nodes.Count; + for( int i = 0; i < count; i++ ) + { + nodes[ i ].PassModule.AdditionalDirectives.AddShaderFunctionItems( OutputId, Function.AdditionalDirectives.DirectivesList ); + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( Function == null ) + return; + + //Debug.Log( "RefreshExternalReferences " + m_function.FunctionName + " " + UIUtils.CurrentWindow.IsShaderFunctionWindow ); + + Function.UpdateDirectivesList(); + + MasterNode masterNode = UIUtils.CurrentWindow.OutsideGraph.CurrentMasterNode; + StandardSurfaceOutputNode surface = masterNode as StandardSurfaceOutputNode; + + + + if( surface != null ) + { + //for( int i = 0; i < Function.AdditionalIncludes.IncludeList.Count; i++ ) + //{ + // //ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalIncludes.OutsideList.Add( Function.AdditionalIncludes.IncludeList[ i ] ); + // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.AddShaderFunctionItem( AdditionalLineType.Include, Function.AdditionalIncludes.IncludeList[ i ] ); + // m_includes.Add( Function.AdditionalIncludes.IncludeList[ i ] ); + //} + + //for( int i = 0; i < Function.AdditionalPragmas.PragmaList.Count; i++ ) + //{ + // //ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalPragmas.OutsideList.Add( Function.AdditionalPragmas.PragmaList[ i ] ); + // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.AddShaderFunctionItem(AdditionalLineType.Pragma, Function.AdditionalPragmas.PragmaList[ i ] ); + // m_pragmas.Add( Function.AdditionalPragmas.PragmaList[ i ] ); + //} + surface.AdditionalDirectives.AddShaderFunctionItems( OutputId, Function.AdditionalDirectives.DirectivesList ); + } + else + { + if( ContainerGraph.ParentWindow.OutsideGraph.MultiPassMasterNodes.Count > 0 ) + { + for( int lod = -1; lod < ContainerGraph.ParentWindow.OutsideGraph.LodMultiPassMasternodes.Count; lod++ ) + { + AddShaderFunctionDirectivesInternal( lod ); + } + } + else + { + // Assuring that we're not editing a Shader Function, as directives setup is not needed there + if( !UIUtils.CurrentWindow.IsShaderFunctionWindow ) + { + // This function is nested inside a shader function itself and this method + // was called before the main output node was created. + // This is possible since all nodes RefreshExternalReferences(...) are called at the end + // of a LoadFromMeta + // Need to delay this setup to after all nodes are loaded to then setup the directives + m_lateRefresh = true; + return; + } + } + + } + m_directives.AddRange( Function.AdditionalDirectives.DirectivesList ); + + if( m_refreshIdsRequired ) + { + m_refreshIdsRequired = false; + int inputCount = m_inputPorts.Count; + for( int i = 0; i < inputCount; i++ ) + { + m_inputPorts[ i ].ChangePortId( m_allFunctionInputs[ i ].UniqueId ); + } + + int outputCount = m_outputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + m_outputPorts[ i ].ChangePortId( m_allFunctionOutputs[ i ].UniqueId ); + } + } + + if( ContainerGraph.ParentWindow.CurrentGraph != m_functionGraph ) + ContainerGraph.ParentWindow.CurrentGraph.InstancePropertyCount += m_functionGraph.InstancePropertyCount; + + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + + if( ReadOptionsHelper.Length > 2 ) + { + for( int i = 1; i < ReadOptionsHelper.Length; i += 2 ) + { + int optionId = Convert.ToInt32( ReadOptionsHelper[ i ] ); + int optionValue = Convert.ToInt32( ReadOptionsHelper[ i + 1 ] ); + for( int j = 0; j < m_allFunctionSwitches.Count; j++ ) + { + if( m_allFunctionSwitches[ j ].UniqueId == optionId ) + { + m_allFunctionSwitches[ j ].SetCurrentSelectedInput( optionValue, m_allFunctionSwitches[ j ].GetCurrentSelectedInput() ); + break; + } + } + } + } + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + m_portsChanged = true; + } + + void InputPortSwitchRestriction( WirePort port ) + { + switch( port.DataType ) + { + case WirePortDataType.OBJECT: + break; + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + case WirePortDataType.INT: + { + port.CreatePortRestrictions( WirePortDataType.FLOAT, WirePortDataType.FLOAT2, WirePortDataType.FLOAT3, WirePortDataType.FLOAT4, WirePortDataType.COLOR, WirePortDataType.INT, WirePortDataType.OBJECT ); + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + port.CreatePortRestrictions( WirePortDataType.FLOAT3x3, WirePortDataType.FLOAT4x4, WirePortDataType.OBJECT ); + } + break; + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + { + port.CreatePortRestrictions( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.SAMPLER2DARRAY, WirePortDataType.OBJECT ); + } + break; + case WirePortDataType.SAMPLERSTATE: + { + port.CreatePortRestrictions( WirePortDataType.SAMPLERSTATE ); + } + break; + default: + break; + } + } + + void OutputPortSwitchRestriction( WirePort port ) + { + switch( port.DataType ) + { + case WirePortDataType.OBJECT: + break; + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + case WirePortDataType.INT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + port.AddPortForbiddenTypes( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.SAMPLER2DARRAY ); + } + break; + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + { + port.CreatePortRestrictions( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.SAMPLER2DARRAY, WirePortDataType.OBJECT ); + } + break; + case WirePortDataType.SAMPLERSTATE: + { + port.CreatePortRestrictions( WirePortDataType.SAMPLERSTATE ); + } + break; + default: + break; + } + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + m_outsideGraph = cachedGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + + for( int i = 0; i < m_allFunctionOutputs.Count; i++ ) + { + m_allFunctionOutputs[ i ].PropagateNodeData( nodeData, ref dataCollector ); + } + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + base.PropagateNodeData( nodeData, ref dataCollector ); + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + UIUtils.RegisterFunctionNode( this ); + } + + public override void SetupFromCastObject( UnityEngine.Object obj ) + { + base.SetupFromCastObject( obj ); + AmplifyShaderFunction function = obj as AmplifyShaderFunction; + CommonInit( function, UniqueId ); + RefreshExternalReferences(); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + FunctionInput functionInput = m_refreshIdsRequired ? m_allFunctionInputs[ portId ] : GetFunctionInputByUniqueId( portId ); + functionInput.PreviewIsDirty = true; + if( functionInput.AutoCast ) + { + InputPort inputPort = m_refreshIdsRequired ? m_inputPorts[ portId ] : GetInputPortByUniqueId( portId ); + inputPort.MatchPortToConnection(); + + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + functionInput.ChangeOutputType( inputPort.DataType, false ); + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + } + + for( int i = 0; i < m_allFunctionOutputs.Count; i++ ) + { + m_outputPorts[ i ].ChangeType( m_allFunctionOutputs[ i ].InputPorts[ 0 ].DataType, false ); + } + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + + FunctionInput functionInput = m_refreshIdsRequired ? m_allFunctionInputs[ portId ] : GetFunctionInputByUniqueId( portId ); + functionInput.PreviewIsDirty = true; + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + FunctionInput functionInput = m_refreshIdsRequired ? m_allFunctionInputs[ inputPortId ] : GetFunctionInputByUniqueId( inputPortId ); + functionInput.PreviewIsDirty = true; + if( functionInput.AutoCast ) + { + InputPort inputPort = m_refreshIdsRequired ? m_inputPorts[ inputPortId ] : GetInputPortByUniqueId( inputPortId ); + inputPort.MatchPortToConnection(); + + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + functionInput.ChangeOutputType( inputPort.DataType, false ); + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + } + + for( int i = 0; i < m_allFunctionOutputs.Count; i++ ) + { + m_outputPorts[ i ].ChangeType( m_allFunctionOutputs[ i ].InputPorts[ 0 ].DataType, false ); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + + if( Function == null ) + return; + + if( Function.Description.Length > 0 || m_allFunctionSwitches.Count > 0 ) + NodeUtils.DrawPropertyGroup( ref m_parametersFoldout, "Parameters", DrawDescription ); + + bool drawInternalDataUI = false; + int inputCount = m_inputPorts.Count; + if( inputCount > 0 ) + { + for( int i = 0; i < inputCount; i++ ) + { + if( m_inputPorts[ i ].Available && m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].AutoDrawInternalData /*&& ( m_inputPorts[ i ].AutoDrawInternalData || ( m_autoDrawInternalPortData && m_useInternalPortData ) )*/ /*&& m_inputPorts[ i ].AutoDrawInternalData*/ ) + { + drawInternalDataUI = true; + break; + } + } + } + + if( drawInternalDataUI ) + NodeUtils.DrawPropertyGroup( ref m_internalDataFoldout, Constants.InternalDataLabelStr, () => + { + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].Visible && m_inputPorts[ i ].AutoDrawInternalData ) + { + EditorGUI.BeginChangeCheck(); + m_inputPorts[ i ].ShowInternalData( this ); + if( EditorGUI.EndChangeCheck() ) + { + m_allFunctionInputs[ i ].PreviewIsDirty = true; + } + } + } + } ); + } + + private void DrawDescription() + { + if( Function.Description.Length > 0 ) + EditorGUILayout.HelpBox( Function.Description, MessageType.Info ); + + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + for( int i = 0; i < m_allFunctionSwitches.Count; i++ ) + { + m_allFunctionSwitches[ i ].AsDrawn = false; + } + + for( int i = 0; i < m_allFunctionSwitches.Count; i++ ) + { + if( m_allFunctionSwitches[ i ].DrawOption( this ) ) + { + m_portsChanged = true; + } + } + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + } + + private void RemoveShaderFunctionDirectivesInternal( int lod ) + { + List nodes = ContainerGraph.ParentWindow.OutsideGraph.GetMultiPassMasterNodes( lod ); + int count = nodes.Count; + for( int i = 0; i < count; i++ ) + { + nodes[ i ].PassModule.AdditionalDirectives.RemoveShaderFunctionItems( OutputId ); + } + } + + public override void Destroy() + { + m_mainPreviewNode = null; + base.Destroy(); + + m_duplicatesBuffer.Clear(); + m_duplicatesBuffer = null; + + if( m_functionGraph != null && ContainerGraph.ParentWindow.CurrentGraph != m_functionGraph ) + ContainerGraph.ParentWindow.CurrentGraph.InstancePropertyCount -= m_functionGraph.InstancePropertyCount; + + if( ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface != null ) + { + //for( int i = 0; i < m_includes.Count; i++ ) + //{ + // //if( ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalIncludes.OutsideList.Contains( m_includes[ i ] ) ) + // //{ + // // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalIncludes.OutsideList.Remove( m_includes[ i ] ); + // //} + // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.RemoveShaderFunctionItem( AdditionalLineType.Include, m_includes[ i ] ); + //} + + //for( int i = 0; i < m_pragmas.Count; i++ ) + //{ + // //if( ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalPragmas.OutsideList.Contains( m_pragmas[ i ] ) ) + // //{ + // // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalPragmas.OutsideList.Remove( m_pragmas[ i ] ); + // //} + // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.RemoveShaderFunctionItem( AdditionalLineType.Pragma, m_pragmas[ i ] ); + //} + ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.RemoveShaderFunctionItems( OutputId/*, m_directives */); + } + else + { + if( ContainerGraph.ParentWindow.OutsideGraph.MultiPassMasterNodes.Count > 0 ) + { + for( int lod = -1; lod < ContainerGraph.ParentWindow.OutsideGraph.LodMultiPassMasternodes.Count; lod++ ) + { + RemoveShaderFunctionDirectivesInternal( lod ); + } + } + } + + + + + // Cannot GameObject.Destroy(m_directives[i]) since we would be removing them from + // the shader function asset itself + + m_directives.Clear(); + m_directives = null; + + if( m_reordenator != null ) + { + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = null; + UIUtils.UnregisterPropertyNode( m_reordenator ); + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + m_reordenator.Destroy(); + m_reordenator = null; + } + + UIUtils.UnregisterFunctionNode( this ); + + ParentGraph cachedGraph2 = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + + if( m_allFunctionInputs != null ) + m_allFunctionInputs.Clear(); + m_allFunctionInputs = null; + + if( m_allFunctionOutputs != null ) + m_allFunctionOutputs.Clear(); + m_allFunctionOutputs = null; + + if( m_functionGraph != null ) + m_functionGraph.SoftDestroy(); + m_functionGraph = null; + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph2; + m_function = null; + + m_allFunctionOutputsDict.Clear(); + m_allFunctionOutputsDict = null; + + m_allFunctionSwitchesDict.Clear(); + m_allFunctionSwitchesDict = null; + + m_allFunctionInputsDict.Clear(); + m_allFunctionInputsDict = null; + + UIUtils.CurrentWindow.OutsideGraph.OnLODMasterNodesAddedEvent -= OnLODMasterNodesAddedEvent; + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + if( m_lateRefresh ) + { + m_lateRefresh = false; + RefreshExternalReferences(); + } + + CheckForChangesRecursively(); + + base.OnNodeLogicUpdate( drawInfo ); + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + + if( m_functionGraph != null ) + { + int nodeCount = m_functionGraph.AllNodes.Count; + for( int i = 0; i < nodeCount; i++ ) + { + m_functionGraph.AllNodes[ i ].OnNodeLogicUpdate( drawInfo ); + } + + //if( !string.IsNullOrEmpty( FunctionGraph.CurrentFunctionOutput.SubTitle ) ) + { + SetAdditonalTitleText( FunctionGraph.CurrentFunctionOutput.SubTitle ); + } + } + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + if( m_portsChanged ) + { + m_portsChanged = false; + for( int i = 0; i < m_allFunctionOutputs.Count; i++ ) + { + m_outputPorts[ i ].ChangeType( m_allFunctionOutputs[ i ].InputPorts[ 0 ].DataType, false ); + } + + CheckPortVisibility(); + } + } + + public override void Draw( DrawInfo drawInfo ) + { + //CheckForChangesRecursively(); + + if( !m_initialGraphDraw && drawInfo.CurrentEventType == EventType.Repaint ) + { + m_initialGraphDraw = true; + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + if( m_functionGraph != null ) + { + for( int i = 0; i < m_functionGraph.AllNodes.Count; i++ ) + { + ParentNode node = m_functionGraph.AllNodes[ i ]; + if( node != null ) + { + node.OnNodeLayout( drawInfo ); + } + } + } + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + } + + base.Draw( drawInfo ); + } + + public bool CheckForChanges( bool forceCheck = false, bool forceChange = false ) + { + if( ( ContainerGraph.ParentWindow.CheckFunctions || forceCheck || forceChange ) && m_function != null ) + { + //string newCheckSum = LastLine( m_function.FunctionInfo ); + string newCheckSum = AssetDatabase.GetAssetDependencyHash( AssetDatabase.GetAssetPath( m_function ) ).ToString(); + if( !m_functionCheckSum.Equals( newCheckSum ) || forceChange ) + { + m_functionCheckSum = newCheckSum; + ContainerGraph.OnDuplicateEvent += DuplicateMe; + return true; + } + } + return false; + } + + public bool CheckForChangesRecursively() + { + if( m_functionGraph == null ) + return false; + + bool result = false; + for( int i = 0; i < m_functionGraph.FunctionNodes.NodesList.Count; i++ ) + { + if( m_functionGraph.FunctionNodes.NodesList[ i ].CheckForChangesRecursively() ) + result = true; + } + if( CheckForChanges( false, result ) ) + result = true; + + return result; + } + + public void DuplicateMe() + { + bool previewOpen = m_showPreview; + + string allOptions = m_allFunctionSwitches.Count.ToString(); + for( int i = 0; i < m_allFunctionSwitches.Count; i++ ) + { + allOptions += "," + m_allFunctionSwitches[ i ].UniqueId + "," + m_allFunctionSwitches[ i ].GetCurrentSelectedInput(); + } + + ReadOptionsHelper = allOptions.Split( ',' ); + + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = null; + MasterNode masterNode = ContainerGraph.ParentWindow.CurrentGraph.CurrentMasterNode; + if( masterNode != null ) + masterNode.InvalidateMaterialPropertyCount(); + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + ParentNode newNode = ContainerGraph.CreateNode( m_function, false, Vec2Position ); + newNode.ShowPreview = previewOpen; + ( newNode as FunctionNode ).ReadOptionsHelper = ReadOptionsHelper; + newNode.RefreshExternalReferences(); + if( ( newNode as FunctionNode ).m_reordenator && m_reordenator ) + ( newNode as FunctionNode ).m_reordenator.OrderIndex = m_reordenator.OrderIndex; + + for( int i = 0; i < m_outputPorts.Count; i++ ) + { + if( m_outputPorts[ i ].IsConnected ) + { + OutputPort newOutputPort = newNode.GetOutputPortByUniqueId( m_outputPorts[ i ].PortId ); + if( newNode.OutputPorts != null && newOutputPort != null ) + { + for( int j = m_outputPorts[ i ].ExternalReferences.Count - 1; j >= 0; j-- ) + { + ContainerGraph.CreateConnection( m_outputPorts[ i ].ExternalReferences[ j ].NodeId, m_outputPorts[ i ].ExternalReferences[ j ].PortId, newOutputPort.NodeId, newOutputPort.PortId ); + } + } + } + //else + //{ + //if( newNode.OutputPorts != null && newNode.OutputPorts[ i ] != null ) + //{ + // ContainerGraph.DeleteConnection( false, newNode.UniqueId, newNode.OutputPorts[ i ].PortId, false, false, false ); + //} + //} + } + + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + InputPort newInputPort = newNode.GetInputPortByUniqueId( m_inputPorts[ i ].PortId ); + if( newNode.InputPorts != null && newInputPort != null ) + { + ContainerGraph.CreateConnection( newInputPort.NodeId, newInputPort.PortId, m_inputPorts[ i ].ExternalReferences[ 0 ].NodeId, m_inputPorts[ i ].ExternalReferences[ 0 ].PortId ); + } + } + } + + ContainerGraph.OnDuplicateEvent -= DuplicateMe; + + if( Selected ) + { + ContainerGraph.DeselectNode( this ); + ContainerGraph.SelectNode( newNode, true, false ); + } + + ContainerGraph.DestroyNode( this, false ); + } + + private FunctionOutput GetFunctionOutputByUniqueId( int uniqueId ) + { + int listCount = m_allFunctionOutputs.Count; + if( m_allFunctionOutputsDict.Count != m_allFunctionOutputs.Count ) + { + m_allFunctionOutputsDict.Clear(); + for( int i = 0; i < listCount; i++ ) + { + m_allFunctionOutputsDict.Add( m_allFunctionOutputs[ i ].UniqueId, m_allFunctionOutputs[ i ] ); + } + } + + if( m_allFunctionOutputsDict.ContainsKey( uniqueId ) ) + return m_allFunctionOutputsDict[ uniqueId ]; + + return null; + } + + private FunctionInput GetFunctionInputByUniqueId( int uniqueId ) + { + int listCount = m_allFunctionInputs.Count; + if( m_allFunctionInputsDict.Count != m_allFunctionInputs.Count ) + { + m_allFunctionInputsDict.Clear(); + for( int i = 0; i < listCount; i++ ) + { + m_allFunctionInputsDict.Add( m_allFunctionInputs[ i ].UniqueId, m_allFunctionInputs[ i ] ); + } + } + + if( m_allFunctionInputsDict.ContainsKey( uniqueId ) ) + return m_allFunctionInputsDict[ uniqueId ]; + + return null; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + OutputPort outputPort = GetOutputPortByUniqueId( outputId ); + FunctionOutput functionOutput = GetFunctionOutputByUniqueId( outputId ); + + if( outputPort.IsLocalValue( dataCollector.PortCategory ) ) + return outputPort.LocalValue( dataCollector.PortCategory ); + + m_functionGraph.CurrentPrecision = ContainerGraph.ParentWindow.CurrentGraph.CurrentPrecision; + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + m_outsideGraph = cachedGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; +#if ADD_SHADER_FUNCTION_HEADERS + if( m_reordenator != null && m_reordenator.RecursiveCount() > 0 && m_reordenator.HasTitle ) + { + dataCollector.AddToProperties( UniqueId, "[Header(" + m_reordenator.HeaderTitle.Replace( "-", " " ) + ")]", m_reordenator.OrderIndex ); + } +#endif + string result = string.Empty; + for( int i = 0; i < m_allFunctionInputs.Count; i++ ) + { + if( !m_allFunctionInputs[ i ].InputPorts[ 0 ].IsConnected || m_inputPorts[ i ].IsConnected ) + m_allFunctionInputs[ i ].OnPortGeneration += FunctionNodeOnPortGeneration; + } + + result += functionOutput.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + + for( int i = 0; i < m_allFunctionInputs.Count; i++ ) + { + if( !m_allFunctionInputs[ i ].InputPorts[ 0 ].IsConnected || m_inputPorts[ i ].IsConnected ) + m_allFunctionInputs[ i ].OnPortGeneration -= FunctionNodeOnPortGeneration; + } + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + if( outputPort.ConnectionCount > 1 ) + RegisterLocalVariable( outputId, result, ref dataCollector ); + else + outputPort.SetLocalValue( result, dataCollector.PortCategory ); + + return outputPort.LocalValue( dataCollector.PortCategory ); + } + + private string FunctionNodeOnPortGeneration( ref MasterNodeDataCollector dataCollector, int index, ParentGraph graph ) + { + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_outsideGraph; + string result = m_inputPorts[ index ].GeneratePortInstructions( ref dataCollector ); + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + return result; + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + + if( Function != null ) + IOUtils.AddFieldValueToString( ref nodeInfo, m_function.name ); + else + IOUtils.AddFieldValueToString( ref nodeInfo, m_filename ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_reordenator != null ? m_reordenator.RawOrderIndex : -1 ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_headerTitle ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_functionGraphId ); + IOUtils.AddFieldValueToString( ref nodeInfo, AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_function ) ) ); + + int functionSwitchCount = m_allFunctionSwitches != null ? m_allFunctionSwitches.Count : 0; + string allOptions = functionSwitchCount.ToString(); + for( int i = 0; i < functionSwitchCount; i++ ) + { + allOptions += "," + m_allFunctionSwitches[ i ].UniqueId + "," + m_allFunctionSwitches[ i ].GetCurrentSelectedInput(); + } + IOUtils.AddFieldValueToString( ref nodeInfo, allOptions ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_filename = GetCurrentParam( ref nodeParams ); + m_orderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_headerTitle = GetCurrentParam( ref nodeParams ); + + if( UIUtils.CurrentShaderVersion() > 7203 ) + { + m_functionGraphId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 13704 ) + { + m_functionGUID = GetCurrentParam( ref nodeParams ); + } + + AmplifyShaderFunction loaded = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( m_functionGUID ) ); + if( loaded != null ) + { + CommonInit( loaded, UniqueId ); + } + else + { + string[] guids = AssetDatabase.FindAssets( "t:AmplifyShaderFunction " + m_filename ); + if( guids.Length > 0 ) + { + string sfGuid = null; + + foreach( string guid in guids ) + { + string assetPath = AssetDatabase.GUIDToAssetPath( guid ); + string name = System.IO.Path.GetFileNameWithoutExtension( assetPath ); + if( name.Equals( m_filename, StringComparison.OrdinalIgnoreCase ) ) + { + sfGuid = guid; + break; + } + } + loaded = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( sfGuid ) ); + + if( loaded != null ) + { + CommonInit( loaded, UniqueId ); + } + else + { + SetTitleText( "ERROR" ); + UIUtils.ShowMessage( UniqueId, string.Format( "Error loading {0} shader function from project folder", m_filename ), MessageSeverity.Error ); + } + } + else + { + SetTitleText( "Missing Function" ); + UIUtils.ShowMessage( UniqueId, string.Format( "Missing {0} shader function on project folder", m_filename ), MessageSeverity.Error ); + } + } + if( UIUtils.CurrentShaderVersion() > 14203 ) + { + ReadOptionsHelper = GetCurrentParam( ref nodeParams ).Split( ',' ); + } + } + + public override void ReadOutputDataFromString( ref string[] nodeParams ) + { + if( Function == null ) + return; + + base.ReadOutputDataFromString( ref nodeParams ); + + ConfigureInputportsAfterRead(); + } + + public override void OnNodeDoubleClicked( Vector2 currentMousePos2D ) + { + if( Function == null ) + return; + + ContainerGraph.DeSelectAll(); + this.Selected = true; + + ContainerGraph.ParentWindow.OnLeftMouseUp(); + AmplifyShaderEditorWindow.LoadShaderFunctionToASE( Function, true ); + this.Selected = false; + } + + private void ConfigureInputportsAfterRead() + { + if( InputPorts != null ) + { + int inputCount = InputPorts.Count; + for( int i = 0; i < inputCount; i++ ) + { + InputPorts[ i ].ChangeProperties( m_allFunctionInputs[ i ].InputName, m_allFunctionInputs[ i ].SelectedInputType, false ); + } + } + + if( OutputPorts != null ) + { + int outputCount = OutputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + OutputPorts[ i ].ChangeProperties( m_allFunctionOutputs[ i ].OutputName, m_allFunctionOutputs[ i ].AutoOutputType, false ); + } + } + } + + private void CheckPortVisibility() + { + bool changes = false; + if( InputPorts != null ) + { + for( int i = 0; i < m_allFunctionInputs.Count; i++ ) + { + if( m_inputPorts[ i ].Visible != m_allFunctionInputs[ i ].IsConnected ) + { + m_inputPorts[ i ].Visible = m_allFunctionInputs[ i ].IsConnected; + changes = true; + } + } + } + + if( changes ) + m_sizeIsDirty = true; + } + + public bool HasProperties { get { return m_reordenator != null; } } + + public ParentGraph FunctionGraph + { + get { return m_functionGraph; } + set { m_functionGraph = value; } + } + + public AmplifyShaderFunction Function + { + get { return m_function; } + set { m_function = value; } + } + + public override void RecordObjectOnDestroy( string Id ) + { + base.RecordObjectOnDestroy( Id ); + if( m_reordenator != null ) + m_reordenator.RecordObject( Id ); + + if( m_functionGraph != null ) + { + Undo.RegisterCompleteObjectUndo( m_functionGraph, Id ); + for( int i = 0; i < m_functionGraph.AllNodes.Count; i++ ) + { + m_functionGraph.AllNodes[ i ].RecordObject( Id ); + } + } + } + + public override void SetContainerGraph( ParentGraph newgraph ) + { + base.SetContainerGraph( newgraph ); + if( m_functionGraph == null ) + return; + for( int i = 0; i < m_functionGraph.AllNodes.Count; i++ ) + { + m_functionGraph.AllNodes[ i ].SetContainerGraph( m_functionGraph ); + } + } + + public override void OnMasterNodeReplaced( MasterNode newMasterNode ) + { + base.OnMasterNodeReplaced( newMasterNode ); + if( m_functionGraph == null ) + return; + + m_functionGraph.FireMasterNodeReplacedEvent( newMasterNode ); + + StandardSurfaceOutputNode surface = newMasterNode as StandardSurfaceOutputNode; + if( surface != null ) + { + surface.AdditionalDirectives.AddShaderFunctionItems( OutputId, Function.AdditionalDirectives.DirectivesList ); + } + else + { + if( ContainerGraph.ParentWindow.OutsideGraph.MultiPassMasterNodes.Count > 0 ) + { + for( int lod = -1; lod < ContainerGraph.ParentWindow.OutsideGraph.LodMultiPassMasternodes.Count; lod++ ) + { + AddShaderFunctionDirectivesInternal( lod ); + } + } + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs.meta new file mode 100644 index 0000000..15ea8d3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7b3de46feda5b0f4ea58c852c4a521a9 +timeCreated: 1492001141 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionOutput.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionOutput.cs new file mode 100644 index 0000000..baa4963 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionOutput.cs @@ -0,0 +1,318 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Function Output", "Functions", "Function Output adds an output port to the shader function, it's port type is determined automatically.", NodeAvailabilityFlags = (int)NodeAvailability.ShaderFunction )] + public sealed class FunctionOutput : OutputNode + { + public FunctionOutput() : base() { CommonInit(); } + public FunctionOutput( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { CommonInit(); } + + [SerializeField] + private bool m_previewNode = false; + + [SerializeField] + private string m_outputName = "Output"; + + [SerializeField] + private int m_orderIndex = -1; + + [SerializeField] + private AmplifyShaderFunction m_function; + + //Title editing + [SerializeField] + private string m_uniqueName; + + private bool m_isEditing; + private bool m_stopEditing; + private bool m_startEditing; + private double m_clickTime; + private double m_doubleClickTime = 0.3; + private Rect m_titleClickArea; + private bool m_showTitleWhenNotEditing = true; + + [SerializeField] + private string m_subTitle = string.Empty; + + + void CommonInit() + { + m_isMainOutputNode = false; + m_connStatus = NodeConnectionStatus.Connected; + m_activeType = GetType(); + m_currentPrecisionType = PrecisionType.Inherit; + m_textLabelWidth = 100; + m_autoWrapProperties = true; + AddInputPort( WirePortDataType.FLOAT, false, " " ); + AddOutputPort( WirePortDataType.FLOAT, " " ); + m_outputPorts[ 0 ].Visible = false; + SetTitleText( m_outputName ); + m_previewShaderGUID = "e6d5f64114b18e24f99dc65290c0fe98"; + } + + public override void SetupNodeCategories() + { + //base.SetupNodeCategories(); + ContainerGraph.ResetNodesData(); + MasterNode masterNode = ContainerGraph.ParentWindow.CurrentGraph.CurrentMasterNode; + if( masterNode != null ) + { + int count = m_inputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + NodeData nodeData = new NodeData( m_inputPorts[ i ].Category ); + ParentNode node = m_inputPorts[ i ].GetOutputNode(); + MasterNodeDataCollector temp = masterNode.CurrentDataCollector; + node.PropagateNodeData( nodeData, ref temp ); + temp = null; + } + } + } + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + UIUtils.RegisterFunctionOutputNode( this ); + if( m_nodeAttribs != null ) + m_uniqueName = m_nodeAttribs.Name + UniqueId; + } + + + public override void Destroy() + { + base.Destroy(); + UIUtils.UnregisterFunctionOutputNode( this ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + return m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_outputName = EditorGUILayoutTextField( "Name", m_outputName ); + + if( EditorGUI.EndChangeCheck() ) + { + SetTitleText( m_outputName ); + UIUtils.UpdateFunctionOutputData( UniqueId, m_outputName ); + } + + EditorGUI.BeginDisabledGroup( m_previewNode ); + if( GUILayout.Button( "Set as Preview" ) ) + { + List allOutputs = UIUtils.FunctionOutputList(); + + foreach( FunctionOutput item in allOutputs ) + item.PreviewNode = false; + + m_previewNode = true; + } + EditorGUI.EndDisabledGroup(); + } + [SerializeField] + private string m_currentTitle = string.Empty; + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( m_previewNode ) + m_currentTitle = "Preview"; + else + m_currentTitle = string.Empty; + + SetAdditonalTitleTextOnCallback( m_currentTitle, ( instance, newSubTitle ) => instance.AdditonalTitleContent.text = newSubTitle ); + + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + if( !m_isEditing && ( ( !ContainerGraph.ParentWindow.MouseInteracted && drawInfo.CurrentEventType == EventType.MouseDown && m_titleClickArea.Contains( drawInfo.MousePosition ) ) ) ) + { + if( ( EditorApplication.timeSinceStartup - m_clickTime ) < m_doubleClickTime ) + m_startEditing = true; + else + GUI.FocusControl( null ); + m_clickTime = EditorApplication.timeSinceStartup; + } + else if( m_isEditing && ( ( drawInfo.CurrentEventType == EventType.MouseDown && !m_titleClickArea.Contains( drawInfo.MousePosition ) ) || !EditorGUIUtility.editingTextField ) ) + { + m_stopEditing = true; + } + + if( m_isEditing || m_startEditing ) + { + EditorGUI.BeginChangeCheck(); + GUI.SetNextControlName( m_uniqueName ); + m_outputName = EditorGUITextField( m_titleClickArea, string.Empty, m_outputName, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + if( EditorGUI.EndChangeCheck() ) + { + SetTitleText( m_outputName ); + UIUtils.UpdateFunctionInputData( UniqueId, m_outputName ); + } + + if( m_startEditing ) + EditorGUI.FocusTextInControl( m_uniqueName ); + + } + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + if( m_startEditing ) + { + m_startEditing = false; + m_isEditing = true; + } + + if( m_stopEditing ) + { + m_stopEditing = false; + m_isEditing = false; + GUI.FocusControl( null ); + } + } + } + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + // RUN LAYOUT CHANGES AFTER TITLES CHANGE + base.OnNodeLayout( drawInfo ); + m_titleClickArea = m_titlePos; + m_titleClickArea.height = Constants.NODE_HEADER_HEIGHT; + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + + if( !m_isVisible ) + return; + + // Fixed Title ( only renders when not editing ) + if( m_showTitleWhenNotEditing && !m_isEditing && !m_startEditing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + GUI.Label( m_titleClickArea, m_content, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + } + } + + public override void OnNodeDoubleClicked( Vector2 currentMousePos2D ) + { + if( currentMousePos2D.y - m_globalPosition.y > ( Constants.NODE_HEADER_HEIGHT + Constants.NODE_HEADER_EXTRA_HEIGHT ) * ContainerGraph.ParentWindow.CameraDrawInfo.InvertedZoom ) + { + ContainerGraph.ParentWindow.ParametersWindow.IsMaximized = !ContainerGraph.ParentWindow.ParametersWindow.IsMaximized; + } + } + + public WirePortDataType AutoOutputType + { + get { return m_inputPorts[ 0 ].DataType; } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_outputName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_orderIndex ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_previewNode ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_outputName = GetCurrentParam( ref nodeParams ); + m_orderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + + if( UIUtils.CurrentShaderVersion() > 13706 ) + m_previewNode = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + + if( IsNodeBeingCopied ) + PreviewNode = false; + + if( m_function == null ) + m_function = UIUtils.CurrentWindow.OpenedShaderFunction; + + if( m_isMainOutputNode && m_function != null ) + { + m_function.UpdateDirectivesList(); + } + + SetTitleText( m_outputName ); + UIUtils.UpdateFunctionOutputData( UniqueId, m_outputName ); + } + + public AmplifyShaderFunction Function + { + get { return m_function; } + set + { + m_function = value; + if( m_isMainOutputNode && m_function != null ) + { + m_function.UpdateDirectivesList(); + } + } + } + + public string OutputName + { + get { return m_outputName; } + } + + public int OrderIndex + { + get { return m_orderIndex; } + set { m_orderIndex = value; } + } + + public string SubTitle + { + get { return m_subTitle; } + set { m_subTitle = value; } + } + + public bool PreviewNode + { + get { return m_previewNode; } + set + { + m_previewNode = value; + m_sizeIsDirty = true; + if( m_previewNode ) + { + m_currentTitle = "Preview"; + } + else + { + m_currentTitle = ""; + } + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionOutput.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionOutput.cs.meta new file mode 100644 index 0000000..7ece512 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionOutput.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6293b1f56d13d6c4ca6a8e2a8099cca9 +timeCreated: 1491917775 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSubtitle.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSubtitle.cs new file mode 100644 index 0000000..b912446 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSubtitle.cs @@ -0,0 +1,124 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Function Subtitle", "Functions", "Adds a subtitle to its shader function", NodeAvailabilityFlags = (int)NodeAvailability.ShaderFunction )] + public sealed class FunctionSubtitle : ParentNode + { + + //protected override void CommonInit( int uniqueId ) + //{ + // base.CommonInit( uniqueId ); + // AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + // AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + // m_autoWrapProperties = true; + // m_textLabelWidth = 100; + // //SetTitleText( m_inputName ); + // //SetAdditonalTitleText( "( " + m_inputValueTypes[ m_selectedInputTypeInt ] + " )" ); + // m_previewShaderGUID = "04bc8e7b317dccb4d8da601680dd8140"; + //} + [SerializeField] + private string m_subtitle = "Subtitle"; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_autoWrapProperties = true; + m_textLabelWidth = 100; + SetTitleText( m_subtitle ); + m_previewShaderGUID = "74e4d859fbdb2c0468de3612145f4929"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + return m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, m_inputPorts[ 0 ].DataType, ignoreLocalvar ); + } + + //public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + //{ + // base.PropagateNodeData( nodeData, ref dataCollector ); + + // //if( m_containerGraph.CurrentShaderFunction != null ) + // //m_containerGraph.CurrentShaderFunction.FunctionSubtitle = m_subttile; + //} + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + //public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + //{ + // base.PropagateNodeData( nodeData, ref dataCollector ); + //Debug.Log( IsConnected + " " + m_containerGraph.CurrentFunctionOutput ); + if( m_containerGraph.CurrentFunctionOutput != null && IsConnected ) + m_containerGraph.CurrentFunctionOutput.SubTitle = m_subtitle; + // m_containerGraph.CurrentShaderFunction.FunctionSubtitle = m_subttile; + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUILayout.BeginVertical(); + EditorGUI.BeginChangeCheck(); + m_subtitle = EditorGUILayoutTextField( "Name", m_subtitle ); + if( EditorGUI.EndChangeCheck() ) + { + SetTitleText( m_subtitle ); + //UIUtils.UpdateFunctionInputData( UniqueId, m_inputName ); + } + EditorGUI.BeginChangeCheck(); + //m_selectedInputTypeInt = EditorGUILayoutPopup( InputTypeStr, m_selectedInputTypeInt, m_inputValueTypes ); + //if( EditorGUI.EndChangeCheck() ) + //{ + // UpdatePorts(); + // SetAdditonalTitleText( "( " + m_inputValueTypes[ m_selectedInputTypeInt ] + " )" ); + //} + + //m_autoCast = EditorGUILayoutToggle( "Auto Cast", m_autoCast ); + + //EditorGUILayout.Separator(); + //if( !m_inputPorts[ 0 ].IsConnected && m_inputPorts[ 0 ].ValidInternalData ) + //{ + // m_inputPorts[ 0 ].ShowInternalData( this, true, "Default Value" ); + //} + + + EditorGUILayout.EndVertical(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_subtitle ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_subtitle = GetCurrentParam( ref nodeParams ); + SetTitleText( m_subtitle ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSubtitle.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSubtitle.cs.meta new file mode 100644 index 0000000..bd87bd9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSubtitle.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 97d5e0cd26200a64fa9d127599406008 +timeCreated: 1522434121 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitch.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitch.cs new file mode 100644 index 0000000..d10be2d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitch.cs @@ -0,0 +1,885 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Function Switch", "Functions", "Function Switch allows switching options at compile time for shader function", NodeAvailabilityFlags = (int)NodeAvailability.ShaderFunction )] + public sealed class FunctionSwitch : ParentNode + { + private const string InputPortNameStr = "In "; + + private const string ToggleFalseStr = "False"; + private const string ToggleTrueStr = "True"; + + private const string CurrSelectedStr = "Current"; + private const string MaxAmountStr = "Amount"; + private const int MaxAllowedAmount = 9; + + private const int MinComboSize = 50; + private const int MaxComboSize = 105; + + [SerializeField] + private string m_optionLabel = "Option"; + + [SerializeField] + private string[] AvailableInputsLabels = { "In 0", "In 1" }; + + [SerializeField] + private int[] AvailableInputsValues = { 0, 1 }; + + [SerializeField] + private int m_previousSelectedInput = 0; + + [SerializeField] + private int m_currentSelectedInput = 0; + + [SerializeField] + private int m_maxAmountInputs = 2; + + [SerializeField] + private bool m_toggleMode = false; + + [SerializeField] + private string[] m_optionNames = { "In 0", "In 1", "In 2", "In 3", "In 4", "In 5", "In 6", "In 7", "In 8" }; + + [SerializeField] + private int m_orderIndex = -1; + + [SerializeField] + private TexReferenceType m_referenceType = TexReferenceType.Object; + + [SerializeField] + private FunctionSwitch m_functionSwitchReference = null; + + [SerializeField] + private int m_referenceUniqueId = -1; + + [SerializeField] + private bool m_validReference = false; + + private bool m_asDrawn = false; + + private GUIContent m_checkContent; + private GUIContent m_popContent; + + private const double MaxTimestamp = 1; + private bool m_nameModified = false; + private double m_lastTimeNameModified = 0; + + private Rect m_varRect; + private Rect m_imgRect; + private bool m_editing; + + private int m_cachedPropertyId = -1; + + private bool m_dirtySettings = false; + + [SerializeField] + private int m_refMaxInputs = -1; + + [SerializeField] + private string m_refOptionLabel = string.Empty; + + [SerializeField] + private int m_refSelectedInput = -1; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + for( int i = 0; i < MaxAllowedAmount; i++ ) + { + AddInputPort( WirePortDataType.FLOAT, false, InputPortNameStr + i ); + m_inputPorts[ i ].Visible = ( i < 2 ); + } + AddOutputPort( WirePortDataType.FLOAT, " " ); + + m_checkContent = new GUIContent(); + m_checkContent.image = UIUtils.CheckmarkIcon; + + m_popContent = new GUIContent(); + m_popContent.image = UIUtils.PopupIcon; + + m_textLabelWidth = 100; + m_autoWrapProperties = true; + m_insideSize.Set( 80, 25 ); + m_previewShaderGUID = "a58e46feaa5e3d14383bfeac24d008bc"; + } + + public void SetCurrentSelectedInput( int newValue, int prevValue ) + { + m_previousSelectedInput = prevValue; + if( m_validReference ) + m_currentSelectedInput = Mathf.Clamp( newValue, 0, m_refMaxInputs - 1 ); + else + m_currentSelectedInput = Mathf.Clamp( newValue, 0, m_maxAmountInputs - 1 ); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ m_currentSelectedInput ].DataType, false ); + PreviewIsDirty = true; + ChangeSignalPropagation(); + } + + public int GetCurrentSelectedInput() + { + return m_currentSelectedInput; + } + + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_Current" ); + + PreviewMaterial.SetInt( m_cachedPropertyId, m_currentSelectedInput ); + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + if( m_referenceType == TexReferenceType.Object ) + { + UIUtils.RegisterFunctionSwitchNode( this ); + } + else + { + if( ContainerGraph.ParentWindow.CustomGraph != null ) + UIUtils.RegisterFunctionSwitchNode( this ); + UIUtils.RegisterFunctionSwitchCopyNode( this ); + } + } + + public override void Destroy() + { + base.Destroy(); + + m_functionSwitchReference = null; + m_referenceUniqueId = -1; + + if( m_referenceType == TexReferenceType.Object ) + { + UIUtils.UnregisterFunctionSwitchNode( this ); + } + else + { + UIUtils.UnregisterFunctionSwitchNode( this ); + UIUtils.UnregisterFunctionSwitchCopyNode( this ); + } + } + + public override void OnConnectedOutputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( portId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ portId ].MatchPortToConnection(); + if( portId == m_currentSelectedInput ) + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ portId ].DataType, false ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + InputPort port = GetInputPortByUniqueId( portId ); + int arrayPos = m_inputPorts.IndexOf( port ); + if( activateNode && m_connStatus == NodeConnectionStatus.Connected && arrayPos == m_currentSelectedInput ) + { + port.GetOutputNode().ActivateNode( m_activeNode, m_activePort, m_activeType ); + } + + OnNodeChange(); + SetSaveIsDirty(); + + m_inputPorts[ portId ].MatchPortToConnection(); + if( arrayPos == m_currentSelectedInput ) + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ portId ].DataType, false ); + } + + public override void ActivateNode( int signalGenNodeId, int signalGenPortId, Type signalGenNodeType ) + { + if( m_selfPowered ) + return; + + ConnStatus = m_restrictions.GetRestiction( signalGenNodeType, signalGenPortId ) ? NodeConnectionStatus.Error : NodeConnectionStatus.Connected; + m_activeConnections += 1; + + m_activeType = signalGenNodeType; + m_activeNode = signalGenNodeId; + m_activePort = signalGenPortId; + if( m_activeConnections == 1 ) + if( m_inputPorts[ m_currentSelectedInput ].IsConnected ) + m_inputPorts[ m_currentSelectedInput ].GetOutputNode().ActivateNode( signalGenNodeId, signalGenPortId, signalGenNodeType ); + + SetSaveIsDirty(); + } + + public override void DeactivateInputPortNode( int deactivatedPort, bool forceComplete ) + { + InputPort port = GetInputPortByUniqueId( deactivatedPort ); + if( deactivatedPort == m_currentSelectedInput ) + port.GetOutputNode().DeactivateNode( deactivatedPort, false ); + } + + public override void DeactivateNode( int deactivatedPort, bool forceComplete ) + { + if( m_selfPowered ) + return; + + SetSaveIsDirty(); + m_activeConnections -= 1; + + if( ( forceComplete || m_activeConnections <= 0 ) ) + { + m_activeConnections = 0; + ConnStatus = NodeConnectionStatus.Not_Connected; + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].IsConnected && i == m_currentSelectedInput ) + { + ParentNode node = m_inputPorts[ i ].GetOutputNode(); + if( node != null ) + node.DeactivateNode( deactivatedPort == -1 ? m_inputPorts[ i ].PortId : deactivatedPort, false ); + } + } + } + } + + public void ChangeSignalPropagation() + { + if( m_previousSelectedInput != m_currentSelectedInput && ConnStatus == NodeConnectionStatus.Connected ) + { + if( m_inputPorts[ m_previousSelectedInput ].IsConnected ) + m_inputPorts[ m_previousSelectedInput ].GetOutputNode().DeactivateNode( m_inputPorts[ m_previousSelectedInput ].PortId, false ); + + if( m_inputPorts[ m_currentSelectedInput ].IsConnected ) + m_inputPorts[ m_currentSelectedInput ].GetOutputNode().ActivateNode( UniqueId, m_inputPorts[ m_currentSelectedInput ].PortId, m_activeType ); + } + } + + public bool DrawOption( ParentNode owner, bool forceDraw = false ) + { + if( !IsConnected && !forceDraw ) + { + //EditorGUILayout.LabelField( "Not Connected" ); + return false; + } + + if( m_asDrawn ) //used to prevent the same property to be drawn more than once + return false; + + if( m_validReference ) + { + return m_functionSwitchReference.DrawOption( owner, true ); + } + + int prev = m_currentSelectedInput; + m_asDrawn = true; + if( m_toggleMode ) + { + m_currentSelectedInput = owner.EditorGUILayoutToggle( m_optionLabel, ( m_currentSelectedInput != 0 ? true : false ) ) ? 1 : 0; + + if( m_currentSelectedInput != prev ) + { + SetCurrentSelectedInput( m_currentSelectedInput, prev ); + return true; + } + else + { + return false; + } + } + else + { + m_currentSelectedInput = owner.EditorGUILayoutIntPopup( m_optionLabel, m_currentSelectedInput, AvailableInputsLabels, AvailableInputsValues ); + + if( m_currentSelectedInput != prev ) + { + SetCurrentSelectedInput( m_currentSelectedInput, prev ); + return true; + } + else + { + return false; + } + } + } + + public void CheckReference() + { + if( m_referenceType != TexReferenceType.Instance ) + { + m_validReference = false; + return; + } + + if( m_functionSwitchReference == null ) + { + m_validReference = false; + ResetToSelf(); + return; + } + + if( m_referenceUniqueId != m_functionSwitchReference.UniqueId ) + { + UpdateFromSelected(); + } + if( m_refSelectedInput != m_functionSwitchReference.GetCurrentSelectedInput() || m_refMaxInputs != m_functionSwitchReference.MaxAmountInputs || m_refOptionLabel != m_functionSwitchReference.OptionLabel ) + { + UpdateFromSelected(); + } + + if( m_functionSwitchReference.DirtySettings ) + { + UpdateFromSelected(); + } + + m_validReference = true; + } + + void ResetToSelf() + { + m_functionSwitchReference = null; + m_validReference = false; + m_referenceUniqueId = -1; + m_refMaxInputs = -1; + m_refOptionLabel = string.Empty; + m_refSelectedInput = -1; + + for( int i = 0; i < MaxAllowedAmount; i++ ) + { + m_inputPorts[ i ].Visible = ( i < m_maxAmountInputs ); + m_inputPorts[ i ].Name = m_optionNames[ i ]; + } + + if( m_currentSelectedInput >= m_maxAmountInputs ) + { + m_currentSelectedInput = m_maxAmountInputs - 1; + } + + UpdateLabels(); + m_sizeIsDirty = true; + } + + void UpdateFromSelected() + { + if( m_referenceUniqueId < 0 ) + return; + + m_functionSwitchReference = UIUtils.GetNode( m_referenceUniqueId ) as FunctionSwitch; + if( m_functionSwitchReference != null ) + { + m_validReference = true; + for( int i = 0; i < MaxAllowedAmount; i++ ) + { + m_inputPorts[ i ].Visible = ( i < m_functionSwitchReference.MaxAmountInputs ); + m_inputPorts[ i ].Name = m_functionSwitchReference.InputPorts[ i ].Name; + } + UpdateLabels(); + m_refMaxInputs = m_functionSwitchReference.m_maxAmountInputs; + m_refOptionLabel = m_functionSwitchReference.OptionLabel; + m_refSelectedInput = m_functionSwitchReference.GetCurrentSelectedInput(); + OrderIndex = m_functionSwitchReference.OrderIndex; + + SetCurrentSelectedInput( m_functionSwitchReference.GetCurrentSelectedInput(), m_currentSelectedInput ); + } + + m_sizeIsDirty = true; + m_isDirty = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + { + EditorGUI.BeginChangeCheck(); + m_referenceType = (TexReferenceType)EditorGUILayoutPopup( Constants.ReferenceTypeStr, (int)m_referenceType, Constants.ReferenceArrayLabels ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_referenceType == TexReferenceType.Object ) + { + if( ContainerGraph.ParentWindow.CustomGraph == null ) + UIUtils.UnregisterFunctionSwitchCopyNode( this ); + UIUtils.RegisterFunctionSwitchNode( this ); + ResetToSelf(); + } + else + { + if( ContainerGraph.ParentWindow.CustomGraph == null ) + UIUtils.UnregisterFunctionSwitchNode( this ); + UIUtils.RegisterFunctionSwitchCopyNode( this ); + } + } + + if( m_referenceType == TexReferenceType.Instance ) + { + EditorGUI.BeginChangeCheck(); + string[] arr = new string[ UIUtils.FunctionSwitchList().Count ]; + int[] ids = new int[ UIUtils.FunctionSwitchList().Count ]; + for( int i = 0; i < arr.Length; i++ ) + { + arr[ i ] = i + " - " + UIUtils.FunctionSwitchList()[ i ].OptionLabel; + ids[ i ] = UIUtils.FunctionSwitchList()[ i ].UniqueId; + } + m_referenceUniqueId = EditorGUILayout.IntPopup( Constants.AvailableReferenceStr, m_referenceUniqueId, arr, ids ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromSelected(); + } + return; + } + + EditorGUI.BeginChangeCheck(); + m_optionLabel = EditorGUILayoutTextField( "Option Label", m_optionLabel ); + if( EditorGUI.EndChangeCheck() ) + { + m_optionLabel = UIUtils.RemoveInvalidEnumCharacters( m_optionLabel ); + if( string.IsNullOrEmpty( m_optionLabel ) ) + { + m_optionLabel = "Option"; + } + + UIUtils.UpdateFunctionSwitchData( UniqueId, m_optionLabel ); + } + + EditorGUI.BeginChangeCheck(); + m_toggleMode = EditorGUILayoutToggle( "Toggle Mode", m_toggleMode ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_toggleMode ) + { + m_inputPorts[ 0 ].Name = ToggleFalseStr; + m_inputPorts[ 1 ].Name = ToggleTrueStr; + + for( int i = 0; i < MaxAllowedAmount; i++ ) + { + m_inputPorts[ i ].Visible = ( i < 2 ); + } + + if( m_currentSelectedInput >= 2 ) + { + m_currentSelectedInput = 1; + } + UpdateLabels(); + m_sizeIsDirty = true; + } + else + { + m_inputPorts[ 0 ].Name = m_optionNames[ 0 ]; + m_inputPorts[ 1 ].Name = m_optionNames[ 1 ]; + + for( int i = 0; i < MaxAllowedAmount; i++ ) + { + m_inputPorts[ i ].Visible = ( i < m_maxAmountInputs ); + } + + if( m_currentSelectedInput >= m_maxAmountInputs ) + { + m_currentSelectedInput = m_maxAmountInputs - 1; + } + + UpdateLabels(); + m_sizeIsDirty = true; + } + } + + if( !m_toggleMode ) + { + EditorGUI.BeginChangeCheck(); + m_maxAmountInputs = EditorGUILayoutIntSlider( MaxAmountStr, m_maxAmountInputs, 2, MaxAllowedAmount ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < MaxAllowedAmount; i++ ) + { + m_inputPorts[ i ].Visible = ( i < m_maxAmountInputs ); + } + + if( m_currentSelectedInput >= m_maxAmountInputs ) + { + m_currentSelectedInput = m_maxAmountInputs - 1; + } + + UpdateLabels(); + m_sizeIsDirty = true; + } + + EditorGUI.indentLevel++; + for( int i = 0; i < m_maxAmountInputs; i++ ) + { + EditorGUI.BeginChangeCheck(); + m_inputPorts[ i ].Name = EditorGUILayoutTextField( "Item " + i, m_inputPorts[ i ].Name ); + if( EditorGUI.EndChangeCheck() ) + { + m_nameModified = true; + m_lastTimeNameModified = EditorApplication.timeSinceStartup; + m_inputPorts[ i ].Name = UIUtils.RemoveInvalidEnumCharacters( m_inputPorts[ i ].Name ); + m_optionNames[ i ] = m_inputPorts[ i ].Name; + if( string.IsNullOrEmpty( m_inputPorts[ i ].Name ) ) + { + m_inputPorts[ i ].Name = InputPortNameStr + i; + } + m_sizeIsDirty = true; + } + } + EditorGUI.indentLevel--; + + if( m_nameModified ) + { + UpdateLabels(); + } + } + + if( m_toggleMode ) + { + EditorGUI.BeginChangeCheck(); + int prevVal = m_currentSelectedInput; + m_currentSelectedInput = EditorGUILayoutToggle( CurrSelectedStr, ( m_currentSelectedInput != 0 ? true : false ) ) ? 1 : 0; + if( EditorGUI.EndChangeCheck() ) + SetCurrentSelectedInput( m_currentSelectedInput, prevVal ); + } + else + { + EditorGUI.BeginChangeCheck(); + int prevVal = m_currentSelectedInput; + m_currentSelectedInput = EditorGUILayoutIntPopup( CurrSelectedStr, m_currentSelectedInput, AvailableInputsLabels, AvailableInputsValues ); + if( EditorGUI.EndChangeCheck() ) + { + SetCurrentSelectedInput( m_currentSelectedInput, prevVal ); + } + } + } + if( EditorGUI.EndChangeCheck() ) + { + m_dirtySettings = true; + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( UIUtils.CurrentShaderVersion() > 14205 ) + { + if( m_referenceType == TexReferenceType.Instance ) + { + m_functionSwitchReference = UIUtils.GetNode( m_referenceUniqueId ) as FunctionSwitch; + UpdateFromSelected(); + } + } + + SetCurrentSelectedInput( m_currentSelectedInput, m_previousSelectedInput ); + } + + public void UpdateLabels() + { + int maxinputs = m_maxAmountInputs; + if( m_validReference ) + maxinputs = m_functionSwitchReference.MaxAmountInputs; + + AvailableInputsLabels = new string[ maxinputs ]; + AvailableInputsValues = new int[ maxinputs ]; + + for( int i = 0; i < maxinputs; i++ ) + { + AvailableInputsLabels[ i ] = m_optionNames[ i ]; + AvailableInputsValues[ i ] = i; + } + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + CheckReference(); + if( m_dirtySettings ) + m_dirtySettings = false; + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + float finalSize = 0; + if( !m_toggleMode ) + { + GUIContent dropdown = new GUIContent( m_inputPorts[ m_currentSelectedInput ].Name ); + int cacheSize = UIUtils.GraphDropDown.fontSize; + UIUtils.GraphDropDown.fontSize = 10; + Vector2 calcSize = UIUtils.GraphDropDown.CalcSize( dropdown ); + UIUtils.GraphDropDown.fontSize = cacheSize; + finalSize = Mathf.Clamp( calcSize.x, MinComboSize, MaxComboSize ); + if( m_insideSize.x != finalSize ) + { + m_insideSize.Set( finalSize, 25 ); + m_sizeIsDirty = true; + } + } + + base.OnNodeLayout( drawInfo ); + + bool toggleMode = m_toggleMode; + if( m_validReference ) + { + toggleMode = m_functionSwitchReference.m_toggleMode; + } + + if( toggleMode ) + { + m_varRect = m_remainingBox; + m_varRect.size = Vector2.one * 22 * drawInfo.InvertedZoom; + m_varRect.center = m_remainingBox.center; + if( m_showPreview ) + m_varRect.y = m_remainingBox.y; + } + else + { + m_varRect = m_remainingBox; + m_varRect.width = finalSize * drawInfo.InvertedZoom; + m_varRect.height = 16 * drawInfo.InvertedZoom; + m_varRect.x = m_remainingBox.xMax - m_varRect.width; + m_varRect.y += 1 * drawInfo.InvertedZoom; + + m_imgRect = m_varRect; + m_imgRect.x = m_varRect.xMax - 16 * drawInfo.InvertedZoom; + m_imgRect.width = 16 * drawInfo.InvertedZoom; + m_imgRect.height = m_imgRect.width; + } + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + if( m_validReference ) + { + base.DrawGUIControls( drawInfo ); + } + else + { + base.DrawGUIControls( drawInfo ); + + if( drawInfo.CurrentEventType != EventType.MouseDown ) + return; + + if( m_varRect.Contains( drawInfo.MousePosition ) ) + { + m_editing = true; + } + else if( m_editing ) + { + m_editing = false; + } + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( m_nameModified ) + { + if( ( EditorApplication.timeSinceStartup - m_lastTimeNameModified ) > MaxTimestamp ) + { + m_nameModified = false; + } + } + + if( m_validReference ) + { + SetAdditonalTitleTextOnCallback( m_functionSwitchReference.OptionLabel, ( instance, newSubTitle ) => instance.AdditonalTitleContent.text = string.Format( Constants.SubTitleVarNameFormatStr, newSubTitle ) ); + } + else + { + SetAdditonalTitleTextOnCallback( m_optionLabel, ( instance, newSubTitle ) => instance.AdditonalTitleContent.text = string.Format( Constants.SubTitleValueFormatStr, newSubTitle ) ); + + if( m_editing ) + { + if( m_toggleMode ) + { + if( GUI.Button( m_varRect, GUIContent.none, UIUtils.GraphButton ) ) + { + PreviewIsDirty = true; + int prevVal = m_currentSelectedInput; + m_currentSelectedInput = m_currentSelectedInput == 1 ? 0 : 1; + if( m_currentSelectedInput != prevVal ) + SetCurrentSelectedInput( m_currentSelectedInput, prevVal ); + m_editing = false; + } + + if( m_currentSelectedInput == 1 ) + { + GUI.Label( m_varRect, m_checkContent, UIUtils.GraphButtonIcon ); + } + } + else + { + EditorGUI.BeginChangeCheck(); + int prevVal = m_currentSelectedInput; + m_currentSelectedInput = EditorGUIIntPopup( m_varRect, m_currentSelectedInput, AvailableInputsLabels, AvailableInputsValues, UIUtils.GraphDropDown ); + if( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + SetCurrentSelectedInput( m_currentSelectedInput, prevVal ); + m_editing = false; + } + } + } + } + + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + + if( !m_isVisible ) + return; + + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + { + if( m_validReference ) + { + bool cacheState = GUI.enabled; + GUI.enabled = false; + if( m_functionSwitchReference.m_toggleMode ) + { + GUI.Label( m_varRect, GUIContent.none, UIUtils.GraphButton ); + if( m_functionSwitchReference.GetCurrentSelectedInput() == 1 ) + { + GUI.Label( m_varRect, m_checkContent, UIUtils.GraphButtonIcon ); + } + } + else + { + GUI.Label( m_varRect, m_functionSwitchReference.AvailableInputsLabels[ m_currentSelectedInput ], UIUtils.GraphDropDown ); + } + GUI.enabled = cacheState; + } + else + { + if( !m_editing ) + { + if( m_toggleMode ) + { + GUI.Label( m_varRect, GUIContent.none, UIUtils.GraphButton ); + + if( m_currentSelectedInput == 1 ) + { + GUI.Label( m_varRect, m_checkContent, UIUtils.GraphButtonIcon ); + } + } + else + { + GUI.Label( m_varRect, AvailableInputsLabels[ m_currentSelectedInput ], UIUtils.GraphDropDown ); + GUI.Label( m_imgRect, m_popContent, UIUtils.GraphButtonIcon ); + } + } + } + } + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + if( m_inputPorts[ m_currentSelectedInput ].IsConnected ) + m_inputPorts[ m_currentSelectedInput ].GetOutputNode().PropagateNodeData( nodeData, ref dataCollector ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + return m_inputPorts[ m_currentSelectedInput ].GeneratePortInstructions( ref dataCollector ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_optionLabel = GetCurrentParam( ref nodeParams ); + m_toggleMode = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_currentSelectedInput = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_previousSelectedInput = m_currentSelectedInput; + m_maxAmountInputs = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_orderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + + for( int i = 0; i < MaxAllowedAmount; i++ ) + { + m_inputPorts[ i ].Visible = ( i < m_maxAmountInputs ); + } + + if( m_currentSelectedInput >= m_maxAmountInputs ) + { + m_currentSelectedInput = m_maxAmountInputs - 1; + } + + for( int i = 0; i < m_maxAmountInputs; i++ ) + { + m_optionNames[ i ] = GetCurrentParam( ref nodeParams ); + m_inputPorts[ i ].Name = m_optionNames[ i ]; + } + + if( m_toggleMode ) + { + m_inputPorts[ 0 ].Name = ToggleFalseStr; + m_inputPorts[ 1 ].Name = ToggleTrueStr; + } + + UpdateLabels(); + m_sizeIsDirty = true; + + UIUtils.UpdateFunctionSwitchData( UniqueId, m_optionLabel ); + UIUtils.UpdateFunctionSwitchCopyData( UniqueId, m_optionLabel ); + if( UIUtils.CurrentShaderVersion() > 14205 ) + { + m_referenceType = (TexReferenceType)Enum.Parse( typeof( TexReferenceType ), GetCurrentParam( ref nodeParams ) ); + m_referenceUniqueId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + + if( m_referenceType == TexReferenceType.Object ) + { + if( ContainerGraph.ParentWindow.CustomGraph == null ) + UIUtils.UnregisterFunctionSwitchCopyNode( this ); + UIUtils.RegisterFunctionSwitchNode( this ); + ResetToSelf(); + } + else + { + if( ContainerGraph.ParentWindow.CustomGraph == null ) + UIUtils.UnregisterFunctionSwitchNode( this ); + UIUtils.RegisterFunctionSwitchCopyNode( this ); + } + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_optionLabel ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_toggleMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentSelectedInput ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_maxAmountInputs ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_orderIndex ); + + for( int i = 0; i < m_maxAmountInputs; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_optionNames[ i ] ); + } + + IOUtils.AddFieldValueToString( ref nodeInfo, m_referenceType ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_functionSwitchReference != null ? m_functionSwitchReference.UniqueId : -1 ) ); + } + + public int OrderIndex + { + get { return m_orderIndex; } + set { m_orderIndex = value; } + } + + public string OptionLabel + { + get { return m_optionLabel; } + set { m_optionLabel = value; } + } + + public bool AsDrawn { get { return m_asDrawn; } set { m_asDrawn = value; } } + + public override string DataToArray { get { return m_optionLabel; } } + public int MaxAmountInputs + { + get { return m_maxAmountInputs; } + } + public bool DirtySettings { get { return m_dirtySettings; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitch.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitch.cs.meta new file mode 100644 index 0000000..8929a45 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitch.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2bd66b9ffd0acf84ab46c9f83300495c +timeCreated: 1515408158 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitchByPipeline.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitchByPipeline.cs new file mode 100644 index 0000000..5a05605 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitchByPipeline.cs @@ -0,0 +1,102 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Switch by Pipeline", "Functions", "Executes branch according to current pipeline", NodeAvailabilityFlags = (int)NodeAvailability.ShaderFunction )] + public sealed class FunctionSwitchByPipeline : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "Surface", -1, MasterNodePortCategory.Fragment, 0 ); + AddInputPort( WirePortDataType.FLOAT, false, "Default RP", -1, MasterNodePortCategory.Fragment, 3 ); + AddInputPort( WirePortDataType.FLOAT, false, "Lightweight", -1, MasterNodePortCategory.Fragment, 1 ); + AddInputPort( WirePortDataType.FLOAT, false, "HD", -1, MasterNodePortCategory.Fragment, 2 ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + GetInputPortByUniqueId( portId ).MatchPortToConnection(); + UpdateOutputPort(); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + GetInputPortByUniqueId( outputPortId ).MatchPortToConnection(); + UpdateOutputPort(); + } + + void UpdateOutputPort() + { + switch( UIUtils.CurrentWindow.OutsideGraph.CurrentSRPType ) + { + case TemplateSRPType.BuiltIn: + { + InputPort port = UIUtils.CurrentWindow.OutsideGraph.IsStandardSurface ? GetInputPortByUniqueId( 0 ) : GetInputPortByUniqueId( 3 ); + m_outputPorts[ 0 ].ChangeType( port.DataType, false ); + } + break; + case TemplateSRPType.Lightweight: + { + InputPort port = GetInputPortByUniqueId( 1 ); + m_outputPorts[ 0 ].ChangeType( port.DataType, false ); + } + break; + case TemplateSRPType.HD: + { + InputPort port = GetInputPortByUniqueId( 2 ); + m_outputPorts[ 0 ].ChangeType( port.DataType, false ); + } + break; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + switch( dataCollector.CurrentSRPType ) + { + case TemplateSRPType.BuiltIn: + { + InputPort port = UIUtils.CurrentWindow.OutsideGraph.IsStandardSurface ? GetInputPortByUniqueId( 0 ) : GetInputPortByUniqueId( 3 ); + return port.GeneratePortInstructions( ref dataCollector ); + } + case TemplateSRPType.Lightweight: + { + InputPort port = GetInputPortByUniqueId( 1 ); + return port.GeneratePortInstructions( ref dataCollector ); + } + case TemplateSRPType.HD: + { + InputPort port = GetInputPortByUniqueId( 2 ); + return port.GeneratePortInstructions( ref dataCollector ); + } + } + + return "0"; + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( UIUtils.CurrentShaderVersion() < 16303 ) + { + InputPort standardPort = GetInputPortByUniqueId( 0 ); + if( standardPort.IsConnected ) + { + UIUtils.SetConnection( UniqueId, 3, standardPort.GetConnection().NodeId, standardPort.GetConnection().PortId ); + } + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitchByPipeline.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitchByPipeline.cs.meta new file mode 100644 index 0000000..9ecd808 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionSwitchByPipeline.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 84a4868e0b1e8dd4bb0e71c8d9a9c130 +timeCreated: 1535365719 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/LogNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/LogNode.cs new file mode 100644 index 0000000..d431cbb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/LogNode.cs @@ -0,0 +1,80 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Log", "Master", "Debug node to dump output to log", null, KeyCode.None, false )] + public sealed class LogNode : MasterNode + { + private const string InputAmountStr = "Input amount"; + + [SerializeField] + private int m_inputCount = 1; + + [SerializeField] + private int m_lastInputCount = 1; + + public LogNode() : base() { } + public LogNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddMasterPorts(); + } + + public override void AddMasterPorts() + { + DeleteAllInputConnections( true ); + base.AddMasterPorts(); + + for ( int i = 0; i < m_inputCount; i++ ) + { + AddInputPort( WirePortDataType.OBJECT, false, i.ToString() ); + } + m_sizeIsDirty = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUILayout.BeginVertical(); + { + EditorGUILayout.LabelField( InputAmountStr ); + m_inputCount = EditorGUILayoutIntField( m_inputCount ); + } + EditorGUILayout.EndVertical(); + if ( m_inputCount != m_lastInputCount ) + { + m_lastInputCount = Mathf.Max( m_inputCount, 1 ); + AddMasterPorts(); + } + } + + public override void Execute( Shader currentSelected ) + { + string valueDump = ""; + string valueInstructions = ""; + + MasterNodeDataCollector dataCollector = new MasterNodeDataCollector( this ); + foreach ( InputPort port in InputPorts ) + { + if ( port.IsConnected ) + { + valueInstructions += "Port: " + port.PortId + " Value: " + port.GenerateShaderForOutput( ref dataCollector, port.DataType, false ); + } + } + Debug.Log( "Value: " + valueDump ); + Debug.Log( "Instructions: " + valueInstructions ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/LogNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/LogNode.cs.meta new file mode 100644 index 0000000..d2debab --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/LogNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3b0e734d4c354c74999e20ce054628d2 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNode.cs new file mode 100644 index 0000000..14fd0a5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNode.cs @@ -0,0 +1,1031 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using UnityEditorInternal; + +namespace AmplifyShaderEditor +{ + public enum PrecisionType + { + Float = 0, + Half, + Inherit + } + + public enum AvailableShaderTypes + { + SurfaceShader = 0, + Template + } + + [Serializable] + public class MasterNodeCategoriesData + { + public AvailableShaderTypes Category; + public string Name; + public MasterNodeCategoriesData( AvailableShaderTypes category, string name ) { Category = category; Name = name; } + } + + [Serializable] + public class MasterNode : OutputNode + { + protected const string CustomInspectorStr = "Custom Editor"; + protected const string CustomInspectorFormat = "CustomEditor \"{0}\""; + + private const string PropertyOrderFoldoutStr = " Material Properties"; + private const string PropertyOrderTemplateFoldoutStr = "Material Properties"; + + protected MasterNodeDataCollector m_currentDataCollector; + + protected const string ShaderNameStr = "Shader Name"; + protected GUIContent m_shaderNameContent; + + private const string IndentationHelper = "\t\t{0}\n"; + private const string ShaderLODFormat = "\t\tLOD {0}\n"; + + public delegate void OnMaterialUpdated( MasterNode masterNode ); + public event OnMaterialUpdated OnMaterialUpdatedEvent; + public event OnMaterialUpdated OnShaderUpdatedEvent; + + protected const string GeneralFoldoutStr = " General"; + + protected readonly string[] ShaderModelTypeArr = { "2.0", "2.5", "3.0", "3.5", "4.0", "4.5", "4.6", "5.0" }; + private const string ShaderKeywordsStr = "Shader Keywords"; + + [SerializeField] + protected int m_shaderLOD = 0; + + [SerializeField] + protected int m_shaderModelIdx = 2; + + [SerializeField] + protected Shader m_currentShader; + + [SerializeField] + protected Material m_currentMaterial; + + //[SerializeField] + //private bool m_isMainMasterNode = false; + + [SerializeField] + private Rect m_masterNodeIconCoords; + + [SerializeField] + protected string m_shaderName = Constants.DefaultShaderName; + + [SerializeField] + protected string m_croppedShaderName = Constants.DefaultShaderName; + + [SerializeField] + protected string m_customInspectorName = Constants.DefaultCustomInspector; + + [SerializeField] + protected int m_masterNodeCategory = 0;// MasterNodeCategories.SurfaceShader; + + [SerializeField] + protected bool m_samplingMacros = false; + + [SerializeField] + protected string m_currentShaderData = string.Empty; + + private Texture2D m_masterNodeOnTex; + private Texture2D m_masterNodeOffTex; + + private Texture2D m_gpuInstanceOnTex; + private Texture2D m_gpuInstanceOffTex; + + // Shader Keywords + [SerializeField] + private List m_shaderKeywords = new List(); + + [SerializeField] + private bool m_shaderKeywordsFoldout = true; + + private GUIStyle m_addShaderKeywordStyle; + private GUIStyle m_removeShaderKeywordStyle; + private GUIStyle m_smallAddShaderKeywordItemStyle; + private GUIStyle m_smallRemoveShaderKeywordStyle; + private const float ShaderKeywordButtonLayoutWidth = 15; + + + public MasterNode() : base() { CommonInit(); } + public MasterNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { CommonInit(); } + + protected GUIContent m_categoryLabel = new GUIContent( "Shader Type ", "Specify the shader type you want to be working on" ); + + protected GUIContent[] m_availableCategoryLabels; + protected MasterNodeCategoriesData[] m_availableCategories; + + [SerializeField] + private List m_propertyNodesVisibleList = new List(); + + private ReorderableList m_propertyReordableList; + protected bool m_propertyOrderChanged = false; + //private int m_availableCount = 0; + private int m_lastCount = 0; + + private GUIStyle m_propertyAdjustment; + protected bool m_shaderNameIsTitle = true; + + void CommonInit() + { + m_currentMaterial = null; + m_masterNodeIconCoords = new Rect( 0, 0, 64, 64 ); + m_isMainOutputNode = false; + m_connStatus = NodeConnectionStatus.Connected; + m_activeType = GetType(); + m_currentPrecisionType = PrecisionType.Float; + m_textLabelWidth = 120; + m_shaderNameContent = new GUIContent( ShaderNameStr, string.Empty ); + + AddMasterPorts(); + } + + void InitAvailableCategories() + { + int templateCount = m_containerGraph.ParentWindow.TemplatesManagerInstance.TemplateCount; + m_availableCategories = new MasterNodeCategoriesData[ templateCount + 1 ]; + m_availableCategoryLabels = new GUIContent[ templateCount + 1 ]; + + m_availableCategories[ 0 ] = new MasterNodeCategoriesData( AvailableShaderTypes.SurfaceShader, string.Empty ); + m_availableCategoryLabels[ 0 ] = new GUIContent( "Surface" ); + + for( int i = 0; i < templateCount; i++ ) + { + int idx = i + 1; + TemplateDataParent templateData = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( i ); + m_availableCategories[ idx ] = new MasterNodeCategoriesData( AvailableShaderTypes.Template, templateData.GUID ); + m_availableCategoryLabels[ idx ] = new GUIContent( templateData.Name ); + } + } + + public void SetMasterNodeCategoryFromGUID( string GUID ) + { + if( m_availableCategories == null ) + InitAvailableCategories(); + + m_masterNodeCategory = 0; + for( int i = 1; i < m_availableCategories.Length; i++ ) + { + if( m_availableCategories[ i ].Name.Equals( GUID ) ) + m_masterNodeCategory = i; + } + + } + + public override void SetupNodeCategories() + { + //base.SetupNodeCategories(); + ContainerGraph.ResetNodesData(); + int count = m_inputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + NodeData nodeData = new NodeData( m_inputPorts[ i ].Category ); + ParentNode node = m_inputPorts[ i ].GetOutputNode(); + node.PropagateNodeData( nodeData, ref m_currentDataCollector ); + } + else if( m_inputPorts[ i ].HasExternalLink ) + { + InputPort linkedPort = m_inputPorts[ i ].ExternalLink; + if( linkedPort != null && linkedPort.IsConnected ) + { + NodeData nodeData = new NodeData( linkedPort.Category ); + ParentNode node = linkedPort.GetOutputNode(); + node.PropagateNodeData( nodeData, ref m_currentDataCollector ); + } + } + } + } + + public virtual void RefreshAvailableCategories() + { + InitAvailableCategories(); + } + + public virtual void AddMasterPorts() { } + + public virtual void ForcePortType() { } + + public virtual void UpdateMasterNodeMaterial( Material material ) { } + + public virtual void SetName( string name ) { } + + public void CopyFrom( MasterNode other ) + { + Vec2Position = other.Vec2Position; + CurrentShader = other.CurrentShader; + CurrentMaterial = other.CurrentMaterial; + ShaderName = other.ShaderName; + m_masterNodeCategory = other.CurrentMasterNodeCategoryIdx; + } + + protected void DrawCurrentShaderType() + { + if( m_availableCategories == null ) + InitAvailableCategories(); + + int oldType = m_masterNodeCategory; + m_masterNodeCategory = EditorGUILayoutPopup( m_categoryLabel, m_masterNodeCategory, m_availableCategoryLabels ); + if( oldType != m_masterNodeCategory ) + { + m_containerGraph.ParentWindow.ReplaceMasterNode( m_availableCategories[ m_masterNodeCategory ], false ); + } + } + + protected void DrawCustomInspector( bool dropdown ) + { +#if !UNITY_2018_3_OR_NEWER + dropdown = false; +#else + if( ASEPackageManagerHelper.CurrentHDVersion <= ASESRPVersions.ASE_SRP_5_16_1 ) + dropdown = false; +#endif + + EditorGUILayout.BeginHorizontal(); + m_customInspectorName = EditorGUILayoutTextField( CustomInspectorStr, m_customInspectorName ); + if( !dropdown ) + { + if( GUILayoutButton( string.Empty, UIUtils.GetCustomStyle( CustomStyle.ResetToDefaultInspectorButton ), GUILayout.Width( 15 ), GUILayout.Height( 15 ) ) ) + { + GUIUtility.keyboardControl = 0; + m_customInspectorName = Constants.DefaultCustomInspector; + } + } + else + { + if( GUILayoutButton( string.Empty, UIUtils.InspectorPopdropdownFallback, GUILayout.Width( 17 ), GUILayout.Height( 19 ) ) ) + { + EditorGUI.FocusTextInControl( null ); + GUI.FocusControl( null ); + + GenericMenu menu = new GenericMenu(); + AddMenuItem( menu, Constants.DefaultCustomInspector ); +#if UNITY_2018_3_OR_NEWER + if( ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_6_9_1 ) + { + if( ASEPackageManagerHelper.CurrentHDVersion >= ASESRPVersions.ASE_SRP_11_0_0 ) + { + AddMenuItem( menu , "Rendering.HighDefinition.DecalShaderGraphGUI" ); + AddMenuItem( menu , "Rendering.HighDefinition.LightingShaderGraphGUI" ); + AddMenuItem( menu , "Rendering.HighDefinition.LitShaderGraphGUI" ); + AddMenuItem( menu , "Rendering.HighDefinition.HDUnlitGUI" ); + } + else + if( ASEPackageManagerHelper.CurrentHDVersion >= ASESRPVersions.ASE_SRP_10_0_0 ) + { + AddMenuItem( menu , "Rendering.HighDefinition.DecalGUI" ); + AddMenuItem( menu , "Rendering.HighDefinition.LitShaderGraphGUI" ); + AddMenuItem( menu , "Rendering.HighDefinition.LightingShaderGraphGUI" ); + AddMenuItem( menu , "Rendering.HighDefinition.HDUnlitGUI" ); + } + else + { + AddMenuItem( menu, "UnityEditor.Rendering.HighDefinition.HDLitGUI" ); + } + AddMenuItem( menu, "UnityEditor.ShaderGraph.PBRMasterGUI" ); + } + else + { + AddMenuItem( menu, "UnityEditor.Experimental.Rendering.HDPipeline.HDLitGUI" ); + } +#else + AddMenuItem( menu, "UnityEditor.Experimental.Rendering.HDPipeline.HDLitGUI" ); +#endif + menu.ShowAsContext(); + } + } + EditorGUILayout.EndHorizontal(); + } + + private void AddMenuItem( GenericMenu menu, string newClass ) + { + menu.AddItem( new GUIContent( newClass ), m_customInspectorName.Equals( newClass ), OnSelection, newClass ); + } + + private void OnSelection( object newClass ) + { + m_customInspectorName = (string)newClass; + } + + protected void DrawShaderName() + { +#if UNITY_2019_1_OR_NEWER + // this is a hack to control the automatic selection of text fields when the window is selected after serialization + // by having a selectable label the focus happens on it instead and doesn't interupt the usual flow of the editor + EditorGUILayout.SelectableLabel( "", GUILayout.Height( 0 ) ); +#endif + EditorGUI.BeginChangeCheck(); + string newShaderName = EditorGUILayoutTextField( m_shaderNameContent, m_shaderName ); + if( EditorGUI.EndChangeCheck() ) + { + if( newShaderName.Length > 0 ) + { + newShaderName = UIUtils.RemoveShaderInvalidCharacters( newShaderName ); + } + else + { + newShaderName = Constants.DefaultShaderName; + } + ShaderName = newShaderName; + ContainerGraph.ParentWindow.UpdateTabTitle( ShaderName, true ); + } + m_shaderNameContent.tooltip = m_shaderName; + } + + protected void DrawSamplingMacros() + { + EditorGUI.BeginChangeCheck(); + m_samplingMacros = EditorGUILayoutToggle( "Use Sampling Macros", m_samplingMacros ); + if( EditorGUI.EndChangeCheck() ) + ContainerGraph.SamplingMacros = SamplingMacros; + } + + public void DrawShaderKeywords() + { + if( m_addShaderKeywordStyle == null ) + m_addShaderKeywordStyle = UIUtils.PlusStyle; + + if( m_removeShaderKeywordStyle == null ) + m_removeShaderKeywordStyle = UIUtils.MinusStyle; + + if( m_smallAddShaderKeywordItemStyle == null ) + m_smallAddShaderKeywordItemStyle = UIUtils.PlusStyle; + + if( m_smallRemoveShaderKeywordStyle == null ) + m_smallRemoveShaderKeywordStyle = UIUtils.MinusStyle; + + EditorGUILayout.BeginHorizontal(); + { + m_shaderKeywordsFoldout = EditorGUILayout.Foldout( m_shaderKeywordsFoldout, ShaderKeywordsStr ); + + // Add keyword + if( GUILayout.Button( string.Empty, m_addShaderKeywordStyle ) ) + { + m_shaderKeywords.Insert( 0, "" ); + } + + //Remove keyword + if( GUILayout.Button( string.Empty, m_removeShaderKeywordStyle ) ) + { + m_shaderKeywords.RemoveAt( m_shaderKeywords.Count - 1 ); + } + } + EditorGUILayout.EndHorizontal(); + + if( m_shaderKeywordsFoldout ) + { + EditorGUI.indentLevel += 1; + int itemCount = m_shaderKeywords.Count; + int markedToDelete = -1; + for( int i = 0; i < itemCount; i++ ) + { + EditorGUILayout.BeginHorizontal(); + { + GUILayout.Label( " " ); + // Add new port + if( GUILayoutButton( string.Empty, m_smallAddShaderKeywordItemStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_shaderKeywords.Insert( i, "" ); + } + + //Remove port + if( GUILayoutButton( string.Empty, m_smallRemoveShaderKeywordStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + markedToDelete = i; + } + } + EditorGUILayout.EndHorizontal(); + } + if( markedToDelete > -1 ) + { + m_shaderKeywords.RemoveAt( markedToDelete ); + } + EditorGUI.indentLevel -= 1; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + if( m_availableCategories == null ) + InitAvailableCategories(); + + base.Draw( drawInfo ); + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + + if( m_isMainOutputNode ) + { + if( m_masterNodeOnTex == null ) + { + m_masterNodeOnTex = UIUtils.MasterNodeOnTexture; + } + + if( m_masterNodeOffTex == null ) + { + m_masterNodeOffTex = UIUtils.MasterNodeOffTexture; + } + + if( m_gpuInstanceOnTex == null ) + { + m_gpuInstanceOnTex = UIUtils.GPUInstancedOnTexture; + } + + if( m_gpuInstanceOffTex == null ) + { + m_gpuInstanceOffTex = UIUtils.GPUInstancedOffTexture; + } + + m_masterNodeIconCoords = m_globalPosition; + m_masterNodeIconCoords.x += m_globalPosition.width - m_masterNodeOffTex.width * drawInfo.InvertedZoom; + m_masterNodeIconCoords.y += m_globalPosition.height - m_masterNodeOffTex.height * drawInfo.InvertedZoom; + m_masterNodeIconCoords.width = m_masterNodeOffTex.width * drawInfo.InvertedZoom; + m_masterNodeIconCoords.height = m_masterNodeOffTex.height * drawInfo.InvertedZoom; + + GUI.DrawTexture( m_masterNodeIconCoords, m_masterNodeOffTex ); + + if( m_gpuInstanceOnTex == null ) + { + m_gpuInstanceOnTex = UIUtils.GPUInstancedOnTexture; + } + } + } + + protected void DrawInstancedIcon( DrawInfo drawInfo ) + { + if( m_gpuInstanceOffTex == null || drawInfo.CurrentEventType != EventType.Repaint ) + return; + + m_masterNodeIconCoords = m_globalPosition; + m_masterNodeIconCoords.x += m_globalPosition.width - 5 - m_gpuInstanceOffTex.width * drawInfo.InvertedZoom; + m_masterNodeIconCoords.y += m_headerPosition.height; + m_masterNodeIconCoords.width = m_gpuInstanceOffTex.width * drawInfo.InvertedZoom; + m_masterNodeIconCoords.height = m_gpuInstanceOffTex.height * drawInfo.InvertedZoom; + GUI.DrawTexture( m_masterNodeIconCoords, m_gpuInstanceOffTex ); + } + //public override void DrawProperties() + //{ + // base.DrawProperties(); + // //EditorGUILayout.LabelField( _shaderTypeLabel ); + //} + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + //IOUtils.AddFieldValueToString( ref nodeInfo, m_isMainMasterNode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_shaderModelIdx ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_customInspectorName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_shaderLOD ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_masterNodeCategory ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 21 ) + { + m_shaderModelIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() < 17005 ) + { + string val = GetCurrentParam( ref nodeParams ); + if( m_customPrecision ) + { + if( val.Equals( "Fixed" ) ) + m_currentPrecisionType = PrecisionType.Half; + else + m_currentPrecisionType = (PrecisionType)Enum.Parse( typeof( PrecisionType ), val ); + } + else + { + m_currentPrecisionType = PrecisionType.Inherit; + } + } + } + + if( UIUtils.CurrentShaderVersion() > 2404 ) + { + m_customInspectorName = GetCurrentParam( ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 6101 ) + { + ShaderLOD = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() >= 13001 ) + { + //Debug.LogWarning( "Add correct version as soon as it is merged into master" ); + m_masterNodeCategory = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + if( activateNode ) + { + InputPort port = GetInputPortByUniqueId( portId ); + port.GetOutputNode().ActivateNode( UniqueId, portId, m_activeType ); + } + } + + public void FireMaterialChangedEvt() + { + if( OnMaterialUpdatedEvent != null ) + { + OnMaterialUpdatedEvent( this ); + } + } + + public void FireShaderChangedEvt() + { + if( OnShaderUpdatedEvent != null ) + OnShaderUpdatedEvent( this ); + } + + public void RegisterStandaloneFuntions() + { + List nodes = m_containerGraph.CustomExpressionOnFunctionMode.NodesList; + int count = nodes.Count; + Dictionary examinedNodes = new Dictionary(); + for( int i = 0; i < count; i++ ) + { + if( nodes[ i ].AutoRegisterMode ) + { + nodes[ i ].CheckDependencies( ref m_currentDataCollector, ref examinedNodes ); + } + } + examinedNodes.Clear(); + examinedNodes = null; + } + + // What operation this node does + public virtual void Execute( Shader selectedShader ) + { + Execute( AssetDatabase.GetAssetPath( selectedShader ), false ); + } + + public virtual Shader Execute( string pathname, bool isFullPath ) + { + ContainerGraph.ResetNodesLocalVariables(); + m_currentDataCollector = new MasterNodeDataCollector( this ); + return null; + } + + public void CheckSamplingMacrosFlag() + { + if( ContainerGraph.SamplingMacros && m_currentDataCollector != null ) + m_currentDataCollector.AddToDirectives( Constants.SamplingMacrosDirective ); + + } + protected void SortInputPorts( ref List vertexPorts, ref List fragmentPorts ) + { + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].Category == MasterNodePortCategory.Fragment || m_inputPorts[ i ].Category == MasterNodePortCategory.Debug ) + { + if( fragmentPorts != null ) + fragmentPorts.Add( m_inputPorts[ i ] ); + } + else + { + if( vertexPorts != null ) + vertexPorts.Add( m_inputPorts[ i ] ); + } + } + + if( fragmentPorts.Count > 0 ) + { + fragmentPorts.Sort( ( x, y ) => x.OrderId.CompareTo( y.OrderId ) ); + } + + if( vertexPorts.Count > 0 ) + { + vertexPorts.Sort( ( x, y ) => x.OrderId.CompareTo( y.OrderId ) ); + } + } + + protected void UpdateShaderAsset( ref string pathname, ref string shaderBody, bool isFullPath ) + { + // Generate Graph info + shaderBody += ContainerGraph.ParentWindow.GenerateGraphInfo(); + + //TODO: Remove current SaveDebugShader and uncomment SaveToDisk as soon as pathname is editable + if( !String.IsNullOrEmpty( pathname ) ) + { + IOUtils.StartSaveThread( shaderBody, ( isFullPath ? pathname : ( IOUtils.dataPath + pathname ) ) ); + } + else + { + IOUtils.StartSaveThread( shaderBody, Application.dataPath + "/AmplifyShaderEditor/Samples/Shaders/" + m_shaderName + ".shader" ); + } + + + if( CurrentShader == null ) + { + AssetDatabase.Refresh( ImportAssetOptions.ForceUpdate ); + CurrentShader = Shader.Find( ShaderName ); + } + + //else + //{ + // // need to always get asset datapath because a user can change and asset location from the project window + // AssetDatabase.ImportAsset( AssetDatabase.GetAssetPath( m_currentShader ) ); + // //ShaderUtil.UpdateShaderAsset( m_currentShader, ShaderBody ); + // //ShaderImporter importer = (ShaderImporter)ShaderImporter.GetAtPath( AssetDatabase.GetAssetPath( CurrentShader ) ); + // //importer.SaveAndReimport(); + //} + + if( m_currentShader != null ) + { + m_currentDataCollector.UpdateShaderImporter( ref m_currentShader ); + if( m_currentMaterial != null ) + { + if( m_currentMaterial.shader != m_currentShader ) + m_currentMaterial.shader = m_currentShader; + + //m_currentDataCollector.UpdateMaterialOnPropertyNodes( m_currentMaterial ); + //This master node UpdateMaterial is needed on Standard Surface node to update its internal properties + UpdateMaterial( m_currentMaterial ); + + UIUtils.CurrentWindow.OutsideGraph.UpdateMaterialOnPropertyNodes( m_currentMaterial ); + + FireMaterialChangedEvt(); + // need to always get asset datapath because a user can change and asset location from the project window + //AssetDatabase.ImportAsset( AssetDatabase.GetAssetPath( m_currentMaterial ) ); + } + + } + + m_currentDataCollector.Destroy(); + m_currentDataCollector = null; + } + + + public void InvalidateMaterialPropertyCount() + { + m_lastCount = -1; + } + + private void RefreshVisibleList( ref List allNodes ) + { + // temp reference for lambda expression + List nodes = allNodes; + m_propertyNodesVisibleList.Clear(); + + for( int i = 0; i < nodes.Count; i++ ) + { + ReordenatorNode rnode = nodes[ i ] as ReordenatorNode; + if( ( rnode == null || !rnode.IsInside ) && ( !m_propertyNodesVisibleList.Exists( x => x.PropertyName.Equals( nodes[ i ].PropertyName ) ) ) ) + m_propertyNodesVisibleList.Add( nodes[ i ] ); + } + + m_propertyNodesVisibleList.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + } + + public void DrawMaterialInputs( GUIStyle toolbarstyle, bool style = true ) + { + m_propertyOrderChanged = false; + Color cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f ); + EditorGUILayout.BeginHorizontal( toolbarstyle ); + GUI.color = cachedColor; + + EditorGUI.BeginChangeCheck(); + if( style ) + { + ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties = GUILayoutToggle( ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties, PropertyOrderFoldoutStr, UIUtils.MenuItemToggleStyle ); + } + else + { + ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties = GUILayoutToggle( ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties, PropertyOrderTemplateFoldoutStr, UIUtils.MenuItemToggleStyle ); + } + + if( EditorGUI.EndChangeCheck() ) + { + EditorPrefs.SetBool( "ExpandedProperties", ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties ); + } + + EditorGUILayout.EndHorizontal(); + if( !ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedProperties ) + return; + + cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) ); + EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + GUI.color = cachedColor; + + List nodes = UIUtils.PropertyNodesList(); + + if( nodes.Count != m_lastCount ) + { + RefreshVisibleList( ref nodes ); + m_lastCount = nodes.Count; + } + + if( m_propertyReordableList == null ) + { + m_propertyReordableList = new ReorderableList( m_propertyNodesVisibleList, typeof( PropertyNode ), true, false, false, false ) + { + headerHeight = 0, + footerHeight = 0, + showDefaultBackground = false, + + drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) => + { + var first = rect; + first.width *= 0.60f; + EditorGUI.LabelField( first, m_propertyNodesVisibleList[ index ].PropertyInspectorName ); + var second = rect; + second.width *= 0.4f; + second.x += first.width; + if( GUI.Button( second, m_propertyNodesVisibleList[ index ].PropertyName, new GUIStyle( "AssetLabel Partial" ) ) ) + { + UIUtils.FocusOnNode( m_propertyNodesVisibleList[ index ], 1, false ); + } + }, + + onReorderCallback = ( list ) => + { + ReorderList( ref nodes ); + m_propertyOrderChanged = true; + //RecursiveLog(); + } + }; + ReorderList( ref nodes ); + } + + if( m_propertyReordableList != null ) + { + if( m_propertyAdjustment == null ) + { + m_propertyAdjustment = new GUIStyle(); + m_propertyAdjustment.padding.left = 17; + } + EditorGUILayout.BeginVertical( m_propertyAdjustment ); + m_propertyReordableList.DoLayoutList(); + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndVertical(); + } + + public void ForceReordering() + { + List nodes = UIUtils.PropertyNodesList(); + + if( nodes.Count != m_lastCount ) + { + RefreshVisibleList( ref nodes ); + m_lastCount = nodes.Count; + } + + ReorderList( ref nodes ); + //RecursiveLog(); + } + + private void RecursiveLog() + { + List nodes = UIUtils.PropertyNodesList(); + nodes.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + for( int i = 0; i < nodes.Count; i++ ) + { + if( ( nodes[ i ] is ReordenatorNode ) ) + ( nodes[ i ] as ReordenatorNode ).RecursiveLog(); + else + Debug.Log( nodes[ i ].OrderIndex + " " + nodes[ i ].PropertyName ); + } + } + + private void ReorderList( ref List nodes ) + { + // clear lock list before reordering because of multiple sf being used + for( int i = 0; i < nodes.Count; i++ ) + { + ReordenatorNode rnode = nodes[ i ] as ReordenatorNode; + if( rnode != null ) + rnode.RecursiveClear(); + } + + int propoffset = 0; + int count = 0; + for( int i = 0; i < m_propertyNodesVisibleList.Count; i++ ) + { + ReordenatorNode renode = m_propertyNodesVisibleList[ i ] as ReordenatorNode; + if( renode != null ) + { + if( !renode.IsInside ) + { + m_propertyNodesVisibleList[ i ].OrderIndex = count + propoffset; + + if( renode.PropertyListCount > 0 ) + { + propoffset += renode.RecursiveCount(); + // the same reordenator can exist multiple times, apply ordering to all of them + for( int j = 0; j < nodes.Count; j++ ) + { + ReordenatorNode pnode = ( nodes[ j ] as ReordenatorNode ); + if( pnode != null && pnode.PropertyName.Equals( renode.PropertyName ) ) + { + pnode.OrderIndex = renode.RawOrderIndex; + pnode.RecursiveSetOrderOffset( renode.RawOrderIndex, true ); + } + } + } + else + { + count++; + } + } + else + { + m_propertyNodesVisibleList[ i ].OrderIndex = 0; + } + } + else + { + m_propertyNodesVisibleList[ i ].OrderIndex = count + propoffset; + count++; + } + } + } + + public void CopyPropertyListFrom( MasterNode masterNode ) + { + m_lastCount = masterNode.ReordableListLastCount; + m_propertyNodesVisibleList.Clear(); + m_propertyNodesVisibleList.AddRange( masterNode.PropertyNodesVisibleList ); + } + + public virtual void UpdateFromShader( Shader newShader ) { } + + public void ClearUpdateEvents() + { + OnShaderUpdatedEvent = null; + OnMaterialUpdatedEvent = null; + } + + public Material CurrentMaterial { get { return m_currentMaterial; } set { m_currentMaterial = value; } } + public Shader CurrentShader + { + set + { + if( value != null ) + { + SetName( value.name ); + } + + m_currentShader = value; + FireShaderChangedEvt(); + } + get { return m_currentShader; } + } + public virtual void OnRefreshLinkedPortsComplete() { } + public virtual void ReleaseResources() { } + public override void Destroy() + { + base.Destroy(); + OnMaterialUpdatedEvent = null; + OnShaderUpdatedEvent = null; + m_masterNodeOnTex = null; + m_masterNodeOffTex = null; + m_gpuInstanceOnTex = null; + m_gpuInstanceOffTex = null; + m_addShaderKeywordStyle = null; + m_removeShaderKeywordStyle = null; + m_smallAddShaderKeywordItemStyle = null; + m_smallRemoveShaderKeywordStyle = null; + m_shaderKeywords.Clear(); + m_shaderKeywords = null; + m_propertyReordableList = null; + m_propertyAdjustment = null; + if( m_currentDataCollector != null ) + { + m_currentDataCollector.Destroy(); + m_currentDataCollector = null; + } + } + + public static void OpenShaderBody( ref string result, string name ) + { + result += string.Format( "Shader \"{0}\"\n", name ) + "{\n"; + } + + public static void CloseShaderBody( ref string result ) + { + result += "}\n"; + } + + public static void OpenSubShaderBody( ref string result ) + { + result += "\n\tSubShader\n\t{\n"; + } + + public static void CloseSubShaderBody( ref string result ) + { + result += "\t}\n"; + } + + public static void AddShaderProperty( ref string result, string name, string value ) + { + result += string.Format( "\t{0} \"{1}\"\n", name, value ); + } + + public static void AddShaderPragma( ref string result, string value ) + { + result += string.Format( "\t\t#pragma {0}\n", value ); + } + + public static void AddRenderState( ref string result, string state, string stateParams ) + { + result += string.Format( "\t\t{0} {1}\n", state, stateParams ); + } + + public static void AddRenderTags( ref string result, string tags ) + { + result += string.Format( IndentationHelper, tags ); ; + } + + public static void AddShaderLOD( ref string result, int shaderLOD ) + { + if( shaderLOD > 0 ) + { + result += string.Format( ShaderLODFormat, shaderLOD ); + } + } + + public static void AddMultilineBody( ref string result, string[] lines ) + { + for( int i = 0; i < lines.Length; i++ ) + { + result += string.Format( IndentationHelper, lines[ i ] ); + } + } + + public static void OpenCGInclude( ref string result ) + { + result += "\t\tCGINCLUDE\n"; + } + + public static void OpenCGProgram( ref string result ) + { + result += "\t\tCGPROGRAM\n"; + } + + public static void CloseCGProgram( ref string result ) + { + result += "\n\t\tENDCG\n"; + } + + public string ShaderName + { + //get { return ( ( _isHidden ? "Hidden/" : string.Empty ) + ( String.IsNullOrEmpty( _shaderCategory ) ? "" : ( _shaderCategory + "/" ) ) + _shaderName ); } + get { return m_shaderName; } + set + { + m_shaderName = value; + string[] shaderNameArr = m_shaderName.Split( '/' ); + m_croppedShaderName = shaderNameArr[ shaderNameArr.Length - 1 ]; + + if( m_shaderNameIsTitle ) + m_content.text = GenerateClippedTitle( m_croppedShaderName ); + + m_sizeIsDirty = true; + } + } + public string CurrentInspector { get { return m_customInspectorName; } } + public string CustomInspectorFormatted { get { return string.Format( CustomInspectorFormat, m_customInspectorName ); } } + public string CroppedShaderName { get { return m_croppedShaderName; } } + public virtual AvailableShaderTypes CurrentMasterNodeCategory { get { return ( m_masterNodeCategory == 0 ) ? AvailableShaderTypes.SurfaceShader : AvailableShaderTypes.Template; } } + public int CurrentMasterNodeCategoryIdx { get { return m_masterNodeCategory; } } + public MasterNodeDataCollector CurrentDataCollector { get { return m_currentDataCollector; } set { m_currentDataCollector = value; } } + public List PropertyNodesVisibleList { get { return m_propertyNodesVisibleList; } } + public ReorderableList PropertyReordableList { get { return m_propertyReordableList; } } + public int ReordableListLastCount { get { return m_lastCount; } } + public MasterNodeCategoriesData CurrentCategoriesData { get { return m_availableCategories[ m_masterNodeCategory ]; } } + public int ShaderLOD + { + get { return m_shaderLOD; } + set + { + m_shaderLOD = Mathf.Max( 0, value ); + } + } + public bool SamplingMacros + { + get { return m_samplingMacros; } + set + { + m_samplingMacros = value; + if( IsLODMainMasterNode ) + ContainerGraph.SamplingMacros = value; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNode.cs.meta new file mode 100644 index 0000000..8a8a933 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7fc2c839ab9f3a045877b59493c51502 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNodeDataCollector.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNodeDataCollector.cs new file mode 100644 index 0000000..2fd789d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNodeDataCollector.cs @@ -0,0 +1,2311 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using System.Text.RegularExpressions; + +namespace AmplifyShaderEditor +{ + public class PropertyDataCollector + { + public int NodeId; + public int OrderIndex; + public string PropertyName; + public WirePortDataType DataType; + public bool IsDirective; + + public PropertyDataCollector( int nodeId, string propertyName, int orderIndex = -1, bool isDirective = false ) + { + NodeId = nodeId; + PropertyName = propertyName; + OrderIndex = orderIndex; + IsDirective = isDirective; + } + } + + public class InputCoordsCollector + { + public int NodeId; + public string CoordName; + public WirePortDataType DataType; + public PrecisionType Precision; + public int TextureSlot; + public int TextureIndex; + + public InputCoordsCollector( int nodeId, string coordName, WirePortDataType dataType, PrecisionType precision, int textureSlot, int textureIndex ) + { + NodeId = nodeId; + CoordName = coordName; + DataType = dataType; + Precision = precision; + TextureSlot = textureSlot; + TextureIndex = textureIndex; + } + } + + public class TextureDefaultsDataColector + { + private List m_names = new List(); + private List m_values = new List(); + public void AddValue( string newName, Texture newValue ) + { + m_names.Add( newName ); + m_values.Add( newValue ); + } + + public void Destroy() + { + m_names.Clear(); + m_names = null; + + m_values.Clear(); + m_values = null; + } + + public string[] NamesArr { get { return m_names.ToArray(); } } + public Texture[] ValuesArr { get { return m_values.ToArray(); } } + } + + public enum TextureChannelUsage + { + Not_Used, + Used, + Required + } + + [Flags] + public enum MacrosMask + { + NONE = 0, + AUTO = 1 << 1, + LOD = 1 << 2, + BIAS = 1 << 3, + GRAD = 1 << 4, + } + + public class MasterNodeDataCollector + { + private bool m_showDebugMessages = false; + private string m_input; + private string m_customInput; + private string m_properties; + private string m_instancedProperties; + private string m_instanceBlockName; + private string m_uniforms; + private string m_includes; + private string m_pragmas; + private string m_defines; + private string m_instructions; + private string m_localVariables; + private string m_vertexLocalVariables; + private string m_specialLocalVariables; + private string m_vertexData; + private string m_customOutput; + private string m_functions; + private string m_grabPass; + + private List m_inputList; + private List m_customInputList; + private List m_propertiesList; + private List m_instancedPropertiesList; + private List m_dotsPropertiesList; + private List m_dotsDefinesList; + private List m_uniformsList; + private List m_includesList; + private List m_additionalDirectivesList; + //private List m_tagsList; + private List m_pragmasList; + private List m_definesList; + private List m_instructionsList; + private List m_localVariablesList; + private List m_vertexLocalVariablesList; + private List m_specialLocalVariablesList; + private List m_vertexDataList; + private List m_customOutputList; + private List m_functionsList; + private List m_grabPassList; + private List m_aboveUsePassesList; + private List m_belowUsePassesList; + + private List m_customShadowCoordsList; + private List m_packSlotsList; + private string m_customAppDataItems; + + private Dictionary m_inputDict; + private Dictionary m_customInputDict; + private Dictionary m_propertiesDict; + private Dictionary m_instancedPropertiesDict; + private Dictionary m_dotsPropertiesDict; + private Dictionary m_uniformsDict; + private Dictionary m_softRegisteredUniformsDict; + private Dictionary m_includesDict; + private Dictionary m_additionalDirectivesDict; + private Dictionary m_includesExclusionDict; + + //private Dictionary m_tagsDict; + private Dictionary m_pragmasDict; + private Dictionary m_definesDict; + private Dictionary m_virtualCoordinatesDict; + private Dictionary m_virtualVariablesDict; + private Dictionary m_localVariablesDict; + private Dictionary m_vertexLocalVariablesDict; + private Dictionary m_specialLocalVariablesDict; + private Dictionary m_vertexDataDict; + private Dictionary m_customOutputDict; + private Dictionary m_localFunctions; + private Dictionary m_grabPassDict; + private Dictionary m_usePassesDict; + private Dictionary m_customAppDataItemsDict; + + private Dictionary m_customShadowCoordsDict; + + private TextureChannelUsage[] m_requireTextureProperty = { TextureChannelUsage.Not_Used, TextureChannelUsage.Not_Used, TextureChannelUsage.Not_Used, TextureChannelUsage.Not_Used }; + + private bool m_dirtyAppData; + private bool m_dirtyInputs; + private bool m_dirtyCustomInputs; + private bool m_dirtyFunctions; + private bool m_dirtyProperties; + private bool m_dirtyInstancedProperties; + private bool m_dirtyUniforms; + private bool m_dirtyIncludes; + private bool m_dirtyPragmas; + private bool m_dirtyDefines; + private bool m_dirtyAdditionalDirectives; + private bool m_dirtyInstructions; + private bool m_dirtyLocalVariables; + private bool m_dirtyVertexLocalVariables; + private bool m_dirtySpecialLocalVariables; + private bool m_dirtyPerVertexData; + private bool m_dirtyNormal; + private bool m_forceNormal; + + private bool m_usingInternalData; + private bool m_usingVertexColor; + private bool m_usingWorldPosition; + private bool m_usingWorldNormal; + private bool m_usingScreenPos; + private bool m_usingWorldReflection; + private bool m_usingViewDirection; + private bool m_usingLightAttenuation; + private bool m_usingArrayDerivatives; + private bool m_usingTextureArrays; + private bool m_usingExtraStandardMacros; + private MacrosMask m_using2DMacrosMask; + private MacrosMask m_using3DMacrosMask; + private MacrosMask m_usingCUBEMacrosMask; + private MacrosMask m_using2DArrayMacrosMask; + private bool m_usingExtra3DSRPMacros; + + private bool m_usingHigherSizeTexcoords; + private bool m_usingCustomScreenPos; + + private bool m_usingCustomOutlineColor; + private bool m_usingCustomOutlineWidth; + private bool m_usingCustomOutlineAlpha; + private int m_customOutlineSelectedAlpha = 0; + private bool m_usingCustomOutput; + + private bool m_safeNormalizeLightDir; + private bool m_safeNormalizeViewDir; + + private bool m_isOutlineDataCollector = false; + + private bool m_forceNormalIsDirty; + private bool m_grabPassIsDirty; + private bool m_tesselationActive; + + private Dictionary m_propertyNodes; + private MasterNode m_masterNode; + + private int m_availableVertexTempId = 0; + private int m_availableFragTempId = 0; + + private MasterNodePortCategory m_portCategory; + private PortGenType m_genType; + private RenderPath m_renderPath = RenderPath.All; + private NodeAvailability m_currentCanvasMode = NodeAvailability.SurfaceShader; + + //Templates specific data + private AvailableShaderTypes m_masterNodeCategory; + private List m_vertexInputList; + private Dictionary m_vertexInputDict; + private List m_interpolatorsList; + private Dictionary m_interpolatorsDict; + private List m_vertexInterpDeclList; + private Dictionary m_vertexInterpDeclDict; + private TemplateDataCollector m_templateDataCollector; + + public MasterNodeDataCollector( MasterNode masterNode ) : this() + { + m_masterNode = masterNode; + m_masterNodeCategory = masterNode.CurrentMasterNodeCategory; + m_currentCanvasMode = masterNode.ContainerGraph.CurrentCanvasMode; + } + + public MasterNodeDataCollector() + { + //m_masterNode = masterNode; + m_input = "struct Input\n\t\t{\n"; + m_customInput = "\t\tstruct SurfaceOutput{0}\n\t\t{\n"; + m_properties = IOUtils.PropertiesBegin;//"\tProperties\n\t{\n"; + m_uniforms = string.Empty; + m_instructions = string.Empty; + m_includes = string.Empty; + m_pragmas = string.Empty; + m_defines = string.Empty; + m_localVariables = string.Empty; + m_specialLocalVariables = string.Empty; + m_customOutput = string.Empty; + + m_inputList = new List(); + m_customInputList = new List(); + m_propertiesList = new List(); + m_instancedPropertiesList = new List(); + m_dotsPropertiesList = new List(); + m_dotsDefinesList = new List(); + m_uniformsList = new List(); + m_includesList = new List(); + m_additionalDirectivesList = new List(); + //m_tagsList = new List(); + m_pragmasList = new List(); + m_definesList = new List(); + m_instructionsList = new List(); + m_localVariablesList = new List(); + m_vertexLocalVariablesList = new List(); + m_specialLocalVariablesList = new List(); + m_vertexDataList = new List(); + m_customOutputList = new List(); + m_functionsList = new List(); + m_grabPassList = new List(); + m_aboveUsePassesList = new List(); + m_belowUsePassesList = new List(); + m_customAppDataItems = string.Empty; + m_customAppDataItemsDict = new Dictionary(); + m_customShadowCoordsList = new List(); + m_packSlotsList = new List(); + + m_inputDict = new Dictionary(); + m_customInputDict = new Dictionary(); + + m_propertiesDict = new Dictionary(); + m_instancedPropertiesDict = new Dictionary(); + m_dotsPropertiesDict = new Dictionary(); + m_uniformsDict = new Dictionary(); + m_softRegisteredUniformsDict = new Dictionary(); + m_includesDict = new Dictionary(); + m_additionalDirectivesDict = new Dictionary(); + m_includesExclusionDict = new Dictionary(); + + //m_tagsDict = new Dictionary(); + m_pragmasDict = new Dictionary(); + m_definesDict = new Dictionary(); + m_virtualCoordinatesDict = new Dictionary(); + m_localVariablesDict = new Dictionary(); + m_virtualVariablesDict = new Dictionary(); + m_specialLocalVariablesDict = new Dictionary(); + m_vertexLocalVariablesDict = new Dictionary(); + m_localFunctions = new Dictionary(); + m_vertexDataDict = new Dictionary(); + m_customOutputDict = new Dictionary(); + m_grabPassDict = new Dictionary(); + m_usePassesDict = new Dictionary(); + + m_customShadowCoordsDict = new Dictionary(); + + m_dirtyAppData = false; + m_dirtyInputs = false; + m_dirtyCustomInputs = false; + m_dirtyProperties = false; + m_dirtyInstancedProperties = false; + m_dirtyUniforms = false; + m_dirtyInstructions = false; + m_dirtyIncludes = false; + m_dirtyPragmas = false; + m_dirtyDefines = false; + m_dirtyAdditionalDirectives = false; + m_dirtyLocalVariables = false; + m_dirtySpecialLocalVariables = false; + m_grabPassIsDirty = false; + + m_portCategory = MasterNodePortCategory.Fragment; + m_propertyNodes = new Dictionary(); + m_showDebugMessages = ( m_showDebugMessages && DebugConsoleWindow.DeveloperMode ); + + //templates + //m_masterNodeCategory = masterNode.CurrentMasterNodeCategory; + + m_vertexInputList = new List(); + m_vertexInputDict = new Dictionary(); + + m_interpolatorsList = new List(); + m_interpolatorsDict = new Dictionary(); + + m_vertexInterpDeclList = new List(); + m_vertexInterpDeclDict = new Dictionary(); + + m_templateDataCollector = new TemplateDataCollector(); + } + + public void SetChannelUsage( int channelId, TextureChannelUsage usage ) + { + if( channelId > -1 && channelId < 4 ) + m_requireTextureProperty[ channelId ] = usage; + } + + public TextureChannelUsage GetChannelUsage( int channelId ) + { + if( channelId > -1 && channelId < 4 ) + return m_requireTextureProperty[ channelId ]; + + return TextureChannelUsage.Not_Used; + } + + public void OpenPerVertexHeader( bool includeCustomData ) + { + string appData = "inout " + ( m_dirtyAppData ? Constants.CustomAppDataFullName : Constants.AppDataFullName ) + " "; + if( m_dirtyPerVertexData ) + return; + + m_dirtyPerVertexData = true; + if( m_tesselationActive ) + { + m_vertexData = "\t\tvoid " + Constants.VertexDataFunc + "( " + appData + Constants.VertexShaderInputStr + " )\n\t\t{\n"; + } + else + { + m_vertexData = "\t\tvoid " + Constants.VertexDataFunc + "( " + appData + Constants.VertexShaderInputStr + ( includeCustomData ? ( string.Format( ", out Input {0}", Constants.VertexShaderOutputStr ) ) : string.Empty ) + " )\n\t\t{\n"; + if( includeCustomData ) + m_vertexData += string.Format( "\t\t\tUNITY_INITIALIZE_OUTPUT( Input, {0} );\n", Constants.VertexShaderOutputStr ); + } + } + + public void ClosePerVertexHeader() + { + if( m_dirtyPerVertexData ) + m_vertexData += "\t\t}\n\n"; + } + + public void AddToVertexDisplacement( string value, VertexMode vertexMode ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + if( !m_dirtyPerVertexData ) + { + OpenPerVertexHeader( true ); + } + + switch( vertexMode ) + { + default: + case VertexMode.Relative: + { + m_vertexData += "\t\t\t" + Constants.VertexShaderInputStr + ".vertex.xyz += " + value + ";\n"; + } + break; + case VertexMode.Absolute: + { + m_vertexData += "\t\t\t" + Constants.VertexShaderInputStr + ".vertex.xyz = " + value + ";\n"; + } + break; + } + m_vertexData += "\t\t\t" + Constants.VertexShaderInputStr + ".vertex.w = 1;\n"; + } + + + public void AddToVertexNormal( string value ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + if( !m_dirtyPerVertexData ) + { + OpenPerVertexHeader( true ); + } + + m_vertexData += "\t\t\t" + Constants.VertexShaderInputStr + ".normal = " + value + ";\n"; + } + + + public void AddVertexInstruction( string value, int nodeId = -1, bool addDelimiters = true ) + { + if( !m_dirtyPerVertexData && !IsOutlineDataCollector/*&& !(m_usingCustomOutlineColor || m_usingCustomOutlineWidth)*/ ) + { + OpenPerVertexHeader( true ); + } + if( !m_vertexDataDict.ContainsKey( value ) ) + { + m_vertexDataDict.Add( value, new PropertyDataCollector( nodeId, value ) ); + m_vertexDataList.Add( m_vertexDataDict[ value ] ); + m_vertexData += ( addDelimiters ? ( "\t\t\t" + value + ";\n" ) : value ); + } + } + + public bool ContainsInput( string value ) + { + return m_inputDict.ContainsKey( value ); + } + + public void AddToInput( int nodeId, string interpName, WirePortDataType dataType, PrecisionType precision = PrecisionType.Float, bool addSemiColon = true ) + { + string value = UIUtils.PrecisionWirePortToCgType( precision, dataType ) + " " + interpName; + AddToInput( nodeId, value, addSemiColon ); + + if( !m_customShadowCoordsDict.ContainsKey( interpName ) ) + { + int slot = 0; + int index = 0; + int size = UIUtils.GetChannelsAmount( dataType ); + + if( m_packSlotsList.Count == 0 ) + m_packSlotsList.Add( 4 ); + + for( int i = 0; i < m_packSlotsList.Count; i++ ) + { + slot = i; + if( m_packSlotsList[ i ] >= size ) + { + index = 4 - m_packSlotsList[ i ]; + m_packSlotsList[ i ] -= size; + break; + } + else if( i == m_packSlotsList.Count - 1 ) + { + m_packSlotsList.Add( 4 ); + } + } + m_customShadowCoordsDict.Add( interpName, new InputCoordsCollector( nodeId, interpName, dataType, precision, slot, index ) ); + m_customShadowCoordsList.Add( m_customShadowCoordsDict[ interpName ] ); + } + } + + public void AddToInput( int nodeId, SurfaceInputs surfaceInput, PrecisionType precision = PrecisionType.Float, bool addSemiColon = true ) + { + switch( surfaceInput ) + { + case SurfaceInputs.VIEW_DIR: + UsingViewDirection = true; + break; + case SurfaceInputs.SCREEN_POS: + UsingScreenPos = true; + break; + case SurfaceInputs.WORLD_POS: + UsingWorldPosition = true; + break; + case SurfaceInputs.WORLD_REFL: + UsingWorldReflection = true; + break; + case SurfaceInputs.WORLD_NORMAL: + UsingWorldNormal = true; + break; + case SurfaceInputs.INTERNALDATA: + UsingInternalData = true; + break; + case SurfaceInputs.COLOR: + UsingVertexColor = true; + break; + } + + AddToInput( nodeId, UIUtils.GetInputDeclarationFromType( precision, surfaceInput ), addSemiColon ); + } + + /// + /// Direct access to inputs, plese use another overload + /// + /// + /// + /// + public void AddToInput( int nodeId, string value, bool addSemiColon ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + if( !m_inputDict.ContainsKey( value ) ) + { + m_inputDict.Add( value, new PropertyDataCollector( nodeId, value ,-1, !addSemiColon) ); + m_inputList.Add( m_inputDict[ value ] ); + + m_input += "\t\t\t" + value + ( ( addSemiColon ) ? ( ";\n" ) : "\n" ); + m_dirtyInputs = true; + } + } + + public void CloseInputs() + { + m_input += "\t\t};"; + } + + public void ChangeCustomInputHeader( string value ) + { + m_customInput = m_customInput.Replace( "{0}", value ); + } + + public void AddToCustomInput( int nodeId, string value, bool addSemiColon ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + if( !m_customInputDict.ContainsKey( value ) ) + { + m_customInputDict.Add( value, new PropertyDataCollector( nodeId, value ) ); + m_customInputList.Add( m_customInputDict[ value ] ); + m_customInput += "\t\t\t" + value + ( ( addSemiColon ) ? ( ";\n" ) : "\n" ); + m_dirtyCustomInputs = true; + } + } + + public void CloseCustomInputs() + { + m_customInput += "\t\t};"; + } + + + // Used by Template Master Node to add tabs into variable declaration + public void TabifyInstancedVars() + { + for( int i = 0; i < m_instancedPropertiesList.Count; i++ ) + { + m_instancedPropertiesList[ i ].PropertyName = '\t' + m_instancedPropertiesList[ i ].PropertyName; + } + } + + private int GetWeightForInstancedType( WirePortDataType type ) + { + switch( type ) + { + case WirePortDataType.INT: + case WirePortDataType.FLOAT: return -1; + case WirePortDataType.FLOAT2: return -2; + case WirePortDataType.FLOAT3: return -3; + case WirePortDataType.COLOR: + case WirePortDataType.FLOAT4: return -4; + case WirePortDataType.FLOAT3x3: return -9; + case WirePortDataType.FLOAT4x4: return -16; + default: + case WirePortDataType.OBJECT: + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + case WirePortDataType.SAMPLERSTATE: + return 0; + } + } + + public void OptimizeInstancedProperties() + { + if( m_instancedPropertiesList.Count > 0 ) + { + m_instancedProperties = string.Empty; + m_instancedPropertiesList.Sort( ( x, y ) => { return GetWeightForInstancedType( x.DataType ).CompareTo( GetWeightForInstancedType( y.DataType ) ); } ); + int count = m_instancedPropertiesList.Count; + for( int i = 0; i < count; i++ ) + { + m_instancedProperties += m_instancedPropertiesList[ i ].PropertyName; + } + } + } + // Instanced properties + public void SetupInstancePropertiesBlock( string blockName ) + { + m_instanceBlockName = blockName; + if( IsTemplate ) + { + //if( DebugConsoleWindow.DeveloperMode ) + // Debug.LogWarning( "SetupInstancePropertiesBlock should not be used during template mode" ); + + return; + } + + OptimizeInstancedProperties(); + + if( m_dirtyInstancedProperties ) + { + m_instancedProperties = string.Format( IOUtils.InstancedPropertiesBeginTabs, blockName ) + m_instancedProperties + IOUtils.InstancedPropertiesEndTabs; + } + } + + public void AddToDotsProperties( WirePortDataType dataType, int nodeId, string value, int orderIndex, PrecisionType precision ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + string prop = string.Format( IOUtils.DotsInstancedPropertiesData, UIUtils.PrecisionWirePortToCgType( precision, dataType ), value ); + string define = string.Format( IOUtils.DotsInstancedDefinesData, UIUtils.PrecisionWirePortToCgType( precision, dataType ), value ); + + if( !m_dotsPropertiesDict.ContainsKey( value ) ) + { + PropertyDataCollector dataColl = new PropertyDataCollector( nodeId, prop, orderIndex ); + dataColl.DataType = dataType; + m_dotsPropertiesDict.Add( value, dataColl ); + m_dotsPropertiesList.Add( dataColl ); + + dataColl = new PropertyDataCollector( nodeId, define, orderIndex ); + m_dotsDefinesList.Add( dataColl ); + } + } + + public void AddToInstancedProperties( WirePortDataType dataType, int nodeId, string value, int orderIndex ) + { + if( string.IsNullOrEmpty( value ) ) + return; + string uniformValue = value.Contains( "uniform" ) ? value : "uniform " + value; + if( !m_instancedPropertiesDict.ContainsKey( value ) && + !m_uniformsDict.ContainsKey( value ) && + !m_uniformsDict.ContainsKey( uniformValue ) + ) + { + PropertyDataCollector dataColl = new PropertyDataCollector( nodeId, value, orderIndex ); + dataColl.DataType = dataType; + m_instancedPropertiesDict.Add( value, dataColl ); + m_instancedPropertiesList.Add( dataColl ); + m_instancedProperties += value; + m_dirtyInstancedProperties = true; + } + } + + public void CloseInstancedProperties() + { + if( m_dirtyInstancedProperties ) + { + m_instancedProperties += IOUtils.InstancedPropertiesEnd; + } + } + + // Properties + public void CopyPropertiesFromDataCollector( MasterNodeDataCollector dataCollector ) + { + if( dataCollector == null ) + return; + + int propertyCount = dataCollector.PropertiesList.Count; + for( int i = 0; i < propertyCount; i++ ) + { + AddToProperties( dataCollector.PropertiesList[ i ].NodeId, + dataCollector.PropertiesList[ i ].PropertyName, + dataCollector.PropertiesList[ i ].OrderIndex ); + } + + foreach( KeyValuePair kvp in dataCollector.GrabPassDict ) + { + AddGrabPass( kvp.Value ); + } + + m_templateDataCollector.CopySRPPropertiesFromDataCollector( -1, dataCollector.TemplateDataCollectorInstance ); + } + + public void AddToProperties( int nodeId, string value, int orderIndex ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + if( !m_propertiesDict.ContainsKey( value ) ) + { + //Debug.Log( UIUtils ); + m_propertiesDict.Add( value, new PropertyDataCollector( nodeId, value, orderIndex ) ); + m_propertiesList.Add( m_propertiesDict[ value ] ); + m_properties += string.Format( IOUtils.PropertiesElement, value ); + m_dirtyProperties = true; + } + } + + public string BuildPropertiesString() + { + List list = new List( m_propertiesDict.Values ); + //for ( int i = 0; i < list.Count; i++ ) + //{ + // Debug.Log( list[ i ].OrderIndex + " " + list[ i ].PropertyName ); + //} + + list.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + CleanUpList( ref list ); + m_properties = IOUtils.PropertiesBegin; + for( int i = 0; i < list.Count; i++ ) + { + m_properties += string.Format( IOUtils.PropertiesElement, list[ i ].PropertyName ); + //Debug.Log() + } + m_properties += IOUtils.PropertiesEnd; + return m_properties; + } + + public bool ContainsProperty( string propertyName ) + { + // TODO: this needs to change, find the property should be dependant of have a "(" + List list = new List( m_propertiesDict.Values ); + return list.Find( x => x.PropertyName.Contains( propertyName+"(" ) ) != null; + } + + public string[] BuildUnformatedPropertiesStringArr() + { + List list = new List( m_propertiesDict.Values ); + list.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + CleanUpList( ref list ); + string[] arr = new string[ list.Count ]; + for( int i = 0; i < list.Count; i++ ) + { + arr[ i ] = list[ i ].PropertyName; + } + return arr; + } + //This clean up was set to remove Header attributes from shader functions which would be last on the property list + //Thus creating a label on the inspector with no properties below + public void CleanUpList( ref List list ) + { + if( list.Count == 0 ) + return; + + if( list[ list.Count - 1 ].PropertyName.Contains( "[Header(" ) ) + { + //Check if this is a complete property or just a standalone header + Match match = Regex.Match( list[ list.Count - 1 ].PropertyName, TemplateHelperFunctions.PropertiesPatternG ); + if( !match.Success ) + { + list.RemoveAt( list.Count - 1 ); + CleanUpList( ref list ); + } + } + } + + public void CloseProperties() + { + if( m_dirtyProperties ) + { + m_properties += IOUtils.PropertiesEnd; + } + } + + public void AddUsePass( string value, bool above ) + { + if( m_usePassesDict.ContainsKey( value ) ) + return; + m_usePassesDict.Add( value, value ); + if( above ) + { + m_aboveUsePassesList.Add( new PropertyDataCollector( -1, value ) ); + } + else + { + m_belowUsePassesList.Add( new PropertyDataCollector( -1, value ) ); + } + } + + public void AddGrabPass( string value ) + { + if( m_grabPassDict.ContainsKey( value ) ) + return; + + m_grabPassDict.Add( value, value ); + + if( string.IsNullOrEmpty( value ) ) + { + if( !m_grabPassIsDirty ) + m_grabPass += IOUtils.GrabPassEmpty; + } + else + { + m_grabPass += IOUtils.GrabPassBegin + value + IOUtils.GrabPassEnd; + } + m_grabPassList.Add( new PropertyDataCollector( -1, m_grabPass.Replace( "\t", string.Empty ).Replace( "\n", string.Empty ) ) ); + m_grabPassIsDirty = true; + } + + // This is used by templates global variables to register already existing globals/properties + //public void SoftRegisterUniform( string dataName ) + //{ + // if( !m_uniformsDict.ContainsKey( dataName ) ) + // { + // m_uniformsDict.Add( dataName, new PropertyDataCollector( -1, dataName ) ); + // } + //} + + public string GenerateInstanced(PrecisionType precisionType, WirePortDataType dataType,string propertyName ) + { + if( IsSRP ) + { + return string.Format( IOUtils.LWSRPInstancedPropertiesElement, UIUtils.PrecisionWirePortToCgType( precisionType, dataType ), propertyName ); + } + else + { + return string.Format( IOUtils.InstancedPropertiesElement, UIUtils.PrecisionWirePortToCgType( precisionType, dataType ), propertyName ); + } + } + + public bool CheckIfSoftRegistered( string name ) + { + return m_softRegisteredUniformsDict.ContainsKey( name ); + } + + public void SoftRegisterUniform( TemplateShaderPropertyData data ) + { + bool excludeUniformKeyword = ( data.PropertyType == PropertyType.InstancedProperty ) || IsSRP; + + string uniformName = data.IsMacro? data.PropertyName: + UIUtils.GenerateUniformName( excludeUniformKeyword, data.PropertyDataType, data.PropertyName ); + if( !m_uniformsDict.ContainsKey( uniformName ) ) + { + PropertyDataCollector newEntry = new PropertyDataCollector( -1, uniformName ); + m_uniformsDict.Add( uniformName, newEntry ); + m_softRegisteredUniformsDict.Add( uniformName, newEntry ); + } + + string instancedUniform = GenerateInstanced( PrecisionType.Float, data.PropertyDataType, data.PropertyName ); + if( !m_uniformsDict.ContainsKey( instancedUniform ) ) + { + PropertyDataCollector newEntry = new PropertyDataCollector( -1, instancedUniform ); + m_uniformsDict.Add( instancedUniform, newEntry ); + m_softRegisteredUniformsDict.Add( instancedUniform, newEntry ); + } + + instancedUniform = GenerateInstanced( PrecisionType.Half, data.PropertyDataType, data.PropertyName ); + if( !m_uniformsDict.ContainsKey( instancedUniform ) ) + { + PropertyDataCollector newEntry = new PropertyDataCollector( -1, instancedUniform ); + m_uniformsDict.Add( instancedUniform, newEntry ); + m_softRegisteredUniformsDict.Add( instancedUniform, newEntry ); + } + } + + public void AddToUniforms( int nodeId, string dataType, string dataName, bool checkSRPBatch = false, bool excludeUniform = false ) + { + if( string.IsNullOrEmpty( dataName ) || string.IsNullOrEmpty( dataType ) ) + return; + + string value = UIUtils.GenerateUniformName( IsSRP || excludeUniform, dataType, dataName ); + if( !m_uniformsDict.ContainsKey( value ) && !m_uniformsDict.ContainsKey( dataName ) ) + { + m_uniformsDict.Add( value, new PropertyDataCollector( nodeId, value ) ); + if( IsSRP && checkSRPBatch ) + { + m_templateDataCollector.AddSRPBatcherProperty( nodeId, value ); + } + else + { + m_uniforms += "\t\t" + value + '\n'; + m_uniformsList.Add( m_uniformsDict[ value ] ); + } + m_dirtyUniforms = true; + } + } + + public void AddToUniforms( int nodeId, string value, bool checkSRPBatch = false ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + if( !m_uniformsDict.ContainsKey( value ) ) + { + m_uniformsDict.Add( value, new PropertyDataCollector( nodeId, value ) ); + if( IsSRP && checkSRPBatch ) + { + m_templateDataCollector.AddSRPBatcherProperty( nodeId, value ); + } + else + { + m_uniforms += "\t\t" + value + '\n'; + m_uniformsList.Add( m_uniformsDict[ value ] ); + } + m_dirtyUniforms = true; + } + } + public void AddFaceMacros() + { + for( int i = 0 ; i < Constants.FaceMacros.Length; i++ ) + { + AddToDirectives( Constants.FaceMacros[ i ] ); + } + } + + public void AddASEMacros() + { + if( Using2DMacrosMask == MacrosMask.NONE && Using3DMacrosMask == MacrosMask.NONE && UsingCUBEMacrosMask == MacrosMask.NONE && Using2DArrayMacrosMask == MacrosMask.NONE ) + return; + + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; +#if !UNITY_2018_1_OR_NEWER + if( outsideGraph.IsStandardSurface && ( ( Using2DArrayMacrosMask & MacrosMask.AUTO ) == MacrosMask.AUTO || ( Using2DArrayMacrosMask & MacrosMask.LOD ) == MacrosMask.LOD ) ) + { + return; + } +#endif + + //Debug.Log( UsingMacrosMask ); + AddToDirectives( Constants.CustomASEStandarSamplingMacrosHelper[ 0 ], 1 ); + + if( ( Using2DMacrosMask & MacrosMask.AUTO ) == MacrosMask.AUTO ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 0 ], 1 ); + if( ( Using2DMacrosMask & MacrosMask.LOD ) == MacrosMask.LOD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 1 ], 1 ); + if( ( Using2DMacrosMask & MacrosMask.BIAS ) == MacrosMask.BIAS ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 2 ], 1 ); + if( ( Using2DMacrosMask & MacrosMask.GRAD ) == MacrosMask.GRAD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 3 ], 1 ); + + if( ( Using3DMacrosMask & MacrosMask.AUTO ) == MacrosMask.AUTO ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 4 ], 1 ); + if( ( Using3DMacrosMask & MacrosMask.LOD ) == MacrosMask.LOD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 5 ], 1 ); + if( ( Using3DMacrosMask & MacrosMask.BIAS ) == MacrosMask.BIAS ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 6 ], 1 ); + if( ( Using3DMacrosMask & MacrosMask.GRAD ) == MacrosMask.GRAD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 7 ], 1 ); + + if( ( UsingCUBEMacrosMask & MacrosMask.AUTO ) == MacrosMask.AUTO ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 8 ], 1 ); + if( ( UsingCUBEMacrosMask & MacrosMask.LOD ) == MacrosMask.LOD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 9 ], 1 ); + if( ( UsingCUBEMacrosMask & MacrosMask.BIAS ) == MacrosMask.BIAS ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 10 ], 1 ); + if( ( UsingCUBEMacrosMask & MacrosMask.GRAD ) == MacrosMask.GRAD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 11 ], 1 ); + +#if !UNITY_2018_1_OR_NEWER + if( outsideGraph.IsStandardSurface ) + { + //if( ( Using2DArrayMacrosMask & MacrosMask.AUTO ) == MacrosMask.AUTO ) + // AddToDirectives( Constants.CustomASEArraySamplingMacrosRecent[ 0 ], 1 ); + //if( ( Using2DArrayMacrosMask & MacrosMask.LOD ) == MacrosMask.LOD ) + // AddToDirectives( Constants.CustomASEArraySamplingMacrosRecent[ 1 ], 1 ); + if( ( Using2DArrayMacrosMask & MacrosMask.BIAS ) == MacrosMask.BIAS ) + AddToDirectives( Constants.CustomASEArraySamplingMacrosRecent[ 2 ], 1 ); + if( ( Using2DArrayMacrosMask & MacrosMask.GRAD ) == MacrosMask.GRAD ) + AddToDirectives( Constants.CustomASEArraySamplingMacrosRecent[ 3 ], 1 ); + } + else +#endif + { + if( ( Using2DArrayMacrosMask & MacrosMask.AUTO ) == MacrosMask.AUTO ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 12 ], 1 ); + if( ( Using2DArrayMacrosMask & MacrosMask.LOD ) == MacrosMask.LOD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 13 ], 1 ); + if( ( Using2DArrayMacrosMask & MacrosMask.BIAS ) == MacrosMask.BIAS ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 14 ], 1 ); + if( ( Using2DArrayMacrosMask & MacrosMask.GRAD ) == MacrosMask.GRAD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosRecent[ 15 ], 1 ); + } + + AddToDirectives( Constants.CustomASEStandarSamplingMacrosHelper[ 1 ], 1 ); + + if( ( Using2DMacrosMask & MacrosMask.AUTO ) == MacrosMask.AUTO ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 0 ], 1 ); + if( ( Using2DMacrosMask & MacrosMask.LOD ) == MacrosMask.LOD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 1 ], 1 ); + if( ( Using2DMacrosMask & MacrosMask.BIAS ) == MacrosMask.BIAS ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 2 ], 1 ); + if( ( Using2DMacrosMask & MacrosMask.GRAD ) == MacrosMask.GRAD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 3 ], 1 ); + + if( ( Using3DMacrosMask & MacrosMask.AUTO ) == MacrosMask.AUTO ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 4 ], 1 ); + if( ( Using3DMacrosMask & MacrosMask.LOD ) == MacrosMask.LOD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 5 ], 1 ); + if( ( Using3DMacrosMask & MacrosMask.BIAS ) == MacrosMask.BIAS ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 6 ], 1 ); + if( ( Using3DMacrosMask & MacrosMask.GRAD ) == MacrosMask.GRAD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 7 ], 1 ); + + if( ( UsingCUBEMacrosMask & MacrosMask.AUTO ) == MacrosMask.AUTO ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 8 ], 1 ); + if( ( UsingCUBEMacrosMask & MacrosMask.LOD ) == MacrosMask.LOD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 9 ], 1 ); + if( ( UsingCUBEMacrosMask & MacrosMask.BIAS ) == MacrosMask.BIAS ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 10 ], 1 ); + if( ( UsingCUBEMacrosMask & MacrosMask.GRAD ) == MacrosMask.GRAD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 11 ], 1 ); + +#if !UNITY_2018_1_OR_NEWER + if( outsideGraph.IsStandardSurface ) + { + //if( ( Using2DArrayMacrosMask & MacrosMask.AUTO ) == MacrosMask.AUTO ) + // AddToDirectives( Constants.CustomASEArraySamplingMacrosOlder[ 0 ], 1 ); + //if( ( Using2DArrayMacrosMask & MacrosMask.LOD ) == MacrosMask.LOD ) + // AddToDirectives( Constants.CustomASEArraySamplingMacrosOlder[ 1 ], 1 ); + if( ( Using2DArrayMacrosMask & MacrosMask.BIAS ) == MacrosMask.BIAS ) + AddToDirectives( Constants.CustomASEArraySamplingMacrosOlder[ 2 ], 1 ); + if( ( Using2DArrayMacrosMask & MacrosMask.GRAD ) == MacrosMask.GRAD ) + AddToDirectives( Constants.CustomASEArraySamplingMacrosOlder[ 3 ], 1 ); + } + else +#endif + { + if( ( Using2DArrayMacrosMask & MacrosMask.AUTO ) == MacrosMask.AUTO ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 12 ], 1 ); + if( ( Using2DArrayMacrosMask & MacrosMask.LOD ) == MacrosMask.LOD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 13 ], 1 ); + if( ( Using2DArrayMacrosMask & MacrosMask.BIAS ) == MacrosMask.BIAS ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 14 ], 1 ); + if( ( Using2DArrayMacrosMask & MacrosMask.GRAD ) == MacrosMask.GRAD ) + AddToDirectives( Constants.CustomASEStandarSamplingMacrosOlder[ 15 ], 1 ); + } + + AddToDirectives( Constants.CustomASEStandarSamplingMacrosHelper[ 2 ], 1 ); + } + + public void AddToDirectives( string value, int orderIndex = -1 , AdditionalLineType type = AdditionalLineType.Custom ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + switch( type ) + { + case AdditionalLineType.Include:value = "#include " + value;break; + case AdditionalLineType.Define:value = "#define " + value; break; + case AdditionalLineType.Pragma:value = "#pragma " + value; break; + } + if( !m_additionalDirectivesDict.ContainsKey( value ) ) + { + PropertyDataCollector data = new PropertyDataCollector( -1, value, orderIndex ); + m_additionalDirectivesDict.Add( value, data ); + m_additionalDirectivesList.Add( data ); + m_dirtyAdditionalDirectives = true; + } + } + + public void AddToIncludes( int nodeId, string value ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + if( m_includesExclusionDict.ContainsKey( value ) ) + { + return; + } + + if( IsTemplate ) + { + if( m_templateDataCollector.HasDirective( AdditionalLineType.Include, value ) ) + return; + } + + if( !m_includesDict.ContainsKey( value ) ) + { + PropertyDataCollector data = new PropertyDataCollector( nodeId, "#include \"" + value + "\"" ); + m_includesDict.Add( value, data ); + m_includesList.Add( data ); + m_includes += "\t\t#include \"" + value + "\"\n"; + m_dirtyIncludes = true; + } + else + { + if( m_showDebugMessages ) UIUtils.ShowMessage( "AddToIncludes:Attempting to add duplicate " + value, MessageSeverity.Warning ); + } + } + + + public void RemoveFromIncludes( string value ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + if( !m_includesExclusionDict.ContainsKey( value ) ) + { + m_includesExclusionDict.Add( value, value ); + } + + if( m_includesDict.ContainsKey( value ) ) + { + PropertyDataCollector data = m_includesDict[ value ]; + m_includesDict.Remove( value ); + m_includesList.Remove( data ); + m_dirtyIncludes = true; + string finalValueName = "\t\t#include \"" + value + "\"\n"; + m_includes = m_includes.Replace( finalValueName, string.Empty ); + } + } + + //public void AddToTags( int nodeId, string name, string value ) + //{ + // if( string.IsNullOrEmpty( name ) || string.IsNullOrEmpty( value ) ) + // return; + + // if( !m_tagsDict.ContainsKey( name ) ) + // { + // string finalResult = string.Format( "\"{0}\"=\"{1}\"", name, value ); + // m_tagsDict.Add( name, new PropertyDataCollector( nodeId, finalResult ) ); + // m_tagsList.Add( new PropertyDataCollector( nodeId, finalResult ) ); + // } + //} + + public bool ContainsPragma( string value ) + { + return m_pragmasDict.ContainsKey( value ); + } + + public void AddToPragmas( int nodeId, string value ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + if( IsTemplate ) + { + if( m_templateDataCollector.HasDirective( AdditionalLineType.Pragma, value ) ) + return; + } + + if( !m_pragmasDict.ContainsKey( value ) ) + { + string finalValue = "#pragma " + value; + PropertyDataCollector dataCollector = new PropertyDataCollector( nodeId , finalValue ); + + //Adding both versions to dict so check can take both into account + m_pragmasDict.Add( value, dataCollector ); + m_pragmasDict.Add( finalValue , dataCollector ); + + m_pragmasList.Add( m_pragmasDict[ value ] ); + m_pragmas += "\t\t#pragma " + value + "\n"; + m_dirtyPragmas = true; + } + else + { + if( m_showDebugMessages ) UIUtils.ShowMessage( "AddToPragmas:Attempting to add duplicate " + value, MessageSeverity.Warning ); + } + } + + public bool ContainsDefine( string value ) + { + return m_definesDict.ContainsKey( value ); + } + + public void AddToDefines( int nodeId, string value, bool define = true ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + if( IsTemplate ) + { + if( m_templateDataCollector.HasDirective( AdditionalLineType.Define, value ) ) + return; + } + + if( !m_definesDict.ContainsKey( value ) ) + { + string defineValue = ( define ? "#define " : "#undef " ) + value; + PropertyDataCollector dataCollector = new PropertyDataCollector( nodeId , defineValue ); + + //Adding both versions to dict so check can take both into account + m_definesDict.Add( value, dataCollector ); + m_definesDict.Add( defineValue , dataCollector ); + + m_definesList.Add( m_definesDict[ value ] ); + m_defines += "\t\t" + defineValue + "\n"; + m_dirtyDefines = true; + } + else + { + if( m_showDebugMessages ) UIUtils.ShowMessage( "AddToDefines:Attempting to add duplicate " + value, MessageSeverity.Warning ); + } + } + + public int GetVirtualCoordinatesId( int nodeId, string coord, string lodBias ) + { + if( !m_virtualCoordinatesDict.ContainsKey( coord ) ) + { + m_virtualCoordinatesDict.Add( coord, nodeId ); + AddLocalVariable( nodeId, "VirtualCoord " + Constants.VirtualCoordNameStr + nodeId + " = VTComputeVirtualCoord" + lodBias + "(" + coord + ");" ); + return nodeId; + } + else + { + int fetchedId = 0; + m_virtualCoordinatesDict.TryGetValue( coord, out fetchedId ); + return fetchedId; + } + } + + public bool AddToLocalVariables( MasterNodePortCategory category, int nodeId, PrecisionType precisionType, WirePortDataType type, string varName, string varValue ) + { + if( string.IsNullOrEmpty( varName ) || string.IsNullOrEmpty( varValue ) ) + return false; + + string value = UIUtils.PrecisionWirePortToCgType( precisionType, type ) + " " + varName + " = " + varValue + ";"; + return AddToLocalVariables( category, nodeId, value ); + } + + public bool AddToLocalVariables( int nodeId, PrecisionType precisionType, WirePortDataType type, string varName, string varValue ) + { + if( string.IsNullOrEmpty( varName ) || string.IsNullOrEmpty( varValue ) ) + return false; + + string value = UIUtils.PrecisionWirePortToCgType( precisionType, type ) + " " + varName + " = " + varValue + ";"; + return AddToFragmentLocalVariables( nodeId, value ); + } + + public bool AddToLocalVariables( MasterNodePortCategory category, int nodeId, string value, bool ignoreDuplicates = false ) + { + if( string.IsNullOrEmpty( value ) ) + return false; + + switch( category ) + { + case MasterNodePortCategory.Vertex: + case MasterNodePortCategory.Tessellation: + { + return AddToVertexLocalVariables( nodeId, value, ignoreDuplicates ); + } + case MasterNodePortCategory.Fragment: + case MasterNodePortCategory.Debug: + { + return AddToFragmentLocalVariables( nodeId, value, ignoreDuplicates ); + } + } + + return false; + } + + public bool AddLocalVariable( int nodeId, string customType, string varName, string varValue ) + { + if( string.IsNullOrEmpty( varName ) || string.IsNullOrEmpty( varValue ) ) + return false; + + string value = customType + " " + varName + " = " + varValue + ";"; + return AddLocalVariable( nodeId, value ); + } + + private bool UsedLocalVariable( string value ) + { + switch( m_portCategory ) + { + case MasterNodePortCategory.Vertex: + case MasterNodePortCategory.Tessellation: + { + if( m_vertexLocalVariablesDict.ContainsKey( value ) ) + { + return true; + } + } + break; + case MasterNodePortCategory.Fragment: + case MasterNodePortCategory.Debug: + { + if( m_usingCustomOutput ) + { + if( m_customOutputDict.ContainsKey( value ) ) + { + return true; + } + } + else + { + if( m_localVariablesDict.ContainsKey( value ) ) + { + return true; + } + } + } + break; + } + return false; + } + + private bool ValidadeLocalVariable( PrecisionType precisionType, WirePortDataType type, string varName, string varValue, ref string result ) + { + Array enumValues = Enum.GetValues( typeof( PrecisionType ) ); + foreach( PrecisionType currPrecision in enumValues) + { + string value = UIUtils.PrecisionWirePortToTypeValue( currPrecision, type, varName ) + " = " + varValue + ";"; + if( UsedLocalVariable( value ) ) + return false; + + if( precisionType == currPrecision ) + result = value; + } + + return true; + } + + public bool AddLocalVariable( int nodeId, PrecisionType precisionType, WirePortDataType type, string varName, string varValue ) + { + if( string.IsNullOrEmpty( varName ) || string.IsNullOrEmpty( varValue ) ) + return false; + + //string value = UIUtils.PrecisionWirePortToTypeValue( precisionType, type, varName ) + " = " + varValue + ";"; + string value = string.Empty; + if( ValidadeLocalVariable( precisionType, type, varName, varValue, ref value)) + return AddLocalVariable( nodeId, value ); + + return false; + } + + public bool AddLocalVariable( int nodeId, string name, string value, bool ignoreDuplicates = false , bool addSemiColon = false ) + { + string finalValue = addSemiColon ? name + " = " + value + ";" : name + " = " + value; + return AddLocalVariable( nodeId, finalValue, ignoreDuplicates ); + } + + public bool AddLocalVariable( int nodeId, string value, bool ignoreDuplicates = false ) + { + if( string.IsNullOrEmpty( value ) ) + return false; + + switch( m_portCategory ) + { + case MasterNodePortCategory.Vertex: + case MasterNodePortCategory.Tessellation: + { + return AddToVertexLocalVariables( nodeId, value, ignoreDuplicates ); + } + case MasterNodePortCategory.Fragment: + case MasterNodePortCategory.Debug: + { + return AddToFragmentLocalVariables( nodeId, value, ignoreDuplicates ); + } + } + + return false; + } + + public string AddVirtualLocalVariable( int nodeId, string variable, string value ) + { + if( string.IsNullOrEmpty( value ) ) + return string.Empty; + + string result = string.Empty; + + //switch ( m_portCategory ) + //{ + //case MasterNodePortCategory.Vertex: + //case MasterNodePortCategory.Tessellation: + //{ + //} + //break; + //case MasterNodePortCategory.Fragment: + //case MasterNodePortCategory.Debug: + //{ + if( !m_virtualVariablesDict.ContainsKey( value ) ) + { + m_virtualVariablesDict.Add( value, variable ); + result = variable; + } + else + { + m_virtualVariablesDict.TryGetValue( value, out result ); + } + //} + //break; + //} + + return result; + } + + public void AddCodeComments( bool forceForwardSlash, params string[] comments ) + { + if( m_portCategory == MasterNodePortCategory.Tessellation || m_portCategory == MasterNodePortCategory.Vertex ) + { + AddToVertexLocalVariables( 0, IOUtils.CreateCodeComments( forceForwardSlash, comments ) ); + } + else + { + AddToFragmentLocalVariables( 0, IOUtils.CreateCodeComments( forceForwardSlash, comments ) ); + } + } + + public bool HasLocalVariable( string value ) + { + switch( m_portCategory ) + { + case MasterNodePortCategory.Vertex: + case MasterNodePortCategory.Tessellation: + { + return m_vertexLocalVariablesDict.ContainsKey( value ); + } + case MasterNodePortCategory.Fragment: + case MasterNodePortCategory.Debug: + { + if( m_usingCustomOutput ) + { + return m_customOutputDict.ContainsKey( value ); + } + else + { + return m_localVariablesDict.ContainsKey( value ); + } + } + } + return false; + } + + public bool AddToFragmentLocalVariables( int nodeId, string value, bool ignoreDuplicates = false ) + { + if( string.IsNullOrEmpty( value ) ) + return false; + + if( m_usingCustomOutput ) + { + if( !m_customOutputDict.ContainsKey( value ) || ignoreDuplicates ) + { + if( !m_customOutputDict.ContainsKey( value ) ) + m_customOutputDict.Add( value, new PropertyDataCollector( nodeId, value ) ); + + m_customOutputList.Add( m_customOutputDict[ value ] ); + m_customOutput += "\t\t\t" + value + '\n'; + return true; + } + else + { + if( m_showDebugMessages ) UIUtils.ShowMessage( "AddToLocalVariables:Attempting to add duplicate " + value, MessageSeverity.Warning ); + } + } + else + { + if( !m_localVariablesDict.ContainsKey( value ) || ignoreDuplicates ) + { + if( !m_localVariablesDict.ContainsKey( value ) ) + m_localVariablesDict.Add( value, new PropertyDataCollector( nodeId, value ) ); + + m_localVariablesList.Add( m_localVariablesDict[ value ] ); + AddToSpecialLocalVariables( nodeId, value, ignoreDuplicates ); + return true; + } + else + { + if( m_showDebugMessages ) UIUtils.ShowMessage( "AddToLocalVariables:Attempting to add duplicate " + value, MessageSeverity.Warning ); + } + } + return false; + } + + public void AddToSpecialLocalVariables( int nodeId, string value, bool ignoreDuplicates = false ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + if( m_usingCustomOutput ) + { + if( !m_customOutputDict.ContainsKey( value ) || ignoreDuplicates ) + { + if( !m_customOutputDict.ContainsKey( value ) ) + m_customOutputDict.Add( value, new PropertyDataCollector( nodeId, value ) ); + + m_customOutputList.Add( m_customOutputDict[ value ] ); + m_customOutput += "\t\t\t" + value + '\n'; + m_dirtySpecialLocalVariables = true; + } + else + { + if( m_showDebugMessages ) UIUtils.ShowMessage( "AddToSpecialLocalVariables:Attempting to add duplicate " + value, MessageSeverity.Warning ); + } + } + else + { + if( !m_specialLocalVariablesDict.ContainsKey( value ) || ignoreDuplicates ) + { + if( !m_specialLocalVariablesDict.ContainsKey( value ) ) + m_specialLocalVariablesDict.Add( value, new PropertyDataCollector( nodeId, value ) ); + + m_specialLocalVariablesList.Add( m_specialLocalVariablesDict[ value ] ); + m_specialLocalVariables += "\t\t\t" + value + '\n'; + m_dirtySpecialLocalVariables = true; + } + else + { + if( m_showDebugMessages ) UIUtils.ShowMessage( "AddToSpecialLocalVariables:Attempting to add duplicate " + value, MessageSeverity.Warning ); + } + } + } + + public void ClearSpecialLocalVariables() + { + //m_specialLocalVariablesDict.Clear(); + m_specialLocalVariables = string.Empty; + m_dirtySpecialLocalVariables = false; + } + + public bool AddToVertexLocalVariables( int nodeId, string varName, string varValue ) + { + if( string.IsNullOrEmpty( varName ) || string.IsNullOrEmpty( varValue ) ) + return false; + + string value = varName + " = " + varValue + ";"; + return AddToVertexLocalVariables( nodeId, value ); + } + + public bool AddToVertexLocalVariables( int nodeId, PrecisionType precisionType, WirePortDataType type, string varName, string varValue ) + { + if( string.IsNullOrEmpty( varName ) || string.IsNullOrEmpty( varValue ) ) + return false; + + string value = UIUtils.PrecisionWirePortToCgType( precisionType, type ) + " " + varName + " = " + varValue + ";"; + return AddToVertexLocalVariables( nodeId, value ); + } + + public bool AddToVertexLocalVariables( int nodeId, string value, bool ignoreDuplicates = false ) + { + if( string.IsNullOrEmpty( value ) ) + return false; + + if( !m_vertexLocalVariablesDict.ContainsKey( value ) || ignoreDuplicates ) + { + if( !m_vertexLocalVariablesDict.ContainsKey( value ) ) + m_vertexLocalVariablesDict.Add( value, new PropertyDataCollector( nodeId, value ) ); + + m_vertexLocalVariablesList.Add( m_vertexLocalVariablesDict[ value ] ); + m_vertexLocalVariables += "\t\t\t" + value + '\n'; + m_dirtyVertexLocalVariables = true; + return true; + } + else + { + if( m_showDebugMessages ) UIUtils.ShowMessage( "AddToVertexLocalVariables:Attempting to add duplicate " + value, MessageSeverity.Warning ); + } + + return false; + } + + public void ClearVertexLocalVariables() + { + //m_vertexLocalVariablesDict.Clear(); + m_vertexLocalVariables = string.Empty; + m_dirtyVertexLocalVariables = false; + } + + + public bool CheckFunction( string header ) + { + return m_localFunctions.ContainsKey( header ); + } + + public string AddFunctions( string header, string body, params object[] inParams ) + { + if( !m_localFunctions.ContainsKey( header ) ) + { + m_localFunctions.Add( header, body ); + m_functionsList.Add( new PropertyDataCollector( -1, body.Replace( "\t\t", string.Empty ) ) ); + m_functions += "\n" + body + "\n"; + m_dirtyFunctions = true; + } + + return String.Format( header, inParams ); + } + + public string AddFunctions( string header, string[] bodyLines, bool addNewLine, params object[] inParams ) + { + if( !m_localFunctions.ContainsKey( header ) ) + { + string body = string.Empty; + for( int i = 0; i < bodyLines.Length; i++ ) + { + body += ( m_masterNodeCategory == AvailableShaderTypes.Template ) ? bodyLines[ i ] : "\t\t" + bodyLines[ i ]; + if( addNewLine ) + body += '\n'; + } + + m_localFunctions.Add( header, body ); + m_functionsList.Add( new PropertyDataCollector( -1, body ) ); + m_functions += "\n" + body + "\n"; + m_dirtyFunctions = true; + } + + return String.Format( header, inParams ); + } + + public bool HasFunction( string functionId ) + { + return m_localFunctions.ContainsKey( functionId ); + } + + public void AddFunction( string functionId, string body ) + { + if( !m_localFunctions.ContainsKey( functionId ) ) + { + m_functionsList.Add( new PropertyDataCollector( -1, body ) ); + + m_localFunctions.Add( functionId, body ); + m_functions += "\n" + body + "\n"; + m_dirtyFunctions = true; + } + } + + public void AddFunction( string functionId, string[] bodyLines, bool addNewline ) + { + if( !m_localFunctions.ContainsKey( functionId ) ) + { + string body = string.Empty; + for( int i = 0; i < bodyLines.Length; i++ ) + { + body += ( m_masterNodeCategory == AvailableShaderTypes.Template ) ? bodyLines[ i ] : "\t\t" + bodyLines[ i ]; + if( addNewline ) + body += '\n'; + + } + m_functionsList.Add( new PropertyDataCollector( -1, body ) ); + + m_localFunctions.Add( functionId, body ); + m_functions += "\n" + body + "\n"; + m_dirtyFunctions = true; + } + } + + public void AddInstructions( string value, bool addTabs = false, bool addLineEnding = false ) + { + m_instructionsList.Add( new PropertyDataCollector( -1, value ) ); + m_instructions += addTabs ? "\t\t\t" + value : value; + if( addLineEnding ) + { + m_instructions += '\n'; + } + m_dirtyInstructions = true; + } + + + public void AddInstructions( bool addLineEnding, bool addTabs, params string[] values ) + { + for( int i = 0; i < values.Length; i++ ) + { + m_instructionsList.Add( new PropertyDataCollector( -1, values[ i ] ) ); + m_instructions += addTabs ? "\t\t\t" + values[ i ] : values[ i ]; + if( addLineEnding ) + { + m_instructions += '\n'; + } + } + m_dirtyInstructions = true; + } + + + + public void AddToStartInstructions( string value ) + { + if( string.IsNullOrEmpty( value ) ) + return; + + m_instructions = value + m_instructions; + m_dirtyInstructions = true; + } + + public void ResetInstructions() + { + m_instructionsList.Clear(); + m_instructions = string.Empty; + m_dirtyInstructions = false; + } + + + public void ResetVertexInstructions() + { + m_vertexDataList.Clear(); + m_vertexData = string.Empty; + m_dirtyPerVertexData = false; + } + + public void AddPropertyNode( PropertyNode node ) + { + if( !m_propertyNodes.ContainsKey( node.UniqueId ) ) + { + m_propertyNodes.Add( node.UniqueId, node ); + } + } + + public void UpdateMaterialOnPropertyNodes( Material material ) + { + m_masterNode.UpdateMaterial( material ); + foreach( KeyValuePair kvp in m_propertyNodes ) + { + kvp.Value.UpdateMaterial( material ); + } + } + + public void AddToVertexInput( string value ) + { + if( !m_vertexInputDict.ContainsKey( value ) ) + { + m_vertexInputDict.Add( value, value ); + m_vertexInputList.Add( value ); + } + } + + public void AddToInterpolators( string value ) + { + if( !m_interpolatorsDict.ContainsKey( value ) ) + { + m_interpolatorsDict.Add( value, value ); + m_interpolatorsList.Add( value ); + } + } + + public void AddToVertexInterpolatorsDecl( string value ) + { + if( !m_vertexInterpDeclDict.ContainsKey( value ) ) + { + m_vertexInterpDeclDict.Add( value, value ); + m_vertexInterpDeclList.Add( value ); + } + } + + public void UpdateShaderImporter( ref Shader shader ) + { + ShaderImporter importer = (ShaderImporter)ShaderImporter.GetAtPath( AssetDatabase.GetAssetPath( shader ) ); + if( m_propertyNodes.Count > 0 ) + { + try + { + bool hasContents = false; + TextureDefaultsDataColector defaultCol = new TextureDefaultsDataColector(); + foreach( KeyValuePair kvp in m_propertyNodes ) + { + hasContents = kvp.Value.UpdateShaderDefaults( ref shader, ref defaultCol ) || hasContents; + } + + if( hasContents ) + { + importer.SetDefaultTextures( defaultCol.NamesArr, defaultCol.ValuesArr ); + defaultCol.Destroy(); + defaultCol = null; + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + importer.SaveAndReimport(); + } + + public void AddCustomAppData( string value ) + { + if( m_customAppDataItemsDict.ContainsKey( value ) ) + return; + + m_customAppDataItemsDict.Add( value, value ); + m_customAppDataItems += "\t\t\t" + value + "\n"; + m_dirtyAppData = true; + } + + public void ForceCustomAppDataUsage() + { + m_dirtyAppData = true; + } + + //public string CustomAppDataName { get { return m_dirtyAppData ? Constants.CustomAppDataFullName : Constants.AppDataFullName; } } + public string SurfaceVertexStructure { get { return ( m_dirtyAppData ? Constants.CustomAppDataFullName : Constants.AppDataFullName ); } } + public string CustomAppData + { + get + { + if( m_dirtyPerVertexData ) + return Constants.CustomAppDataFullBody + m_customAppDataItems + "\t\t};\n"; + + return string.Empty; + } + } + + public void Destroy() + { + m_masterNode = null; + + m_customAppDataItemsDict.Clear(); + m_customAppDataItemsDict = null; + + m_inputList.Clear(); + m_inputList = null; + + m_customInputList.Clear(); + m_customInputList = null; + + m_propertiesList.Clear(); + m_propertiesList = null; + + m_instancedPropertiesList.Clear(); + m_instancedPropertiesList = null; + + m_dotsPropertiesList.Clear(); + m_dotsPropertiesList = null; + + m_dotsDefinesList.Clear(); + m_dotsDefinesList = null; + + m_uniformsList.Clear(); + m_uniformsList = null; + + m_additionalDirectivesList.Clear(); + m_additionalDirectivesList = null; + + m_includesList.Clear(); + m_includesList = null; + + //m_tagsList.Clear(); + //m_tagsList = null; + + m_pragmasList.Clear(); + m_pragmasList = null; + + m_definesList.Clear(); + m_definesList = null; + + m_instructionsList.Clear(); + m_instructionsList = null; + + m_localVariablesList.Clear(); + m_localVariablesList = null; + + m_vertexLocalVariablesList.Clear(); + m_vertexLocalVariablesList = null; + + m_specialLocalVariablesList.Clear(); + m_specialLocalVariablesList = null; + + m_vertexDataList.Clear(); + m_vertexDataList = null; + + m_customOutputList.Clear(); + m_customOutputList = null; + + m_functionsList.Clear(); + m_functionsList = null; + + m_grabPassList.Clear(); + m_grabPassList = null; + + m_aboveUsePassesList.Clear(); + m_aboveUsePassesList = null; + + m_belowUsePassesList.Clear(); + m_belowUsePassesList = null; + + m_grabPassDict.Clear(); + m_grabPassDict = null; + + m_usePassesDict.Clear(); + m_usePassesDict = null; + + m_propertyNodes.Clear(); + m_propertyNodes = null; + + m_inputDict.Clear(); + m_inputDict = null; + + m_customInputDict.Clear(); + m_customInputDict = null; + + m_propertiesDict.Clear(); + m_propertiesDict = null; + + m_dotsPropertiesDict.Clear(); + m_dotsPropertiesDict = null; + + m_instancedPropertiesDict.Clear(); + m_instancedPropertiesDict = null; + + m_uniformsDict.Clear(); + m_uniformsDict = null; + + m_softRegisteredUniformsDict.Clear(); + m_softRegisteredUniformsDict = null; + + m_includesDict.Clear(); + m_includesDict = null; + + m_additionalDirectivesDict.Clear(); + m_additionalDirectivesDict = null; + + m_includesExclusionDict.Clear(); + m_includesExclusionDict = null; + //m_tagsDict.Clear(); + //m_tagsDict = null; + + m_pragmasDict.Clear(); + m_pragmasDict = null; + + m_definesDict.Clear(); + m_definesDict = null; + + m_virtualCoordinatesDict.Clear(); + m_virtualCoordinatesDict = null; + + m_virtualVariablesDict.Clear(); + m_virtualVariablesDict = null; + + m_localVariablesDict.Clear(); + m_localVariablesDict = null; + + m_specialLocalVariablesDict.Clear(); + m_specialLocalVariablesDict = null; + + m_vertexLocalVariablesDict.Clear(); + m_vertexLocalVariablesDict = null; + + m_localFunctions.Clear(); + m_localFunctions = null; + + m_vertexDataDict.Clear(); + m_vertexDataDict = null; + + m_customOutputDict.Clear(); + m_customOutputDict = null; + + //templates + m_vertexInputList.Clear(); + m_vertexInputList = null; + + m_vertexInputDict.Clear(); + m_vertexInputDict = null; + + m_interpolatorsList.Clear(); + m_interpolatorsList = null; + + m_interpolatorsDict.Clear(); + m_interpolatorsDict = null; + + m_vertexInterpDeclList.Clear(); + m_vertexInterpDeclList = null; + + m_vertexInterpDeclDict.Clear(); + m_vertexInterpDeclDict = null; + + m_templateDataCollector.Destroy(); + m_templateDataCollector = null; + + m_customShadowCoordsDict.Clear(); + m_customShadowCoordsDict = null; + + m_customShadowCoordsList.Clear(); + m_customShadowCoordsDict = null; + + m_packSlotsList.Clear(); + m_packSlotsList = null; + } + + public string Inputs { get { return m_input; } } + public string CustomInput { get { return m_customInput; } } + public string Properties { get { return m_properties; } } + public string InstanceBlockName { get { return m_instanceBlockName; } } + public string InstancedProperties { get { return m_instancedProperties; } } + public string Uniforms { get { return m_uniforms; } } + public string Instructions { get { return m_instructions; } } + public string Includes { get { return m_includes; } } + public string Pragmas { get { return m_pragmas; } } + public string Defines { get { return m_defines; } } + public string LocalVariables { get { return m_localVariables; } } + public string SpecialLocalVariables { get { return m_specialLocalVariables; } } + public string VertexLocalVariables { get { return m_vertexLocalVariables; } } + //public string VertexLocalVariablesFromList + //{ + // get + // { + // string result = string.Empty; + // int count = m_vertexLocalVariablesList.Count; + // for( int i = 0; i < count; i++ ) + // { + // result += m_vertexLocalVariablesList[ i ].PropertyName + "\n"; + // } + // return result; + // } + //} + public string VertexData { get { return m_vertexData; } } + public string CustomOutput { get { return m_customOutput; } } + public string Functions { get { return m_functions; } } + public string GrabPass { get { return m_grabPass; } } + public bool DirtyAppData { get { return m_dirtyAppData; } } + public bool DirtyInstructions { get { return m_dirtyInstructions; } } + public bool DirtyUniforms { get { return m_dirtyUniforms; } } + public bool DirtyProperties { get { return m_dirtyProperties; } } + public bool DirtyInstancedProperties { get { return m_dirtyInstancedProperties; } } + public bool DirtyInputs { get { return m_dirtyInputs; } } + public bool DirtyCustomInput { get { return m_dirtyCustomInputs; } } + public bool DirtyIncludes { get { return m_dirtyIncludes; } } + public bool DirtyPragmas { get { return m_dirtyPragmas; } } + public bool DirtyDefines { get { return m_dirtyDefines; } } + public bool DirtyAdditionalDirectives { get { return m_dirtyAdditionalDirectives; } } + public bool DirtyLocalVariables { get { return m_dirtyLocalVariables; } } + public bool DirtyVertexVariables { get { return m_dirtyVertexLocalVariables; } } + public bool DirtySpecialLocalVariables { get { return m_dirtySpecialLocalVariables; } } + public bool DirtyPerVertexData { get { return m_dirtyPerVertexData; } } + public bool DirtyFunctions { get { return m_dirtyFunctions; } } + public bool DirtyGrabPass { get { return m_grabPassIsDirty; } } + public int LocalVariablesAmount { get { return m_localVariablesDict.Count; } } + public int SpecialLocalVariablesAmount { get { return m_specialLocalVariablesDict.Count; } } + public int VertexLocalVariablesAmount { get { return m_vertexLocalVariablesDict.Count; } } + public bool TesselationActive { set { m_tesselationActive = value; } get { return m_tesselationActive; } } + + + public int AvailableVertexTempId { get { return m_availableVertexTempId++; } } + public int AvailableFragTempId { get { return m_availableFragTempId++; } } + + /// + /// Returns true if Normal output is being written by something else + /// + public bool DirtyNormal + { + get { return m_dirtyNormal; } + set { m_dirtyNormal = value; } + } + + public bool IsFragmentCategory + { + get { return m_portCategory == MasterNodePortCategory.Fragment || m_portCategory == MasterNodePortCategory.Debug; } + } + + public MasterNodePortCategory PortCategory + { + get { return m_portCategory; } + set { m_portCategory = value; } + } + + public PortGenType GenType + { + get { return m_genType; } + set { m_genType = value; } + } + + public bool IsTemplate { get { return m_masterNodeCategory == AvailableShaderTypes.Template; } } + + public bool IsSRP { get { return ( TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.Lightweight || TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ); } } + + public AvailableShaderTypes MasterNodeCategory + { + get { return m_masterNodeCategory; } + set { m_masterNodeCategory = value; } + } + + /// + /// Forces write to Normal output when the output is not connected + /// + public bool ForceNormal + { + get { return m_forceNormal; } + set + { + if( value ) + { + if( !m_forceNormalIsDirty ) + { + m_forceNormal = value; + m_forceNormalIsDirty = value; + } + } + else + { + m_forceNormal = value; + } + } + } + + public bool UsingVertexColor + { + get { return m_usingVertexColor; } + set { m_usingVertexColor = value; } + } + + public bool UsingInternalData + { + get { return m_usingInternalData; } + set { m_usingInternalData = value; } + } + + public bool UsingScreenPos + { + get { return m_usingScreenPos; } + set { m_usingScreenPos = value; } + } + + public bool UsingCustomScreenPos + { + get { return m_usingCustomScreenPos; } + set { m_usingCustomScreenPos = value; } + } + + public bool UsingWorldNormal + { + get { return m_usingWorldNormal; } + set { m_usingWorldNormal = value; } + } + + public bool UsingWorldReflection + { + get { return m_usingWorldReflection; } + set { m_usingWorldReflection = value; } + } + + public bool UsingWorldPosition + { + get { return m_usingWorldPosition; } + set { m_usingWorldPosition = value; } + } + + public bool UsingViewDirection + { + get { return m_usingViewDirection; } + set { m_usingViewDirection = value; } + } + + public bool IsOutlineDataCollector + { + get { return m_isOutlineDataCollector; } + set { m_isOutlineDataCollector = value; } + } + + public bool UsingCustomOutlineColor + { + get { return m_usingCustomOutlineColor; } + set { m_usingCustomOutlineColor = value; } + } + + public bool UsingCustomOutlineWidth + { + get { return m_usingCustomOutlineWidth; } + set { m_usingCustomOutlineWidth = value; } + } + + public bool UsingCustomOutlineAlpha + { + get { return m_usingCustomOutlineAlpha; } + set { m_usingCustomOutlineAlpha = value; } + } + + public int CustomOutlineSelectedAlpha + { + get { return m_customOutlineSelectedAlpha; } + set { m_customOutlineSelectedAlpha = value; } + } + + public bool UsingCustomOutput + { + get { return m_usingCustomOutput; } + set { m_usingCustomOutput = value; } + } + + public bool UsingHigherSizeTexcoords + { + get { return m_usingHigherSizeTexcoords; } + set { m_usingHigherSizeTexcoords = value; } + } + + public bool UsingLightAttenuation + { + get { return m_usingLightAttenuation; } + set { m_usingLightAttenuation = value; } + } + + public bool UsingTextureArrays + { + get { return m_usingTextureArrays; } + set { m_usingTextureArrays = value; } + } + + public bool UsingExtraStandardMacros + { + get { return m_usingExtraStandardMacros; } + set { m_usingExtraStandardMacros = value; } + } + + public MacrosMask Using2DMacrosMask + { + get { return m_using2DMacrosMask; } + set { m_using2DMacrosMask = value; } + } + + public MacrosMask Using3DMacrosMask + { + get { return m_using3DMacrosMask; } + set { m_using3DMacrosMask = value; } + } + + public MacrosMask UsingCUBEMacrosMask + { + get { return m_usingCUBEMacrosMask; } + set { m_usingCUBEMacrosMask = value; } + } + + public MacrosMask Using2DArrayMacrosMask + { + get { return m_using2DArrayMacrosMask; } + set { m_using2DArrayMacrosMask = value; } + } + + public bool UsingExtra3DSRPMacros + { + get { return m_usingExtra3DSRPMacros; } + set { m_usingExtra3DSRPMacros = value; } + } + + public bool UsingArrayDerivatives + { + get { return m_usingArrayDerivatives; } + set { m_usingArrayDerivatives = value; } + } + + public bool SafeNormalizeLightDir + { + get { return m_safeNormalizeLightDir; } + set { m_safeNormalizeLightDir = value; } + } + + public bool SafeNormalizeViewDir + { + get { return m_safeNormalizeViewDir; } + set { m_safeNormalizeViewDir = value; } + } + + public string StandardAdditionalDirectives + { + get + { + string body = string.Empty; + int count = m_additionalDirectivesList.Count; + for( int i = 0; i < count; i++ ) + { + body += "\t\t" + m_additionalDirectivesList[ i ].PropertyName + "\n"; + } + return body; + } + } + + public List InputList { get { return m_inputList; } } + public List CustomInputList { get { return m_customInputList; } } + public List PropertiesList { get { return m_propertiesList; } } + public List InstancedPropertiesList { get { return m_instancedPropertiesList; } } + public List DotsPropertiesList { get { return m_dotsPropertiesList; } } + public List DotsDefinesList { get { return m_dotsDefinesList; } } + public List UniformsList { get { return m_uniformsList; } } + public List MiscList { get { return m_additionalDirectivesList; } } + public List BeforeNativeDirectivesList { get { return m_additionalDirectivesList.FindAll( obj => obj.OrderIndex < 0 ); } } + public List AfterNativeDirectivesList { get { return m_additionalDirectivesList.FindAll( obj => obj.OrderIndex > 0 ); } } + public List IncludesList { get { return m_includesList; } } + //public List TagsList { get { return m_tagsList; } } + public List PragmasList { get { return m_pragmasList; } } + public List DefinesList { get { return m_definesList; } } + public List InstructionsList { get { return m_instructionsList; } } + public List LocalVariablesList { get { return m_localVariablesList; } } + public List VertexLocalVariablesList { get { return m_vertexLocalVariablesList; } } + public List SpecialLocalVariablesList { get { return m_specialLocalVariablesList; } } + public List VertexDataList { get { return m_vertexDataList; } } + public List CustomOutputList { get { return m_customOutputList; } } + public List FunctionsList { get { return m_functionsList; } } + public List GrabPassList { get { return m_grabPassList; } } + public Dictionary GrabPassDict { get { return m_grabPassDict; } } + public List AboveUsePassesList { get { return m_aboveUsePassesList; } } + public List BelowUsePassesList { get { return m_belowUsePassesList; } } + public Dictionary AboveUsePassesDict { get { return m_usePassesDict; } } + public List CustomShadowCoordsList { get { return m_customShadowCoordsList; } } + public List PackSlotsList { get { return m_packSlotsList; } } + public Dictionary LocalFunctions { get { return m_localFunctions; } } + //Templates + public List VertexInputList { get { return m_vertexInputList; } } + public List InterpolatorList { get { return m_interpolatorsList; } } + public List VertexInterpDeclList { get { return m_vertexInterpDeclList; } } + public TemplateDataCollector TemplateDataCollectorInstance { get { return m_templateDataCollector; } } + public RenderPath CurrentRenderPath + { + get { return m_renderPath; } + set { m_renderPath = value; } + } + + public NodeAvailability CurrentCanvasMode { get { return m_currentCanvasMode; } set { m_currentCanvasMode = value; } } + public TemplateSRPType CurrentSRPType + { + get + { + if( IsTemplate ) + return m_templateDataCollector.CurrentSRPType; + + return TemplateSRPType.BuiltIn; + } + } + + public Dictionary PropertiesDict { get { return m_propertiesDict; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNodeDataCollector.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNodeDataCollector.cs.meta new file mode 100644 index 0000000..2b16420 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/MasterNodeDataCollector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d026d775ff431f34789437db3fb4abbb +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutlineOpHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutlineOpHelper.cs new file mode 100644 index 0000000..2c068a7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutlineOpHelper.cs @@ -0,0 +1,633 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public enum OutlineMode + { + VertexOffset, + VertexScale + } + + [Serializable] + public sealed class OutlineOpHelper + { + + private string[] ModeTags = + { + "Tags{ }", + "Tags{ \"RenderType\" = \"TransparentCutout\" \"Queue\" = \"AlphaTest+0\"}", + "Tags{ \"RenderType\" = \"Transparent\" \"Queue\" = \"Transparent+0\"}", + "Tags{ \"RenderType\" = \"Transparent\" \"Queue\" = \"Transparent+0\" }" + }; + + private string[] ModePragma = + { + string.Empty, + string.Empty, + "alpha:fade ", + "alpha:premul " + }; + + + private readonly string OutlineSurfaceConfig = "#pragma surface outlineSurf Outline {0} keepalpha noshadow noambient novertexlights nolightmap nodynlightmap nodirlightmap nometa noforwardadd vertex:outlineVertexDataFunc "; + + private readonly string OutlineBodyStructBegin = "struct Input {"; + private readonly string OutlineBodyStructDefault = "\thalf filler;"; + private readonly string OutlineBodyStructEnd = "};"; + + private readonly string OutlineDefaultUniformColor = "half4 _ASEOutlineColor;"; + private readonly string OutlineDefaultUniformWidth = "half _ASEOutlineWidth;"; + private readonly string OutlineDefaultUniformColorInstanced = "UNITY_DEFINE_INSTANCED_PROP( half4, _ASEOutlineColor )"; + private readonly string OutlineDefaultUniformWidthInstanced = "UNITY_DEFINE_INSTANCED_PROP( half, _ASEOutlineWidth )"; + + private readonly string OutlineDefaultVertexHeader = "void outlineVertexDataFunc( inout appdata_full v, out Input o )\n\t\t{"; + private readonly string OutlineTessVertexHeader = "void outlineVertexDataFunc( inout appdata_full v )\n\t\t{"; + + private readonly string OutlineDefaultVertexOutputDeclaration = "\tUNITY_INITIALIZE_OUTPUT( Input, o );"; + + private readonly string[] OutlineSurfBody = { + "\to.Emission = _ASEOutlineColor.rgb;", + "\to.Alpha = 1;" + }; + + private readonly string[] OutlineSurfBodyInstanced = { + "\to.Emission = UNITY_ACCESS_INSTANCED_PROP(_ASEOutlineColor).rgb;", + "\to.Alpha = 1;" + }; + + private readonly string[] OutlineBodyDefaultSurfBegin = { + "}", + "inline half4 LightingOutline( SurfaceOutput s, half3 lightDir, half atten ) { return half4 ( 0,0,0, s.Alpha); }", + "void outlineSurf( Input i, inout SurfaceOutput o )", + "{"}; + + private readonly string[] OutlineBodyDefaultSurfEnd = { + "}", + "ENDCG", + "\n"}; + + //private const string OutlineInstancedHeader = "#pragma multi_compile_instancing"; + + //private readonly string[] OutlineBodyInstancedBegin = { + // "UNITY_INSTANCING_CBUFFER_START({0})", + // "\tUNITY_DEFINE_INSTANCED_PROP( half4, _ASEOutlineColor )", + // "\tUNITY_DEFINE_INSTANCED_PROP(half, _ASEOutlineWidth)", + // "UNITY_INSTANCING_CBUFFER_END", + // "void outlineVertexDataFunc( inout appdata_full v, out Input o )", + // "{", + // "\tUNITY_INITIALIZE_OUTPUT( Input, o );"}; + + //private readonly string[] OutlineBodyInstancedEnd = { + // "}", + // "inline half4 LightingOutline( SurfaceOutput s, half3 lightDir, half atten ) { return half4 ( 0,0,0, s.Alpha); }", + // "void outlineSurf( Input i, inout SurfaceOutput o ) { o.Emission = UNITY_ACCESS_INSTANCED_PROP( _ASEOutlineColor ).rgb; o.Alpha = 1; }", + // "ENDCG", + // "\n"}; + + private const string WidthVariableAccessInstanced = "UNITY_ACCESS_INSTANCED_PROP( _ASEOutlineWidth )"; + + private const string OutlineVertexOffsetMode = "\tv.vertex.xyz += ( v.normal * {0} );"; + private const string OutlineVertexScaleMode = "\tv.vertex.xyz *= ( 1 + {0});"; + private const string OutlineVertexCustomMode = "\tv.vertex.xyz += {0};"; + + private const string OutlineColorLabel = "Color"; + private const string OutlineWidthLabel = "Width"; + + private const string ColorPropertyName = "_ASEOutlineColor"; + private const string WidthPropertyName = "_ASEOutlineWidth"; + + + private const string WidthPropertyNameInstanced = "UNITY_ACCESS_INSTANCED_PROP(_ASEOutlineWidth)"; + + + + private const string ColorPropertyDec = "_ASEOutlineColor( \"Outline Color\", Color ) = ({0})"; + private const string OutlinePropertyDec = "_ASEOutlineWidth( \"Outline Width\", Float ) = {0}"; + + private const string ModePropertyStr = "Mode"; + + private const string NoFogStr = "No Fog"; + + private const string BillboardInstructionFormat = "\t{0};"; + + [SerializeField] + private Color m_outlineColor; + + [SerializeField] + private float m_outlineWidth; + + [SerializeField] + private bool m_enabled; + + [SerializeField] + private OutlineMode m_mode = OutlineMode.VertexOffset; + + [SerializeField] + private bool m_noFog = true; + + private CullMode m_cullMode = CullMode.Front; + private int m_zTestMode = 0; + private int m_zWriteMode = 0; + private bool m_dirtyInput = false; + private string m_inputs = string.Empty; + private List m_inputList = new List(); + private string m_uniforms = string.Empty; + private List m_uniformList = new List(); + private List m_instancedPropertiesList = new List(); + private string m_instancedProperties = string.Empty; + private string m_instructions = string.Empty; + private string m_functions = string.Empty; + private string m_includes = string.Empty; + private string m_pragmas = string.Empty; + private string m_defines = string.Empty; + private string m_standardAdditionalDirectives = string.Empty; + private string m_vertexData = string.Empty; + private string m_grabPasses = string.Empty; + private Dictionary m_localFunctions; + + //private OutlineMode m_customMode = OutlineMode.VertexOffset; + private int m_offsetMode = 0; + private bool m_customNoFog = true; + + public void Draw( ParentNode owner, GUIStyle toolbarstyle, Material mat ) + { + Color cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f ); + EditorGUILayout.BeginHorizontal( toolbarstyle ); + GUI.color = cachedColor; + owner.ContainerGraph.ParentWindow.InnerWindowVariables.OutlineActiveMode = owner.GUILayoutToggle( owner.ContainerGraph.ParentWindow.InnerWindowVariables.OutlineActiveMode , EditorVariablesManager.OutlineActiveMode.LabelName, UIUtils.MenuItemToggleStyle, GUILayout.ExpandWidth( true ) ); + EditorGUI.BeginChangeCheck(); + m_enabled = owner.EditorGUILayoutToggle( string.Empty, m_enabled, UIUtils.MenuItemEnableStyle, GUILayout.Width( 16 ) ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_enabled ) + UpdateToMaterial( mat ); + + UIUtils.RequestSave(); + } + EditorGUILayout.EndHorizontal(); + + if( owner.ContainerGraph.ParentWindow.InnerWindowVariables.OutlineActiveMode ) + { + cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) ); + EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + GUI.color = cachedColor; + + EditorGUILayout.Separator(); + EditorGUI.BeginDisabledGroup( !m_enabled ); + + EditorGUI.indentLevel += 1; + { + m_mode = (OutlineMode)owner.EditorGUILayoutEnumPopup( ModePropertyStr, m_mode ); + + EditorGUI.BeginChangeCheck(); + m_outlineColor = owner.EditorGUILayoutColorField( OutlineColorLabel, m_outlineColor ); + if( EditorGUI.EndChangeCheck() && mat != null ) + { + if( mat.HasProperty( ColorPropertyName ) ) + { + mat.SetColor( ColorPropertyName, m_outlineColor ); + } + } + + EditorGUI.BeginChangeCheck(); + m_outlineWidth = owner.EditorGUILayoutFloatField( OutlineWidthLabel, m_outlineWidth ); + if( EditorGUI.EndChangeCheck() && mat != null ) + { + if( mat.HasProperty( WidthPropertyName ) ) + { + mat.SetFloat( WidthPropertyName, m_outlineWidth ); + } + } + + m_noFog = owner.EditorGUILayoutToggle( NoFogStr, m_noFog ); + } + + EditorGUI.indentLevel -= 1; + EditorGUI.EndDisabledGroup(); + EditorGUILayout.Separator(); + EditorGUILayout.EndVertical(); + } + } + + public void UpdateToMaterial( Material mat ) + { + if( mat == null ) + return; + + if( mat.HasProperty( ColorPropertyName ) ) + { + mat.SetColor( ColorPropertyName, m_outlineColor ); + } + + if( mat.HasProperty( WidthPropertyName ) ) + { + mat.SetFloat( WidthPropertyName, m_outlineWidth ); + } + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + m_enabled = Convert.ToBoolean( nodeParams[ index++ ] ); + m_outlineWidth = Convert.ToSingle( nodeParams[ index++ ] ); + m_outlineColor = IOUtils.StringToColor( nodeParams[ index++ ] ); + if( UIUtils.CurrentShaderVersion() > 5004 ) + { + m_mode = (OutlineMode)Enum.Parse( typeof( OutlineMode ), nodeParams[ index++ ] ); + } + + if( UIUtils.CurrentShaderVersion() > 13902 ) + { + m_noFog = Convert.ToBoolean( nodeParams[ index++ ] ); + } + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_enabled ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_outlineWidth ); + IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.ColorToString( m_outlineColor ) ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_mode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_noFog ); + } + + public void AddToDataCollector( ref MasterNodeDataCollector dataCollector ) + { + if( !dataCollector.UsingCustomOutlineColor ) + dataCollector.AddToProperties( -1, string.Format( ColorPropertyDec, IOUtils.ColorToString( m_outlineColor ) ), -1 ); + if( !dataCollector.UsingCustomOutlineWidth ) + dataCollector.AddToProperties( -1, string.Format( OutlinePropertyDec, m_outlineWidth ), -1 ); + } + + public void UpdateFromMaterial( Material mat ) + { + if( mat.HasProperty( ColorPropertyName ) ) + { + m_outlineColor = mat.GetColor( ColorPropertyName ); + } + + if( mat.HasProperty( WidthPropertyName ) ) + { + m_outlineWidth = mat.GetFloat( WidthPropertyName ); + } + } + + void AddMultibodyString( string body , List list ) + { + body = body.Replace( "\t\t", string.Empty ); + string[] strArr = body.Split( '\n' ); + for( int i = 0; i < strArr.Length; i++ ) + { + list.Add( strArr[ i ] ); + } + + } + public string[] OutlineFunctionBody( ref MasterNodeDataCollector dataCollector, bool instanced, bool isShadowCaster, string shaderName, string[] billboardInfo, ref TessellationOpHelper tessOpHelper, string target, PrecisionType precision ) + { + List body = new List(); + body.Add( ModeTags[ dataCollector.CustomOutlineSelectedAlpha ] ); + if( !string.IsNullOrEmpty( m_grabPasses )) + body.Add( m_grabPasses.Replace( "\t\t",string.Empty )); + + if( m_zWriteMode != 0 ) + body.Add( "ZWrite " + ZBufferOpHelper.ZWriteModeValues[ m_zWriteMode ] ); + if( m_zTestMode != 0 ) + body.Add( "ZTest " + ZBufferOpHelper.ZTestModeValues[ m_zTestMode ] ); + + body.Add( "Cull " + m_cullMode ); + body.Add( "CGPROGRAM" ); + if( tessOpHelper.EnableTesselation ) + { + body.Add( "#include \"" + TessellationOpHelper.TessInclude + "\"" ); + body.Add( "#pragma target " + target ); + } + else + { + body.Add( "#pragma target 3.0" ); + } + bool customOutline = dataCollector.UsingCustomOutlineColor || dataCollector.UsingCustomOutlineWidth || dataCollector.UsingCustomOutlineAlpha; + int outlineMode = customOutline ? m_offsetMode : ( m_mode == OutlineMode.VertexOffset ? 0 : 1 ); + string extraOptions = ( customOutline ? m_customNoFog : m_noFog ) ? "nofog " : string.Empty; + if( dataCollector.CustomOutlineSelectedAlpha > 0 ) + { + extraOptions += ModePragma[ dataCollector.CustomOutlineSelectedAlpha ]; + } + + string surfConfig = string.Format( OutlineSurfaceConfig, extraOptions ); + + if( tessOpHelper.EnableTesselation ) + tessOpHelper.WriteToOptionalParams( ref surfConfig ); + + body.Add( surfConfig ); + if( !isShadowCaster ) + { + AddMultibodyString( m_defines, body ); + AddMultibodyString( m_includes, body ); + AddMultibodyString( m_pragmas, body ); + } + AddMultibodyString( m_standardAdditionalDirectives, body ); + //if( instanced ) + //{ + // body.Add( OutlineInstancedHeader ); + //} + + if( customOutline ) + { + if( isShadowCaster ) + { + + for( int i = 0; i < InputList.Count; i++ ) + { + dataCollector.AddToInput( InputList[ i ].NodeId, InputList[ i ].PropertyName, !InputList[ i ].IsDirective ); + } + } + else + { + if( !string.IsNullOrEmpty( m_inputs ) ) + body.Add( m_inputs.Trim( '\t', '\n' ) ); + } + + if( !DirtyInput && !isShadowCaster ) + body.Add( OutlineBodyStructDefault ); + + if( !isShadowCaster ) + body.Add( OutlineBodyStructEnd ); + } + else if( !isShadowCaster ) + { + body.Add( OutlineBodyStructBegin ); + body.Add( OutlineBodyStructDefault ); + body.Add( OutlineBodyStructEnd ); + } + + if( instanced ) + { + //for( int i = 0; i < OutlineBodyInstancedBegin.Length; i++ ) + //{ + // body.Add( ( i == 0 ) ? string.Format( OutlineBodyInstancedBegin[ i ], shaderName ) : OutlineBodyInstancedBegin[ i ] ); + //} + + //if( (object)billboardInfo != null ) + //{ + // for( int j = 0; j < billboardInfo.Length; j++ ) + // { + // body.Add( string.Format( BillboardInstructionFormat, billboardInfo[ j ] ) ); + // } + //} + + //switch( outlineMode ) + //{ + // case 0: body.Add( string.Format( OutlineVertexOffsetMode, WidthVariableAccessInstanced ) ); break; + // case 1: body.Add( string.Format( OutlineVertexScaleMode, WidthVariableAccessInstanced ) ); break; + // case 2: body.Add( string.Format( OutlineVertexCustomMode, WidthVariableAccessInstanced ) ); break; + //} + //for( int i = 0; i < OutlineBodyInstancedEnd.Length; i++ ) + //{ + // body.Add( OutlineBodyInstancedEnd[ i ] ); + //} + + //Instanced block name must differ from used on main shader so it won't throw a duplicate name error + shaderName = shaderName+ "Outline"; + bool openCBuffer = true; + if( customOutline ) + { + if( isShadowCaster ) + { + for( int i = 0; i < UniformList.Count; i++ ) + { + dataCollector.AddToUniforms( UniformList[ i ].NodeId, UniformList[ i ].PropertyName ); + } + + foreach( KeyValuePair kvp in m_localFunctions ) + { + dataCollector.AddFunction( kvp.Key, kvp.Value ); + } + } + else + { + if( !string.IsNullOrEmpty( Uniforms ) ) + body.Add( Uniforms.Trim( '\t', '\n' ) ); + + openCBuffer = false; + body.Add( string.Format( IOUtils.InstancedPropertiesBegin, shaderName )); + if( !string.IsNullOrEmpty( InstancedProperties ) ) + body.Add( InstancedProperties.Trim( '\t', '\n' ) ); + } + } + + if( openCBuffer) + body.Add( string.Format( IOUtils.InstancedPropertiesBegin, shaderName ) ); + + if( !dataCollector.UsingCustomOutlineColor ) + body.Add( precision == PrecisionType.Float ? OutlineDefaultUniformColorInstanced.Replace( "half", "float" ) : OutlineDefaultUniformColorInstanced ); + + if( !dataCollector.UsingCustomOutlineWidth ) + body.Add( precision == PrecisionType.Float ? OutlineDefaultUniformWidthInstanced.Replace( "half", "float" ) : OutlineDefaultUniformWidthInstanced ); + + body.Add( IOUtils.InstancedPropertiesEnd ); + + //Functions + if( customOutline && !isShadowCaster ) + body.Add( Functions ); + + if( tessOpHelper.EnableTesselation && !isShadowCaster ) + { + body.Add( tessOpHelper.Uniforms().TrimStart( '\t' ) ); + body.Add( tessOpHelper.GetCurrentTessellationFunction( ref dataCollector ).Trim( '\t', '\n' ) + "\n" ); + } + + if( tessOpHelper.EnableTesselation ) + { + body.Add( OutlineTessVertexHeader ); + } + else + { + body.Add( OutlineDefaultVertexHeader ); + body.Add( OutlineDefaultVertexOutputDeclaration ); + } + + if( customOutline ) + { + if( !string.IsNullOrEmpty( VertexData ) ) + body.Add( "\t" + VertexData.Trim( '\t', '\n' ) ); + } + + if( (object)billboardInfo != null ) + { + for( int j = 0; j < billboardInfo.Length; j++ ) + { + body.Add( string.Format( BillboardInstructionFormat, billboardInfo[ j ] ) ); + } + } + + switch( outlineMode ) + { + case 0: body.Add( string.Format( OutlineVertexOffsetMode, dataCollector.UsingCustomOutlineWidth ? "outlineVar" : WidthPropertyNameInstanced ) ); break; + case 1: body.Add( string.Format( OutlineVertexScaleMode, dataCollector.UsingCustomOutlineWidth ? "outlineVar" : WidthPropertyNameInstanced ) ); break; + case 2: body.Add( string.Format( OutlineVertexCustomMode, dataCollector.UsingCustomOutlineWidth ? "outlineVar" : WidthPropertyNameInstanced ) ); break; + } + + for( int i = 0; i < OutlineBodyDefaultSurfBegin.Length; i++ ) + { + body.Add( OutlineBodyDefaultSurfBegin[ i ] ); + } + if( dataCollector.UsingCustomOutlineColor || dataCollector.CustomOutlineSelectedAlpha > 0 ) + { + body.Add( "\t" + Instructions.Trim( '\t', '\n' ) ); + } + else + { + for( int i = 0; i < OutlineSurfBodyInstanced.Length; i++ ) + { + body.Add( OutlineSurfBodyInstanced[ i ] ); + } + } + + for( int i = 0; i < OutlineBodyDefaultSurfEnd.Length; i++ ) + { + body.Add( OutlineBodyDefaultSurfEnd[ i ] ); + } + } + else + { + if( customOutline ) + { + if( isShadowCaster ) + { + for( int i = 0; i < UniformList.Count; i++ ) + { + dataCollector.AddToUniforms( UniformList[ i ].NodeId, UniformList[ i ].PropertyName ); + } + + foreach( KeyValuePair kvp in m_localFunctions ) + { + dataCollector.AddFunction( kvp.Key, kvp.Value ); + } + } + else + { + if( !string.IsNullOrEmpty( Uniforms ) ) + body.Add( Uniforms.Trim( '\t', '\n' ) ); + } + } + + if( !dataCollector.UsingCustomOutlineColor ) + body.Add( precision == PrecisionType.Float ? OutlineDefaultUniformColor.Replace( "half", "float" ) : OutlineDefaultUniformColor ); + + if( !dataCollector.UsingCustomOutlineWidth ) + body.Add( precision == PrecisionType.Float ? OutlineDefaultUniformWidth.Replace( "half", "float" ) : OutlineDefaultUniformWidth ); + + //Functions + if( customOutline && !isShadowCaster ) + body.Add( Functions ); + + if( tessOpHelper.EnableTesselation && !isShadowCaster ) + { + body.Add( tessOpHelper.Uniforms().TrimStart( '\t' ) ); + body.Add( tessOpHelper.GetCurrentTessellationFunction( ref dataCollector ).Trim( '\t', '\n' ) + "\n" ); + } + + if( tessOpHelper.EnableTesselation ) + { + body.Add( OutlineTessVertexHeader ); + } + else + { + body.Add( OutlineDefaultVertexHeader ); + body.Add( OutlineDefaultVertexOutputDeclaration ); + } + + if( customOutline ) + { + if( !string.IsNullOrEmpty( VertexData ) ) + body.Add( "\t" + VertexData.Trim( '\t', '\n' ) ); + } + + if( (object)billboardInfo != null ) + { + for( int j = 0; j < billboardInfo.Length; j++ ) + { + body.Add( string.Format( BillboardInstructionFormat, billboardInfo[ j ] ) ); + } + } + + switch( outlineMode ) + { + case 0: body.Add( string.Format( OutlineVertexOffsetMode, dataCollector.UsingCustomOutlineWidth ? "outlineVar" : WidthPropertyName ) ); break; + case 1: body.Add( string.Format( OutlineVertexScaleMode, dataCollector.UsingCustomOutlineWidth ? "outlineVar" : WidthPropertyName ) ); break; + case 2: body.Add( string.Format( OutlineVertexCustomMode, dataCollector.UsingCustomOutlineWidth ? "outlineVar" : WidthPropertyName ) ); break; + } + for( int i = 0; i < OutlineBodyDefaultSurfBegin.Length; i++ ) + { + body.Add( OutlineBodyDefaultSurfBegin[ i ] ); + } + if( dataCollector.UsingCustomOutlineColor || dataCollector.CustomOutlineSelectedAlpha > 0 ) + { + body.Add( "\t" + Instructions.Trim( '\t', '\n' ) ); + } + else + { + for( int i = 0; i < OutlineSurfBody.Length; i++ ) + { + body.Add( OutlineSurfBody[ i ] ); + } + } + + for( int i = 0; i < OutlineBodyDefaultSurfEnd.Length; i++ ) + { + body.Add( OutlineBodyDefaultSurfEnd[ i ] ); + } + } + + string[] bodyArr = body.ToArray(); + body.Clear(); + body = null; + return bodyArr; + } + + + public void Destroy() + { + m_inputList = null; + m_uniformList = null; + m_instancedPropertiesList = null; + m_localFunctions = null; + } + + public bool EnableOutline { get { return m_enabled; } } + + public bool UsingCullMode { get { return m_cullMode != CullMode.Front; } } + public bool UsingZWrite { get { return m_zWriteMode != 0; } } + public bool UsingZTest { get { return m_zTestMode != 0; } } + public int ZWriteMode { get { return m_zWriteMode; } set { m_zWriteMode = value; } } + public int ZTestMode { get { return m_zTestMode; } set { m_zTestMode = value; } } + public CullMode OutlineCullMode { get { return m_cullMode; } set { m_cullMode = value; } } + public string Inputs { get { return m_inputs; } set { m_inputs = value; } } + public string Uniforms { get { return m_uniforms; } set { m_uniforms = value; } } + public string InstancedProperties { get { return m_instancedProperties; } set { m_instancedProperties = value; } } + public string Instructions { get { return m_instructions; } set { m_instructions = value; } } + public string Functions { get { return m_functions; } set { m_functions = value; } } + public string Includes { get { return m_includes; } set { m_includes = value; } } + public string Pragmas { get { return m_pragmas; } set { m_pragmas = value; } } + public string Defines { get { return m_defines; } set { m_defines = value; } } + public string StandardAdditionalDirectives { get { return m_standardAdditionalDirectives; } set { m_standardAdditionalDirectives = value; } } + public string VertexData { get { return m_vertexData; } set { m_vertexData = value; } } + public string GrabPasses { get { return m_grabPasses; } set { m_grabPasses = value; } } + public List InputList { get { return m_inputList; } set { m_inputList = value; } } + public List UniformList { get { return m_uniformList; } set { m_uniformList = value; } } + public List InstancedPropertiesList { get { return m_instancedPropertiesList; } set { m_instancedPropertiesList = value; } } + + public Dictionary LocalFunctions { get { return m_localFunctions; } set { m_localFunctions = value; } } + public bool DirtyInput { get { return m_dirtyInput; } set { m_dirtyInput = value; } } + + //public OutlineMode CustomMode { get { return m_customMode; } set { m_customMode = value; } } + public int OffsetMode { get { return m_offsetMode; } set { m_offsetMode = value; } } + public bool CustomNoFog { get { return m_customNoFog; } set { m_customNoFog = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutlineOpHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutlineOpHelper.cs.meta new file mode 100644 index 0000000..bb79b68 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutlineOpHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d0900a4b7d1563e49b6184d7579dcbec +timeCreated: 1487331466 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutputNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutputNode.cs new file mode 100644 index 0000000..1fffc29 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutputNode.cs @@ -0,0 +1,90 @@ +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public class OutputNode : SignalGeneratorNode + { + public static int LOD_SUBSHADER_VERSION = 17200; + [SerializeField] + protected bool m_isMainOutputNode = false; + + [SerializeField] + protected int m_lodIndex = -1; + + public OutputNode() : base() { } + public OutputNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + + public override void ResetNodeData() + { + base.ResetNodeData(); + m_graphDepth = -1; + } + + public virtual void SetupNodeCategories() + { + ContainerGraph.ResetNodesData(); + //int count = m_inputPorts.Count; + //for( int i = 0; i < count; i++ ) + //{ + // if( m_inputPorts[ i ].IsConnected ) + // { + // NodeData nodeData = new NodeData( m_inputPorts[ i ].Category ); + // ParentNode node = m_inputPorts[ i ].GetOutputNode(); + // node.PropagateNodeData( nodeData, ref collector ); + // } + //} + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_isMainOutputNode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_lodIndex ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_isMainOutputNode = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > LOD_SUBSHADER_VERSION ) + { + m_lodIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + if( IsLODMainMasterNode && !ContainerGraph.IsDuplicating ) + { + ContainerGraph.AssignMasterNode( this, true ); + } + } + + public override void AfterDuplication() + { + base.AfterDuplication(); + m_isMainOutputNode = false; + } + + public bool IsMainOutputNode + { + get { return m_isMainOutputNode; } + set + { + if( value != m_isMainOutputNode ) + { + m_isMainOutputNode = value; + if( m_isMainOutputNode ) + { + GenerateSignalPropagation(); + } + else + { + GenerateSignalInibitor(); + } + } + } + } + + public int LODIndex { get { return m_lodIndex; } set { m_lodIndex = value; } } + public bool IsLODMainMasterNode { get { return m_isMainOutputNode && m_lodIndex == -1; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutputNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutputNode.cs.meta new file mode 100644 index 0000000..79cae85 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/OutputNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ed0ee3a73f11f344495d16b54bb3af29 +timeCreated: 1491918470 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingOptionsOpHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingOptionsOpHelper.cs new file mode 100644 index 0000000..34c8e54 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingOptionsOpHelper.cs @@ -0,0 +1,227 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public enum DisableBatchingTagValues + { + True, + False, + LODFading + } + + [Serializable] + public class RenderingOptionsOpHelper + { + private const string RenderingOptionsStr = " Rendering Options"; + private readonly static GUIContent EmissionGIFlags = new GUIContent( "Emission GI Flag", "Modifies Emission GI flags" ); + private readonly static GUIContent LODCrossfadeContent = new GUIContent( " LOD Group Cross Fade", "Applies a dither crossfade to be used with LOD groups for smoother transitions. Uses one interpolator\nDefault: OFF" ); + private readonly static GUIContent DisableBatchingContent = new GUIContent( "Disable Batching", "\nDisables objects to be batched and used with DrawCallBatching Default: False" ); + private readonly static GUIContent IgnoreProjectorContent = new GUIContent( " Ignore Projector", "\nIf True then an object that uses this shader will not be affected by Projectors Default: False" ); + private readonly static GUIContent UseDefaultCasterContent = new GUIContent( " Use Default Shadow Caster", "\nIf True always use surface default shadow caster Default: False" ); + private readonly static GUIContent ForceNoShadowCastingContent = new GUIContent( " Force No Shadow Casting", "\nIf True then an object that is rendered using this subshader will never cast shadows Default: False" ); + private readonly static GUIContent ForceEnableInstancingContent = new GUIContent( " Force Enable Instancing", "\nIf True forces instancing on shader independent of having instanced properties" ); +#if UNITY_5_6_OR_NEWER + private readonly static GUIContent ForceDisableInstancingContent = new GUIContent( " Force Disable Instancing", "\nIf True forces disable instancing on shader independent of having instanced properties" ); +#endif + private readonly static GUIContent SpecularHightlightsContent = new GUIContent( " Fwd Specular Highlights Toggle", "\nIf True creates a material toggle to set Unity's internal specular highlight rendering keyword" ); + private readonly static GUIContent ReflectionsContent = new GUIContent( " Fwd Reflections Toggle", "\nIf True creates a material toggle to set Unity's internal reflections rendering keyword" ); + + [SerializeField] + private bool m_forceEnableInstancing = false; + + [SerializeField] + private bool m_forceDisableInstancing = false; + + [SerializeField] + private bool m_specularHighlightToggle = false; + + [SerializeField] + private bool m_reflectionsToggle = false; + + [SerializeField] + private bool m_lodCrossfade = false; + + [SerializeField] + private DisableBatchingTagValues m_disableBatching = DisableBatchingTagValues.False; + + [SerializeField] + private bool m_ignoreProjector = false; + + [SerializeField] + private bool m_useDefaultShadowCaster = false; + + [SerializeField] + private bool m_forceNoShadowCasting = false; + + [SerializeField] + private List m_codeGenerationDataList; + + public RenderingOptionsOpHelper() + { + m_codeGenerationDataList = new List(); + m_codeGenerationDataList.Add( new CodeGenerationData( " Exclude Deferred", "exclude_path:deferred" ) ); + m_codeGenerationDataList.Add( new CodeGenerationData( " Exclude Forward", "exclude_path:forward" ) ); + m_codeGenerationDataList.Add( new CodeGenerationData( " Exclude Legacy Deferred", "exclude_path:prepass" ) ); + m_codeGenerationDataList.Add( new CodeGenerationData( " Shadows", "noshadow" ) ); + m_codeGenerationDataList.Add( new CodeGenerationData( " Ambient Light", "noambient" ) ); + m_codeGenerationDataList.Add( new CodeGenerationData( " Per Vertex Light", "novertexlights" ) ); + m_codeGenerationDataList.Add( new CodeGenerationData( " Lightmaps", "nolightmap " ) ); + m_codeGenerationDataList.Add( new CodeGenerationData( " Dynamic Global GI", "nodynlightmap" ) ); + m_codeGenerationDataList.Add( new CodeGenerationData( " Directional lightmaps", "nodirlightmap" ) ); + m_codeGenerationDataList.Add( new CodeGenerationData( " Built-in Fog", "nofog" ) ); + m_codeGenerationDataList.Add( new CodeGenerationData( " Meta Pass", "nometa" ) ); + m_codeGenerationDataList.Add( new CodeGenerationData( " Add Pass", "noforwardadd" ) ); + } + + public bool IsOptionActive( string option ) + { + return !m_codeGenerationDataList.Find( x => x.Name.Equals( option ) ).IsActive; + } + + public void Draw( StandardSurfaceOutputNode owner ) + { + bool value = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedRenderingOptions; + NodeUtils.DrawPropertyGroup( ref value, RenderingOptionsStr, () => + { + int codeGenCount = m_codeGenerationDataList.Count; + // Starting from index 4 because other options are already contemplated with m_renderPath and add/receive shadows + for( int i = 4; i < codeGenCount; i++ ) + { + m_codeGenerationDataList[ i ].IsActive = !owner.EditorGUILayoutToggleLeft( m_codeGenerationDataList[ i ].Name, !m_codeGenerationDataList[ i ].IsActive ); + } + m_lodCrossfade = owner.EditorGUILayoutToggleLeft( LODCrossfadeContent, m_lodCrossfade ); + m_ignoreProjector = owner.EditorGUILayoutToggleLeft( IgnoreProjectorContent, m_ignoreProjector ); + EditorGUI.BeginDisabledGroup( !owner.CastShadows ); + m_useDefaultShadowCaster = owner.EditorGUILayoutToggleLeft( UseDefaultCasterContent, m_useDefaultShadowCaster ); + EditorGUI.EndDisabledGroup(); + m_forceNoShadowCasting = owner.EditorGUILayoutToggleLeft( ForceNoShadowCastingContent, m_forceNoShadowCasting ); + if( owner.ContainerGraph.IsInstancedShader ) + { + GUI.enabled = false; + owner.EditorGUILayoutToggleLeft( ForceEnableInstancingContent, true ); + GUI.enabled = true; + } + else + { + m_forceEnableInstancing = owner.EditorGUILayoutToggleLeft( ForceEnableInstancingContent, m_forceEnableInstancing ); + } + +#if UNITY_5_6_OR_NEWER + m_forceDisableInstancing = owner.EditorGUILayoutToggleLeft( ForceDisableInstancingContent, m_forceDisableInstancing ); +#endif + m_specularHighlightToggle = owner.EditorGUILayoutToggleLeft( SpecularHightlightsContent, m_specularHighlightToggle ); + m_reflectionsToggle = owner.EditorGUILayoutToggleLeft( ReflectionsContent, m_reflectionsToggle ); + m_disableBatching = (DisableBatchingTagValues)owner.EditorGUILayoutEnumPopup( DisableBatchingContent, m_disableBatching ); + Material mat = owner.ContainerGraph.CurrentMaterial; + if( mat != null ) + { + mat.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)owner.EditorGUILayoutEnumPopup( EmissionGIFlags, mat.globalIlluminationFlags ); + } + } ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedRenderingOptions = value; + } + + public void Build( ref string OptionalParameters ) + { + int codeGenCount = m_codeGenerationDataList.Count; + + for( int i = 0; i < codeGenCount; i++ ) + { + if( m_codeGenerationDataList[ i ].IsActive ) + { + OptionalParameters += m_codeGenerationDataList[ i ].Value + Constants.OptionalParametersSep; + } + } + +#if UNITY_2017_1_OR_NEWER + if( m_lodCrossfade ) + { + OptionalParameters += Constants.LodCrossFadeOption2017 + Constants.OptionalParametersSep; + } +#endif + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + for( int i = 0; i < m_codeGenerationDataList.Count; i++ ) + { + m_codeGenerationDataList[ i ].IsActive = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( UIUtils.CurrentShaderVersion() > 10005 ) + { + m_lodCrossfade = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( UIUtils.CurrentShaderVersion() > 10007 ) + { + m_disableBatching = (DisableBatchingTagValues)Enum.Parse( typeof( DisableBatchingTagValues ), nodeParams[ index++ ] ); + m_ignoreProjector = Convert.ToBoolean( nodeParams[ index++ ] ); + m_forceNoShadowCasting = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( UIUtils.CurrentShaderVersion() > 11002 ) + { + m_forceEnableInstancing = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( UIUtils.CurrentShaderVersion() > 15205 ) + { + m_forceDisableInstancing = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( UIUtils.CurrentShaderVersion() > 14403 ) + { + m_specularHighlightToggle = Convert.ToBoolean( nodeParams[ index++ ] ); + m_reflectionsToggle = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( UIUtils.CurrentShaderVersion() > 16307 ) + { + m_useDefaultShadowCaster = Convert.ToBoolean( nodeParams[ index++ ] ); + } + } + + public void WriteToString( ref string nodeInfo ) + { + for( int i = 0; i < m_codeGenerationDataList.Count; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_codeGenerationDataList[ i ].IsActive ); + } + + IOUtils.AddFieldValueToString( ref nodeInfo, m_lodCrossfade ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_disableBatching ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_ignoreProjector ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_forceNoShadowCasting ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_forceEnableInstancing ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_forceDisableInstancing ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_specularHighlightToggle ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_reflectionsToggle ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_useDefaultShadowCaster ); + } + + public void Destroy() + { + m_codeGenerationDataList.Clear(); + m_codeGenerationDataList = null; + } + public bool UseDefaultShadowCaster { get { return m_useDefaultShadowCaster; } } + public bool ForceEnableInstancing { get { return m_forceEnableInstancing; } } + public bool ForceDisableInstancing { get { return m_forceDisableInstancing; } } + + public bool LodCrossfade { get { return m_lodCrossfade; } } + public bool IgnoreProjectorValue { get { return m_ignoreProjector; } set { m_ignoreProjector = value; } } + public bool SpecularHighlightToggle { get { return m_specularHighlightToggle; } set { m_specularHighlightToggle = value; } } + public bool ReflectionsToggle { get { return m_reflectionsToggle; } set { m_reflectionsToggle = value; } } + + public string DisableBatchingTag { get { return ( m_disableBatching != DisableBatchingTagValues.False ) ? string.Format( Constants.TagFormat, "DisableBatching", m_disableBatching ) : string.Empty; } } + public string IgnoreProjectorTag { get { return ( m_ignoreProjector ) ? string.Format( Constants.TagFormat, "IgnoreProjector", "True" ) : string.Empty; } } + public string ForceNoShadowCastingTag { get { return ( m_forceNoShadowCasting ) ? string.Format( Constants.TagFormat, "ForceNoShadowCasting", "True" ) : string.Empty; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingOptionsOpHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingOptionsOpHelper.cs.meta new file mode 100644 index 0000000..e94a152 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingOptionsOpHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 26d840af03d4f7b418e9c7bece143648 +timeCreated: 1488906067 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingPlatformsOpHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingPlatformsOpHelper.cs new file mode 100644 index 0000000..46611bb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingPlatformsOpHelper.cs @@ -0,0 +1,373 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class RenderPlatformInfo + { + public string Label; + public RenderPlatforms Value; + } + + [Serializable] + public class RenderingPlatformOpHelper + { + private const string RenderingPlatformsStr = " Rendering Platforms"; + public static readonly RenderPlatformInfo[] RenderingPlatformsInfo = + { +#if UNITY_2019_4_OR_NEWER + new RenderPlatformInfo(){Label = " Direct3D 9", Value = RenderPlatforms.d3d9}, + new RenderPlatformInfo(){Label = " Direct3D 11 9.x", Value = RenderPlatforms.d3d11_9x}, + new RenderPlatformInfo(){Label = " Direct3D 11/12", Value = RenderPlatforms.d3d11}, + new RenderPlatformInfo(){Label = " OpenGL 3.x/4.x", Value = RenderPlatforms.glcore}, + new RenderPlatformInfo(){Label = " OpenGL ES 2.0", Value = RenderPlatforms.gles}, + new RenderPlatformInfo(){Label = " OpenGL ES 3.x", Value = RenderPlatforms.gles3}, + new RenderPlatformInfo(){Label = " iOS/Mac Metal", Value = RenderPlatforms.metal}, + new RenderPlatformInfo(){Label = " Vulkan", Value = RenderPlatforms.vulkan}, + new RenderPlatformInfo(){Label = " Xbox 360", Value = RenderPlatforms.xbox360}, + new RenderPlatformInfo(){Label = " Xbox One", Value = RenderPlatforms.xboxone}, + new RenderPlatformInfo(){Label = " Xbox Series X", Value = RenderPlatforms.xboxseries}, + new RenderPlatformInfo(){Label = " PlayStation 4 (Legacy)", Value = RenderPlatforms.ps4}, + new RenderPlatformInfo(){Label = " PlayStation", Value = RenderPlatforms.playstation}, + new RenderPlatformInfo(){Label = " PlayStation Vita", Value = RenderPlatforms.psp2}, + new RenderPlatformInfo(){Label = " Nintendo 3DS", Value = RenderPlatforms.n3ds}, + new RenderPlatformInfo(){Label = " Nintendo Wii U", Value = RenderPlatforms.wiiu}, + new RenderPlatformInfo(){Label = " Nintendo Switch", Value = RenderPlatforms.@switch}, + new RenderPlatformInfo(){Label = " No MRT", Value = RenderPlatforms.nomrt} +#else + new RenderPlatformInfo(){Label = " Direct3D 9", Value = RenderPlatforms.d3d9}, + new RenderPlatformInfo(){Label = " Direct3D 11 9.x", Value = RenderPlatforms.d3d11_9x}, + new RenderPlatformInfo(){Label = " Direct3D 11/12", Value = RenderPlatforms.d3d11}, + new RenderPlatformInfo(){Label = " OpenGL 3.x/4.x", Value = RenderPlatforms.glcore}, + new RenderPlatformInfo(){Label = " OpenGL ES 2.0", Value = RenderPlatforms.gles}, + new RenderPlatformInfo(){Label = " OpenGL ES 3.x", Value = RenderPlatforms.gles3}, + new RenderPlatformInfo(){Label = " iOS/Mac Metal", Value = RenderPlatforms.metal}, + new RenderPlatformInfo(){Label = " Vulkan", Value = RenderPlatforms.vulkan}, + new RenderPlatformInfo(){Label = " Xbox 360", Value = RenderPlatforms.xbox360}, + new RenderPlatformInfo(){Label = " Xbox One", Value = RenderPlatforms.xboxone}, + new RenderPlatformInfo(){Label = " PlayStation 4", Value = RenderPlatforms.ps4}, + new RenderPlatformInfo(){Label = " PlayStation Vita", Value = RenderPlatforms.psp2}, + new RenderPlatformInfo(){Label = " Nintendo 3DS", Value = RenderPlatforms.n3ds}, + new RenderPlatformInfo(){Label = " Nintendo Wii U", Value = RenderPlatforms.wiiu}, + new RenderPlatformInfo(){Label = " Nintendo Switch", Value = RenderPlatforms.@switch}, + new RenderPlatformInfo(){Label = " No MRT", Value = RenderPlatforms.nomrt} +#endif + }; + + // Values from this dictionary must be the indices corresponding from the list above + public static readonly Dictionary PlatformToIndex = new Dictionary() + { +#if UNITY_2019_4_OR_NEWER + {RenderPlatforms.d3d9, 0}, + {RenderPlatforms.d3d11_9x, 1}, + {RenderPlatforms.d3d11, 2}, + {RenderPlatforms.glcore, 3}, + {RenderPlatforms.gles, 4}, + {RenderPlatforms.gles3, 5}, + {RenderPlatforms.metal, 6}, + {RenderPlatforms.vulkan, 7}, + {RenderPlatforms.xbox360, 8}, + {RenderPlatforms.xboxone, 9}, + {RenderPlatforms.xboxseries, 10}, + {RenderPlatforms.ps4, 11}, + {RenderPlatforms.playstation, 12}, + {RenderPlatforms.psp2, 13}, + {RenderPlatforms.n3ds, 14}, + {RenderPlatforms.wiiu, 15}, + {RenderPlatforms.@switch, 16}, + {RenderPlatforms.nomrt, 17} +#else + {RenderPlatforms.d3d9, 0}, + {RenderPlatforms.d3d11_9x, 1}, + {RenderPlatforms.d3d11, 2}, + {RenderPlatforms.glcore, 3}, + {RenderPlatforms.gles, 4}, + {RenderPlatforms.gles3, 5}, + {RenderPlatforms.metal, 6}, + {RenderPlatforms.vulkan, 7}, + {RenderPlatforms.xbox360, 8}, + {RenderPlatforms.xboxone, 9}, + {RenderPlatforms.ps4, 10}, + {RenderPlatforms.psp2, 11}, + {RenderPlatforms.n3ds, 12}, + {RenderPlatforms.wiiu, 13}, + {RenderPlatforms.@switch, 14}, + {RenderPlatforms.nomrt, 15} +#endif + }; + + + public static readonly List LegacyIndexToPlatform = new List() + { + RenderPlatforms.d3d9, + RenderPlatforms.d3d11, + RenderPlatforms.glcore, + RenderPlatforms.gles, + RenderPlatforms.gles3, + RenderPlatforms.metal, + RenderPlatforms.d3d11_9x, + RenderPlatforms.xbox360, + RenderPlatforms.xboxone, + RenderPlatforms.ps4, + RenderPlatforms.psp2, + RenderPlatforms.n3ds, + RenderPlatforms.wiiu + }; + + [SerializeField] + private bool[] m_renderingPlatformValues; + + public RenderingPlatformOpHelper() + { + m_renderingPlatformValues = new bool[ RenderingPlatformsInfo.Length ]; + for( int i = 0; i < m_renderingPlatformValues.Length; i++ ) + { + m_renderingPlatformValues[ i ] = true; + } + } + + + public void Draw( ParentNode owner ) + { + bool value = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedRenderingPlatforms; + NodeUtils.DrawPropertyGroup( ref value, RenderingPlatformsStr, () => + { + for( int i = 0; i < m_renderingPlatformValues.Length; i++ ) + { + m_renderingPlatformValues[ i ] = owner.EditorGUILayoutToggleLeft( RenderingPlatformsInfo[ i ].Label, m_renderingPlatformValues[ i ] ); + } + } ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedRenderingPlatforms = value; + } + + public void DrawNested( ParentNode owner ) + { + bool value = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedRenderingPlatforms; + NodeUtils.DrawNestedPropertyGroup( ref value , RenderingPlatformsStr , () => + { + for( int i = 0 ; i < m_renderingPlatformValues.Length ; i++ ) + { + m_renderingPlatformValues[ i ] = owner.EditorGUILayoutToggleLeft( RenderingPlatformsInfo[ i ].Label , m_renderingPlatformValues[ i ] ); + } + } ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedRenderingPlatforms = value; + } + + + public string CreateResult( bool addPragmaPrefix = false ) + { + int checkedPlatforms = 0; + int uncheckedPlatforms = 0; + + for( int i = 0 ; i < m_renderingPlatformValues.Length ; i++ ) + { + if( m_renderingPlatformValues[ i ] ) + { + checkedPlatforms += 1; + } + else + { + uncheckedPlatforms += 1; + } + } + + if( checkedPlatforms > 0 && checkedPlatforms < m_renderingPlatformValues.Length ) + { + string result = string.Empty; + if( checkedPlatforms < uncheckedPlatforms ) + { + result = "only_renderers "; + for( int i = 0 ; i < m_renderingPlatformValues.Length ; i++ ) + { + if( m_renderingPlatformValues[ i ] ) + { + result += (RenderPlatforms)RenderingPlatformsInfo[ i ].Value + " "; + } + } + } + else + { + result = "exclude_renderers "; + for( int i = 0 ; i < m_renderingPlatformValues.Length ; i++ ) + { + if( !m_renderingPlatformValues[ i ] ) + { + result += (RenderPlatforms)RenderingPlatformsInfo[ i ].Value + " "; + } + } + } + if( addPragmaPrefix ) + { + result = "#pragma " + result; + } + return result; + } + + return string.Empty; + } + + public void SetRenderingPlatforms( ref string ShaderBody ) + { + string result = CreateResult(); + if( !string.IsNullOrEmpty(result)) + { + MasterNode.AddShaderPragma( ref ShaderBody, result ); + } + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + if( UIUtils.CurrentShaderVersion() < 17006 ) + { + for( int i = 0; i < m_renderingPlatformValues.Length; i++ ) + { + m_renderingPlatformValues[ i ] = false; + } + + int count = LegacyIndexToPlatform.Count; + int activeCount = 0; + for( int i = 0; i < count; i++ ) + { + RenderPlatforms platform = LegacyIndexToPlatform[ i ]; + int newIndex = PlatformToIndex[ platform ]; + bool value = Convert.ToBoolean( nodeParams[ index++ ] ); + if( value ) + { + m_renderingPlatformValues[ newIndex ] = true; + activeCount += 1; + } + else + { + m_renderingPlatformValues[ newIndex ] = false; + } + } + + if( activeCount == count ) + { + m_renderingPlatformValues[ PlatformToIndex[ RenderPlatforms.vulkan ] ] = true; + } + } + else + { + int count = Convert.ToInt32( nodeParams[ index++ ] ); + if( count > 0 ) + { + RenderPlatforms firstPlatform = (RenderPlatforms)Enum.Parse( typeof(RenderPlatforms), nodeParams[ index++ ] ); + if( firstPlatform == RenderPlatforms.all ) + { + for( int i = 0; i < m_renderingPlatformValues.Length; i++ ) + { + m_renderingPlatformValues[ i ] = true; + } + } + else + { + for( int i = 0; i < m_renderingPlatformValues.Length; i++ ) + { + m_renderingPlatformValues[ i ] = false; + } + + m_renderingPlatformValues[ PlatformToIndex[ firstPlatform ]] = true; + for( int i = 1; i < count; i++ ) + { + RenderPlatforms currPlatform = (RenderPlatforms)Enum.Parse( typeof( RenderPlatforms ), nodeParams[ index++ ] ); + m_renderingPlatformValues[ PlatformToIndex[ currPlatform ] ] = true; + } + } + } + } + } + + public void WriteToString( ref string nodeInfo ) + { + int active = 0; + for( int i = 0; i < m_renderingPlatformValues.Length; i++ ) + { + if( m_renderingPlatformValues[ i ] ) + active += 1; + } + IOUtils.AddFieldValueToString( ref nodeInfo, active ); + if( active == m_renderingPlatformValues.Length ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, RenderPlatforms.all ); + } + else + { + for( int i = 0; i < m_renderingPlatformValues.Length; i++ ) + { + if( m_renderingPlatformValues[ i ] ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, RenderingPlatformsInfo[i].Value ); + } + } + } + + } + + public void Destroy() + { + m_renderingPlatformValues = null; + } + + //TEMPLATE SPECIFIC + [SerializeField] + private bool m_loadedFromTemplate = false; + + [SerializeField] + private bool m_validData = false; + public void SetupFromTemplate( TemplateRenderPlatformHelper template ) + { + if( m_loadedFromTemplate ) + return; + + if( m_renderingPlatformValues.Length != template.RenderingPlatforms.Length ) + { + Debug.LogError( "Rendering platform length mismatch" ); + return; + } + + + m_loadedFromTemplate = true; + m_validData = true; + + for( int i = 0 ; i < m_renderingPlatformValues.Length ; i++ ) + { + m_renderingPlatformValues[ i ] = template.RenderingPlatforms[ i ]; + } + } + + public void ReadFromStringTemplate( ref uint index , ref string[] nodeParams ) + { + if( UIUtils.CurrentShaderVersion() > 18911 ) + { + bool isValid = Convert.ToBoolean( nodeParams[ index++ ] ); + if( isValid ) + { + ReadFromString( ref index , ref nodeParams ); + } + } + else + { + ReadFromString( ref index , ref nodeParams ); + } + } + + public void WriteToStringTemplate( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo , m_validData ); + if( m_validData ) + { + WriteToString( ref nodeInfo ); + } + } + + public bool LoadedFromTemplate { get { return m_loadedFromTemplate; } } + public bool ValidData { get { return m_validData; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingPlatformsOpHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingPlatformsOpHelper.cs.meta new file mode 100644 index 0000000..96f1924 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/RenderingPlatformsOpHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 50a1f03b042823f469cef7d97c73fdc3 +timeCreated: 1488907373 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StandardSurface.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StandardSurface.cs new file mode 100644 index 0000000..b3ec15e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StandardSurface.cs @@ -0,0 +1,3342 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using UnityEditorInternal; + +namespace AmplifyShaderEditor +{ + public enum VertexMode + { + Relative, + Absolute + } + + public enum RenderPath + { + All, + ForwardOnly, + DeferredOnly + } + + public enum StandardShaderLightModel + { + Standard, + StandardSpecular, + Lambert, + BlinnPhong, + Unlit, + CustomLighting + } + + public enum CullMode + { + Back, + Front, + Off + } + + public enum AlphaMode + { + Opaque = 0, + Masked = 1, + Transparent = 2, // Transparent (alpha:fade) + Translucent = 3, + Premultiply = 4, // Alpha Premul (alpha:premul) + Custom = 5, + } + + public enum DisableBatching + { + True, + False, + LODFading + } + + public enum RenderType + { + Opaque, + Transparent, + TransparentCutout, + Background, + Overlay, + TreeOpaque, + TreeTransparentCutout, + TreeBillboard, + Grass, + GrassBillboard, + Custom + } + + public enum RenderQueue + { + Background, + Geometry, + AlphaTest, + Transparent, + Overlay + } + + public enum RenderPlatforms + { + d3d9, + d3d11, + glcore, + gles, + gles3, + metal, + d3d11_9x, + xbox360, + xboxone, + xboxseries, + ps4, + playstation, + psp2, + n3ds, + wiiu, + @switch, + vulkan, + nomrt, + all + } + + [Serializable] + public class NodeCache + { + public int TargetNodeId = -1; + public int TargetPortId = -1; + + public NodeCache( int targetNodeId, int targetPortId ) + { + SetData( targetNodeId, targetPortId ); + } + + public void SetData( int targetNodeId, int targetPortId ) + { + TargetNodeId = targetNodeId; + TargetPortId = targetPortId; + } + + public void Invalidate() + { + TargetNodeId = -1; + TargetPortId = -1; + } + + public bool IsValid + { + get { return ( TargetNodeId >= 0 ); } + } + + public override string ToString() + { + return "TargetNodeId " + TargetNodeId + " TargetPortId " + TargetPortId; + } + } + + [Serializable] + public class CacheNodeConnections + { + public Dictionary> NodeCacheArray; + + public CacheNodeConnections() + { + NodeCacheArray = new Dictionary>(); + } + + public void Add( string key, NodeCache value ) + { + if( NodeCacheArray.ContainsKey( key ) ) + { + NodeCacheArray[ key ].Add( value ); + } + else + { + NodeCacheArray.Add( key, new List() ); + NodeCacheArray[ key ].Add( value ); + } + } + + public NodeCache Get( string key, int idx = 0 ) + { + if( NodeCacheArray.ContainsKey( key ) ) + { + if( idx < NodeCacheArray[ key ].Count ) + return NodeCacheArray[ key ][ idx ]; + } + return null; + } + + public List GetList( string key ) + { + if( NodeCacheArray.ContainsKey( key ) ) + { + return NodeCacheArray[ key ]; + } + return null; + } + + public void Clear() + { + foreach( KeyValuePair> kvp in NodeCacheArray ) + { + kvp.Value.Clear(); + } + NodeCacheArray.Clear(); + } + } + + [Serializable] + [NodeAttributes( "Standard Surface Output", "Master", "Surface shader generator output", null, KeyCode.None, false )] + public sealed class StandardSurfaceOutputNode : MasterNode, ISerializationCallbackReceiver + { + private readonly static string[] VertexLitFunc = { "\t\tinline half4 LightingUnlit( SurfaceOutput s, half3 lightDir, half atten )", + "\t\t{", + "\t\t\treturn half4 ( 0, 0, 0, s.Alpha );", + "\t\t}\n"}; + + private readonly static string[] FadeModeOptions = { "Opaque", "Masked", "Transparent", "Translucent", "Alpha Premultipled", "Custom" }; + private const string VertexModeStr = "Vertex Output"; + private readonly static GUIContent RenderPathContent = new GUIContent( "Render Path", "Selects and generates passes for the supported rendering paths\nDefault: All" ); + private const string ShaderModelStr = "Shader Model"; + private readonly static GUIContent LightModelContent = new GUIContent( "Light Model", "Surface shader lighting model defines how the surface reflects light\nDefault: Standard" ); + private readonly static GUIContent ShaderLODContent = new GUIContent( "Shader LOD", "Shader LOD" ); + private readonly static GUIContent CullModeContent = new GUIContent( "Cull Mode", "Polygon culling mode prevents rendering of either back-facing or front-facing polygons to save performance, turn it off if you want to render both sides\nDefault: Back" ); + + private const string ChromaticAberrationStr = "Chromatic Aberration"; + private const string DiscardStr = "Opacity Mask"; + private const string VertexDisplacementStr = "Local Vertex Offset"; + private const string VertexPositionStr = "Local Vertex Position"; + private const string VertexDataStr = "VertexData"; + private const string VertexNormalStr = "Local Vertex Normal"; + private const string CustomLightingStr = "Custom Lighting"; + private const string AlbedoStr = "Albedo"; + private const string NormalStr = "Normal"; + private const string EmissionStr = "Emission"; + private const string MetallicStr = "Metallic"; + private const string SmoothnessStr = "Smoothness"; + private const string OcclusionDataStr = "Occlusion"; + private const string OcclusionLabelStr = "Ambient Occlusion"; + private const string TransmissionStr = "Transmission"; + private const string TranslucencyStr = "Translucency"; + private const string RefractionStr = "Refraction"; + private const string AlphaStr = "Opacity"; + private const string AlphaDataStr = "Alpha"; + private const string DebugStr = "Debug"; + private const string SpecularStr = "Specular"; + private const string GlossStr = "Gloss"; + private const string CustomRenderTypeStr = "Custom Type"; + private readonly static GUIContent AlphaModeContent = new GUIContent( " Blend Mode", "Defines how the surface blends with the background\nDefault: Opaque" ); + private const string OpacityMaskClipValueStr = "Mask Clip Value"; + private readonly static GUIContent OpacityMaskClipValueContent = new GUIContent( "Mask Clip Value", "Default clip value to be compared with opacity alpha ( 0 = fully Opaque, 1 = fully Masked )\nDefault: 0.5" ); + private readonly static GUIContent CastShadowsContent = new GUIContent( "Cast Shadows", "Generates a shadow caster pass for vertex modifications and point lights in forward rendering\nDefault: ON" ); + private readonly static GUIContent ReceiveShadowsContent = new GUIContent( "Receive Shadows", "Untick it to disable shadow receiving, this includes self-shadowing (only for forward rendering) \nDefault: ON" ); + private readonly static GUIContent QueueIndexContent = new GUIContent( "Queue Index", "Value to offset the render queue, accepts both positive values to render later and negative values to render sooner\nDefault: 0" ); + private readonly static GUIContent RefractionLayerStr = new GUIContent( "Refraction Layer", "Use it to group or ungroup different refraction shaders into the same or different grabpass (only for forward rendering) \nDefault: 0" ); + private readonly static GUIContent AlphaToCoverageStr = new GUIContent( "Alpha To Coverage", "" ); + private readonly static GUIContent RenderQueueContent = new GUIContent( "Render Queue", "Base rendering queue index\n(Background = 1000, Geometry = 2000, AlphaTest = 2450, Transparent = 3000, Overlay = 4000)\nDefault: Geometry" ); + private readonly static GUIContent RenderTypeContent = new GUIContent( "Render Type", "Categorizes shaders into several predefined groups, usually to be used with screen shader effects\nDefault: Opaque" ); + + private const string ShaderInputOrderStr = "Shader Input Order"; + + + [SerializeField] + private BlendOpsHelper m_blendOpsHelper = new BlendOpsHelper(); + + [SerializeField] + private StencilBufferOpHelper m_stencilBufferHelper = new StencilBufferOpHelper(); + + [SerializeField] + private ZBufferOpHelper m_zBufferHelper = new ZBufferOpHelper(); + + [SerializeField] + private OutlineOpHelper m_outlineHelper = new OutlineOpHelper(); + + [SerializeField] + private TessellationOpHelper m_tessOpHelper = new TessellationOpHelper(); + + [SerializeField] + private ColorMaskHelper m_colorMaskHelper = new ColorMaskHelper(); + + [SerializeField] + private RenderingPlatformOpHelper m_renderingPlatformOpHelper = new RenderingPlatformOpHelper(); + + [SerializeField] + private RenderingOptionsOpHelper m_renderingOptionsOpHelper = new RenderingOptionsOpHelper(); + + [SerializeField] + private BillboardOpHelper m_billboardOpHelper = new BillboardOpHelper(); + + [SerializeField] + private FallbackPickerHelper m_fallbackHelper = null; + + [SerializeField] + private TerrainDrawInstancedHelper m_drawInstancedHelper = new TerrainDrawInstancedHelper(); + + //legacy + [SerializeField] + private AdditionalIncludesHelper m_additionalIncludes = new AdditionalIncludesHelper(); + //legacy + [SerializeField] + private AdditionalPragmasHelper m_additionalPragmas = new AdditionalPragmasHelper(); + //legacy + [SerializeField] + private AdditionalDefinesHelper m_additionalDefines = new AdditionalDefinesHelper(); + + [SerializeField] + private TemplateAdditionalDirectivesHelper m_additionalDirectives = new TemplateAdditionalDirectivesHelper( " Additional Directives" ); + + [SerializeField] + private AdditionalSurfaceOptionsHelper m_additionalSurfaceOptions = new AdditionalSurfaceOptionsHelper(); + + [SerializeField] + private UsePassHelper m_usePass; + + [SerializeField] + private CustomTagsHelper m_customTagsHelper = new CustomTagsHelper(); + + [SerializeField] + private DependenciesHelper m_dependenciesHelper = new DependenciesHelper(); + + [SerializeField] + private StandardShaderLightModel m_currentLightModel; + + [SerializeField] + private StandardShaderLightModel m_lastLightModel; + + [SerializeField] + private CullMode m_cullMode = CullMode.Back; + + [SerializeField] + private InlineProperty m_inlineCullMode = new InlineProperty(); + + [SerializeField] + private InlineProperty m_inlineChromaticAberration = new InlineProperty(0.1f); + + [SerializeField] + private AlphaMode m_alphaMode = AlphaMode.Opaque; + + [SerializeField] + private RenderType m_renderType = RenderType.Opaque; + + [SerializeField] + private string m_customRenderType = string.Empty; + + [SerializeField] + private RenderQueue m_renderQueue = RenderQueue.Geometry; + + [SerializeField] + private RenderPath m_renderPath = RenderPath.All; + + [SerializeField] + private VertexMode m_vertexMode = VertexMode.Relative; + + [SerializeField] + private bool m_customBlendMode = false; + + [SerializeField] + private float m_opacityMaskClipValue = 0.5f; + + [SerializeField] + private InlineProperty m_inlineOpacityMaskClipValue = new InlineProperty(); + + [SerializeField] + private InlineProperty m_inlineAlphaToCoverage = new InlineProperty(); + + [SerializeField] + private int m_customLightingPortId = -1; + + [SerializeField] + private int m_emissionPortId = -1; + + [SerializeField] + private int m_discardPortId = -1; + + [SerializeField] + private int m_opacityPortId = -1; + + [SerializeField] + private int m_vertexPortId = -1; + + [SerializeField] + private bool m_keepAlpha = true; + + [SerializeField] + private bool m_castShadows = true; + + //[SerializeField] + private bool m_customShadowCaster = false; + + [SerializeField] + private bool m_receiveShadows = true; + + [SerializeField] + private int m_queueOrder = 0; + + [SerializeField] + private int m_grabOrder = 0; + + [SerializeField] + private bool m_alphaToCoverage = false; + + private InputPort m_transmissionPort; + private InputPort m_translucencyPort; + private InputPort m_tessellationPort; + private bool m_previousTranslucencyOn = false; + private bool m_previousRefractionOn = false; + + [SerializeField] + private CacheNodeConnections m_cacheNodeConnections = new CacheNodeConnections(); + + + private bool m_usingProSkin = false; + private GUIStyle m_inspectorFoldoutStyle; + private GUIStyle m_inspectorToolbarStyle; + private GUIStyle m_inspectorTooldropdownStyle; + + + private bool m_customBlendAvailable = false; + + private Color m_cachedColor = Color.white; + private float m_titleOpacity = 0.5f; + private float m_boxOpacity = 0.5f; + + private InputPort m_refractionPort; + private InputPort m_normalPort; + + + private GUIStyle m_inspectorDefaultStyle; + + [SerializeField] + private ReordenatorNode m_specColorReorder = null; + + [SerializeField] + private int m_specColorOrderIndex = -1; + + [SerializeField] + private ReordenatorNode m_maskClipReorder = null; + + [SerializeField] + private int m_maskClipOrderIndex = -1; + + [SerializeField] + private ReordenatorNode m_translucencyReorder = null; + + [SerializeField] + private int m_translucencyOrderIndex = -1; + + [SerializeField] + private ReordenatorNode m_refractionReorder = null; + + [SerializeField] + private int m_refractionOrderIndex = -1; + + [SerializeField] + private ReordenatorNode m_tessellationReorder = null; + + [SerializeField] + private int m_tessellationOrderIndex = -1; + + private bool m_previousTessellationOn = false; + private bool m_initialize = true; + private bool m_checkChanges = true; + private bool m_lightModelChanged = true; + + private PropertyNode m_dummyProperty = null; + + protected override void CommonInit( int uniqueId ) + { + m_currentLightModel = m_lastLightModel = StandardShaderLightModel.Standard; + m_textLabelWidth = 120; + m_autoDrawInternalPortData = false; + base.CommonInit( uniqueId ); + m_zBufferHelper.ParentSurface = this; + m_tessOpHelper.ParentSurface = this; + m_customPrecision = true; + } + + public override void OnEnable() + { + base.OnEnable(); + if( m_usePass == null ) + { + m_usePass = ScriptableObject.CreateInstance(); + m_usePass.Init( " Additional Use Passes" ); + } + + if( m_fallbackHelper == null ) + { + m_fallbackHelper = ScriptableObject.CreateInstance(); + m_fallbackHelper.Init(); + } + } + + public override void AddMasterPorts() + { + int vertexCorrection = 2; + int index = vertexCorrection + 2; + base.AddMasterPorts(); + switch( m_currentLightModel ) + { + case StandardShaderLightModel.Standard: + { + AddInputPort( WirePortDataType.FLOAT3, false, AlbedoStr, vertexCorrection + 1, MasterNodePortCategory.Fragment, 0 ); + AddInputPort( WirePortDataType.FLOAT3, false, NormalStr, vertexCorrection + 0, MasterNodePortCategory.Fragment, 1 ); + m_normalPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + AddInputPort( WirePortDataType.FLOAT3, false, EmissionStr, index++, MasterNodePortCategory.Fragment, 2 ); + AddInputPort( WirePortDataType.FLOAT, false, MetallicStr, index++, MasterNodePortCategory.Fragment, 3 ); + AddInputPort( WirePortDataType.FLOAT, false, SmoothnessStr, index++, MasterNodePortCategory.Fragment, 4 ); + AddInputPort( WirePortDataType.FLOAT, false, OcclusionLabelStr, OcclusionDataStr, index++, MasterNodePortCategory.Fragment, 5 ); + } + break; + case StandardShaderLightModel.StandardSpecular: + { + AddInputPort( WirePortDataType.FLOAT3, false, AlbedoStr, vertexCorrection + 1, MasterNodePortCategory.Fragment, 0 ); + AddInputPort( WirePortDataType.FLOAT3, false, NormalStr, vertexCorrection + 0, MasterNodePortCategory.Fragment, 1 ); + m_normalPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + AddInputPort( WirePortDataType.FLOAT3, false, EmissionStr, index++, MasterNodePortCategory.Fragment, 2 ); + AddInputPort( WirePortDataType.FLOAT3, false, SpecularStr, index++, MasterNodePortCategory.Fragment, 3 ); + AddInputPort( WirePortDataType.FLOAT, false, SmoothnessStr, index++, MasterNodePortCategory.Fragment, 4 ); + AddInputPort( WirePortDataType.FLOAT, false, OcclusionLabelStr, OcclusionDataStr, index++, MasterNodePortCategory.Fragment, 5 ); + } + break; + case StandardShaderLightModel.CustomLighting: + { + AddInputPort( WirePortDataType.FLOAT3, false, AlbedoStr, vertexCorrection + 1, MasterNodePortCategory.Fragment, 0 ); + AddInputPort( WirePortDataType.FLOAT3, false, NormalStr, vertexCorrection + 0, MasterNodePortCategory.Fragment, 1 ); + m_normalPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = true; + AddInputPort( WirePortDataType.FLOAT3, false, EmissionStr, index++, MasterNodePortCategory.Fragment, 2 ); + AddInputPort( WirePortDataType.FLOAT, false, SpecularStr, index++, MasterNodePortCategory.Fragment, 3 ); + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = true; + AddInputPort( WirePortDataType.FLOAT, false, GlossStr, index++, MasterNodePortCategory.Fragment, 4 ); + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = true; + } + break; + case StandardShaderLightModel.Unlit: + { + AddInputPort( WirePortDataType.FLOAT3, false, AlbedoStr, vertexCorrection + 1, MasterNodePortCategory.Fragment, 0 ); + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = true; + AddInputPort( WirePortDataType.FLOAT3, false, NormalStr, vertexCorrection + 0, MasterNodePortCategory.Fragment, 1 ); + m_normalPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = true; + AddInputPort( WirePortDataType.FLOAT3, false, EmissionStr, index++, MasterNodePortCategory.Fragment, 2 ); + AddInputPort( WirePortDataType.FLOAT, false, SpecularStr, index++, MasterNodePortCategory.Fragment, 3 ); + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = true; + AddInputPort( WirePortDataType.FLOAT, false, GlossStr, index++, MasterNodePortCategory.Fragment, 4 ); + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = true; + } + break; + case StandardShaderLightModel.Lambert: + { + AddInputPort( WirePortDataType.FLOAT3, false, AlbedoStr, vertexCorrection + 1, MasterNodePortCategory.Fragment, 0 ); + AddInputPort( WirePortDataType.FLOAT3, false, NormalStr, vertexCorrection + 0, MasterNodePortCategory.Fragment, 1 ); + m_normalPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + AddInputPort( WirePortDataType.FLOAT3, false, EmissionStr, index++, MasterNodePortCategory.Fragment, 2 ); + AddInputPort( WirePortDataType.FLOAT, false, SpecularStr, index++, MasterNodePortCategory.Fragment, 3 ); + AddInputPort( WirePortDataType.FLOAT, false, GlossStr, index++, MasterNodePortCategory.Fragment, 4 ); + } + break; + case StandardShaderLightModel.BlinnPhong: + { + AddInputPort( WirePortDataType.FLOAT3, false, AlbedoStr, vertexCorrection + 1, MasterNodePortCategory.Fragment, 0 ); + AddInputPort( WirePortDataType.FLOAT3, false, NormalStr, vertexCorrection + 0, MasterNodePortCategory.Fragment, 1 ); + m_normalPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + AddInputPort( WirePortDataType.FLOAT3, false, EmissionStr, index++, MasterNodePortCategory.Fragment, 2 ); + AddInputPort( WirePortDataType.FLOAT, false, SpecularStr, index++, MasterNodePortCategory.Fragment, 3 ); + AddInputPort( WirePortDataType.FLOAT, false, GlossStr, index++, MasterNodePortCategory.Fragment, 4 ); + } + break; + } + + // instead of setting in the switch emission port is always at position 2; + m_emissionPortId = 2; + + AddInputPort( WirePortDataType.FLOAT3, false, TransmissionStr, index++, MasterNodePortCategory.Fragment, 6 ); + m_transmissionPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = ( m_currentLightModel == StandardShaderLightModel.Standard ) || ( m_currentLightModel == StandardShaderLightModel.StandardSpecular ) ? false : true; + + AddInputPort( WirePortDataType.FLOAT3, false, TranslucencyStr, index++, MasterNodePortCategory.Fragment, 7 ); + m_translucencyPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = ( m_currentLightModel == StandardShaderLightModel.Standard ) || ( m_currentLightModel == StandardShaderLightModel.StandardSpecular ) ? false : true; + + AddInputPort( WirePortDataType.FLOAT, false, RefractionStr, index + 2, MasterNodePortCategory.Fragment, 8 ); + m_refractionPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = ( m_alphaMode == AlphaMode.Opaque || m_alphaMode == AlphaMode.Masked || m_currentLightModel == StandardShaderLightModel.Unlit || m_currentLightModel == StandardShaderLightModel.CustomLighting ); + + AddInputPort( WirePortDataType.FLOAT, false, AlphaStr, index++, MasterNodePortCategory.Fragment, 9 ); + m_inputPorts[ m_inputPorts.Count - 1 ].DataName = AlphaDataStr; + m_opacityPortId = m_inputPorts.Count - 1; + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = ( m_alphaMode == AlphaMode.Opaque || m_alphaMode == AlphaMode.Masked ); + + AddInputPort( WirePortDataType.FLOAT, false, DiscardStr, index++, MasterNodePortCategory.Fragment, 10 ); + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = ( m_alphaMode != AlphaMode.Masked && m_alphaMode != AlphaMode.Custom ); + m_discardPortId = m_inputPorts.Count - 1; + + // This is done to take the index + 2 from refraction port into account and not overlap indexes + index++; + + AddInputPort( WirePortDataType.FLOAT3, false, CustomLightingStr, index++, MasterNodePortCategory.Fragment, 13 ); + m_inputPorts[ m_inputPorts.Count - 1 ].Locked = ( m_currentLightModel != StandardShaderLightModel.CustomLighting ); + m_inputPorts[ m_inputPorts.Count - 1 ].GenType = PortGenType.CustomLighting; + m_customLightingPortId = m_inputPorts.Count - 1; + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Vertex functions - Adding ordex index in order to force these to be the last ones + // Well now they have been moved to be the first ones so operations on vertex are to be taken into account + // by dither, screen position and similar nodes + //////////////////////////////////////////////////////////////////////////////////////////////// + m_vertexPortId = m_inputPorts.Count; + m_tessOpHelper.VertexOffsetIndexPort = m_vertexPortId; + AddInputPort( WirePortDataType.FLOAT3, false, ( m_vertexMode == VertexMode.Relative ? VertexDisplacementStr : VertexPositionStr ), VertexDataStr, 0/*index++*/, MasterNodePortCategory.Vertex, 11 ); + AddInputPort( WirePortDataType.FLOAT3, false, VertexNormalStr, 1/*index++*/, MasterNodePortCategory.Vertex, 12 ); + + //AddInputPort( WirePortDataType.FLOAT3, false, CustomLightModelStr, index++, MasterNodePortCategory.Fragment, 13 ); + //m_inputPorts[ m_inputPorts.Count - 1 ].Locked = true;// !(m_currentLightModel == StandardShaderLightModel.CustomLighting); + + AddInputPort( WirePortDataType.FLOAT4, false, TessellationOpHelper.TessellationPortStr, index++, MasterNodePortCategory.Tessellation, 14 ); + m_tessellationPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + m_tessOpHelper.MasterNodeIndexPort = m_tessellationPort.PortId; + + //////////////////////////////////////////////////////////////////////////////////// + AddInputPort( WirePortDataType.FLOAT3, false, DebugStr, index++, MasterNodePortCategory.Debug, 15 ); + + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + m_inputPorts[ i ].CustomColor = Color.white; + } + m_sizeIsDirty = true; + } + + public override void ForcePortType() + { + int portId = 0; + switch( m_currentLightModel ) + { + case StandardShaderLightModel.Standard: + { + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + } + break; + case StandardShaderLightModel.StandardSpecular: + { + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + } + break; + case StandardShaderLightModel.CustomLighting: + { + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + } + break; + case StandardShaderLightModel.Unlit: + case StandardShaderLightModel.Lambert: + { + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + } + break; + case StandardShaderLightModel.BlinnPhong: + { + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + } + break; + } + + //Transmission + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + //Translucency + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + //Refraction + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + //Alpha + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + //Discard + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT, false ); + //Custom Lighting + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + //Vertex Offset + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + //Vertex Normal + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + //Tessellation + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT4, false ); + //Debug + m_inputPorts[ portId++ ].ChangeType( WirePortDataType.FLOAT3, false ); + } + + public override void SetName( string name ) + { + ShaderName = name; + } + + public void DrawInspectorProperty() + { + if( m_inspectorDefaultStyle == null ) + { + m_inspectorDefaultStyle = UIUtils.GetCustomStyle( CustomStyle.ResetToDefaultInspectorButton ); + } + + DrawCustomInspector( false ); + } + + private void RecursiveLog() + { + List nodes = UIUtils.PropertyNodesList(); + nodes.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + for( int i = 0; i < nodes.Count; i++ ) + { + if( ( nodes[ i ] is ReordenatorNode ) ) + ( nodes[ i ] as ReordenatorNode ).RecursiveLog(); + else + Debug.Log( nodes[ i ].OrderIndex + " " + nodes[ i ].PropertyName ); + } + } + + public void DrawGeneralOptions() + { + DrawShaderName(); + DrawCurrentShaderType(); + + EditorGUI.BeginChangeCheck(); + m_currentLightModel = (StandardShaderLightModel)EditorGUILayoutEnumPopup( LightModelContent, m_currentLightModel ); + if( EditorGUI.EndChangeCheck() ) + { + ContainerGraph.ChangedLightingModel = true; + if( m_currentLightModel == StandardShaderLightModel.CustomLighting ) + { + ContainerGraph.ParentWindow.CurrentNodeAvailability = NodeAvailability.CustomLighting; + //ContainerGraph.CurrentCanvasMode = NodeAvailability.CustomLighting; + } + else + { + ContainerGraph.ParentWindow.CurrentNodeAvailability = NodeAvailability.SurfaceShader; + //ContainerGraph.CurrentCanvasMode = NodeAvailability.SurfaceShader; + } + } + + m_shaderModelIdx = EditorGUILayoutPopup( ShaderModelStr, m_shaderModelIdx, ShaderModelTypeArr ); + + EditorGUI.BeginChangeCheck(); + DrawPrecisionProperty( false ); + if( EditorGUI.EndChangeCheck() ) + ContainerGraph.CurrentPrecision = m_currentPrecisionType; + //m_cullMode = (CullMode)EditorGUILayoutEnumPopup( CullModeContent, m_cullMode ); + UndoParentNode inst = this; + m_inlineCullMode.CustomDrawer( ref inst, ( x ) => { m_cullMode = (CullMode)EditorGUILayoutEnumPopup( CullModeContent, m_cullMode ); }, CullModeContent.text ); + //m_inlineCullMode.Value = (int)m_cullMode; + //m_inlineCullMode.EnumTypePopup( ref inst, CullModeContent.text, Enum.GetNames( typeof( CullMode ) ) ); + //m_cullMode = (CullMode) m_inlineCullMode.Value; + + m_renderPath = (RenderPath)EditorGUILayoutEnumPopup( RenderPathContent, m_renderPath ); + + m_castShadows = EditorGUILayoutToggle( CastShadowsContent, m_castShadows ); + + m_receiveShadows = EditorGUILayoutToggle( ReceiveShadowsContent, m_receiveShadows ); + + DrawSamplingMacros(); + + m_drawInstancedHelper.Draw( this ); + + m_queueOrder = EditorGUILayoutIntField( QueueIndexContent, m_queueOrder ); + EditorGUI.BeginChangeCheck(); + m_vertexMode = (VertexMode)EditorGUILayoutEnumPopup( VertexModeStr, m_vertexMode ); + if( EditorGUI.EndChangeCheck() ) + { + m_inputPorts[ m_vertexPortId ].Name = m_vertexMode == VertexMode.Relative ? VertexDisplacementStr : VertexPositionStr; + m_sizeIsDirty = true; + } + + ShaderLOD = Mathf.Clamp( EditorGUILayoutIntField( ShaderLODContent, ShaderLOD ), 0, Shader.globalMaximumLOD ); + ////m_lodCrossfade = EditorGUILayoutToggle( LODCrossfadeContent, m_lodCrossfade ); + m_fallbackHelper.Draw( this ); + DrawInspectorProperty(); + + } + + public void ShowOpacityMaskValueUI() + { + EditorGUI.BeginChangeCheck(); + UndoParentNode inst = this; + m_inlineOpacityMaskClipValue.CustomDrawer( ref inst, ( x ) => { m_opacityMaskClipValue = EditorGUILayoutFloatField( OpacityMaskClipValueContent, m_opacityMaskClipValue ); }, OpacityMaskClipValueContent.text ); + if( EditorGUI.EndChangeCheck() ) + { + m_checkChanges = true; + if( m_currentMaterial != null && m_currentMaterial.HasProperty( IOUtils.MaskClipValueName ) ) + { + m_currentMaterial.SetFloat( IOUtils.MaskClipValueName, m_opacityMaskClipValue ); + } + } + } + + public override void DrawProperties() + { + if( m_inspectorFoldoutStyle == null || EditorGUIUtility.isProSkin != m_usingProSkin ) + m_inspectorFoldoutStyle = new GUIStyle( GUI.skin.GetStyle( "foldout" ) ); + + if( m_inspectorToolbarStyle == null || EditorGUIUtility.isProSkin != m_usingProSkin ) + { + m_inspectorToolbarStyle = new GUIStyle( GUI.skin.GetStyle( "toolbarbutton" ) ) + { + fixedHeight = 20 + }; + } + + if( m_inspectorTooldropdownStyle == null || EditorGUIUtility.isProSkin != m_usingProSkin ) + { + m_inspectorTooldropdownStyle = new GUIStyle( GUI.skin.GetStyle( "toolbardropdown" ) ) + { + fixedHeight = 20 + }; + m_inspectorTooldropdownStyle.margin.bottom = 2; + } + + if( EditorGUIUtility.isProSkin != m_usingProSkin ) + m_usingProSkin = EditorGUIUtility.isProSkin; + + base.DrawProperties(); + + EditorGUILayout.BeginVertical(); + { + EditorGUILayout.Separator(); + + m_titleOpacity = 0.5f; + m_boxOpacity = ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ); + m_cachedColor = GUI.color; + + // General + bool generalIsVisible = ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedGeneralShaderOptions; + NodeUtils.DrawPropertyGroup( ref generalIsVisible, GeneralFoldoutStr, DrawGeneralOptions ); + ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedGeneralShaderOptions = generalIsVisible; + + //Blend Mode + GUI.color = new Color( m_cachedColor.r, m_cachedColor.g, m_cachedColor.b, m_titleOpacity ); + EditorGUILayout.BeginHorizontal( m_inspectorToolbarStyle ); + GUI.color = m_cachedColor; + + bool blendOptionsVisible = GUILayout.Toggle( ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedBlendOptions, AlphaModeContent, UIUtils.MenuItemToggleStyle, GUILayout.ExpandWidth( true ) ); + if( Event.current.button == Constants.FoldoutMouseId ) + { + ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedBlendOptions = blendOptionsVisible; + } + + + if( !EditorGUIUtility.isProSkin ) + GUI.color = new Color( 0.25f, 0.25f, 0.25f, 1f ); + + float boxSize = 60; + switch( m_alphaMode ) + { + case AlphaMode.Transparent: + boxSize = 85; + break; + case AlphaMode.Translucent: + boxSize = 80; + break; + case AlphaMode.Premultiply: + boxSize = 120; + break; + } + EditorGUI.BeginChangeCheck(); + m_alphaMode = (AlphaMode)EditorGUILayoutPopup( string.Empty, (int)m_alphaMode, FadeModeOptions, UIUtils.InspectorPopdropdownStyle, GUILayout.Width( boxSize ), GUILayout.Height( 19 ) ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromBlendMode(); + } + + GUI.color = m_cachedColor; + EditorGUILayout.EndHorizontal(); + + m_customBlendAvailable = ( m_alphaMode == AlphaMode.Custom || m_alphaMode == AlphaMode.Opaque ); + + if( ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedBlendOptions ) + { + GUI.color = new Color( m_cachedColor.r, m_cachedColor.g, m_cachedColor.b, m_boxOpacity ); + EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + GUI.color = m_cachedColor; + EditorGUI.indentLevel++; + EditorGUILayout.Separator(); + EditorGUI.BeginChangeCheck(); + + + m_renderType = (RenderType)EditorGUILayoutEnumPopup( RenderTypeContent, m_renderType ); + if( m_renderType == RenderType.Custom ) + { + EditorGUI.BeginChangeCheck(); + m_customRenderType = EditorGUILayoutTextField( CustomRenderTypeStr, m_customRenderType ); + if( EditorGUI.EndChangeCheck() ) + { + m_customRenderType = UIUtils.RemoveInvalidCharacters( m_customRenderType ); + } + } + + m_renderQueue = (RenderQueue)EditorGUILayoutEnumPopup( RenderQueueContent, m_renderQueue ); + + if( EditorGUI.EndChangeCheck() ) + { + if( m_renderType == RenderType.Opaque && m_renderQueue == RenderQueue.Geometry ) + m_alphaMode = AlphaMode.Opaque; + else if( m_renderType == RenderType.TransparentCutout && m_renderQueue == RenderQueue.AlphaTest ) + m_alphaMode = AlphaMode.Masked; + else if( m_renderType == RenderType.Transparent && m_renderQueue == RenderQueue.Transparent ) + m_alphaMode = AlphaMode.Transparent; + else if( m_renderType == RenderType.Opaque && m_renderQueue == RenderQueue.Transparent ) + m_alphaMode = AlphaMode.Translucent; + else + m_alphaMode = AlphaMode.Custom; + + + UpdateFromBlendMode(); + } + + bool bufferedEnabled = GUI.enabled; + + GUI.enabled = ( m_alphaMode == AlphaMode.Masked || m_alphaMode == AlphaMode.Custom ); + m_inputPorts[ m_discardPortId ].Locked = !GUI.enabled; + ShowOpacityMaskValueUI(); + + GUI.enabled = bufferedEnabled; + + EditorGUI.BeginDisabledGroup( !( m_alphaMode == AlphaMode.Transparent || m_alphaMode == AlphaMode.Premultiply || m_alphaMode == AlphaMode.Translucent || m_alphaMode == AlphaMode.Custom ) ); + m_grabOrder = EditorGUILayoutIntField( RefractionLayerStr, m_grabOrder ); + float cachedLabelWidth = EditorGUIUtility.labelWidth; + UndoParentNode inst = this; + if( m_refractionPort.IsConnected ) + { + EditorGUIUtility.labelWidth = 145; + EditorGUI.BeginChangeCheck(); + m_inlineChromaticAberration.RangedFloatField( ref inst, ChromaticAberrationStr, 0.0f,0.3f ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_currentMaterial != null && m_currentMaterial.HasProperty( IOUtils.ChromaticAberrationProperty ) ) + { + m_currentMaterial.SetFloat( IOUtils.ChromaticAberrationProperty, m_inlineChromaticAberration.FloatValue ); + } + } + } + + //EditorGUIUtility.labelWidth = 130; + m_inlineAlphaToCoverage.CustomDrawer( ref inst, ( x ) => { m_alphaToCoverage = EditorGUILayoutToggle( AlphaToCoverageStr, m_alphaToCoverage ); }, AlphaToCoverageStr.text ); + //EditorGUIUtility.labelWidth = cachedLabelWidth; + EditorGUI.EndDisabledGroup(); + + EditorGUILayout.Separator(); + + if( !m_customBlendAvailable ) + { + EditorGUILayout.HelpBox( "Advanced options are only available for Custom blend modes", MessageType.Warning ); + } + + EditorGUI.BeginDisabledGroup( !m_customBlendAvailable ); + m_blendOpsHelper.Draw( this, m_customBlendAvailable ); + m_colorMaskHelper.Draw( this ); + + EditorGUI.EndDisabledGroup(); + EditorGUILayout.Separator(); + EditorGUI.indentLevel--; + EditorGUILayout.EndVertical(); + } + + m_stencilBufferHelper.Draw( this ); + m_tessOpHelper.Draw( this, m_inspectorToolbarStyle, m_currentMaterial, m_tessellationPort.IsConnected ); + m_outlineHelper.Draw( this, m_inspectorToolbarStyle, m_currentMaterial ); + m_billboardOpHelper.Draw( this ); + m_zBufferHelper.Draw( this, m_inspectorToolbarStyle, m_customBlendAvailable ); + m_renderingOptionsOpHelper.Draw( this ); + m_renderingPlatformOpHelper.Draw( this ); + //m_additionalDefines.Draw( this ); + //m_additionalIncludes.Draw( this ); + //m_additionalPragmas.Draw( this ); + m_additionalSurfaceOptions.Draw( this ); + m_usePass.Draw( this ); + m_additionalDirectives.Draw( this ); + m_customTagsHelper.Draw( this ); + m_dependenciesHelper.Draw( this ); + DrawMaterialInputs( m_inspectorToolbarStyle ); + } + + EditorGUILayout.EndVertical(); + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + + if( m_initialize ) + { + m_initialize = false; + + if( m_dummyProperty == null ) + { + m_dummyProperty = ScriptableObject.CreateInstance(); + m_dummyProperty.ContainerGraph = ContainerGraph; + } + } + + if( m_currentLightModel != m_lastLightModel ) + m_lightModelChanged = true; + + if( m_lightModelChanged ) + { + m_lightModelChanged = false; + if( m_currentLightModel == StandardShaderLightModel.BlinnPhong ) + { + if( m_specColorReorder == null ) + { + m_specColorReorder = ScriptableObject.CreateInstance(); + m_specColorReorder.ContainerGraph = ContainerGraph; + m_specColorReorder.OrderIndex = m_specColorOrderIndex; + m_specColorReorder.Init( "_SpecColor", "Specular Color", null ); + } + + UIUtils.RegisterPropertyNode( m_specColorReorder ); + } + else + { + if( m_specColorReorder != null ) + UIUtils.UnregisterPropertyNode( m_specColorReorder ); + } + + if( m_currentLightModel == StandardShaderLightModel.CustomLighting && m_masterNodeCategory == 0 ) + ContainerGraph.CurrentCanvasMode = NodeAvailability.CustomLighting; + else if( m_masterNodeCategory == 0 ) + ContainerGraph.CurrentCanvasMode = NodeAvailability.SurfaceShader; + CacheCurrentSettings(); + m_lastLightModel = m_currentLightModel; + DeleteAllInputConnections( true, true ); + AddMasterPorts(); + ConnectFromCache(); + } + + if( drawInfo.CurrentEventType != EventType.Layout ) + return; + + if( m_transmissionPort != null && m_transmissionPort.IsConnected && m_renderPath != RenderPath.ForwardOnly ) + { + m_renderPath = RenderPath.ForwardOnly; + UIUtils.ShowMessage( "Render Path changed to Forward Only since transmission only works in forward rendering" ); + } + + if( m_translucencyPort != null && m_translucencyPort.IsConnected && m_renderPath != RenderPath.ForwardOnly ) + { + m_renderPath = RenderPath.ForwardOnly; + UIUtils.ShowMessage( "Render Path changed to Forward Only since translucency only works in forward rendering" ); + } + + if( m_translucencyPort.IsConnected != m_previousTranslucencyOn ) + m_checkChanges = true; + + if( m_refractionPort.IsConnected != m_previousRefractionOn ) + m_checkChanges = true; + + if( ( m_tessOpHelper.EnableTesselation && !m_tessellationPort.IsConnected ) != m_previousTessellationOn ) + m_checkChanges = true; + + m_previousTranslucencyOn = m_translucencyPort.IsConnected; + + m_previousRefractionOn = m_refractionPort.IsConnected; + + m_previousTessellationOn = ( m_tessOpHelper.EnableTesselation && !m_tessellationPort.IsConnected ); + + if( m_checkChanges ) + { + if( m_translucencyPort.IsConnected ) + { + if( m_translucencyReorder == null ) + { + List translucencyList = new List(); + for( int i = 0; i < 7; i++ ) + { + translucencyList.Add( m_dummyProperty ); + } + + m_translucencyReorder = ScriptableObject.CreateInstance(); + m_translucencyReorder.ContainerGraph = ContainerGraph; + m_translucencyReorder.OrderIndex = m_translucencyOrderIndex; + m_translucencyReorder.Init( "_TranslucencyGroup", "Translucency", translucencyList ); + } + + UIUtils.RegisterPropertyNode( m_translucencyReorder ); + } + else + { + if( m_translucencyReorder != null ) + UIUtils.UnregisterPropertyNode( m_translucencyReorder ); + } + + if( m_refractionPort.IsConnected ) + { + if( m_refractionReorder == null ) + { + List refractionList = new List(); + for( int i = 0; i < 2; i++ ) + { + refractionList.Add( m_dummyProperty ); + } + + m_refractionReorder = ScriptableObject.CreateInstance(); + m_refractionReorder.ContainerGraph = ContainerGraph; + m_refractionReorder.OrderIndex = m_refractionOrderIndex; + m_refractionReorder.Init( "_RefractionGroup", "Refraction", refractionList ); + } + + UIUtils.RegisterPropertyNode( m_refractionReorder ); + } + else + { + if( m_refractionReorder != null ) + UIUtils.UnregisterPropertyNode( m_refractionReorder ); + } + + if( m_tessOpHelper.EnableTesselation && !m_tessellationPort.IsConnected ) + { + if( m_tessellationReorder == null ) + { + List tessellationList = new List(); + for( int i = 0; i < 4; i++ ) + { + tessellationList.Add( m_dummyProperty ); + } + + m_tessellationReorder = ScriptableObject.CreateInstance(); + m_tessellationReorder.ContainerGraph = ContainerGraph; + m_tessellationReorder.OrderIndex = m_tessellationOrderIndex; + m_tessellationReorder.Init( "_TessellationGroup", "Tessellation", tessellationList ); + m_tessellationReorder.HeaderTitle = "Tesselation"; + } + + UIUtils.RegisterPropertyNode( m_tessellationReorder ); + } + else + { + if( m_tessellationReorder != null ) + UIUtils.UnregisterPropertyNode( m_tessellationReorder ); + } + + if( m_inputPorts[ m_discardPortId ].Available && !m_inlineOpacityMaskClipValue.IsValid ) + { + if( m_maskClipReorder == null ) + { + // Create dragable clip material property + m_maskClipReorder = ScriptableObject.CreateInstance(); + m_maskClipReorder.ContainerGraph = ContainerGraph; + m_maskClipReorder.OrderIndex = m_maskClipOrderIndex; + m_maskClipReorder.Init( "_Cutoff", "Mask Clip Value", null ); + } + + UIUtils.RegisterPropertyNode( m_maskClipReorder ); + } + else + { + if( m_maskClipReorder != null ) + UIUtils.UnregisterPropertyNode( m_maskClipReorder ); + } + + m_checkChanges = false; + } + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + + if( m_containerGraph.IsInstancedShader || m_renderingOptionsOpHelper.ForceEnableInstancing ) + { + DrawInstancedIcon( drawInfo ); + } + } + + private void CacheCurrentSettings() + { + m_cacheNodeConnections.Clear(); + for( int portId = 0; portId < m_inputPorts.Count; portId++ ) + { + if( m_inputPorts[ portId ].IsConnected ) + { + WireReference connection = m_inputPorts[ portId ].GetConnection(); + m_cacheNodeConnections.Add( m_inputPorts[ portId ].Name, new NodeCache( connection.NodeId, connection.PortId ) ); + } + } + } + + private void ConnectFromCache() + { + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + NodeCache cache = m_cacheNodeConnections.Get( m_inputPorts[ i ].Name ); + if( cache != null ) + { + UIUtils.SetConnection( UniqueId, m_inputPorts[ i ].PortId, cache.TargetNodeId, cache.TargetPortId ); + } + } + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if( m_alphaMode == AlphaMode.Masked || m_alphaMode == AlphaMode.Custom ) + { + if( mat.HasProperty( IOUtils.MaskClipValueName ) ) + mat.SetFloat( IOUtils.MaskClipValueName, m_opacityMaskClipValue ); + } + + if( m_refractionPort.IsConnected && !m_inlineChromaticAberration.Active ) + { + if( mat.HasProperty( IOUtils.ChromaticAberrationProperty ) ) + mat.SetFloat( IOUtils.ChromaticAberrationProperty, m_inlineChromaticAberration.FloatValue ); + } + } + + public override void SetMaterialMode( Material mat, bool fetchMaterialValues ) + { + base.SetMaterialMode( mat, fetchMaterialValues ); + if( m_alphaMode == AlphaMode.Masked || m_alphaMode == AlphaMode.Custom ) + { + if( fetchMaterialValues && m_materialMode && mat.HasProperty( IOUtils.MaskClipValueName ) ) + { + m_opacityMaskClipValue = mat.GetFloat( IOUtils.MaskClipValueName ); + } + } + + if( m_refractionPort.IsConnected && !m_inlineChromaticAberration.Active ) + { + if( fetchMaterialValues && m_materialMode && mat.HasProperty( IOUtils.ChromaticAberrationProperty ) ) + m_inlineChromaticAberration.FloatValue = mat.GetFloat( IOUtils.ChromaticAberrationProperty); + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + m_tessOpHelper.UpdateFromMaterial( material ); + m_outlineHelper.UpdateFromMaterial( material ); + + if( m_alphaMode == AlphaMode.Masked || m_alphaMode == AlphaMode.Custom ) + { + if( material.HasProperty( IOUtils.MaskClipValueName ) ) + m_opacityMaskClipValue = material.GetFloat( IOUtils.MaskClipValueName ); + } + + if( m_refractionPort.IsConnected && !m_inlineChromaticAberration.Active ) + { + if( material.HasProperty( IOUtils.ChromaticAberrationProperty ) ) + m_inlineChromaticAberration.FloatValue = material.GetFloat( IOUtils.ChromaticAberrationProperty ); + } + } + + public override void UpdateMasterNodeMaterial( Material material ) + { + m_currentMaterial = material; + UpdateMaterialEditor(); + } + + void UpdateMaterialEditor() + { + FireMaterialChangedEvt(); + } + + public string CreateInstructionsForVertexPort( InputPort port ) + { + //Vertex displacement and per vertex custom data + WireReference connection = port.GetConnection(); + ParentNode node = UIUtils.GetNode( connection.NodeId ); + + string vertexInstructions = node.GetValueFromOutputStr( connection.PortId, port.DataType, ref m_currentDataCollector, false ); + + if( m_currentDataCollector.DirtySpecialLocalVariables ) + { + m_currentDataCollector.AddVertexInstruction( m_currentDataCollector.SpecialLocalVariables, UniqueId, false ); + m_currentDataCollector.ClearSpecialLocalVariables(); + } + + if( m_currentDataCollector.DirtyVertexVariables ) + { + m_currentDataCollector.AddVertexInstruction( m_currentDataCollector.VertexLocalVariables, UniqueId, false ); + m_currentDataCollector.ClearVertexLocalVariables(); + } + + return vertexInstructions; + } + + public void CreateInstructionsForPort( InputPort port, string portName, bool addCustomDelimiters = false, string customDelimiterIn = null, string customDelimiterOut = null, bool ignoreLocalVar = false, bool normalIsConnected = false , bool isDebugPort = false ) + { + WireReference connection = port.GetConnection(); + ParentNode node = UIUtils.GetNode( connection.NodeId ); + + string newInstruction = node.GetValueFromOutputStr( connection.PortId, port.DataType, ref m_currentDataCollector, ignoreLocalVar ); + + if( m_currentDataCollector.DirtySpecialLocalVariables ) + { + m_currentDataCollector.AddInstructions( m_currentDataCollector.SpecialLocalVariables ); + m_currentDataCollector.ClearSpecialLocalVariables(); + } + + if( m_currentDataCollector.DirtyVertexVariables ) + { + m_currentDataCollector.AddVertexInstruction( m_currentDataCollector.VertexLocalVariables, port.NodeId, false ); + m_currentDataCollector.ClearVertexLocalVariables(); + } + + if( m_currentDataCollector.ForceNormal && !normalIsConnected ) + { + m_currentDataCollector.AddToStartInstructions( "\t\t\t" + Constants.OutputVarStr + ".Normal = float3(0,0,1);\n" ); + m_currentDataCollector.DirtyNormal = true; + m_currentDataCollector.ForceNormal = false; + } + + m_currentDataCollector.AddInstructions( addCustomDelimiters ? customDelimiterIn : ( "\t\t\t" + portName + " = " ) ); + m_currentDataCollector.AddInstructions( newInstruction ); + m_currentDataCollector.AddInstructions( addCustomDelimiters ? customDelimiterOut :((isDebugPort)?" + 1E-5;\n":";\n") ); + } + + public string CreateInstructionStringForPort( InputPort port, bool ignoreLocalVar = false ) + { + WireReference connection = port.GetConnection(); + ParentNode node = UIUtils.GetNode( connection.NodeId ); + + string newInstruction = node.GetValueFromOutputStr( connection.PortId, port.DataType, ref m_currentDataCollector, ignoreLocalVar ); + + if( m_currentDataCollector.DirtySpecialLocalVariables ) + { + m_currentDataCollector.AddInstructions( m_currentDataCollector.SpecialLocalVariables ); + m_currentDataCollector.ClearSpecialLocalVariables(); + } + + if( m_currentDataCollector.DirtyVertexVariables ) + { + m_currentDataCollector.AddVertexInstruction( m_currentDataCollector.VertexLocalVariables, port.NodeId, false ); + m_currentDataCollector.ClearVertexLocalVariables(); + } + + if( m_currentDataCollector.ForceNormal ) + { + m_currentDataCollector.AddToStartInstructions( "\t\t\t" + Constants.OutputVarStr + ".Normal = float3(0,0,1);\n" ); + m_currentDataCollector.DirtyNormal = true; + m_currentDataCollector.ForceNormal = false; + } + + return newInstruction; + } + + public override Shader Execute( string pathname, bool isFullPath ) + { + ForcePortType(); + ForceReordering(); + UpdateFromBlendMode(); + base.Execute( pathname, isFullPath ); + RegisterStandaloneFuntions(); + + bool isInstancedShader = m_renderingOptionsOpHelper.ForceEnableInstancing || UIUtils.IsInstancedShader(); + bool hasVirtualTexture = UIUtils.HasVirtualTexture(); + bool hasTranslucency = false; + bool hasTransmission = false; + bool hasEmission = false; + bool hasOpacity = false; + bool hasOpacityMask = false; + bool hasRefraction = false; + //bool hasVertexOffset = false; + //bool hasCustomLightingAlpha = false; + bool hasCustomLightingMask = false; + + string customLightingCode = string.Empty; + string customLightingAlphaCode = string.Empty; + string customLightingMaskCode = string.Empty; + string customLightingInstructions = string.Empty; + + string refractionCode = string.Empty; + string refractionInstructions = string.Empty; + string refractionFix = string.Empty; + + string aboveUsePasses = string.Empty; + string bellowUsePasses = string.Empty; + + + m_currentDataCollector.TesselationActive = m_tessOpHelper.EnableTesselation; + #if UNITY_IOS + // On iOS custom app data must be used since fixed4 color from appdata_full generates an error on it when tessellation is active + m_currentDataCollector.ForceCustomAppDataUsage(); + #endif + m_currentDataCollector.CurrentRenderPath = m_renderPath; + + StandardShaderLightModel cachedLightModel = m_currentLightModel; + NodeAvailability cachedAvailability = ContainerGraph.CurrentCanvasMode; + + bool debugIsUsingCustomLighting = false; + bool usingDebugPort = false; + if( m_inputPorts[ m_inputPorts.Count - 1 ].IsConnected ) + { + usingDebugPort = true; + debugIsUsingCustomLighting = m_currentLightModel == StandardShaderLightModel.CustomLighting; + + m_currentDataCollector.GenType = PortGenType.CustomLighting; + m_currentLightModel = StandardShaderLightModel.CustomLighting; + ContainerGraph.CurrentCanvasMode = NodeAvailability.CustomLighting; + } + + if( isInstancedShader ) + { + m_currentDataCollector.AddToPragmas( UniqueId, IOUtils.InstancedPropertiesHeader ); + } + + if( m_renderingOptionsOpHelper.SpecularHighlightToggle || m_renderingOptionsOpHelper.ReflectionsToggle ) + m_currentDataCollector.AddToProperties( UniqueId, "[Header(Forward Rendering Options)]", 10001 ); + if( m_renderingOptionsOpHelper.SpecularHighlightToggle ) + { + m_currentDataCollector.AddToProperties( UniqueId, "[ToggleOff] _SpecularHighlights(\"Specular Highlights\", Float) = 1.0", 10002 ); + m_currentDataCollector.AddToPragmas( UniqueId, "shader_feature _SPECULARHIGHLIGHTS_OFF" ); + } + if( m_renderingOptionsOpHelper.ReflectionsToggle ) + { + m_currentDataCollector.AddToProperties( UniqueId, "[ToggleOff] _GlossyReflections(\"Reflections\", Float) = 1.0", 10003 ); + m_currentDataCollector.AddToPragmas( UniqueId, "shader_feature _GLOSSYREFLECTIONS_OFF" ); + } + + + // See if each node is being used on frag and/or vert ports + SetupNodeCategories(); + m_containerGraph.CheckPropertiesAutoRegister( ref m_currentDataCollector ); + + if( m_refractionPort.IsConnected || m_inputPorts[ m_inputPorts.Count - 1 ].IsConnected ) + { + m_currentDataCollector.DirtyNormal = true; + m_currentDataCollector.ForceNormal = true; + } + //this.PropagateNodeData( nodeData ); + + string tags = "\"RenderType\" = \"{0}\" \"Queue\" = \"{1}\""; + string finalRenderType = ( m_renderType == RenderType.Custom && m_customRenderType.Length > 0 ) ? m_customRenderType : m_renderType.ToString(); + tags = string.Format( tags, finalRenderType, ( m_renderQueue + ( ( m_queueOrder >= 0 ) ? "+" : string.Empty ) + m_queueOrder ) ); + //if ( !m_customBlendMode ) + { + if( m_alphaMode == AlphaMode.Transparent || m_alphaMode == AlphaMode.Premultiply ) + { + //tags += " \"IgnoreProjector\" = \"True\""; + if( !m_renderingOptionsOpHelper.IgnoreProjectorValue ) + { + Debug.Log( string.Format( "Setting Ignore Projector to True since it's requires by Blend Mode {0}.", m_alphaMode ) ); + m_renderingOptionsOpHelper.IgnoreProjectorValue = true; + } + } + } + + tags += m_renderingOptionsOpHelper.IgnoreProjectorTag; + tags += m_renderingOptionsOpHelper.ForceNoShadowCastingTag; + tags += m_renderingOptionsOpHelper.DisableBatchingTag; + + //add virtual texture support + if( hasVirtualTexture ) + { + tags += " \"Amplify\" = \"True\" "; + } + + //tags = "Tags{ " + tags + " }"; + + string outputStruct = ""; + switch( m_currentLightModel ) + { + case StandardShaderLightModel.CustomLighting: outputStruct = "SurfaceOutputCustomLightingCustom"; break; + case StandardShaderLightModel.Standard: outputStruct = "SurfaceOutputStandard"; break; + case StandardShaderLightModel.StandardSpecular: outputStruct = "SurfaceOutputStandardSpecular"; break; + case StandardShaderLightModel.Unlit: + case StandardShaderLightModel.Lambert: + case StandardShaderLightModel.BlinnPhong: outputStruct = "SurfaceOutput"; break; + } + + if( m_currentLightModel == StandardShaderLightModel.CustomLighting ) + { + m_currentDataCollector.AddToIncludes( UniqueId, Constants.UnityPBSLightingLib ); + + m_currentDataCollector.ChangeCustomInputHeader( m_currentLightModel.ToString() + Constants.CustomLightStructStr ); + m_currentDataCollector.AddToCustomInput( UniqueId, "half3 Albedo", true ); + m_currentDataCollector.AddToCustomInput( UniqueId, "half3 Normal", true ); + m_currentDataCollector.AddToCustomInput( UniqueId, "half3 Emission", true ); + m_currentDataCollector.AddToCustomInput( UniqueId, "half Metallic", true ); + m_currentDataCollector.AddToCustomInput( UniqueId, "half Smoothness", true ); + m_currentDataCollector.AddToCustomInput( UniqueId, "half Occlusion", true ); + m_currentDataCollector.AddToCustomInput( UniqueId, "half Alpha", true ); + m_currentDataCollector.AddToCustomInput( UniqueId, "Input SurfInput", true ); + m_currentDataCollector.AddToCustomInput( UniqueId, "UnityGIInput GIData", true ); + } + + //Terrain Draw Instanced + if( m_drawInstancedHelper.Enabled ) + { + if( !m_currentDataCollector.DirtyPerVertexData ) + { + m_currentDataCollector.OpenPerVertexHeader( !m_tessOpHelper.EnableTesselation ); + } + m_drawInstancedHelper.UpdateDataCollectorForStandard( ref m_currentDataCollector ); + } + + // Need to sort before creating local vars so they can inspect the normal port correctly + SortedList sortedPorts = new SortedList(); + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + sortedPorts.Add( m_inputPorts[ i ].OrderId, m_inputPorts[ i ] ); + } + + bool normalIsConnected = m_normalPort.IsConnected; + m_tessOpHelper.Reset(); + if( m_inputPorts[ m_inputPorts.Count - 1 ].IsConnected ) + { + //Debug Port active + InputPort debugPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + m_currentDataCollector.PortCategory = debugPort.Category; + if( debugIsUsingCustomLighting ) + { + m_currentDataCollector.UsingCustomOutput = true; + WireReference connection = m_inputPorts[ m_inputPorts.Count - 1 ].GetConnection(); + ParentNode node = UIUtils.GetNode( connection.NodeId ); + customLightingCode = node.GetValueFromOutputStr( connection.PortId, WirePortDataType.FLOAT3, ref m_currentDataCollector, false ); + customLightingInstructions = m_currentDataCollector.CustomOutput; + + if( m_currentDataCollector.ForceNormal ) + { + m_currentDataCollector.AddToStartInstructions( "\t\t\t" + Constants.OutputVarStr + ".Normal = float3(0,0,1);\n" ); + m_currentDataCollector.DirtyNormal = true; + m_currentDataCollector.ForceNormal = false; + } + + if( m_currentDataCollector.DirtyVertexVariables ) + { + m_currentDataCollector.AddVertexInstruction( m_currentDataCollector.VertexLocalVariables, UniqueId, false ); + m_currentDataCollector.ClearVertexLocalVariables(); + } + m_currentDataCollector.UsingCustomOutput = false; + } + else + { + CreateInstructionsForPort( debugPort, Constants.OutputVarStr + ".Emission", false, null, null, false, false,true ); + } + } + else + { + MasterNodePortCategory currentCategory = sortedPorts[ 0 ].Category; + //Collect data from standard nodes + for( int i = 0; i < sortedPorts.Count; i++ ) + { + // prepare ports for custom lighting + m_currentDataCollector.GenType = sortedPorts[ i ].GenType; + if( m_currentLightModel == StandardShaderLightModel.CustomLighting && sortedPorts[ i ].Name.Equals( AlphaStr ) ) + ContainerGraph.ResetNodesLocalVariablesIfNot( MasterNodePortCategory.Vertex ); + + if( sortedPorts[ i ].IsConnected ) + { + m_currentDataCollector.PortCategory = sortedPorts[ i ].Category; + + if( sortedPorts[ i ].Name.Equals( NormalStr ) )// Normal Map is Connected + { + m_currentDataCollector.DirtyNormal = true; + } + if( sortedPorts[ i ].Name.Equals( TranslucencyStr ) ) + { + hasTranslucency = true; + } + if( sortedPorts[ i ].Name.Equals( TransmissionStr ) ) + { + hasTransmission = true; + } + if( sortedPorts[ i ].Name.Equals( EmissionStr ) ) + { + hasEmission = true; + } + + if( sortedPorts[ i ].Name.Equals( RefractionStr ) ) + { + hasRefraction = true; + } + + if( sortedPorts[ i ].Name.Equals( AlphaStr ) ) + { + hasOpacity = true; + } + + if( sortedPorts[ i ].Name.Equals( DiscardStr ) ) + { + hasOpacityMask = true; + } + + if( hasRefraction ) + { + m_currentDataCollector.AddToInput( UniqueId, SurfaceInputs.SCREEN_POS ); + m_currentDataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_POS ); + + //not necessary, just being safe + m_currentDataCollector.DirtyNormal = true; + m_currentDataCollector.ForceNormal = true; + + if( m_grabOrder != 0 ) + { + m_currentDataCollector.AddGrabPass( "RefractionGrab" + m_grabOrder ); + m_currentDataCollector.AddToUniforms( UniqueId, "uniform sampler2D RefractionGrab" + m_grabOrder + ";" ); + } + else + { + m_currentDataCollector.AddGrabPass( "" ); + m_currentDataCollector.AddToUniforms( UniqueId, "uniform sampler2D _GrabTexture;" ); + } + + if( !m_inlineChromaticAberration.Active ) + { + m_currentDataCollector.AddToUniforms( UniqueId, "uniform float _ChromaticAberration;" ); + + m_currentDataCollector.AddToProperties( UniqueId, "[Header(Refraction)]", m_refractionReorder.OrderIndex ); + m_currentDataCollector.AddToProperties( UniqueId, "_ChromaticAberration(\"Chromatic Aberration\", Range( 0 , 0.3)) = 0.1", m_refractionReorder.OrderIndex + 1 ); + } + + m_currentDataCollector.AddToPragmas( UniqueId, "multi_compile _ALPHAPREMULTIPLY_ON" ); + } + + if( hasTranslucency || hasTransmission ) + { + //Translucency and Transmission Generation + + //Add properties and uniforms + m_currentDataCollector.AddToIncludes( UniqueId, Constants.UnityPBSLightingLib ); + + if( hasTranslucency ) + { + m_currentDataCollector.AddToProperties( UniqueId, "[Header(Translucency)]", m_translucencyReorder.OrderIndex ); + m_currentDataCollector.AddToProperties( UniqueId, "_Translucency(\"Strength\", Range( 0 , 50)) = 1", m_translucencyReorder.OrderIndex + 1 ); + m_currentDataCollector.AddToProperties( UniqueId, "_TransNormalDistortion(\"Normal Distortion\", Range( 0 , 1)) = 0.1", m_translucencyReorder.OrderIndex + 2 ); + m_currentDataCollector.AddToProperties( UniqueId, "_TransScattering(\"Scaterring Falloff\", Range( 1 , 50)) = 2", m_translucencyReorder.OrderIndex + 3 ); + m_currentDataCollector.AddToProperties( UniqueId, "_TransDirect(\"Direct\", Range( 0 , 1)) = 1", m_translucencyReorder.OrderIndex + 4 ); + m_currentDataCollector.AddToProperties( UniqueId, "_TransAmbient(\"Ambient\", Range( 0 , 1)) = 0.2", m_translucencyReorder.OrderIndex + 5 ); + m_currentDataCollector.AddToProperties( UniqueId, "_TransShadow(\"Shadow\", Range( 0 , 1)) = 0.9", m_translucencyReorder.OrderIndex + 6 ); + + m_currentDataCollector.AddToUniforms( UniqueId, "uniform half _Translucency;" ); + m_currentDataCollector.AddToUniforms( UniqueId, "uniform half _TransNormalDistortion;" ); + m_currentDataCollector.AddToUniforms( UniqueId, "uniform half _TransScattering;" ); + m_currentDataCollector.AddToUniforms( UniqueId, "uniform half _TransDirect;" ); + m_currentDataCollector.AddToUniforms( UniqueId, "uniform half _TransAmbient;" ); + m_currentDataCollector.AddToUniforms( UniqueId, "uniform half _TransShadow;" ); + } + + //Add custom struct + switch( m_currentLightModel ) + { + case StandardShaderLightModel.Standard: + case StandardShaderLightModel.StandardSpecular: + outputStruct = "SurfaceOutput" + m_currentLightModel.ToString() + Constants.CustomLightStructStr; break; + } + + m_currentDataCollector.ChangeCustomInputHeader( m_currentLightModel.ToString() + Constants.CustomLightStructStr ); + m_currentDataCollector.AddToCustomInput( UniqueId, "half3 Albedo", true ); + m_currentDataCollector.AddToCustomInput( UniqueId, "half3 Normal", true ); + m_currentDataCollector.AddToCustomInput( UniqueId, "half3 Emission", true ); + switch( m_currentLightModel ) + { + case StandardShaderLightModel.Standard: + m_currentDataCollector.AddToCustomInput( UniqueId, "half Metallic", true ); + break; + case StandardShaderLightModel.StandardSpecular: + m_currentDataCollector.AddToCustomInput( UniqueId, "half3 Specular", true ); + break; + } + m_currentDataCollector.AddToCustomInput( UniqueId, "half Smoothness", true ); + m_currentDataCollector.AddToCustomInput( UniqueId, "half Occlusion", true ); + m_currentDataCollector.AddToCustomInput( UniqueId, "half Alpha", true ); + if( hasTranslucency ) + m_currentDataCollector.AddToCustomInput( UniqueId, "half3 Translucency", true ); + + if( hasTransmission ) + m_currentDataCollector.AddToCustomInput( UniqueId, "half3 Transmission", true ); + } + + if( sortedPorts[ i ].Name.Equals( DiscardStr ) ) + { + //Discard Op Node + if( m_currentLightModel == StandardShaderLightModel.CustomLighting ) + { + hasCustomLightingMask = true; + m_currentDataCollector.UsingCustomOutput = true; + m_currentDataCollector.GenType = PortGenType.CustomLighting; + WireReference connection = sortedPorts[ i ].GetConnection(); + ParentNode node = UIUtils.GetNode( connection.NodeId ); + + customLightingMaskCode = node.GetValueFromOutputStr( connection.PortId, WirePortDataType.FLOAT, ref m_currentDataCollector, false ); + customLightingMaskCode = "clip( " + customLightingMaskCode + " - " + m_inlineOpacityMaskClipValue.GetValueOrProperty( IOUtils.MaskClipValueName, false ) + " )"; + customLightingInstructions = m_currentDataCollector.CustomOutput; + + m_currentDataCollector.GenType = PortGenType.NonCustomLighting; + m_currentDataCollector.UsingCustomOutput = false; + continue; + } + else + { + string clipIn = "\t\t\tclip( "; + string clipOut = " - " + m_inlineOpacityMaskClipValue.GetValueOrProperty( IOUtils.MaskClipValueName, false ) + " );\n"; + //if( ( m_alphaToCoverage || m_inlineAlphaToCoverage.Active ) && m_castShadows ) + //{ + // clipIn = "\t\t\t#if UNITY_PASS_SHADOWCASTER\n" + clipIn; + // clipOut = clipOut + "\t\t\t#endif\n"; + //} + CreateInstructionsForPort( sortedPorts[ i ], Constants.OutputVarStr + "." + sortedPorts[ i ].DataName, true, clipIn, clipOut, false, normalIsConnected ); + } + } + else if( sortedPorts[ i ].DataName.Equals( VertexDataStr ) ) + { + string vertexInstructions = CreateInstructionsForVertexPort( sortedPorts[ i ] ); + m_currentDataCollector.AddToVertexDisplacement( vertexInstructions, m_vertexMode ); + } + else if( sortedPorts[ i ].DataName.Equals( VertexNormalStr ) ) + { + string vertexInstructions = CreateInstructionsForVertexPort( sortedPorts[ i ] ); + m_currentDataCollector.AddToVertexNormal( vertexInstructions ); + } + else if( m_tessOpHelper.IsTessellationPort( sortedPorts[ i ].PortId ) && sortedPorts[ i ].IsConnected /* && m_tessOpHelper.EnableTesselation*/) + { + //Vertex displacement and per vertex custom data + WireReference connection = sortedPorts[ i ].GetConnection(); + ParentNode node = UIUtils.GetNode( connection.NodeId ); + + string vertexInstructions = node.GetValueFromOutputStr( connection.PortId, sortedPorts[ i ].DataType, ref m_currentDataCollector, false ); + + if( m_currentDataCollector.DirtySpecialLocalVariables ) + { + m_tessOpHelper.AddAdditionalData( m_currentDataCollector.SpecialLocalVariables ); + m_currentDataCollector.ClearSpecialLocalVariables(); + } + + if( m_currentDataCollector.DirtyVertexVariables ) + { + m_tessOpHelper.AddAdditionalData( m_currentDataCollector.VertexLocalVariables ); + m_currentDataCollector.ClearVertexLocalVariables(); + } + + m_tessOpHelper.AddCustomFunction( vertexInstructions ); + } + else if( sortedPorts[ i ].Name.Equals( RefractionStr ) ) + { + ContainerGraph.ResetNodesLocalVariables(); + m_currentDataCollector.UsingCustomOutput = true; + + refractionFix = " + 0.00001 * i.screenPos * i.worldPos"; + m_currentDataCollector.AddInstructions( "\t\t\to.Normal = o.Normal" + refractionFix + ";\n" ); + refractionCode = CreateInstructionStringForPort( sortedPorts[ i ], false ); + refractionInstructions = m_currentDataCollector.CustomOutput; + + m_currentDataCollector.UsingCustomOutput = false; + } + else if( sortedPorts[ i ].Name.Equals( CustomLightingStr ) ) + { + m_currentDataCollector.UsingCustomOutput = true; + WireReference connection = sortedPorts[ i ].GetConnection(); + ParentNode node = UIUtils.GetNode( connection.NodeId ); + + customLightingCode = node.GetValueFromOutputStr( connection.PortId, WirePortDataType.FLOAT3, ref m_currentDataCollector, false ); + customLightingInstructions = m_currentDataCollector.CustomOutput; + + if( m_currentDataCollector.ForceNormal ) + { + m_currentDataCollector.AddToStartInstructions( "\t\t\t" + Constants.OutputVarStr + ".Normal = float3(0,0,1);\n" ); + m_currentDataCollector.DirtyNormal = true; + m_currentDataCollector.ForceNormal = false; + } + + if( m_currentDataCollector.DirtyVertexVariables ) + { + m_currentDataCollector.AddVertexInstruction( m_currentDataCollector.VertexLocalVariables, UniqueId, false ); + m_currentDataCollector.ClearVertexLocalVariables(); + } + + m_currentDataCollector.UsingCustomOutput = false; + + } + else if( sortedPorts[ i ].Name.Equals( AlphaStr ) && m_currentLightModel == StandardShaderLightModel.CustomLighting ) + { + m_currentDataCollector.UsingCustomOutput = true; + m_currentDataCollector.GenType = PortGenType.CustomLighting; + + WireReference connection = sortedPorts[ i ].GetConnection(); + ParentNode node = UIUtils.GetNode( connection.NodeId ); + + customLightingAlphaCode = node.GetValueFromOutputStr( connection.PortId, WirePortDataType.FLOAT, ref m_currentDataCollector, false ); + customLightingInstructions = m_currentDataCollector.CustomOutput; + + if( m_currentDataCollector.ForceNormal ) + { + m_currentDataCollector.AddToStartInstructions( "\t\t\t" + Constants.OutputVarStr + ".Normal = float3(0,0,1);\n" ); + m_currentDataCollector.DirtyNormal = true; + m_currentDataCollector.ForceNormal = false; + } + + if( m_currentDataCollector.DirtyVertexVariables ) + { + m_currentDataCollector.AddVertexInstruction( m_currentDataCollector.VertexLocalVariables, UniqueId, false ); + m_currentDataCollector.ClearVertexLocalVariables(); + } + + m_currentDataCollector.GenType = PortGenType.NonCustomLighting; + m_currentDataCollector.UsingCustomOutput = false; + } + else + { + // Surface shader instruccions + // if working on normals and have normal dependent node then ignore local var generation + CreateInstructionsForPort( sortedPorts[ i ], Constants.OutputVarStr + "." + sortedPorts[ i ].DataName, false, null, null, false, normalIsConnected ); + } + } + else if( sortedPorts[ i ].Name.Equals( AlphaStr ) ) + { + if( m_currentLightModel != StandardShaderLightModel.CustomLighting ) + { + m_currentDataCollector.AddInstructions( string.Format( "\t\t\t{0}.{1} = 1;\n", Constants.OutputVarStr, sortedPorts[ i ].DataName ) ); + } + } + } + + m_billboardOpHelper.FillDataCollectorWithInternalData( ref m_currentDataCollector ); + } + + m_customShadowCaster = CustomShadowCaster; + //if( !m_renderingOptionsOpHelper.UseDefaultShadowCaster && + // ( ( m_castShadows && ( m_alphaToCoverage || m_inlineAlphaToCoverage.Active ) ) || + // ( m_castShadows && hasOpacity ) || + // ( m_castShadows && ( m_currentDataCollector.UsingWorldNormal || m_currentDataCollector.UsingWorldReflection || m_currentDataCollector.UsingViewDirection ) ) || + // ( m_castShadows && m_inputPorts[ m_discardPortId ].Available && m_inputPorts[ m_discardPortId ].IsConnected && m_currentLightModel == StandardShaderLightModel.CustomLighting ) )) + // m_customShadowCaster = true; + //else + // m_customShadowCaster = false; + + //m_customShadowCaster = true; + + for( int i = 0; i < 4; i++ ) + { + if( m_currentDataCollector.GetChannelUsage( i ) == TextureChannelUsage.Required ) + { + string channelName = UIUtils.GetChannelName( i ); + m_currentDataCollector.AddToProperties( -1, UIUtils.GetTex2DProperty( channelName, TexturePropertyValues.white ), -1 ); + } + } + + m_currentDataCollector.AddToProperties( -1, IOUtils.DefaultASEDirtyCheckProperty, 10000 ); + if( m_inputPorts[ m_discardPortId ].Available && m_inputPorts[ m_discardPortId ].IsConnected ) + { + if( m_inlineOpacityMaskClipValue.IsValid ) + { + RangedFloatNode fnode = UIUtils.GetNode( m_inlineOpacityMaskClipValue.NodeId ) as RangedFloatNode; + if( fnode != null ) + { + m_currentDataCollector.AddToProperties( fnode.UniqueId, fnode.GetPropertyValue(), fnode.OrderIndex ); + m_currentDataCollector.AddToUniforms( fnode.UniqueId, fnode.GetUniformValue() ); + } + else + { + IntNode inode = UIUtils.GetNode( m_inlineOpacityMaskClipValue.NodeId ) as IntNode; + m_currentDataCollector.AddToProperties( inode.UniqueId, inode.GetPropertyValue(), inode.OrderIndex ); + m_currentDataCollector.AddToUniforms( inode.UniqueId, inode.GetUniformValue() ); + } + } + else + { + m_currentDataCollector.AddToProperties( -1, string.Format( IOUtils.MaskClipValueProperty, OpacityMaskClipValueStr, m_opacityMaskClipValue ), ( m_maskClipReorder != null ) ? m_maskClipReorder.OrderIndex : -1 ); + m_currentDataCollector.AddToUniforms( -1, string.Format( IOUtils.MaskClipValueUniform, m_opacityMaskClipValue ) ); + } + } + + if( !m_currentDataCollector.DirtyInputs ) + m_currentDataCollector.AddToInput( UniqueId, "half filler", true ); + + if( m_currentLightModel == StandardShaderLightModel.BlinnPhong ) + m_currentDataCollector.AddToProperties( -1, "_SpecColor(\"Specular Color\",Color)=(1,1,1,1)", m_specColorReorder.OrderIndex ); + + //Tesselation + if( m_tessOpHelper.EnableTesselation ) + { + m_tessOpHelper.AddToDataCollector( ref m_currentDataCollector, m_tessellationReorder != null ? m_tessellationReorder.OrderIndex : -1 ); + if( !m_currentDataCollector.DirtyPerVertexData ) + { + m_currentDataCollector.OpenPerVertexHeader( false ); + } + } + + + if( m_outlineHelper.EnableOutline || ( m_currentDataCollector.UsingCustomOutlineColor || m_currentDataCollector.CustomOutlineSelectedAlpha > 0 || m_currentDataCollector.UsingCustomOutlineWidth ) ) + { + m_outlineHelper.AddToDataCollector( ref m_currentDataCollector ); + } + +#if !UNITY_2017_1_OR_NEWER + if( m_renderingOptionsOpHelper.LodCrossfade ) + { + m_currentDataCollector.AddToPragmas( UniqueId, "multi_compile _ LOD_FADE_CROSSFADE" ); + m_currentDataCollector.AddToStartInstructions( "\t\t\tUNITY_APPLY_DITHER_CROSSFADE(i);\n" ); + m_currentDataCollector.AddToInput( UniqueId, "UNITY_DITHER_CROSSFADE_COORDS", false ); + m_currentDataCollector.AddVertexInstruction( "UNITY_TRANSFER_DITHER_CROSSFADE( " + Constants.VertexShaderOutputStr + ", " + Constants.VertexShaderInputStr + ".vertex )", UniqueId, true ); + } +#endif + //m_additionalIncludes.AddToDataCollector( ref m_currentDataCollector ); + //m_additionalPragmas.AddToDataCollector( ref m_currentDataCollector ); + //m_additionalDefines.AddToDataCollector( ref m_currentDataCollector ); + m_additionalDirectives.AddAllToDataCollector( ref m_currentDataCollector ); + + //m_currentDataCollector.CloseInputs(); + m_currentDataCollector.CloseCustomInputs(); + m_currentDataCollector.CloseProperties(); + m_currentDataCollector.ClosePerVertexHeader(); + + //build Shader Body + string ShaderBody = string.Empty; + OpenShaderBody( ref ShaderBody, m_shaderName ); + { + //set properties + if( m_currentDataCollector.DirtyProperties ) + { + ShaderBody += m_currentDataCollector.BuildPropertiesString(); + } + //set subshader + OpenSubShaderBody( ref ShaderBody ); + { + + // Add extra depth pass + m_zBufferHelper.DrawExtraDepthPass( ref ShaderBody ); + + // Add optionalPasses + if( m_outlineHelper.EnableOutline || ( m_currentDataCollector.UsingCustomOutlineColor || m_currentDataCollector.CustomOutlineSelectedAlpha > 0 || m_currentDataCollector.UsingCustomOutlineWidth ) ) + { + if( !usingDebugPort ) + AddMultilineBody( ref ShaderBody, m_outlineHelper.OutlineFunctionBody( ref m_currentDataCollector, isInstancedShader, m_customShadowCaster, UIUtils.RemoveInvalidCharacters( ShaderName ), ( m_billboardOpHelper.IsBillboard && !usingDebugPort ? m_billboardOpHelper.GetInternalMultilineInstructions() : null ), ref m_tessOpHelper, ShaderModelTypeArr[ m_shaderModelIdx ], CurrentPrecisionType ) ); + } + + //Add SubShader tags + if( hasEmission ) + { + tags += " \"IsEmissive\" = \"true\" "; + } + + tags += m_customTagsHelper.GenerateCustomTags(); + + tags = "Tags{ " + tags + " }"; + m_usePass.BuildUsePassInfo( m_currentDataCollector, ref aboveUsePasses, ref bellowUsePasses, "\t\t" ); + if( !string.IsNullOrEmpty( aboveUsePasses ) ) + { + ShaderBody += aboveUsePasses; + } + + AddRenderTags( ref ShaderBody, tags ); + AddShaderLOD( ref ShaderBody, ShaderLOD ); + AddRenderState( ref ShaderBody, "Cull", m_inlineCullMode.GetValueOrProperty( m_cullMode.ToString() ) ); + m_customBlendAvailable = ( m_alphaMode == AlphaMode.Custom || m_alphaMode == AlphaMode.Opaque ); + if( ( m_zBufferHelper.IsActive && m_customBlendAvailable ) || m_outlineHelper.UsingZWrite || m_outlineHelper.UsingZTest ) + { + ShaderBody += m_zBufferHelper.CreateDepthInfo( m_outlineHelper.UsingZWrite, m_outlineHelper.UsingZTest ); + } + if( m_stencilBufferHelper.Active ) + { + ShaderBody += m_stencilBufferHelper.CreateStencilOp( this ); + } + + if( m_blendOpsHelper.Active ) + { + ShaderBody += m_blendOpsHelper.CreateBlendOps(); + } + + if( m_alphaToCoverage || m_inlineAlphaToCoverage.Active ) + { + ShaderBody += "\t\tAlphaToMask "+ m_inlineAlphaToCoverage.GetValueOrProperty( "On" )+"\n"; + } + + // Build Color Mask + m_colorMaskHelper.BuildColorMask( ref ShaderBody, m_customBlendAvailable ); + + //ShaderBody += "\t\tZWrite " + _zWriteMode + '\n'; + //ShaderBody += "\t\tZTest " + _zTestMode + '\n'; + + //Add GrabPass + if( m_currentDataCollector.DirtyGrabPass ) + { + ShaderBody += m_currentDataCollector.GrabPass; + } + + // build optional parameters + string OptionalParameters = string.Empty; + + // addword standard to custom lighting to accepts standard lighting models + string standardCustomLighting = string.Empty; + if( m_currentLightModel == StandardShaderLightModel.CustomLighting ) + standardCustomLighting = "Standard"; + + //add cg program + if( m_customShadowCaster ) + OpenCGInclude( ref ShaderBody ); + else + OpenCGProgram( ref ShaderBody ); + { + //Add Defines + if( m_currentDataCollector.DirtyDefines ) + ShaderBody += m_currentDataCollector.Defines; + + //Add Includes + if( m_customShadowCaster ) + { + m_currentDataCollector.AddToIncludes( UniqueId, Constants.UnityPBSLightingLib ); + m_currentDataCollector.AddToIncludes( UniqueId, "Lighting.cginc" ); + } + if( m_currentDataCollector.DirtyIncludes ) + ShaderBody += m_currentDataCollector.Includes; + + //define as surface shader and specify lighting model + if( UIUtils.GetTextureArrayNodeAmount() > 0 && m_shaderModelIdx < 3 ) + { + UIUtils.ShowMessage( "Automatically changing Shader Model to 3.5 since\nit's the minimum required by texture arrays." ); + m_shaderModelIdx = 3; + } + + // if tessellation is active then we need be at least using shader model 4.6 + if( m_tessOpHelper.EnableTesselation && m_shaderModelIdx < 6 ) + { + UIUtils.ShowMessage( "Automatically changing Shader Model to 4.6 since\nit's the minimum required by tessellation." ); + m_shaderModelIdx = 6; + } + + // if translucency is ON change render path + if( hasTranslucency && m_renderPath != RenderPath.ForwardOnly ) + { + UIUtils.ShowMessage( "Automatically changing Render Path to Forward Only since\ntranslucency only works in forward rendering." ); + m_renderPath = RenderPath.ForwardOnly; + } + + // if outline is ON change render path + if( m_outlineHelper.EnableOutline && m_renderPath != RenderPath.ForwardOnly ) + { + UIUtils.ShowMessage( "Automatically changing Render Path to Forward Only since\noutline only works in forward rendering." ); + m_renderPath = RenderPath.ForwardOnly; + } + + // if transmission is ON change render path + if( hasTransmission && m_renderPath != RenderPath.ForwardOnly ) + { + UIUtils.ShowMessage( "Automatically changing Render Path to Forward Only since\ntransmission only works in forward rendering." ); + m_renderPath = RenderPath.ForwardOnly; + } + + // if refraction is ON change render path + if( hasRefraction && m_renderPath != RenderPath.ForwardOnly ) + { + UIUtils.ShowMessage( "Automatically changing Render Path to Forward Only since\nrefraction only works in forward rendering." ); + m_renderPath = RenderPath.ForwardOnly; + } + + ShaderBody += string.Format( IOUtils.PragmaTargetHeader, ShaderModelTypeArr[ m_shaderModelIdx ] ); + + + //Add pragmas (needs check to see if all pragmas work with custom shadow caster) + if( m_currentDataCollector.DirtyPragmas/* && !m_customShadowCaster */) + ShaderBody += m_currentDataCollector.Pragmas; + + CheckSamplingMacrosFlag(); + m_currentDataCollector.AddASEMacros(); + if( m_currentDataCollector.DirtyAdditionalDirectives ) + ShaderBody += m_currentDataCollector.StandardAdditionalDirectives; + + //if ( !m_customBlendMode ) + { + switch( m_alphaMode ) + { + case AlphaMode.Opaque: + case AlphaMode.Masked: break; + case AlphaMode.Transparent: + { + OptionalParameters += "alpha:fade" + Constants.OptionalParametersSep; + } + break; + case AlphaMode.Premultiply: + { + OptionalParameters += "alpha:premul" + Constants.OptionalParametersSep; + } + break; + } + } + + if( m_keepAlpha ) + { + OptionalParameters += "keepalpha" + Constants.OptionalParametersSep; + } + + if( hasRefraction ) + { + OptionalParameters += "finalcolor:RefractionF" + Constants.OptionalParametersSep; + } + + if( !m_customShadowCaster && m_castShadows ) + { + OptionalParameters += "addshadow" + Constants.OptionalParametersSep; + } + + if( m_castShadows ) + { + OptionalParameters += "fullforwardshadows" + Constants.OptionalParametersSep; + } + + if( !m_receiveShadows ) + { + OptionalParameters += "noshadow" + Constants.OptionalParametersSep; + } + + if( m_renderingOptionsOpHelper.IsOptionActive( " Add Pass" ) && usingDebugPort ) + { + OptionalParameters += "noforwardadd" + Constants.OptionalParametersSep; + } + + if( m_renderingOptionsOpHelper.ForceDisableInstancing ) + { + OptionalParameters += "noinstancing" + Constants.OptionalParametersSep; + } + + switch( m_renderPath ) + { + case RenderPath.All: break; + case RenderPath.DeferredOnly: OptionalParameters += "exclude_path:forward" + Constants.OptionalParametersSep; break; + case RenderPath.ForwardOnly: OptionalParameters += "exclude_path:deferred" + Constants.OptionalParametersSep; break; + } + + //Add code generation options + m_renderingOptionsOpHelper.Build( ref OptionalParameters ); + + if( !m_customShadowCaster ) + { + string customLightSurface = string.Empty; + if( hasTranslucency || hasTransmission ) + customLightSurface = "Custom"; + m_renderingPlatformOpHelper.SetRenderingPlatforms( ref ShaderBody ); + + //Check if Custom Vertex is being used and add tag + if( m_currentDataCollector.DirtyPerVertexData ) + OptionalParameters += "vertex:" + Constants.VertexDataFunc + Constants.OptionalParametersSep; + + if( m_tessOpHelper.EnableTesselation && !usingDebugPort ) + { + m_tessOpHelper.WriteToOptionalParams( ref OptionalParameters ); + } + + m_additionalSurfaceOptions.WriteToOptionalSurfaceOptions( ref OptionalParameters ); + + AddShaderPragma( ref ShaderBody, "surface surf " + standardCustomLighting + m_currentLightModel.ToString() + customLightSurface + Constants.OptionalParametersSep + OptionalParameters ); + } + else + { + if( /*m_currentDataCollector.UsingWorldNormal ||*/ m_currentDataCollector.UsingInternalData ) + { + ShaderBody += "\t\t#ifdef UNITY_PASS_SHADOWCASTER\n"; + ShaderBody += "\t\t\t#undef INTERNAL_DATA\n"; + ShaderBody += "\t\t\t#undef WorldReflectionVector\n"; + ShaderBody += "\t\t\t#undef WorldNormalVector\n"; + ShaderBody += "\t\t\t#define INTERNAL_DATA half3 internalSurfaceTtoW0; half3 internalSurfaceTtoW1; half3 internalSurfaceTtoW2;\n"; + ShaderBody += "\t\t\t#define WorldReflectionVector(data,normal) reflect (data.worldRefl, half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal)))\n"; + ShaderBody += "\t\t\t#define WorldNormalVector(data,normal) half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal))\n"; + ShaderBody += "\t\t#endif\n"; + } + } + + if( m_currentDataCollector.UsingHigherSizeTexcoords ) + { + ShaderBody += "\t\t#undef TRANSFORM_TEX\n"; + ShaderBody += "\t\t#define TRANSFORM_TEX(tex,name) float4(tex.xy * name##_ST.xy + name##_ST.zw, tex.z, tex.w)\n"; + } + + if( m_currentDataCollector.DirtyAppData ) + ShaderBody += m_currentDataCollector.CustomAppData; + + // Add Input struct + if( m_currentDataCollector.DirtyInputs ) + ShaderBody += "\t\t" + m_currentDataCollector.Inputs + "\t\t};" + "\n\n"; + + // Add Custom Lighting struct + if( m_currentDataCollector.DirtyCustomInput ) + ShaderBody += m_currentDataCollector.CustomInput + "\n\n"; + + //Add Uniforms + if( m_currentDataCollector.DirtyUniforms ) + ShaderBody += m_currentDataCollector.Uniforms + "\n"; + + // Add Array Derivatives Macros + //if( m_currentDataCollector.UsingArrayDerivatives ) + //{ + // ShaderBody += "\t\t#if defined(UNITY_COMPILER_HLSL2GLSL) || defined(SHADER_TARGET_SURFACE_ANALYSIS)\n"; + // ShaderBody += "\t\t\t#define ASE_SAMPLE_TEX2DARRAY_GRAD(tex,coord,dx,dy) UNITY_SAMPLE_TEX2DARRAY (tex,coord)\n"; + // ShaderBody += "\t\t#else\n"; + // ShaderBody += "\t\t\t#define ASE_SAMPLE_TEX2DARRAY_GRAD(tex,coord,dx,dy) tex.SampleGrad (sampler##tex,coord,dx,dy)\n"; + // ShaderBody += "\t\t#endif\n\n"; + //} + + //Add Instanced Properties + if( isInstancedShader && m_currentDataCollector.DirtyInstancedProperties ) + { + m_currentDataCollector.SetupInstancePropertiesBlock( UIUtils.RemoveInvalidCharacters( ShaderName ) ); + ShaderBody += m_currentDataCollector.InstancedProperties + "\n"; + } + + if( m_currentDataCollector.DirtyFunctions ) + ShaderBody += m_currentDataCollector.Functions + "\n"; + + + //Tesselation + if( m_tessOpHelper.EnableTesselation && !usingDebugPort ) + { + ShaderBody += m_tessOpHelper.GetCurrentTessellationFunction( ref m_currentDataCollector ) + "\n"; + } + + //Add Custom Vertex Data + if( m_currentDataCollector.DirtyPerVertexData ) + { + ShaderBody += m_currentDataCollector.VertexData; + } + + if( m_currentLightModel == StandardShaderLightModel.Unlit ) + { + for( int i = 0; i < VertexLitFunc.Length; i++ ) + { + ShaderBody += VertexLitFunc[ i ] + "\n"; + } + } + + //Add custom lighting + if( m_currentLightModel == StandardShaderLightModel.CustomLighting ) + { + ShaderBody += "\t\tinline half4 LightingStandard" + m_currentLightModel.ToString() + "( inout " + outputStruct + " " + Constants.CustomLightOutputVarStr + ", half3 viewDir, UnityGI gi )\n\t\t{\n"; + ShaderBody += "\t\t\tUnityGIInput data = s.GIData;\n"; + ShaderBody += "\t\t\tInput i = s.SurfInput;\n"; + ShaderBody += "\t\t\thalf4 c = 0;\n"; + if( m_currentDataCollector.UsingLightAttenuation ) + { + ShaderBody += "\t\t\t#ifdef UNITY_PASS_FORWARDBASE\n"; + ShaderBody += "\t\t\tfloat ase_lightAtten = data.atten;\n"; + ShaderBody += "\t\t\tif( _LightColor0.a == 0)\n"; + ShaderBody += "\t\t\tase_lightAtten = 0;\n"; + ShaderBody += "\t\t\t#else\n"; + ShaderBody += "\t\t\tfloat3 ase_lightAttenRGB = gi.light.color / ( ( _LightColor0.rgb ) + 0.000001 );\n"; + ShaderBody += "\t\t\tfloat ase_lightAtten = max( max( ase_lightAttenRGB.r, ase_lightAttenRGB.g ), ase_lightAttenRGB.b );\n"; + ShaderBody += "\t\t\t#endif\n"; + + ShaderBody += "\t\t\t#if defined(HANDLE_SHADOWS_BLENDING_IN_GI)\n"; + ShaderBody += "\t\t\thalf bakedAtten = UnitySampleBakedOcclusion(data.lightmapUV.xy, data.worldPos);\n"; + ShaderBody += "\t\t\tfloat zDist = dot(_WorldSpaceCameraPos - data.worldPos, UNITY_MATRIX_V[2].xyz);\n"; + ShaderBody += "\t\t\tfloat fadeDist = UnityComputeShadowFadeDistance(data.worldPos, zDist);\n"; + ShaderBody += "\t\t\tase_lightAtten = UnityMixRealtimeAndBakedShadows(data.atten, bakedAtten, UnityComputeShadowFade(fadeDist));\n"; + ShaderBody += "\t\t\t#endif\n"; + } + + //if( m_currentDataCollector.dirtyc ) + ShaderBody += customLightingInstructions; + ShaderBody += "\t\t\tc.rgb = " + ( !string.IsNullOrEmpty( customLightingCode ) ? customLightingCode : "0" ) + ";\n"; + ShaderBody += "\t\t\tc.a = " + ( !string.IsNullOrEmpty( customLightingAlphaCode ) ? customLightingAlphaCode : "1" ) + ";\n"; + if( m_alphaMode == AlphaMode.Premultiply || ( ( m_alphaMode == AlphaMode.Custom || m_alphaMode == AlphaMode.Opaque ) && m_blendOpsHelper.CurrentBlendRGB.IndexOf( "Premultiplied" ) > -1 ) ) + ShaderBody += "\t\t\tc.rgb *= c.a;\n"; + if( hasCustomLightingMask ) + ShaderBody += "\t\t\t" + customLightingMaskCode + ";\n"; + ShaderBody += "\t\t\treturn c;\n"; + ShaderBody += "\t\t}\n\n"; + + //Add GI function + ShaderBody += "\t\tinline void LightingStandard" + m_currentLightModel.ToString() + "_GI( inout " + outputStruct + " " + Constants.CustomLightOutputVarStr + ", UnityGIInput data, inout UnityGI gi )\n\t\t{\n"; + ShaderBody += "\t\t\ts.GIData = data;\n"; + //ShaderBody += "\t\t\tUNITY_GI(gi, " + Constants.CustomLightOutputVarStr + ", data);\n"; + ShaderBody += "\t\t}\n\n"; + } + + //Add custom lighting function + if( hasTranslucency || hasTransmission ) + { + ShaderBody += "\t\tinline half4 Lighting" + m_currentLightModel.ToString() + Constants.CustomLightStructStr + "(" + outputStruct + " " + Constants.CustomLightOutputVarStr + ", half3 viewDir, UnityGI gi )\n\t\t{\n"; + if( hasTranslucency ) + { + //ShaderBody += "\t\t\t#if !DIRECTIONAL\n"; + ShaderBody += "\t\t\t#if !defined(DIRECTIONAL)\n"; + ShaderBody += "\t\t\tfloat3 lightAtten = gi.light.color;\n"; + ShaderBody += "\t\t\t#else\n"; + ShaderBody += "\t\t\tfloat3 lightAtten = lerp( _LightColor0.rgb, gi.light.color, _TransShadow );\n"; + ShaderBody += "\t\t\t#endif\n"; + ShaderBody += "\t\t\thalf3 lightDir = gi.light.dir + " + Constants.CustomLightOutputVarStr + ".Normal * _TransNormalDistortion;\n"; + ShaderBody += "\t\t\thalf transVdotL = pow( saturate( dot( viewDir, -lightDir ) ), _TransScattering );\n"; + ShaderBody += "\t\t\thalf3 translucency = lightAtten * (transVdotL * _TransDirect + gi.indirect.diffuse * _TransAmbient) * " + Constants.CustomLightOutputVarStr + ".Translucency;\n"; + ShaderBody += "\t\t\thalf4 c = half4( " + Constants.CustomLightOutputVarStr + ".Albedo * translucency * _Translucency, 0 );\n\n"; + } + + if( hasTransmission ) + { + ShaderBody += "\t\t\thalf3 transmission = max(0 , -dot(" + Constants.CustomLightOutputVarStr + ".Normal, gi.light.dir)) * gi.light.color * " + Constants.CustomLightOutputVarStr + ".Transmission;\n"; + ShaderBody += "\t\t\thalf4 d = half4(" + Constants.CustomLightOutputVarStr + ".Albedo * transmission , 0);\n\n"; + } + + ShaderBody += "\t\t\tSurfaceOutput" + m_currentLightModel.ToString() + " r;\n"; + ShaderBody += "\t\t\tr.Albedo = " + Constants.CustomLightOutputVarStr + ".Albedo;\n"; + ShaderBody += "\t\t\tr.Normal = " + Constants.CustomLightOutputVarStr + ".Normal;\n"; + ShaderBody += "\t\t\tr.Emission = " + Constants.CustomLightOutputVarStr + ".Emission;\n"; + switch( m_currentLightModel ) + { + case StandardShaderLightModel.Standard: + ShaderBody += "\t\t\tr.Metallic = " + Constants.CustomLightOutputVarStr + ".Metallic;\n"; + break; + case StandardShaderLightModel.StandardSpecular: + ShaderBody += "\t\t\tr.Specular = " + Constants.CustomLightOutputVarStr + ".Specular;\n"; + break; + } + ShaderBody += "\t\t\tr.Smoothness = " + Constants.CustomLightOutputVarStr + ".Smoothness;\n"; + ShaderBody += "\t\t\tr.Occlusion = " + Constants.CustomLightOutputVarStr + ".Occlusion;\n"; + ShaderBody += "\t\t\tr.Alpha = " + Constants.CustomLightOutputVarStr + ".Alpha;\n"; + ShaderBody += "\t\t\treturn Lighting" + m_currentLightModel.ToString() + " (r, viewDir, gi)" + ( hasTranslucency ? " + c" : "" ) + ( hasTransmission ? " + d" : "" ) + ";\n"; + ShaderBody += "\t\t}\n\n"; + + //Add GI function + ShaderBody += "\t\tinline void Lighting" + m_currentLightModel.ToString() + Constants.CustomLightStructStr + "_GI(" + outputStruct + " " + Constants.CustomLightOutputVarStr + ", UnityGIInput data, inout UnityGI gi )\n\t\t{\n"; + + ShaderBody += "\t\t\t#if defined(UNITY_PASS_DEFERRED) && UNITY_ENABLE_REFLECTION_BUFFERS\n"; + ShaderBody += "\t\t\t\tgi = UnityGlobalIllumination(data, " + Constants.CustomLightOutputVarStr + ".Occlusion, " + Constants.CustomLightOutputVarStr + ".Normal);\n"; + ShaderBody += "\t\t\t#else\n"; + ShaderBody += "\t\t\t\tUNITY_GLOSSY_ENV_FROM_SURFACE( g, " + Constants.CustomLightOutputVarStr + ", data );\n"; + ShaderBody += "\t\t\t\tgi = UnityGlobalIllumination( data, " + Constants.CustomLightOutputVarStr + ".Occlusion, " + Constants.CustomLightOutputVarStr + ".Normal, g );\n"; + ShaderBody += "\t\t\t#endif\n"; + + //ShaderBody += "\t\t\tUNITY_GI(gi, " + Constants.CustomLightOutputVarStr + ", data);\n"; + ShaderBody += "\t\t}\n\n"; + } + + if( hasRefraction ) + { + ShaderBody += "\t\tinline float4 Refraction( Input " + Constants.InputVarStr + ", " + outputStruct + " " + Constants.OutputVarStr + ", float indexOfRefraction, float chomaticAberration ) {\n"; + ShaderBody += "\t\t\tfloat3 worldNormal = " + Constants.OutputVarStr + ".Normal;\n"; + ShaderBody += "\t\t\tfloat4 screenPos = " + Constants.InputVarStr + ".screenPos;\n"; + ShaderBody += "\t\t\t#if UNITY_UV_STARTS_AT_TOP\n"; + ShaderBody += "\t\t\t\tfloat scale = -1.0;\n"; + ShaderBody += "\t\t\t#else\n"; + ShaderBody += "\t\t\t\tfloat scale = 1.0;\n"; + ShaderBody += "\t\t\t#endif\n"; + ShaderBody += "\t\t\tfloat halfPosW = screenPos.w * 0.5;\n"; + ShaderBody += "\t\t\tscreenPos.y = ( screenPos.y - halfPosW ) * _ProjectionParams.x * scale + halfPosW;\n"; + ShaderBody += "\t\t\t#if SHADER_API_D3D9 || SHADER_API_D3D11\n"; + ShaderBody += "\t\t\t\tscreenPos.w += 0.00000000001;\n"; + ShaderBody += "\t\t\t#endif\n"; + ShaderBody += "\t\t\tfloat2 projScreenPos = ( screenPos / screenPos.w ).xy;\n"; + ShaderBody += "\t\t\tfloat3 worldViewDir = normalize( UnityWorldSpaceViewDir( " + Constants.InputVarStr + ".worldPos ) );\n"; + ShaderBody += "\t\t\tfloat3 refractionOffset = ( indexOfRefraction - 1.0 ) * mul( UNITY_MATRIX_V, float4( worldNormal, 0.0 ) ) * ( 1.0 - dot( worldNormal, worldViewDir ) );\n"; + ShaderBody += "\t\t\tfloat2 cameraRefraction = float2( refractionOffset.x, refractionOffset.y );\n"; + + string grabpass = "_GrabTexture"; + if( m_grabOrder != 0 ) + grabpass = "RefractionGrab" + m_grabOrder; + ShaderBody += "\t\t\tfloat4 redAlpha = tex2D( " + grabpass + ", ( projScreenPos + cameraRefraction ) );\n"; + ShaderBody += "\t\t\tfloat green = tex2D( " + grabpass + ", ( projScreenPos + ( cameraRefraction * ( 1.0 - chomaticAberration ) ) ) ).g;\n"; + ShaderBody += "\t\t\tfloat blue = tex2D( " + grabpass + ", ( projScreenPos + ( cameraRefraction * ( 1.0 + chomaticAberration ) ) ) ).b;\n"; + ShaderBody += "\t\t\treturn float4( redAlpha.r, green, blue, redAlpha.a );\n"; + ShaderBody += "\t\t}\n\n"; + + ShaderBody += "\t\tvoid RefractionF( Input " + Constants.InputVarStr + ", " + outputStruct + " " + Constants.OutputVarStr + ", inout half4 color )\n"; + ShaderBody += "\t\t{\n"; + ShaderBody += "\t\t\t#ifdef UNITY_PASS_FORWARDBASE\n"; + ShaderBody += refractionInstructions; + if( m_inlineChromaticAberration.Active ) + { + ShaderBody += "\t\t\tcolor.rgb = color.rgb + Refraction( " + Constants.InputVarStr + ", " + Constants.OutputVarStr + ", " + refractionCode + ", " + m_inlineChromaticAberration.GetValueOrProperty(false) + " ) * ( 1 - color.a );\n"; + } + else + { + ShaderBody += "\t\t\tcolor.rgb = color.rgb + Refraction( " + Constants.InputVarStr + ", " + Constants.OutputVarStr + ", " + refractionCode + ", _ChromaticAberration ) * ( 1 - color.a );\n"; + } + ShaderBody += "\t\t\tcolor.a = 1;\n"; + ShaderBody += "\t\t\t#endif\n"; + ShaderBody += "\t\t}\n\n"; + } + + //Add Surface Shader body + ShaderBody += "\t\tvoid surf( Input " + Constants.InputVarStr + " , inout " + outputStruct + " " + Constants.OutputVarStr + " )\n\t\t{\n"; + { + // Pass input information to custom lighting function + if( m_currentLightModel == StandardShaderLightModel.CustomLighting ) + ShaderBody += "\t\t\t" + Constants.OutputVarStr + ".SurfInput = " + Constants.InputVarStr + ";\n"; + + //add local vars + if( m_currentDataCollector.DirtyLocalVariables ) + ShaderBody += m_currentDataCollector.LocalVariables; + + //add nodes ops + if( m_currentDataCollector.DirtyInstructions ) + ShaderBody += m_currentDataCollector.Instructions; + } + ShaderBody += "\t\t}\n"; + } + CloseCGProgram( ref ShaderBody ); + + + //Add custom Shadow Caster + if( m_customShadowCaster ) + { + OpenCGProgram( ref ShaderBody ); + string customLightSurface = hasTranslucency || hasTransmission ? "Custom" : ""; + m_renderingPlatformOpHelper.SetRenderingPlatforms( ref ShaderBody ); + + //Check if Custom Vertex is being used and add tag + if( m_currentDataCollector.DirtyPerVertexData ) + OptionalParameters += "vertex:" + Constants.VertexDataFunc + Constants.OptionalParametersSep; + + if( m_tessOpHelper.EnableTesselation && !usingDebugPort ) + { + m_tessOpHelper.WriteToOptionalParams( ref OptionalParameters ); + } + //if ( hasRefraction ) + // ShaderBody += "\t\t#pragma multi_compile _ALPHAPREMULTIPLY_ON\n"; + + m_additionalSurfaceOptions.WriteToOptionalSurfaceOptions( ref OptionalParameters ); + + AddShaderPragma( ref ShaderBody, "surface surf " + standardCustomLighting + m_currentLightModel.ToString() + customLightSurface + Constants.OptionalParametersSep + OptionalParameters ); + CloseCGProgram( ref ShaderBody ); + + ShaderBody += "\t\tPass\n"; + ShaderBody += "\t\t{\n"; + ShaderBody += "\t\t\tName \"ShadowCaster\"\n"; + ShaderBody += "\t\t\tTags{ \"LightMode\" = \"ShadowCaster\" }\n"; + ShaderBody += "\t\t\tZWrite On\n"; + if( m_alphaToCoverage || m_inlineAlphaToCoverage.Active ) + ShaderBody += "\t\t\tAlphaToMask Off\n"; + ShaderBody += "\t\t\tCGPROGRAM\n"; + ShaderBody += "\t\t\t#pragma vertex vert\n"; + ShaderBody += "\t\t\t#pragma fragment frag\n"; + ShaderBody += "\t\t\t#pragma target " + ShaderModelTypeArr[ m_shaderModelIdx ] + "\n"; + //ShaderBody += "\t\t\t#pragma multi_compile_instancing\n"; + ShaderBody += "\t\t\t#pragma multi_compile_shadowcaster\n"; + ShaderBody += "\t\t\t#pragma multi_compile UNITY_PASS_SHADOWCASTER\n"; + ShaderBody += "\t\t\t#pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2\n"; + ShaderBody += "\t\t\t#include \"HLSLSupport.cginc\"\n"; +#if UNITY_2018_3_OR_NEWER + //Preventing WebGL to throw error Duplicate system value semantic definition: input semantic 'SV_POSITION' and input semantic 'VPOS' + ShaderBody += "\t\t\t#if ( SHADER_API_D3D11 || SHADER_API_GLCORE || SHADER_API_GLES || SHADER_API_GLES3 || SHADER_API_METAL || SHADER_API_VULKAN )\n"; +#else + ShaderBody += "\t\t\t#if ( SHADER_API_D3D11 || SHADER_API_GLCORE || SHADER_API_GLES3 || SHADER_API_METAL || SHADER_API_VULKAN )\n"; +#endif + ShaderBody += "\t\t\t\t#define CAN_SKIP_VPOS\n"; + ShaderBody += "\t\t\t#endif\n"; + ShaderBody += "\t\t\t#include \"UnityCG.cginc\"\n"; + ShaderBody += "\t\t\t#include \"Lighting.cginc\"\n"; + ShaderBody += "\t\t\t#include \"UnityPBSLighting.cginc\"\n"; + + if( !( ( m_alphaToCoverage || m_inlineAlphaToCoverage.Active ) && hasOpacity && hasOpacityMask ) ) + if( hasOpacity ) + ShaderBody += "\t\t\tsampler3D _DitherMaskLOD;\n"; + + //ShaderBody += "\t\t\tsampler3D _DitherMaskLOD;\n"; + + ShaderBody += "\t\t\tstruct v2f\n"; + ShaderBody += "\t\t\t{\n"; + ShaderBody += "\t\t\t\tV2F_SHADOW_CASTER;\n"; + int texcoordIndex = 1; + for( int i = 0; i < m_currentDataCollector.PackSlotsList.Count; i++ ) + { + int size = 4 - m_currentDataCollector.PackSlotsList[ i ]; + if( size > 0 ) + { + ShaderBody += "\t\t\t\tfloat" + size + " customPack" + ( i + 1 ) + " : TEXCOORD" + ( i + 1 ) + ";\n"; + } + texcoordIndex++; + } + + if( !m_currentDataCollector.UsingInternalData ) + ShaderBody += "\t\t\t\tfloat3 worldPos : TEXCOORD" + ( texcoordIndex++ ) + ";\n"; + if( m_currentDataCollector.UsingScreenPos ) + ShaderBody += "\t\t\t\tfloat4 screenPos : TEXCOORD" + ( texcoordIndex++ ) + ";\n"; + if( /*m_currentDataCollector.UsingWorldNormal || m_currentDataCollector.UsingWorldPosition ||*/ m_currentDataCollector.UsingInternalData || m_currentDataCollector.DirtyNormal ) + { + ShaderBody += "\t\t\t\tfloat4 tSpace0 : TEXCOORD" + ( texcoordIndex++ ) + ";\n"; + ShaderBody += "\t\t\t\tfloat4 tSpace1 : TEXCOORD" + ( texcoordIndex++ ) + ";\n"; + ShaderBody += "\t\t\t\tfloat4 tSpace2 : TEXCOORD" + ( texcoordIndex++ ) + ";\n"; + } + else if( !m_currentDataCollector.UsingInternalData && m_currentDataCollector.UsingWorldNormal ) + { + ShaderBody += "\t\t\t\tfloat3 worldNormal : TEXCOORD" + ( texcoordIndex++ ) + ";\n"; + } + + if( m_currentDataCollector.UsingVertexColor ) + ShaderBody += "\t\t\t\thalf4 color : COLOR0;\n"; + ShaderBody += "\t\t\t\tUNITY_VERTEX_INPUT_INSTANCE_ID\n"; + ShaderBody += "\t\t\t\tUNITY_VERTEX_OUTPUT_STEREO\n"; + ShaderBody += "\t\t\t};\n"; + + ShaderBody += "\t\t\tv2f vert( " + m_currentDataCollector.SurfaceVertexStructure + " v )\n"; + ShaderBody += "\t\t\t{\n"; + ShaderBody += "\t\t\t\tv2f o;\n"; + + ShaderBody += "\t\t\t\tUNITY_SETUP_INSTANCE_ID( v );\n"; + ShaderBody += "\t\t\t\tUNITY_INITIALIZE_OUTPUT( v2f, o );\n"; + ShaderBody += "\t\t\t\tUNITY_INITIALIZE_VERTEX_OUTPUT_STEREO( o );\n"; + ShaderBody += "\t\t\t\tUNITY_TRANSFER_INSTANCE_ID( v, o );\n"; + + if( m_currentDataCollector.DirtyPerVertexData || m_currentDataCollector.CustomShadowCoordsList.Count > 0 ) + ShaderBody += "\t\t\t\tInput customInputData;\n"; + if( m_currentDataCollector.DirtyPerVertexData ) + { + ShaderBody += "\t\t\t\tvertexDataFunc( v" + ( m_currentDataCollector.TesselationActive ? "" : ", customInputData" ) + " );\n"; + } + + ShaderBody += "\t\t\t\tfloat3 worldPos = mul( unity_ObjectToWorld, v.vertex ).xyz;\n"; + ShaderBody += "\t\t\t\thalf3 worldNormal = UnityObjectToWorldNormal( v.normal );\n"; + if( m_currentDataCollector.UsingInternalData || m_currentDataCollector.DirtyNormal ) + { + ShaderBody += "\t\t\t\thalf3 worldTangent = UnityObjectToWorldDir( v.tangent.xyz );\n"; + ShaderBody += "\t\t\t\thalf tangentSign = v.tangent.w * unity_WorldTransformParams.w;\n"; + ShaderBody += "\t\t\t\thalf3 worldBinormal = cross( worldNormal, worldTangent ) * tangentSign;\n"; + ShaderBody += "\t\t\t\to.tSpace0 = float4( worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x );\n"; + ShaderBody += "\t\t\t\to.tSpace1 = float4( worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y );\n"; + ShaderBody += "\t\t\t\to.tSpace2 = float4( worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z );\n"; + } + else if( !m_currentDataCollector.UsingInternalData && m_currentDataCollector.UsingWorldNormal ) + { + ShaderBody += "\t\t\t\to.worldNormal = worldNormal;\n"; + } + + for( int i = 0; i < m_currentDataCollector.CustomShadowCoordsList.Count; i++ ) + { + int size = UIUtils.GetChannelsAmount( m_currentDataCollector.CustomShadowCoordsList[ i ].DataType ); + string channels = string.Empty; + for( int j = 0; j < size; j++ ) + { + channels += Convert.ToChar( 120 + m_currentDataCollector.CustomShadowCoordsList[ i ].TextureIndex + j ); + } + channels = channels.Replace( '{', 'w' ); + ShaderBody += "\t\t\t\to.customPack" + ( m_currentDataCollector.CustomShadowCoordsList[ i ].TextureSlot + 1 ) + "." + channels + " = customInputData." + m_currentDataCollector.CustomShadowCoordsList[ i ].CoordName + ";\n"; + + //TODO: TEMPORARY SOLUTION, this needs to go somewhere else, there's no need for these comparisons + if( m_currentDataCollector.CustomShadowCoordsList[ i ].CoordName.StartsWith( "uv_" ) ) + { + ShaderBody += "\t\t\t\to.customPack" + ( m_currentDataCollector.CustomShadowCoordsList[ i ].TextureSlot + 1 ) + "." + channels + " = v.texcoord;\n"; + } + else if( m_currentDataCollector.CustomShadowCoordsList[ i ].CoordName.StartsWith( "uv2_" ) ) + { + ShaderBody += "\t\t\t\to.customPack" + ( m_currentDataCollector.CustomShadowCoordsList[ i ].TextureSlot + 1 ) + "." + channels + " = v.texcoord1;\n"; + } + else if( m_currentDataCollector.CustomShadowCoordsList[ i ].CoordName.StartsWith( "uv3_" ) ) + { + ShaderBody += "\t\t\t\to.customPack" + ( m_currentDataCollector.CustomShadowCoordsList[ i ].TextureSlot + 1 ) + "." + channels + " = v.texcoord2;\n"; + } + else if( m_currentDataCollector.CustomShadowCoordsList[ i ].CoordName.StartsWith( "uv4_" ) ) + { + ShaderBody += "\t\t\t\to.customPack" + ( m_currentDataCollector.CustomShadowCoordsList[ i ].TextureSlot + 1 ) + "." + channels + " = v.texcoord3;\n"; + } + } + + if( !m_currentDataCollector.UsingInternalData ) + ShaderBody += "\t\t\t\to.worldPos = worldPos;\n"; + ShaderBody += "\t\t\t\tTRANSFER_SHADOW_CASTER_NORMALOFFSET( o )\n"; + if( m_currentDataCollector.UsingScreenPos ) + ShaderBody += "\t\t\t\to.screenPos = ComputeScreenPos( o.pos );\n"; + if( m_currentDataCollector.UsingVertexColor ) + ShaderBody += "\t\t\t\to.color = v.color;\n"; + ShaderBody += "\t\t\t\treturn o;\n"; + ShaderBody += "\t\t\t}\n"; + + ShaderBody += "\t\t\thalf4 frag( v2f IN\n"; + ShaderBody += "\t\t\t#if !defined( CAN_SKIP_VPOS )\n"; + ShaderBody += "\t\t\t, UNITY_VPOS_TYPE vpos : VPOS\n"; + ShaderBody += "\t\t\t#endif\n"; + ShaderBody += "\t\t\t) : SV_Target\n"; + ShaderBody += "\t\t\t{\n"; + ShaderBody += "\t\t\t\tUNITY_SETUP_INSTANCE_ID( IN );\n"; + ShaderBody += "\t\t\t\tInput surfIN;\n"; + ShaderBody += "\t\t\t\tUNITY_INITIALIZE_OUTPUT( Input, surfIN );\n"; + + for( int i = 0; i < m_currentDataCollector.CustomShadowCoordsList.Count; i++ ) + { + int size = UIUtils.GetChannelsAmount( m_currentDataCollector.CustomShadowCoordsList[ i ].DataType ); + string channels = string.Empty; + for( int j = 0; j < size; j++ ) + { + channels += Convert.ToChar( 120 + m_currentDataCollector.CustomShadowCoordsList[ i ].TextureIndex + j ); + } + channels = channels.Replace( '{', 'w' ); + ShaderBody += "\t\t\t\tsurfIN." + m_currentDataCollector.CustomShadowCoordsList[ i ].CoordName + " = IN.customPack" + ( m_currentDataCollector.CustomShadowCoordsList[ i ].TextureSlot + 1 ) + "." + channels + ";\n"; + } + + if( m_currentDataCollector.UsingInternalData ) + ShaderBody += "\t\t\t\tfloat3 worldPos = float3( IN.tSpace0.w, IN.tSpace1.w, IN.tSpace2.w );\n"; + else + ShaderBody += "\t\t\t\tfloat3 worldPos = IN.worldPos;\n"; + ShaderBody += "\t\t\t\thalf3 worldViewDir = normalize( UnityWorldSpaceViewDir( worldPos ) );\n"; + + if( m_currentDataCollector.UsingViewDirection && !m_currentDataCollector.DirtyNormal ) + ShaderBody += "\t\t\t\tsurfIN.viewDir = worldViewDir;\n"; + else if( m_currentDataCollector.UsingViewDirection ) + ShaderBody += "\t\t\t\tsurfIN.viewDir = IN.tSpace0.xyz * worldViewDir.x + IN.tSpace1.xyz * worldViewDir.y + IN.tSpace2.xyz * worldViewDir.z;\n"; + + if( m_currentDataCollector.UsingWorldPosition ) + ShaderBody += "\t\t\t\tsurfIN.worldPos = worldPos;\n"; + + if( m_currentDataCollector.UsingWorldNormal && m_currentDataCollector.UsingInternalData ) + ShaderBody += "\t\t\t\tsurfIN.worldNormal = float3( IN.tSpace0.z, IN.tSpace1.z, IN.tSpace2.z );\n"; + else if( !m_currentDataCollector.UsingInternalData && m_currentDataCollector.UsingWorldNormal ) + ShaderBody += "\t\t\t\tsurfIN.worldNormal = IN.worldNormal;\n"; + + if( m_currentDataCollector.UsingWorldReflection ) + ShaderBody += "\t\t\t\tsurfIN.worldRefl = -worldViewDir;\n"; + + if( m_currentDataCollector.UsingInternalData ) + { + ShaderBody += "\t\t\t\tsurfIN.internalSurfaceTtoW0 = IN.tSpace0.xyz;\n"; + ShaderBody += "\t\t\t\tsurfIN.internalSurfaceTtoW1 = IN.tSpace1.xyz;\n"; + ShaderBody += "\t\t\t\tsurfIN.internalSurfaceTtoW2 = IN.tSpace2.xyz;\n"; + } + + if( m_currentDataCollector.UsingScreenPos ) + ShaderBody += "\t\t\t\tsurfIN.screenPos = IN.screenPos;\n"; + + if( m_currentDataCollector.UsingVertexColor ) + ShaderBody += "\t\t\t\tsurfIN.vertexColor = IN.color;\n"; + + ShaderBody += "\t\t\t\t" + outputStruct + " o;\n"; + ShaderBody += "\t\t\t\tUNITY_INITIALIZE_OUTPUT( " + outputStruct + ", o )\n"; + ShaderBody += "\t\t\t\tsurf( surfIN, o );\n"; + if( ( hasOpacity || hasOpacityMask ) && m_currentLightModel == StandardShaderLightModel.CustomLighting ) + { + ShaderBody += "\t\t\t\tUnityGI gi;\n"; + ShaderBody += "\t\t\t\tUNITY_INITIALIZE_OUTPUT( UnityGI, gi );\n"; + ShaderBody += "\t\t\t\to.Alpha = LightingStandardCustomLighting( o, worldViewDir, gi ).a;\n"; + } + ShaderBody += "\t\t\t\t#if defined( CAN_SKIP_VPOS )\n"; + ShaderBody += "\t\t\t\tfloat2 vpos = IN.pos;\n"; + ShaderBody += "\t\t\t\t#endif\n"; + + /*if( ( ( m_alphaToCoverage || m_inlineAlphaToCoverage.Active ) && hasOpacity && m_inputPorts[ m_discardPortId ].IsConnected ) ) + { + + } + else*/ if(!( ( m_alphaToCoverage || m_inlineAlphaToCoverage.Active ) && hasOpacity && m_inputPorts[ m_discardPortId ].IsConnected ) && hasOpacity ) + { + ShaderBody += "\t\t\t\thalf alphaRef = tex3D( _DitherMaskLOD, float3( vpos.xy * 0.25, o.Alpha * 0.9375 ) ).a;\n"; + ShaderBody += "\t\t\t\tclip( alphaRef - 0.01 );\n"; + } + + ShaderBody += "\t\t\t\tSHADOW_CASTER_FRAGMENT( IN )\n"; + ShaderBody += "\t\t\t}\n"; + + ShaderBody += "\t\t\tENDCG\n"; + + ShaderBody += "\t\t}\n"; + } + + } + + if( !string.IsNullOrEmpty( bellowUsePasses ) ) + { + ShaderBody += bellowUsePasses; + } + + CloseSubShaderBody( ref ShaderBody ); + + if( m_dependenciesHelper.HasDependencies ) + { + ShaderBody += m_dependenciesHelper.GenerateDependencies(); + } + + if( m_fallbackHelper.Active ) + { + ShaderBody += m_fallbackHelper.TabbedFallbackShader; + } + else if( m_castShadows || m_receiveShadows ) + { + AddShaderProperty( ref ShaderBody, "Fallback", "Diffuse" ); + } + + if( !string.IsNullOrEmpty( m_customInspectorName ) ) + { + AddShaderProperty( ref ShaderBody, "CustomEditor", m_customInspectorName ); + } + } + CloseShaderBody( ref ShaderBody ); + + if( usingDebugPort ) + { + m_currentLightModel = cachedLightModel; + ContainerGraph.CurrentCanvasMode = cachedAvailability; + } + + // Generate Graph info + ShaderBody += ContainerGraph.ParentWindow.GenerateGraphInfo(); + + //TODO: Remove current SaveDebugShader and uncomment SaveToDisk as soon as pathname is editable + if( !String.IsNullOrEmpty( pathname ) ) + { + IOUtils.StartSaveThread( ShaderBody, ( isFullPath ? pathname : ( IOUtils.dataPath + pathname ) ) ); + } + else + { + IOUtils.StartSaveThread( ShaderBody, Application.dataPath + "/AmplifyShaderEditor/Samples/Shaders/" + m_shaderName + ".shader" ); + } + + // Load new shader into material + + if( CurrentShader == null ) + { + AssetDatabase.Refresh( ImportAssetOptions.ForceUpdate ); + CurrentShader = Shader.Find( ShaderName ); + } + //else + //{ + // // need to always get asset datapath because a user can change and asset location from the project window + // AssetDatabase.ImportAsset( AssetDatabase.GetAssetPath( m_currentShader ) ); + // //ShaderUtil.UpdateShaderAsset( m_currentShader, ShaderBody ); + //} + + if( m_currentShader != null ) + { + m_currentDataCollector.UpdateShaderImporter( ref m_currentShader ); + if( m_currentMaterial != null ) + { + if( m_currentShader != m_currentMaterial.shader ) + m_currentMaterial.shader = m_currentShader; +#if UNITY_5_6_OR_NEWER + if ( isInstancedShader ) + { + m_currentMaterial.enableInstancing = true; + } +#endif + m_currentDataCollector.UpdateMaterialOnPropertyNodes( m_currentMaterial ); + UpdateMaterialEditor(); + // need to always get asset datapath because a user can change and asset location from the project window + //AssetDatabase.ImportAsset( AssetDatabase.GetAssetPath( m_currentMaterial ) ); + } + } + + m_currentDataCollector.Destroy(); + m_currentDataCollector = null; + + return m_currentShader; + } + + public override void UpdateFromShader( Shader newShader ) + { + if( m_currentMaterial != null && m_currentMaterial.shader != newShader ) + { + m_currentMaterial.shader = newShader; + } + CurrentShader = newShader; + } + + public override void Destroy() + { + base.Destroy(); + + if( m_dummyProperty != null ) + { + m_dummyProperty.Destroy(); + GameObject.DestroyImmediate( m_dummyProperty ); + m_dummyProperty = null; + } + + m_drawInstancedHelper = null; + + m_translucencyPort = null; + m_transmissionPort = null; + m_refractionPort = null; + m_normalPort = null; + + m_renderingOptionsOpHelper.Destroy(); + m_renderingOptionsOpHelper = null; + + m_additionalIncludes.Destroy(); + m_additionalIncludes = null; + + m_additionalPragmas.Destroy(); + m_additionalPragmas = null; + + m_additionalDefines.Destroy(); + m_additionalDefines = null; + + m_additionalSurfaceOptions.Destroy(); + m_additionalSurfaceOptions = null; + + m_additionalDirectives.Destroy(); + m_additionalDirectives = null; + + m_customTagsHelper.Destroy(); + m_customTagsHelper = null; + + m_dependenciesHelper.Destroy(); + m_dependenciesHelper = null; + + m_renderingPlatformOpHelper = null; + m_inspectorDefaultStyle = null; + m_inspectorFoldoutStyle = null; + + m_zBufferHelper = null; + m_stencilBufferHelper = null; + m_blendOpsHelper = null; + m_tessOpHelper.Destroy(); + m_tessOpHelper = null; + m_outlineHelper.Destroy(); + m_outlineHelper = null; + m_colorMaskHelper.Destroy(); + m_colorMaskHelper = null; + m_billboardOpHelper = null; + + m_fallbackHelper.Destroy(); + GameObject.DestroyImmediate( m_fallbackHelper ); + m_fallbackHelper = null; + + m_usePass.Destroy(); + GameObject.DestroyImmediate( m_usePass ); + m_usePass = null; + } + + public override int VersionConvertInputPortId( int portId ) + { + int newPort = portId; + + //added translucency input after occlusion + if( UIUtils.CurrentShaderVersion() <= 2404 ) + { + switch( m_currentLightModel ) + { + case StandardShaderLightModel.Standard: + case StandardShaderLightModel.StandardSpecular: + if( portId >= 6 ) + newPort += 1; + break; + case StandardShaderLightModel.CustomLighting: + case StandardShaderLightModel.Unlit: + case StandardShaderLightModel.Lambert: + case StandardShaderLightModel.BlinnPhong: + if( portId >= 5 ) + newPort += 1; + break; + } + } + + portId = newPort; + + //added transmission input after occlusion + if( UIUtils.CurrentShaderVersion() < 2407 ) + { + switch( m_currentLightModel ) + { + case StandardShaderLightModel.Standard: + case StandardShaderLightModel.StandardSpecular: + if( portId >= 6 ) + newPort += 1; + break; + case StandardShaderLightModel.CustomLighting: + case StandardShaderLightModel.Unlit: + case StandardShaderLightModel.Lambert: + case StandardShaderLightModel.BlinnPhong: + if( portId >= 5 ) + newPort += 1; + break; + } + } + + portId = newPort; + + //added tessellation ports + if( UIUtils.CurrentShaderVersion() < 3002 ) + { + switch( m_currentLightModel ) + { + case StandardShaderLightModel.Standard: + case StandardShaderLightModel.StandardSpecular: + if( portId >= 13 ) + newPort += 1; + break; + case StandardShaderLightModel.CustomLighting: + case StandardShaderLightModel.Unlit: + case StandardShaderLightModel.Lambert: + case StandardShaderLightModel.BlinnPhong: + if( portId >= 10 ) + newPort += 1; + break; + } + } + + portId = newPort; + + //added refraction after translucency + if( UIUtils.CurrentShaderVersion() < 3204 ) + { + switch( m_currentLightModel ) + { + case StandardShaderLightModel.Standard: + case StandardShaderLightModel.StandardSpecular: + if( portId >= 8 ) + newPort += 1; + break; + case StandardShaderLightModel.CustomLighting: + case StandardShaderLightModel.Unlit: + case StandardShaderLightModel.Lambert: + case StandardShaderLightModel.BlinnPhong: + if( portId >= 7 ) + newPort += 1; + break; + } + } + + portId = newPort; + + //removed custom lighting port + //if ( UIUtils.CurrentShaderVersion() < 10003 ) //runs everytime because this system is only used after 5000 version + { + switch( m_currentLightModel ) + { + case StandardShaderLightModel.Standard: + case StandardShaderLightModel.StandardSpecular: + if( portId >= 13 ) + newPort -= 1; + break; + case StandardShaderLightModel.CustomLighting: + case StandardShaderLightModel.Unlit: + case StandardShaderLightModel.Lambert: + case StandardShaderLightModel.BlinnPhong: + if( portId >= 12 ) + newPort -= 1; + break; + } + } + + portId = newPort; + + //if( UIUtils.CurrentShaderVersion() < 13802 ) //runs everytime because this system is only used after 5000 version + { + switch( m_currentLightModel ) + { + case StandardShaderLightModel.Standard: + case StandardShaderLightModel.StandardSpecular: + if( portId >= 11 ) + newPort += 1; + break; + case StandardShaderLightModel.CustomLighting: + case StandardShaderLightModel.Unlit: + case StandardShaderLightModel.Lambert: + case StandardShaderLightModel.BlinnPhong: + if( portId >= 10 ) + newPort += 1; + break; + } + } + + portId = newPort; + return newPort; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + try + { + base.ReadFromString( ref nodeParams ); + m_currentLightModel = (StandardShaderLightModel)Enum.Parse( typeof( StandardShaderLightModel ), GetCurrentParam( ref nodeParams ) ); + + if( CurrentMasterNodeCategory == AvailableShaderTypes.SurfaceShader && m_currentLightModel == StandardShaderLightModel.CustomLighting ) + { + ContainerGraph.CurrentCanvasMode = NodeAvailability.CustomLighting; + ContainerGraph.ParentWindow.CurrentNodeAvailability = NodeAvailability.CustomLighting; + } + else if( CurrentMasterNodeCategory == AvailableShaderTypes.SurfaceShader ) + { + ContainerGraph.CurrentCanvasMode = NodeAvailability.SurfaceShader; + ContainerGraph.ParentWindow.CurrentNodeAvailability = NodeAvailability.SurfaceShader; + } + //if ( _shaderCategory.Length > 0 ) + // _shaderCategory = UIUtils.RemoveInvalidCharacters( _shaderCategory ); + ShaderName = GetCurrentParam( ref nodeParams ); + if( m_shaderName.Length > 0 ) + ShaderName = UIUtils.RemoveShaderInvalidCharacters( ShaderName ); + + m_renderingOptionsOpHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + + m_cullMode = (CullMode)Enum.Parse( typeof( CullMode ), GetCurrentParam( ref nodeParams ) ); + m_zBufferHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + + string alphaMode = GetCurrentParam( ref nodeParams ); + + if( UIUtils.CurrentShaderVersion() < 4003 ) + { + if( alphaMode.Equals( "Fade" ) ) + { + alphaMode = "Transparent"; + } + else if( alphaMode.Equals( "Transparent" ) ) + { + alphaMode = "Premultiply"; + } + } + + m_alphaMode = (AlphaMode)Enum.Parse( typeof( AlphaMode ), alphaMode ); + m_opacityMaskClipValue = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + m_keepAlpha = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_keepAlpha = true; + m_castShadows = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_queueOrder = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 11 ) + { + m_customBlendMode = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_renderType = (RenderType)Enum.Parse( typeof( RenderType ), GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 14305 ) + { + m_customRenderType = GetCurrentParam( ref nodeParams ); + } + m_renderQueue = (RenderQueue)Enum.Parse( typeof( RenderQueue ), GetCurrentParam( ref nodeParams ) ); + } + if( UIUtils.CurrentShaderVersion() > 2402 ) + { + m_renderPath = (RenderPath)Enum.Parse( typeof( RenderPath ), GetCurrentParam( ref nodeParams ) ); + } + if( UIUtils.CurrentShaderVersion() > 2405 ) + { + m_renderingPlatformOpHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 2500 ) + { + m_colorMaskHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 2501 ) + { + m_stencilBufferHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 2504 ) + { + m_tessOpHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 2505 ) + { + m_receiveShadows = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 3202 ) + { + m_blendOpsHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 3203 ) + { + m_grabOrder = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 5003 ) + { + m_outlineHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 5110 ) + { + m_billboardOpHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 6101 ) + { + m_vertexMode = (VertexMode)Enum.Parse( typeof( VertexMode ), GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 6102 ) + { + ShaderLOD = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_fallbackHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 7102 ) + { + m_maskClipOrderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_translucencyOrderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_refractionOrderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_tessellationOrderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 10010 && UIUtils.CurrentShaderVersion() < 15312 ) + { + m_additionalIncludes.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 11006 ) + { + m_customTagsHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 13102 && UIUtils.CurrentShaderVersion() < 15312 ) + { + m_additionalPragmas.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 13205 ) + { + m_alphaToCoverage = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 13903 ) + { + m_dependenciesHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 14005 && UIUtils.CurrentShaderVersion() < 15312 ) + { + m_additionalDefines.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 14501 ) + { + m_inlineCullMode.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 14502 ) + { + m_specColorOrderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 15204 ) + { + m_inlineOpacityMaskClipValue.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 15311 ) + { + m_additionalDirectives.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + m_additionalSurfaceOptions.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + else + { + m_additionalDirectives.AddItems( AdditionalLineType.Define, m_additionalDefines.DefineList ); + m_additionalDirectives.AddItems( AdditionalLineType.Include, m_additionalIncludes.IncludeList ); + m_additionalDirectives.AddItems( AdditionalLineType.Pragma, m_additionalPragmas.PragmaList ); + } + + if( UIUtils.CurrentShaderVersion() > 15402 ) + { + m_usePass.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 16203 ) + { + m_drawInstancedHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 16204 ) + m_inlineChromaticAberration.ReadFromString( ref m_currentReadParamIdx, ref nodeParams , false ); + + if( UIUtils.CurrentShaderVersion() > 16207 ) + m_inlineAlphaToCoverage.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + + if( UIUtils.CurrentShaderVersion() > 18302 ) + SamplingMacros = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + else + SamplingMacros = false; + + m_lightModelChanged = true; + m_lastLightModel = m_currentLightModel; + DeleteAllInputConnections( true ); + AddMasterPorts(); + UpdateFromBlendMode(); + m_customBlendMode = TestCustomBlendMode(); + + ContainerGraph.CurrentPrecision = m_currentPrecisionType; + } + catch( Exception e ) + { + Debug.Log( e ); + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + + // change port connection from emission to the new custom lighting port + if( m_currentLightModel == StandardShaderLightModel.CustomLighting && m_inputPorts[ m_emissionPortId ].IsConnected && UIUtils.CurrentShaderVersion() < 13802 ) + { + OutputPort port = m_inputPorts[ m_emissionPortId ].GetOutputConnection( 0 ); + m_inputPorts[ m_emissionPortId ].FullDeleteConnections(); + UIUtils.SetConnection( m_inputPorts[ m_customLightingPortId ].NodeId, m_inputPorts[ m_customLightingPortId ].PortId, port.NodeId, port.PortId ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentLightModel ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_shaderName ); + m_renderingOptionsOpHelper.WriteToString( ref nodeInfo ); + + IOUtils.AddFieldValueToString( ref nodeInfo, m_cullMode ); + m_zBufferHelper.WriteToString( ref nodeInfo ); + + IOUtils.AddFieldValueToString( ref nodeInfo, m_alphaMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_opacityMaskClipValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_keepAlpha ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_castShadows ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_queueOrder ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_customBlendMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_renderType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_customRenderType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_renderQueue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_renderPath ); + m_renderingPlatformOpHelper.WriteToString( ref nodeInfo ); + m_colorMaskHelper.WriteToString( ref nodeInfo ); + m_stencilBufferHelper.WriteToString( ref nodeInfo ); + m_tessOpHelper.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_receiveShadows ); + m_blendOpsHelper.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_grabOrder ); + m_outlineHelper.WriteToString( ref nodeInfo ); + m_billboardOpHelper.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_vertexMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, ShaderLOD ); + m_fallbackHelper.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_maskClipReorder != null ) ? m_maskClipReorder.OrderIndex : -1 ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_translucencyReorder != null ) ? m_translucencyReorder.OrderIndex : -1 ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_refractionReorder != null ) ? m_refractionReorder.OrderIndex : -1 ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_tessellationReorder != null ) ? m_tessellationReorder.OrderIndex : -1 ); + //m_additionalIncludes.WriteToString( ref nodeInfo ); + m_customTagsHelper.WriteToString( ref nodeInfo ); + //m_additionalPragmas.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_alphaToCoverage ); + m_dependenciesHelper.WriteToString( ref nodeInfo ); + //m_additionalDefines.WriteToString( ref nodeInfo ); + m_inlineCullMode.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_specColorReorder != null ) ? m_specColorReorder.OrderIndex : -1 ); + m_inlineOpacityMaskClipValue.WriteToString( ref nodeInfo ); + m_additionalDirectives.WriteToString( ref nodeInfo ); + m_additionalSurfaceOptions.WriteToString( ref nodeInfo ); + m_usePass.WriteToString( ref nodeInfo ); + m_drawInstancedHelper.WriteToString( ref nodeInfo ); + m_inlineChromaticAberration.WriteToString( ref nodeInfo ); + m_inlineAlphaToCoverage.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_samplingMacros ); + } + + private bool TestCustomBlendMode() + { + switch( m_alphaMode ) + { + case AlphaMode.Opaque: + { + if( m_renderType == RenderType.Opaque && m_renderQueue == RenderQueue.Geometry ) + return false; + } + break; + case AlphaMode.Masked: + { + if( m_renderType == RenderType.TransparentCutout && m_renderQueue == RenderQueue.AlphaTest ) + return false; + } + break; + case AlphaMode.Transparent: + case AlphaMode.Premultiply: + { + if( m_renderType == RenderType.Transparent && m_renderQueue == RenderQueue.Transparent ) + return false; + } + break; + case AlphaMode.Translucent: + { + if( m_renderType == RenderType.Opaque && m_renderQueue == RenderQueue.Transparent ) + return false; + } + break; + } + return true; + } + + private void UpdateFromBlendMode() + { + m_checkChanges = true; + bool lockRefractionPort = false; + if( m_currentLightModel == StandardShaderLightModel.Unlit || m_currentLightModel == StandardShaderLightModel.CustomLighting ) + { + lockRefractionPort = true; + } + + switch( m_alphaMode ) + { + case AlphaMode.Opaque: + { + m_renderType = RenderType.Opaque; + m_renderQueue = RenderQueue.Geometry; + m_keepAlpha = true; + m_refractionPort.Locked = true; + m_inputPorts[ m_opacityPortId ].Locked = true; + m_inputPorts[ m_discardPortId ].Locked = true; + } + break; + case AlphaMode.Masked: + { + m_renderType = RenderType.TransparentCutout; + m_renderQueue = RenderQueue.AlphaTest; + m_keepAlpha = true; + m_refractionPort.Locked = true; + m_inputPorts[ m_opacityPortId ].Locked = true; + m_inputPorts[ m_discardPortId ].Locked = false; + } + break; + case AlphaMode.Transparent: + case AlphaMode.Premultiply: + { + m_renderType = RenderType.Transparent; + m_renderQueue = RenderQueue.Transparent; + m_refractionPort.Locked = false || lockRefractionPort; + m_inputPorts[ m_opacityPortId ].Locked = false; + m_inputPorts[ m_discardPortId ].Locked = true; + } + break; + case AlphaMode.Translucent: + { + m_renderType = RenderType.Opaque; + m_renderQueue = RenderQueue.Transparent; + m_refractionPort.Locked = false || lockRefractionPort; + m_inputPorts[ m_opacityPortId ].Locked = false; + m_inputPorts[ m_discardPortId ].Locked = true; + } + break; + case AlphaMode.Custom: + { + m_refractionPort.Locked = false || lockRefractionPort; + m_inputPorts[ m_opacityPortId ].Locked = false; + m_inputPorts[ m_discardPortId ].Locked = false; + } + break; + } + + m_blendOpsHelper.SetBlendOpsFromBlendMode( m_alphaMode, ( m_alphaMode == AlphaMode.Custom || m_alphaMode == AlphaMode.Opaque ) ); + } + + public bool CastShadows { get { return m_castShadows; } } + public StandardShaderLightModel CurrentLightingModel { get { return m_currentLightModel; } } + public CullMode CurrentCullMode { get { return m_cullMode; } } + //public AdditionalIncludesHelper AdditionalIncludes { get { return m_additionalIncludes; } set { m_additionalIncludes = value; } } + //public AdditionalPragmasHelper AdditionalPragmas { get { return m_additionalPragmas; } set { m_additionalPragmas = value; } } + //public AdditionalDefinesHelper AdditionalDefines { get { return m_additionalDefines; } set { m_additionalDefines = value; } } + public TemplateAdditionalDirectivesHelper AdditionalDirectives { get { return m_additionalDirectives; } } + public OutlineOpHelper OutlineHelper { get { return m_outlineHelper; } } + public float OpacityMaskClipValue { get { return m_opacityMaskClipValue; } } + public InlineProperty InlineOpacityMaskClipValue { get { return m_inlineOpacityMaskClipValue; } set { m_inlineOpacityMaskClipValue = value; } } + public bool CustomShadowCaster + { + get + { + bool hasOpacity = m_inputPorts[ m_opacityPortId ].IsConnected; + return + ( !m_renderingOptionsOpHelper.UseDefaultShadowCaster && + ( ( m_castShadows && ( m_alphaToCoverage || m_inlineAlphaToCoverage.Active ) ) || + ( m_castShadows && hasOpacity ) || + ( m_castShadows && ( m_currentDataCollector.UsingWorldNormal || m_currentDataCollector.UsingWorldReflection || m_currentDataCollector.UsingViewDirection ) ) || + ( m_castShadows && m_inputPorts[ m_discardPortId ].Available && m_inputPorts[ m_discardPortId ].IsConnected && m_currentLightModel == StandardShaderLightModel.CustomLighting ) ) ); + } + } + public override AvailableShaderTypes CurrentMasterNodeCategory { get { return AvailableShaderTypes.SurfaceShader; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StandardSurface.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StandardSurface.cs.meta new file mode 100644 index 0000000..0515f8c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StandardSurface.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 59e61f9559385a94a87d4d37dbd556f0 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StencilBufferOpHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StencilBufferOpHelper.cs new file mode 100644 index 0000000..b613f0f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StencilBufferOpHelper.cs @@ -0,0 +1,304 @@ +using System; +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + + [Serializable] + public class StencilBufferOpHelper + { + public static readonly string[] StencilComparisonValues = + { + "", + "Greater" , + "GEqual" , + "Less" , + "LEqual" , + "Equal" , + "NotEqual" , + "Always" , + "Never" + }; + + public static readonly Dictionary StencilComparisonValuesDict = new Dictionary() + { + {"Greater" , 1}, + {"GEqual" , 2}, + {"Less" , 3}, + {"LEqual" , 4}, + {"Equal" , 5}, + {"NotEqual", 6}, + {"Always" , 7}, + {"Never" , 8}, + }; + + public static readonly string[] StencilComparisonLabels = + { + "", + "Greater" , + "Greater or Equal" , + "Less" , + "Less or Equal" , + "Equal" , + "Not Equal" , + "Always" , + "Never" + }; + + + public static readonly string[] StencilOpsValues = + { + "", + "Keep", + "Zero", + "Replace", + "IncrSat", + "DecrSat", + "Invert", + "IncrWrap", + "DecrWrap" + }; + + public static readonly Dictionary StencilOpsValuesDict = new Dictionary() + { + {"Keep", 1}, + {"Zero", 2}, + {"Replace", 3}, + {"IncrSat", 4}, + {"DecrSat", 5}, + {"Invert", 6}, + {"IncrWrap",7}, + {"DecrWrap",8}, + }; + + public static readonly string[] StencilOpsLabels = + { + "", + "Keep", + "Zero", + "Replace", + "IncrSat", + "DecrSat", + "Invert", + "IncrWrap", + "DecrWrap" + }; + + + private const string FoldoutLabelStr = " Stencil Buffer"; + private GUIContent ReferenceValueContent = new GUIContent( "Reference", "The value to be compared against (if Comparison is anything else than always) and/or the value to be written to the buffer (if either Pass, Fail or ZFail is set to replace)" ); + private GUIContent ReadMaskContent = new GUIContent( "Read Mask", "An 8 bit mask as an 0-255 integer, used when comparing the reference value with the contents of the buffer (referenceValue & readMask) comparisonFunction (stencilBufferValue & readMask)" ); + private GUIContent WriteMaskContent = new GUIContent( "Write Mask", "An 8 bit mask as an 0-255 integer, used when writing to the buffer" ); + private const string ComparisonStr = "Comparison"; + private const string PassStr = "Pass"; + private const string FailStr = "Fail"; + private const string ZFailStr = "ZFail"; + + private const string ComparisonFrontStr = "Comp. Front"; + private const string PassFrontStr = "Pass Front"; + private const string FailFrontStr = "Fail Front"; + private const string ZFailFrontStr = "ZFail Front"; + + private const string ComparisonBackStr = "Comp. Back"; + private const string PassBackStr = "Pass Back"; + private const string FailBackStr = "Fail Back"; + private const string ZFailBackStr = "ZFail Back"; + + private const int ReadMaskDefaultValue = 255; + private const int WriteMaskDefaultValue = 255; + private const int ComparisonDefaultValue = 0; + private const int PassStencilOpDefaultValue = 0; + private const int FailStencilOpDefaultValue = 0; + private const int ZFailStencilOpDefaultValue = 0; + + [SerializeField] + private bool m_active; + + [SerializeField] + private InlineProperty m_refValue = new InlineProperty(); + [SerializeField] + private InlineProperty m_readMask = new InlineProperty( ReadMaskDefaultValue ); + [SerializeField] + private InlineProperty m_writeMask = new InlineProperty( WriteMaskDefaultValue ); + + //Comparison Function + [SerializeField] + private InlineProperty m_comparisonFunctionIdx = new InlineProperty( ComparisonDefaultValue ); + [SerializeField] + private InlineProperty m_comparisonFunctionBackIdx = new InlineProperty( ComparisonDefaultValue ); + + //Pass Stencil Op + [SerializeField] + private InlineProperty m_passStencilOpIdx = new InlineProperty( PassStencilOpDefaultValue ); + [SerializeField] + private InlineProperty m_passStencilOpBackIdx = new InlineProperty( PassStencilOpDefaultValue ); + + //Fail Stencil Op + [SerializeField] + private InlineProperty m_failStencilOpIdx = new InlineProperty( FailStencilOpDefaultValue ); + [SerializeField] + private InlineProperty m_failStencilOpBackIdx = new InlineProperty( FailStencilOpDefaultValue ); + + //ZFail Stencil Op + [SerializeField] + private InlineProperty m_zFailStencilOpIdx = new InlineProperty( ZFailStencilOpDefaultValue ); + [SerializeField] + private InlineProperty m_zFailStencilOpBackIdx = new InlineProperty( ZFailStencilOpDefaultValue ); + + public string CreateStencilOp( UndoParentNode owner ) + { + string result = "\t\tStencil\n\t\t{\n"; + result += string.Format( "\t\t\tRef {0}\n", m_refValue.GetValueOrProperty() ); + if( m_readMask.Active || m_readMask.IntValue != ReadMaskDefaultValue ) + { + result += string.Format( "\t\t\tReadMask {0}\n", m_readMask.GetValueOrProperty() ); + } + + if( m_writeMask.Active || m_writeMask.IntValue != WriteMaskDefaultValue ) + { + result += string.Format( "\t\t\tWriteMask {0}\n", m_writeMask.GetValueOrProperty() ); + } + + if( ( owner as StandardSurfaceOutputNode ).CurrentCullMode == CullMode.Off ) + { + if( m_comparisonFunctionIdx.IntValue != ComparisonDefaultValue || m_comparisonFunctionIdx.Active ) + result += string.Format( "\t\t\tCompFront {0}\n", m_comparisonFunctionIdx.GetValueOrProperty( StencilComparisonValues[ m_comparisonFunctionIdx.IntValue ] ) ); + if( m_passStencilOpIdx.IntValue != PassStencilOpDefaultValue || m_passStencilOpIdx.Active ) + result += string.Format( "\t\t\tPassFront {0}\n", m_passStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_passStencilOpIdx.IntValue ] ) ); + if( m_failStencilOpIdx.IntValue != FailStencilOpDefaultValue || m_failStencilOpIdx.Active ) + result += string.Format( "\t\t\tFailFront {0}\n", m_failStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_failStencilOpIdx.IntValue ] ) ); + if( m_zFailStencilOpIdx.IntValue != ZFailStencilOpDefaultValue || m_zFailStencilOpIdx.Active ) + result += string.Format( "\t\t\tZFailFront {0}\n", m_zFailStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_zFailStencilOpIdx.IntValue ] ) ); + + if( m_comparisonFunctionBackIdx.IntValue != ComparisonDefaultValue || m_comparisonFunctionBackIdx.Active ) + result += string.Format( "\t\t\tCompBack {0}\n", m_comparisonFunctionBackIdx.GetValueOrProperty( StencilComparisonValues[ m_comparisonFunctionBackIdx.IntValue ] ) ); + if( m_passStencilOpBackIdx.IntValue != PassStencilOpDefaultValue || m_passStencilOpBackIdx.Active ) + result += string.Format( "\t\t\tPassBack {0}\n", m_passStencilOpBackIdx.GetValueOrProperty( StencilOpsValues[ m_passStencilOpBackIdx.IntValue ] ) ); + if( m_failStencilOpBackIdx.IntValue != FailStencilOpDefaultValue || m_failStencilOpBackIdx.Active ) + result += string.Format( "\t\t\tFailBack {0}\n", m_failStencilOpBackIdx.GetValueOrProperty( StencilOpsValues[ m_failStencilOpBackIdx.IntValue ] ) ); + if( m_zFailStencilOpBackIdx.IntValue != ZFailStencilOpDefaultValue || m_zFailStencilOpBackIdx.Active ) + result += string.Format( "\t\t\tZFailBack {0}\n", m_zFailStencilOpBackIdx.GetValueOrProperty( StencilOpsValues[ m_zFailStencilOpBackIdx.IntValue ] ) ); + } + else + { + if( m_comparisonFunctionIdx.IntValue != ComparisonDefaultValue || m_comparisonFunctionIdx.Active ) + result += string.Format( "\t\t\tComp {0}\n", m_comparisonFunctionIdx.GetValueOrProperty( StencilComparisonValues[ m_comparisonFunctionIdx.IntValue ] ) ); + if( m_passStencilOpIdx.IntValue != PassStencilOpDefaultValue || m_passStencilOpIdx.Active ) + result += string.Format( "\t\t\tPass {0}\n", m_passStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_passStencilOpIdx.IntValue ] ) ); + if( m_failStencilOpIdx.IntValue != FailStencilOpDefaultValue || m_failStencilOpIdx.Active ) + result += string.Format( "\t\t\tFail {0}\n", m_failStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_failStencilOpIdx.IntValue ] ) ); + if( m_zFailStencilOpIdx.IntValue != ZFailStencilOpDefaultValue || m_zFailStencilOpIdx.Active ) + result += string.Format( "\t\t\tZFail {0}\n", m_zFailStencilOpIdx.GetValueOrProperty( StencilOpsValues[ m_zFailStencilOpIdx.IntValue ] ) ); + } + + + result += "\t\t}\n"; + return result; + } + + public void Draw( UndoParentNode owner ) + { + bool foldoutValue = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions; + NodeUtils.DrawPropertyGroup( owner, ref foldoutValue, ref m_active, FoldoutLabelStr, () => + { + float cache = EditorGUIUtility.labelWidth; + float cache2 = EditorGUIUtility.fieldWidth; + EditorGUIUtility.labelWidth = 110; + EditorGUIUtility.fieldWidth = 30; + m_refValue.IntSlider( ref owner, ReferenceValueContent, 0, 255 ); + m_readMask.IntSlider( ref owner, ReadMaskContent, 0, 255 ); + m_writeMask.IntSlider( ref owner, WriteMaskContent, 0, 255 ); + //EditorGUIUtility.labelWidth = cache; + EditorGUIUtility.fieldWidth = cache2; + if( ( owner as StandardSurfaceOutputNode ).CurrentCullMode == CullMode.Off ) + { + m_comparisonFunctionIdx.EnumTypePopup( ref owner, ComparisonFrontStr, StencilComparisonLabels ); + m_passStencilOpIdx.EnumTypePopup( ref owner, PassFrontStr, StencilOpsLabels ); + m_failStencilOpIdx.EnumTypePopup( ref owner, FailFrontStr, StencilOpsLabels ); + m_zFailStencilOpIdx.EnumTypePopup( ref owner, ZFailFrontStr, StencilOpsLabels ); + EditorGUILayout.Separator(); + m_comparisonFunctionBackIdx.EnumTypePopup( ref owner, ComparisonBackStr, StencilComparisonLabels ); + m_passStencilOpBackIdx.EnumTypePopup( ref owner, PassBackStr, StencilOpsLabels ); + m_failStencilOpBackIdx.EnumTypePopup( ref owner, FailBackStr, StencilOpsLabels ); + m_zFailStencilOpBackIdx.EnumTypePopup( ref owner, ZFailBackStr, StencilOpsLabels ); + } + else + { + m_comparisonFunctionIdx.EnumTypePopup( ref owner, ComparisonStr, StencilComparisonLabels ); + m_passStencilOpIdx.EnumTypePopup( ref owner, PassFrontStr, StencilOpsLabels ); + m_failStencilOpIdx.EnumTypePopup( ref owner, FailFrontStr, StencilOpsLabels ); + m_zFailStencilOpIdx.EnumTypePopup( ref owner, ZFailFrontStr, StencilOpsLabels ); + } + EditorGUIUtility.labelWidth = cache; + } ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions = foldoutValue; + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + m_active = Convert.ToBoolean( nodeParams[ index++ ] ); + if( UIUtils.CurrentShaderVersion() > 14501 ) + { + m_refValue.ReadFromString( ref index, ref nodeParams ); + m_readMask.ReadFromString( ref index, ref nodeParams ); + m_writeMask.ReadFromString( ref index, ref nodeParams ); + m_comparisonFunctionIdx.ReadFromString( ref index, ref nodeParams ); + m_passStencilOpIdx.ReadFromString( ref index, ref nodeParams ); + m_failStencilOpIdx.ReadFromString( ref index, ref nodeParams ); + m_zFailStencilOpIdx.ReadFromString( ref index, ref nodeParams ); + } + else + { + m_refValue.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_readMask.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_writeMask.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_comparisonFunctionIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_passStencilOpIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_failStencilOpIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_zFailStencilOpIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + } + + if( UIUtils.CurrentShaderVersion() > 13203 ) + { + if( UIUtils.CurrentShaderVersion() > 14501 ) + { + m_comparisonFunctionBackIdx.ReadFromString( ref index, ref nodeParams ); + m_passStencilOpBackIdx.ReadFromString( ref index, ref nodeParams ); + m_failStencilOpBackIdx.ReadFromString( ref index, ref nodeParams ); + m_zFailStencilOpBackIdx.ReadFromString( ref index, ref nodeParams ); + } + else + { + m_comparisonFunctionBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_passStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_failStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_zFailStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + } + } + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_active ); + m_refValue.WriteToString( ref nodeInfo ); + m_readMask.WriteToString( ref nodeInfo ); + m_writeMask.WriteToString( ref nodeInfo ); + m_comparisonFunctionIdx.WriteToString( ref nodeInfo ); + m_passStencilOpIdx.WriteToString( ref nodeInfo ); + m_failStencilOpIdx.WriteToString( ref nodeInfo ); + m_zFailStencilOpIdx.WriteToString( ref nodeInfo ); + m_comparisonFunctionBackIdx.WriteToString( ref nodeInfo ); + m_passStencilOpBackIdx.WriteToString( ref nodeInfo ); + m_failStencilOpBackIdx.WriteToString( ref nodeInfo ); + m_zFailStencilOpBackIdx.WriteToString( ref nodeInfo ); + } + + public bool Active + { + get { return m_active; } + set { m_active = value; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StencilBufferOpHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StencilBufferOpHelper.cs.meta new file mode 100644 index 0000000..6dc5518 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/StencilBufferOpHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0111d524dc809f14aa95e4e1ab93d37b +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TerrainDrawInstancedHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TerrainDrawInstancedHelper.cs new file mode 100644 index 0000000..00713e6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TerrainDrawInstancedHelper.cs @@ -0,0 +1,375 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; + +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TerrainDrawInstancedHelper + { +#if UNITY_2018_1_OR_NEWER + private readonly string[] InstancedPragmas = + { + "multi_compile_instancing", + "instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap forwardadd" + }; + + private readonly string[] InstancedGlobalsSRP = + { + "#ifdef UNITY_INSTANCING_ENABLED//ASE Terrain Instancing", + "\tTEXTURE2D(_TerrainHeightmapTexture);//ASE Terrain Instancing", + "\tTEXTURE2D( _TerrainNormalmapTexture);//ASE Terrain Instancing", + "\tSAMPLER(sampler_TerrainNormalmapTexture);//ASE Terrain Instancing", + "#endif//ASE Terrain Instancing", + "UNITY_INSTANCING_BUFFER_START( Terrain )//ASE Terrain Instancing", + "\tUNITY_DEFINE_INSTANCED_PROP( float4, _TerrainPatchInstanceData )//ASE Terrain Instancing", + "UNITY_INSTANCING_BUFFER_END( Terrain)//ASE Terrain Instancing", + "CBUFFER_START( UnityTerrain)//ASE Terrain Instancing", + "\t#ifdef UNITY_INSTANCING_ENABLED//ASE Terrain Instancing", + "\t\tfloat4 _TerrainHeightmapRecipSize;//ASE Terrain Instancing", + "\t\tfloat4 _TerrainHeightmapScale;//ASE Terrain Instancing", + "\t#endif//ASE Terrain Instancing", + "CBUFFER_END//ASE Terrain Instancing" + }; + + private readonly string[] InstancedGlobalsDefault = + { + "#ifdef UNITY_INSTANCING_ENABLED//ASE Terrain Instancing", + "\tsampler2D _TerrainHeightmapTexture;//ASE Terrain Instancing", + "\tsampler2D _TerrainNormalmapTexture;//ASE Terrain Instancing", + "#endif//ASE Terrain Instancing", + "UNITY_INSTANCING_BUFFER_START( Terrain )//ASE Terrain Instancing", + "\tUNITY_DEFINE_INSTANCED_PROP( float4, _TerrainPatchInstanceData )//ASE Terrain Instancing", + "UNITY_INSTANCING_BUFFER_END( Terrain)//ASE Terrain Instancing", + "CBUFFER_START( UnityTerrain)//ASE Terrain Instancing", + "\t#ifdef UNITY_INSTANCING_ENABLED//ASE Terrain Instancing", + "\t\tfloat4 _TerrainHeightmapRecipSize;//ASE Terrain Instancing", + "\t\tfloat4 _TerrainHeightmapScale;//ASE Terrain Instancing", + "\t#endif//ASE Terrain Instancing", + "CBUFFER_END//ASE Terrain Instancing" + }; + + + private readonly string ApplyMeshModificationInstruction = "{0} = ApplyMeshModification({0});"; + + private readonly string[] ApplyMeshModificationFunctionSRP = + { + /*0 - struct name 1 - var name*/"{0} ApplyMeshModification( {0} {1} )\n", + "{\n", + "#ifdef UNITY_INSTANCING_ENABLED\n", + /* 0 vertex position*/"\tfloat2 patchVertex = {0}.xy;\n", + "\tfloat4 instanceData = UNITY_ACCESS_INSTANCED_PROP( Terrain, _TerrainPatchInstanceData );\n", + "\tfloat2 sampleCoords = ( patchVertex.xy + instanceData.xy ) * instanceData.z;\n", + "\tfloat height = UnpackHeightmap( _TerrainHeightmapTexture.Load( int3( sampleCoords, 0 ) ) );\n", + /*0 - vertex position*/"\t{0}.xz = sampleCoords* _TerrainHeightmapScale.xz;\n", + /*0 - vertex position*/"\t{0}.y = height* _TerrainHeightmapScale.y;\n", + "\t#ifdef ENABLE_TERRAIN_PERPIXEL_NORMAL\n", + /* 0 - vertex normal*/"\t\t{0} = float3(0, 1, 0);\n", + "\t#else\n", + /* 0 - vertex normal*/"\t\t{0} = _TerrainNormalmapTexture.Load(int3(sampleCoords, 0)).rgb* 2 - 1;\n", + "\t#endif\n", + "",//"#ifdef ENABLE_TERRAIN_PERPIXEL_NORMAL\n", + "",///* 0 - tex coord*/"\t{0}.xy = sampleCoords;\n", + "",//"#else\n", + /* 0 - tex coord*/"\t{0}.xy = sampleCoords* _TerrainHeightmapRecipSize.zw;\n", + "",//"#endif\n", + "#endif\n", + /* 0 - var name*/"\treturn {0};\n", + "}\n" + }; + //{ + // /*0 - struct name 1 - var name*/"{0} ApplyMeshModification( {0} {1} )\n", + // "{\n", + // "#ifdef UNITY_INSTANCING_ENABLED\n", + // /* 0 vertex position*/"\tfloat2 patchVertex = {0}.xy;\n", + // "\t\tfloat4 instanceData = UNITY_ACCESS_INSTANCED_PROP( Terrain, _TerrainPatchInstanceData );\n", + // "\t\tfloat2 sampleCoords = ( patchVertex.xy + instanceData.xy ) * instanceData.z;\n", + // "\t\tfloat height = UnpackHeightmap( _TerrainHeightmapTexture.Load( int3( sampleCoords, 0 ) ) );\n", + // /*0 - vertex position*/"\t\t{0}.xz = sampleCoords* _TerrainHeightmapScale.xz;\n", + // /*0 - vertex position*/"\t\t{0}.y = height* _TerrainHeightmapScale.y;\n", + // "# ifdef ATTRIBUTES_NEED_NORMAL\n", + // /* 0 - vertex normal*/"\t\t{0} = _TerrainNormalmapTexture.Load(int3(sampleCoords, 0)).rgb* 2 - 1;\n", + // "\t#endif\n", + // "\t#if defined(VARYINGS_NEED_TEXCOORD0) || defined(VARYINGS_DS_NEED_TEXCOORD0)\n", + // "\t\t#ifdef ENABLE_TERRAIN_PERPIXEL_NORMAL\n", + // /* 0 - tex coord*/"\t\t\t{0} = sampleCoords;\n", + // "\t\t#else\n", + // /* 0 - tex coord*/"\t\t\t{0}.xy = sampleCoords* _TerrainHeightmapRecipSize.zw;\n", + // "\t\t#endif\n", + // "\t#endif\n", + // "#endif\n", + // "#ifdef ATTRIBUTES_NEED_TANGENT\n", + // /* 0 - tangent 1 - normal*/"\t\t{0}.xyz = cross( {1}, float3(0, 0, 1));\n", + // /*0 - tangent*/"\t{0}.w = -1;\n", + // "#endif\n", + // /* 0 - var name*/"\treturn {0};\n", + // "}\n" + //}; + + + + private readonly string[] ApplyMeshModificationFunctionDefaultTemplate = + { + /* 0 vertex struct */"{0} ApplyMeshModification( {0} {1} )", + "{\n", + "#ifdef UNITY_INSTANCING_ENABLED\n", + /*0 - vertex pos*/"\tfloat2 patchVertex = {0}.xy;\n", + "\tfloat4 instanceData = UNITY_ACCESS_INSTANCED_PROP( Terrain, _TerrainPatchInstanceData );\n", + "\tfloat2 sampleCoords = ( patchVertex.xy + instanceData.xy ) * instanceData.z;\n", + /* 0 - tex coords*/"\t{0} = float4( sampleCoords.xy * _TerrainHeightmapRecipSize.z, 0, 0 );\n", + /* 0 - tex coords*/"\tfloat height = UnpackHeightmap( tex2Dlod( _TerrainHeightmapTexture, {0} ) );\n", + /* 0 - vertex pos*/"\t{0}.xz = sampleCoords * _TerrainHeightmapScale.xz;\n", + /* 0 - vertex pos*/"\t{0}.y = height * _TerrainHeightmapScale.y;\n", + /* 0 - normal 1 - tex coord*/"\t{0} = tex2Dlod( _TerrainNormalmapTexture, {1} ).rgb * 2 - 1;\n", + "#endif\n", + /* var name*/"return {0};\n", + "}\n" + }; + + private readonly string ApplyMeshModificationInstructionStandard = "ApplyMeshModification({0});"; + private readonly string[] ApplyMeshModificationFunctionStandard = + { + "void ApplyMeshModification( inout {0} v )", + "#if defined(UNITY_INSTANCING_ENABLED) && !defined(SHADER_API_D3D11_9X)", + "\tfloat2 patchVertex = v.vertex.xy;", + "\tfloat4 instanceData = UNITY_ACCESS_INSTANCED_PROP(Terrain, _TerrainPatchInstanceData);", + "\t", + "\tfloat4 uvscale = instanceData.z * _TerrainHeightmapRecipSize;", + "\tfloat4 uvoffset = instanceData.xyxy * uvscale;", + "\tuvoffset.xy += 0.5f * _TerrainHeightmapRecipSize.xy;", + "\tfloat2 sampleCoords = (patchVertex.xy * uvscale.xy + uvoffset.xy);", + "\t", + "\tfloat hm = UnpackHeightmap(tex2Dlod(_TerrainHeightmapTexture, float4(sampleCoords, 0, 0)));", + "\tv.vertex.xz = (patchVertex.xy + instanceData.xy) * _TerrainHeightmapScale.xz * instanceData.z;", + "\tv.vertex.y = hm * _TerrainHeightmapScale.y;", + "\tv.vertex.w = 1.0f;", + "\t", + "\tv.texcoord.xy = (patchVertex.xy * uvscale.zw + uvoffset.zw);", + "\tv.texcoord3 = v.texcoord2 = v.texcoord1 = v.texcoord;", + "\t", + "\t#ifdef TERRAIN_INSTANCED_PERPIXEL_NORMAL", + "\t\tv.normal = float3(0, 1, 0);", + "\t\t//data.tc.zw = sampleCoords;", + "\t#else", + "\t\tfloat3 nor = tex2Dlod(_TerrainNormalmapTexture, float4(sampleCoords, 0, 0)).xyz;", + "\t\tv.normal = 2.0f * nor - 1.0f;", + "\t#endif", + "#endif", + }; + private readonly string[] AdditionalUsePasses = + { + "Hidden/Nature/Terrain/Utilities/PICKING", + "Hidden/Nature/Terrain/Utilities/SELECTION" + }; + private readonly string DrawInstancedLabel = "Instanced Terrain"; +#endif + [SerializeField] + private bool m_enable = false; + + public void Draw( UndoParentNode owner ) + { +#if UNITY_2018_1_OR_NEWER + m_enable = owner.EditorGUILayoutToggle( DrawInstancedLabel, m_enable ); +#endif + } + + public void UpdateDataCollectorForTemplates( ref MasterNodeDataCollector dataCollector, ref List vertexInstructions ) + { +#if UNITY_2018_1_OR_NEWER + if( m_enable ) + { + for( int i = 0; i < AdditionalUsePasses.Length; i++ ) + { + dataCollector.AddUsePass( AdditionalUsePasses[ i ], false ); + } + + for( int i = 0; i < InstancedPragmas.Length; i++ ) + { + dataCollector.AddToPragmas( -1, InstancedPragmas[ i ] ); + } + + if( dataCollector.IsSRP ) + { + + TemplateFunctionData functionData = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData; + string uvCoord = dataCollector.TemplateDataCollectorInstance.GetUV( 0, MasterNodePortCategory.Vertex ); + string vertexNormal = dataCollector.TemplateDataCollectorInstance.GetVertexNormal( PrecisionType.Float, false, MasterNodePortCategory.Vertex ); + //string vertexTangent = dataCollector.TemplateDataCollectorInstance.GetVertexTangent( WirePortDataType.FLOAT4, PrecisionType.Float, false, MasterNodePortCategory.Vertex ); + string vertexPos = dataCollector.TemplateDataCollectorInstance.GetVertexPosition( WirePortDataType.OBJECT, PrecisionType.Float, false, MasterNodePortCategory.Vertex ); + + string functionHeader = string.Format( ApplyMeshModificationFunctionSRP[ 0 ], functionData.InVarType, functionData.InVarName ); + + //string functionBody = functionHeader + + // ApplyMeshModificationFunctionSRP[ 1 ] + + // ApplyMeshModificationFunctionSRP[ 2 ] + + // string.Format( ApplyMeshModificationFunctionSRP[ 3 ], vertexPos ) + + // ApplyMeshModificationFunctionSRP[ 4 ] + + // ApplyMeshModificationFunctionSRP[ 5 ] + + // ApplyMeshModificationFunctionSRP[ 6 ] + + // string.Format( ApplyMeshModificationFunctionSRP[ 7 ], vertexPos ) + + // string.Format( ApplyMeshModificationFunctionSRP[ 8 ], vertexPos ) + + // ApplyMeshModificationFunctionSRP[ 9 ] + + // string.Format( ApplyMeshModificationFunctionSRP[ 10 ], vertexNormal ) + + // ApplyMeshModificationFunctionSRP[ 11 ] + + // ApplyMeshModificationFunctionSRP[ 12 ] + + // ApplyMeshModificationFunctionSRP[ 13 ] + + // string.Format( ApplyMeshModificationFunctionSRP[ 14 ], uvCoord ) + + // ApplyMeshModificationFunctionSRP[ 15 ] + + // string.Format( ApplyMeshModificationFunctionSRP[ 16 ], uvCoord ) + + // ApplyMeshModificationFunctionSRP[ 17 ] + + // ApplyMeshModificationFunctionSRP[ 18 ] + + // ApplyMeshModificationFunctionSRP[ 19 ] + + // ApplyMeshModificationFunctionSRP[ 20 ] + + // string.Format( ApplyMeshModificationFunctionSRP[ 21 ], vertexTangent, vertexNormal ) + + // string.Format( ApplyMeshModificationFunctionSRP[ 22 ], vertexTangent ) + + // ApplyMeshModificationFunctionSRP[ 23 ] + + // string.Format( ApplyMeshModificationFunctionSRP[ 24 ], functionData.InVarName ) + + // ApplyMeshModificationFunctionSRP[ 25 ]; + string functionBody = functionHeader + + ApplyMeshModificationFunctionSRP[ 1 ] + + ApplyMeshModificationFunctionSRP[ 2 ] + + string.Format( ApplyMeshModificationFunctionSRP[ 3 ], vertexPos ) + + ApplyMeshModificationFunctionSRP[ 4 ] + + ApplyMeshModificationFunctionSRP[ 5 ] + + ApplyMeshModificationFunctionSRP[ 6 ] + + string.Format( ApplyMeshModificationFunctionSRP[ 7 ], vertexPos ) + + string.Format( ApplyMeshModificationFunctionSRP[ 8 ], vertexPos ) + + ApplyMeshModificationFunctionSRP[ 9 ] + + string.Format( ApplyMeshModificationFunctionSRP[ 10 ], vertexNormal ) + + ApplyMeshModificationFunctionSRP[ 11 ] + + string.Format( ApplyMeshModificationFunctionSRP[ 12 ], vertexNormal ) + + ApplyMeshModificationFunctionSRP[ 13 ] + + ApplyMeshModificationFunctionSRP[ 14 ] + + string.Format( ApplyMeshModificationFunctionSRP[ 15 ], uvCoord ) + + ApplyMeshModificationFunctionSRP[ 16 ] + + string.Format( ApplyMeshModificationFunctionSRP[ 17 ], uvCoord ) + + ApplyMeshModificationFunctionSRP[ 18 ] + + ApplyMeshModificationFunctionSRP[ 19 ] + + string.Format( ApplyMeshModificationFunctionSRP[ 20 ], functionData.InVarName ) + + ApplyMeshModificationFunctionSRP[ 21 ]; + dataCollector.AddFunction( functionHeader, functionBody ); + + for( int i = 0; i < InstancedGlobalsSRP.Length; i++ ) + { + dataCollector.AddToUniforms( -1, InstancedGlobalsSRP[ i ] ); + } + + + string vertexVarName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData.InVarName; + vertexInstructions.Insert( 0, string.Format( ApplyMeshModificationInstruction, vertexVarName ) ); + } + else + { + TemplateFunctionData functionData = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData; + + string uvCoord = dataCollector.TemplateDataCollectorInstance.GetUV( 0, MasterNodePortCategory.Vertex ); + string vertexNormal = dataCollector.TemplateDataCollectorInstance.GetVertexNormal( PrecisionType.Float, false, MasterNodePortCategory.Vertex ); + string vertexPos = dataCollector.TemplateDataCollectorInstance.GetVertexPosition( WirePortDataType.OBJECT, PrecisionType.Float, false, MasterNodePortCategory.Vertex ); + + string functionHeader = string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 0 ], functionData.InVarType, functionData.InVarName ); + string functionBody = functionHeader + + ApplyMeshModificationFunctionDefaultTemplate[ 1 ] + + ApplyMeshModificationFunctionDefaultTemplate[ 2 ] + + string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 3 ], vertexPos ) + + ApplyMeshModificationFunctionDefaultTemplate[ 4 ] + + ApplyMeshModificationFunctionDefaultTemplate[ 5 ] + + string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 6 ], uvCoord ) + + string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 7 ], uvCoord ) + + string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 8 ], vertexPos ) + + string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 9 ], vertexPos ) + + string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 10 ], vertexNormal, uvCoord ) + + ApplyMeshModificationFunctionDefaultTemplate[ 11 ] + + string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 12 ], functionData.InVarName ) + + ApplyMeshModificationFunctionDefaultTemplate[ 13 ]; + + + dataCollector.AddFunction( functionHeader, functionBody ); + for( int i = 0; i < InstancedGlobalsDefault.Length; i++ ) + { + dataCollector.AddToUniforms( -1, InstancedGlobalsDefault[ i ] ); + } + + + string vertexVarName = dataCollector.TemplateDataCollectorInstance.CurrentTemplateData.VertexFunctionData.InVarName; + vertexInstructions.Insert( 0, string.Format( ApplyMeshModificationInstruction, vertexVarName ) ); + + } + } +#endif + } + + public void UpdateDataCollectorForStandard( ref MasterNodeDataCollector dataCollector ) + { +#if UNITY_2018_1_OR_NEWER + if( m_enable ) + { + for( int i = 0; i < AdditionalUsePasses.Length; i++ ) + { + dataCollector.AddUsePass( AdditionalUsePasses[ i ], false ); + } + + for( int i = 0; i < InstancedPragmas.Length; i++ ) + { + dataCollector.AddToPragmas( -1, InstancedPragmas[ i ] ); + } + string functionBody = string.Empty; + + string functionHeader = string.Format( ApplyMeshModificationFunctionStandard[ 0 ], dataCollector.SurfaceVertexStructure ); + IOUtils.AddFunctionHeader( ref functionBody, functionHeader ); + for( int i = 1; i < ApplyMeshModificationFunctionStandard.Length; i++ ) + { + IOUtils.AddFunctionLine( ref functionBody, ApplyMeshModificationFunctionStandard[ i ] ); + } + IOUtils.CloseFunctionBody( ref functionBody ); + + //string inputName = "input"; + //string uvCoord = "input.texcoord"; + //string vertexNormal = "input.normal"; + //string vertexPos = "input.vertex"; + + //string functionHeader = string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 0 ], dataCollector.SurfaceVertexStructure, inputName ); + //IOUtils.AddFunctionHeader( ref functionBody, functionHeader ); + //IOUtils.AddFunctionLine( ref functionBody, ApplyMeshModificationFunctionDefaultTemplate[ 1 ] ); + //IOUtils.AddFunctionLine( ref functionBody,ApplyMeshModificationFunctionDefaultTemplate[ 2 ] ); + //IOUtils.AddFunctionLine( ref functionBody,string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 3 ], vertexPos ) ); + //IOUtils.AddFunctionLine( ref functionBody,ApplyMeshModificationFunctionDefaultTemplate[ 4 ] ); + //IOUtils.AddFunctionLine( ref functionBody,ApplyMeshModificationFunctionDefaultTemplate[ 5 ] ); + //IOUtils.AddFunctionLine( ref functionBody,string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 6 ], uvCoord ) ); + //IOUtils.AddFunctionLine( ref functionBody,string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 7 ], uvCoord ) ); + //IOUtils.AddFunctionLine( ref functionBody,string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 8 ], vertexPos ) ); + //IOUtils.AddFunctionLine( ref functionBody,string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 9 ], vertexPos ) ); + //IOUtils.AddFunctionLine( ref functionBody,string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 10 ], vertexNormal, uvCoord ) ); + //IOUtils.AddFunctionLine( ref functionBody,ApplyMeshModificationFunctionDefaultTemplate[ 11 ] ); + //IOUtils.AddFunctionLine( ref functionBody,string.Format( ApplyMeshModificationFunctionDefaultTemplate[ 12 ], inputName ) ); + //IOUtils.AddFunctionLine( ref functionBody, ApplyMeshModificationFunctionDefaultTemplate[ 13 ] ); + //IOUtils.CloseFunctionBody( ref functionBody ); + + dataCollector.AddFunction( functionHeader, functionBody ); + for( int i = 0; i < InstancedGlobalsDefault.Length; i++ ) + { + dataCollector.AddToUniforms( -1, InstancedGlobalsDefault[ i ] ); + } + + dataCollector.AddVertexInstruction( string.Format( ApplyMeshModificationInstructionStandard, "v" ) ); + } +#endif + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + m_enable = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_enable ); + } + + public bool Enabled { get { return m_enable; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TerrainDrawInstancedHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TerrainDrawInstancedHelper.cs.meta new file mode 100644 index 0000000..9580ad0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TerrainDrawInstancedHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 935c69709205e1c4dbd54da410518cc6 +timeCreated: 1548263010 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TessellationOpHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TessellationOpHelper.cs new file mode 100644 index 0000000..11a392b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TessellationOpHelper.cs @@ -0,0 +1,654 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public sealed class TessellationOpHelper + { + public const string TessellationPortStr = "Tessellation"; + + + public const string TessSurfParam = "tessellate:tessFunction"; + public const string TessInclude = "Tessellation.cginc"; + //public const string CustomAppData = "\t\tstruct appdata\n" + + // "\t\t{\n" + + // "\t\t\tfloat4 vertex : POSITION;\n" + + // "\t\t\tfloat4 tangent : TANGENT;\n" + + // "\t\t\tfloat3 normal : NORMAL;\n" + + // "\t\t\tfloat4 texcoord : TEXCOORD0;\n" + + // "\t\t\tfloat4 texcoord1 : TEXCOORD1;\n" + + // "\t\t\tfloat4 texcoord2 : TEXCOORD2;\n" + + // "\t\t\tfloat4 texcoord3 : TEXCOORD3;\n" + + // "\t\t\tfixed4 color : COLOR;\n" + + // "\t\t\tUNITY_VERTEX_INPUT_INSTANCE_ID\n" + + // "\t\t};\n\n"; + + + + private const string TessUniformName = "_TessValue"; + private const string TessMinUniformName = "_TessMin"; + private const string TessMaxUniformName = "_TessMax"; + + //private GUIContent EnableTessContent = new GUIContent( "Tessellation", "Activates the use of tessellation which subdivides polygons to increase geometry detail using a set of rules\nDefault: OFF" ); + private GUIContent TessFactorContent = new GUIContent( "Tess", "Tessellation factor\nDefault: 4" ); + private GUIContent TessMinDistanceContent = new GUIContent( "Min", "Minimum tessellation distance\nDefault: 10" ); + private GUIContent TessMaxDistanceContent = new GUIContent( "Max", "Maximum tessellation distance\nDefault: 25" ); + + + private readonly int[] TesselationTypeValues = { 0, 1, 2, 3 }; + private readonly string[] TesselationTypeLabels = { "Distance-based", "Fixed", "Edge Length", "Edge Length Cull" }; + private readonly string TesselationTypeStr = "Type"; + + private const string TessProperty = "_TessValue( \"Max Tessellation\", Range( 1, 32 ) ) = {0}"; + private const string TessMinProperty = "_TessMin( \"Tess Min Distance\", Float ) = {0}"; + private const string TessMaxProperty = "_TessMax( \"Tess Max Distance\", Float ) = {0}"; + + private const string TessFunctionOpen = "\t\tfloat4 tessFunction( {0} v0, {0} v1, {0} v2 )\n\t\t{{\n"; + private const string TessFunctionClose = "\t\t}\n"; + + // Custom function + private const string CustomFunctionBody = "\t\t\treturn {0};\n"; + + // Distance based function + private const string DistBasedTessFunctionBody = "\t\t\treturn UnityDistanceBasedTess( v0.vertex, v1.vertex, v2.vertex, _TessMin, _TessMax, _TessValue );\n"; + + // Fixed amount function + private const string FixedAmountTessFunctionOpen = "\t\tfloat4 tessFunction( )\n\t\t{\n"; + private const string FixedAmountTessFunctionBody = "\t\t\treturn _TessValue;\n"; + + // Edge Length + private GUIContent EdgeLengthContent = new GUIContent( "Edge Length", "Tessellation levels ccomputed based on triangle edge length on the screen\nDefault: 4" ); + private const string EdgeLengthTessProperty = "_EdgeLength ( \"Edge length\", Range( 2, 50 ) ) = {0}"; + private const string EdgeLengthTessUniformName = "_EdgeLength"; + + private const string EdgeLengthTessFunctionBody = "\t\t\treturn UnityEdgeLengthBasedTess (v0.vertex, v1.vertex, v2.vertex, _EdgeLength);\n"; + private const string EdgeLengthTessCullFunctionBody = "\t\t\treturn UnityEdgeLengthBasedTessCull (v0.vertex, v1.vertex, v2.vertex, _EdgeLength , _TessMaxDisp );\n"; + + + private const string EdgeLengthTessMaxDispProperty = "_TessMaxDisp( \"Max Displacement\", Float ) = {0}"; + private const string EdgeLengthTessMaxDispUniformName = "_TessMaxDisp"; + private GUIContent EdgeLengthTessMaxDisplacementContent = new GUIContent( "Max Disp.", "Max Displacement" ); + + // Phong + private GUIContent PhongEnableContent = new GUIContent( "Phong", "Modifies positions of the subdivided faces so that the resulting surface follows the mesh normals a bit\nDefault: OFF" ); + private GUIContent PhongStrengthContent = new GUIContent( "Strength", "Strength\nDefault: 0.5" ); + public const string PhongStrengthParam = "tessphong:_TessPhongStrength"; + + private const string PhongStrengthProperty = "_TessPhongStrength( \"Phong Tess Strength\", Range( 0, 1 ) ) = {0}"; + private const string PhongStrengthUniformName = "_TessPhongStrength"; + + [SerializeField] + private bool m_enabled = false; + + //private bool m_expanded = false; + + [SerializeField] + private int m_tessType = 2; + + [SerializeField] + private float m_tessMinDistance = 10f; + + [SerializeField] + private float m_tessMaxDistance = 25f; + + [SerializeField] + private float m_tessFactor = 15f; + + [SerializeField] + private float m_phongStrength = 0.5f; + + [SerializeField] + private bool m_phongEnabled = false; + + [SerializeField] + private string[] m_customData = { string.Empty, string.Empty, string.Empty }; + + [SerializeField] + private bool m_hasCustomFunction = false; + + [SerializeField] + private string m_customFunction = String.Empty; + + [SerializeField] + private string m_additionalData = string.Empty; + + [SerializeField] + private StandardSurfaceOutputNode m_parentSurface; + + private Dictionary m_additionalDataDict = new Dictionary(); + + private int m_masterNodeIndexPort = 0; + private int m_vertexOffsetIndexPort = 0; + //private int m_orderIndex = 1000; + + public void Draw( UndoParentNode owner, GUIStyle toolbarstyle, Material mat, bool connectedInput ) + { + Color cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f ); + EditorGUILayout.BeginHorizontal( toolbarstyle ); + GUI.color = cachedColor; + EditorGUI.BeginChangeCheck(); + m_parentSurface.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedTesselation = GUILayout.Toggle( m_parentSurface.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedTesselation, " Tessellation", UIUtils.MenuItemToggleStyle, GUILayout.ExpandWidth( true ) ); + if ( EditorGUI.EndChangeCheck() ) + { + EditorPrefs.SetBool( "ExpandedTesselation", m_parentSurface.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedTesselation ); + } + + EditorGUI.BeginChangeCheck(); + m_enabled = owner.EditorGUILayoutToggle( string.Empty, m_enabled, UIUtils.MenuItemEnableStyle, GUILayout.Width( 16 ) ); + if ( EditorGUI.EndChangeCheck() ) + { + if ( m_enabled ) + UpdateToMaterial( mat, !connectedInput ); + + UIUtils.RequestSave(); + } + + EditorGUILayout.EndHorizontal(); + + m_enabled = m_enabled || connectedInput; + + if ( m_parentSurface.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedTesselation ) + { + cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) ); + EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + GUI.color = cachedColor; + + EditorGUILayout.Separator(); + EditorGUI.BeginDisabledGroup( !m_enabled ); + + EditorGUI.indentLevel += 1; + + m_phongEnabled = owner.EditorGUILayoutToggle( PhongEnableContent, m_phongEnabled ); + if ( m_phongEnabled ) + { + EditorGUI.indentLevel += 1; + EditorGUI.BeginChangeCheck(); + m_phongStrength = owner.EditorGUILayoutSlider( PhongStrengthContent, m_phongStrength, 0.0f, 1.0f ); + if ( EditorGUI.EndChangeCheck() && mat != null ) + { + if ( mat.HasProperty( PhongStrengthUniformName ) ) + mat.SetFloat( PhongStrengthUniformName, m_phongStrength ); + } + + EditorGUI.indentLevel -= 1; + } + + bool guiEnabled = GUI.enabled; + GUI.enabled = !connectedInput && m_enabled; + + m_tessType = owner.EditorGUILayoutIntPopup( TesselationTypeStr, m_tessType, TesselationTypeLabels, TesselationTypeValues ); + + switch ( m_tessType ) + { + case 0: + { + EditorGUI.BeginChangeCheck(); + m_tessFactor = owner.EditorGUILayoutSlider( TessFactorContent, m_tessFactor, 1, 32 ); + if ( EditorGUI.EndChangeCheck() && mat != null ) + { + if ( mat.HasProperty( TessUniformName ) ) + mat.SetFloat( TessUniformName, m_tessFactor ); + } + + EditorGUI.BeginChangeCheck(); + m_tessMinDistance = owner.EditorGUILayoutFloatField( TessMinDistanceContent, m_tessMinDistance ); + if ( EditorGUI.EndChangeCheck() && mat != null ) + { + if ( mat.HasProperty( TessMinUniformName ) ) + mat.SetFloat( TessMinUniformName, m_tessMinDistance ); + } + + EditorGUI.BeginChangeCheck(); + m_tessMaxDistance = owner.EditorGUILayoutFloatField( TessMaxDistanceContent, m_tessMaxDistance ); + if ( EditorGUI.EndChangeCheck() && mat != null ) + { + if ( mat.HasProperty( TessMaxUniformName ) ) + mat.SetFloat( TessMaxUniformName, m_tessMaxDistance ); + } + } + break; + case 1: + { + EditorGUI.BeginChangeCheck(); + m_tessFactor = owner.EditorGUILayoutSlider( TessFactorContent, m_tessFactor, 1, 32 ); + if ( EditorGUI.EndChangeCheck() && mat != null ) + { + if ( mat.HasProperty( TessUniformName ) ) + mat.SetFloat( TessUniformName, m_tessFactor ); + } + } + break; + case 2: + { + EditorGUI.BeginChangeCheck(); + m_tessFactor = owner.EditorGUILayoutSlider( EdgeLengthContent, m_tessFactor, 2, 50 ); + if ( EditorGUI.EndChangeCheck() && mat != null ) + { + if ( mat.HasProperty( EdgeLengthTessUniformName ) ) + mat.SetFloat( EdgeLengthTessUniformName, m_tessFactor ); + } + } + break; + case 3: + { + EditorGUI.BeginChangeCheck(); + m_tessFactor = owner.EditorGUILayoutSlider( EdgeLengthContent, m_tessFactor, 2, 50 ); + if ( EditorGUI.EndChangeCheck() && mat != null ) + { + if ( mat.HasProperty( EdgeLengthTessUniformName ) ) + mat.SetFloat( EdgeLengthTessUniformName, m_tessFactor ); + } + + EditorGUI.BeginChangeCheck(); + m_tessMaxDistance = owner.EditorGUILayoutFloatField( EdgeLengthTessMaxDisplacementContent, m_tessMaxDistance ); + if ( EditorGUI.EndChangeCheck() && mat != null ) + { + if ( mat.HasProperty( TessMinUniformName ) ) + mat.SetFloat( TessMinUniformName, m_tessMaxDistance ); + } + } + break; + } + GUI.enabled = guiEnabled; + EditorGUI.indentLevel -= 1; + EditorGUI.EndDisabledGroup(); + EditorGUILayout.Separator(); + EditorGUILayout.EndVertical(); + } + } + + public void UpdateToMaterial( Material mat, bool updateInternals ) + { + if ( mat == null ) + return; + + if ( m_phongEnabled ) + { + if ( mat.HasProperty( PhongStrengthUniformName ) ) + mat.SetFloat( PhongStrengthUniformName, m_phongStrength ); + } + + if ( updateInternals ) + { + switch ( m_tessType ) + { + case 0: + { + if ( mat.HasProperty( TessUniformName ) ) + mat.SetFloat( TessUniformName, m_tessFactor ); + + if ( mat.HasProperty( TessMinUniformName ) ) + mat.SetFloat( TessMinUniformName, m_tessMinDistance ); + + if ( mat.HasProperty( TessMaxUniformName ) ) + mat.SetFloat( TessMaxUniformName, m_tessMaxDistance ); + } + break; + case 1: + { + if ( mat.HasProperty( TessUniformName ) ) + mat.SetFloat( TessUniformName, m_tessFactor ); + } + break; + case 2: + { + + if ( mat.HasProperty( EdgeLengthTessUniformName ) ) + mat.SetFloat( EdgeLengthTessUniformName, m_tessFactor ); + } + break; + case 3: + { + if ( mat.HasProperty( EdgeLengthTessUniformName ) ) + mat.SetFloat( EdgeLengthTessUniformName, m_tessFactor ); + + if ( mat.HasProperty( TessMinUniformName ) ) + mat.SetFloat( TessMinUniformName, m_tessMaxDistance ); + } + break; + } + } + } + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + m_enabled = Convert.ToBoolean( nodeParams[ index++ ] ); + m_tessType = Convert.ToInt32( nodeParams[ index++ ] ); + m_tessFactor = Convert.ToSingle( nodeParams[ index++ ] ); + m_tessMinDistance = Convert.ToSingle( nodeParams[ index++ ] ); + m_tessMaxDistance = Convert.ToSingle( nodeParams[ index++ ] ); + if ( UIUtils.CurrentShaderVersion() > 3001 ) + { + m_phongEnabled = Convert.ToBoolean( nodeParams[ index++ ] ); + m_phongStrength = Convert.ToSingle( nodeParams[ index++ ] ); + } + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_enabled ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_tessType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_tessFactor ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_tessMinDistance ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_tessMaxDistance ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_phongEnabled ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_phongStrength ); + } + + public string Uniforms() + { + string uniforms = string.Empty; + switch( m_tessType ) + { + case 0: + { + if( !m_hasCustomFunction ) + { + + //Tess + uniforms += "\t\tuniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + TessUniformName + ";\n"; + + //Min + uniforms += "\t\tuniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + TessMinUniformName + ";\n"; + + //Max + uniforms += "\t\tuniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + TessMaxUniformName + ";\n"; + } + } + break; + case 1: + //Tess + if( !m_hasCustomFunction ) + { + uniforms += "\t\tuniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + TessUniformName + ";\n"; + } + break; + case 2: + if( !m_hasCustomFunction ) + { + uniforms += "\t\tuniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float , WirePortDataType.FLOAT ) + " " + EdgeLengthTessUniformName + ";\n"; + } + break; + case 3: + if( !m_hasCustomFunction ) + { + uniforms += "\t\tuniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float , WirePortDataType.FLOAT ) + " " + EdgeLengthTessUniformName + ";\n"; + uniforms += "\t\tuniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float , WirePortDataType.FLOAT ) + " " + EdgeLengthTessMaxDispUniformName + ";\n"; + } + break; + } + + if( m_phongEnabled ) + { + uniforms += "\t\tuniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + PhongStrengthUniformName + ";\n" ; + } + + return uniforms; + } + + public void AddToDataCollector( ref MasterNodeDataCollector dataCollector, int reorder ) + { + int orderIndex = reorder; + switch ( m_tessType ) + { + case 0: + { + dataCollector.AddToIncludes( -1, TessellationOpHelper.TessInclude ); + if ( !m_hasCustomFunction ) + { + //Tess + dataCollector.AddToProperties( -1, string.Format( TessProperty, m_tessFactor ), orderIndex++ ); + dataCollector.AddToUniforms( -1, "uniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + TessUniformName + ";" ); + + //Min + dataCollector.AddToProperties( -1, string.Format( TessMinProperty, m_tessMinDistance ), orderIndex++ ); + dataCollector.AddToUniforms( -1, "uniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + TessMinUniformName + ";" ); + + //Max + dataCollector.AddToProperties( -1, string.Format( TessMaxProperty, m_tessMaxDistance ), orderIndex++ ); + dataCollector.AddToUniforms( -1, "uniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + TessMaxUniformName + ";" ); + } + } + break; + case 1: + { + //Tess + if ( !m_hasCustomFunction ) + { + dataCollector.AddToProperties( -1, string.Format( TessProperty, m_tessFactor ), orderIndex++ ); + dataCollector.AddToUniforms( -1, "uniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + TessUniformName + ";" ); + } + } + break; + case 2: + { + dataCollector.AddToIncludes( -1, TessellationOpHelper.TessInclude ); + + //Tess + if ( !m_hasCustomFunction ) + { + dataCollector.AddToProperties( -1, string.Format( EdgeLengthTessProperty, m_tessFactor ), orderIndex++ ); + dataCollector.AddToUniforms( -1, "uniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + EdgeLengthTessUniformName + ";" ); + } + } + break; + case 3: + { + dataCollector.AddToIncludes( -1, TessellationOpHelper.TessInclude ); + + if ( !m_hasCustomFunction ) + { + //Tess + dataCollector.AddToProperties( -1, string.Format( EdgeLengthTessProperty, m_tessFactor ), orderIndex++ ); + dataCollector.AddToUniforms( -1, "uniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + EdgeLengthTessUniformName + ";" ); + + //Max Displacement + dataCollector.AddToProperties( -1, string.Format( EdgeLengthTessMaxDispProperty, m_tessMaxDistance ), orderIndex++ ); + dataCollector.AddToUniforms( -1, "uniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + EdgeLengthTessMaxDispUniformName + ";" ); + } + } + break; + } + + if ( m_phongEnabled ) + { + dataCollector.AddToProperties( -1, string.Format( PhongStrengthProperty, m_phongStrength ), orderIndex++ ); + dataCollector.AddToUniforms( -1, "uniform " + UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT ) + " " + PhongStrengthUniformName + ";" ); + } + } + + //ToDo: Optimize material property fetches to use Id instead of string + public void UpdateFromMaterial( Material mat ) + { + if ( m_enabled ) + { + if ( m_phongEnabled ) + { + if ( mat.HasProperty( PhongStrengthUniformName ) ) + m_phongStrength = mat.GetFloat( PhongStrengthUniformName ); + } + + switch ( m_tessType ) + { + case 0: + { + if ( mat.HasProperty( TessUniformName ) ) + m_tessFactor = mat.GetFloat( TessUniformName ); + + if ( mat.HasProperty( TessMinUniformName ) ) + m_tessMinDistance = mat.GetFloat( TessMinUniformName ); + + if ( mat.HasProperty( TessMaxUniformName ) ) + m_tessMaxDistance = mat.GetFloat( TessMaxUniformName ); + } + break; + case 1: + { + if ( mat.HasProperty( TessUniformName ) ) + m_tessFactor = mat.GetFloat( TessUniformName ); + } + break; + case 2: + { + if ( mat.HasProperty( EdgeLengthTessUniformName ) ) + m_tessFactor = mat.GetFloat( EdgeLengthTessUniformName ); + } + break; + case 3: + { + if ( mat.HasProperty( EdgeLengthTessUniformName ) ) + m_tessFactor = mat.GetFloat( EdgeLengthTessUniformName ); + + if ( mat.HasProperty( EdgeLengthTessMaxDispUniformName ) ) + m_tessMaxDistance = mat.GetFloat( EdgeLengthTessMaxDispUniformName ); + } + break; + } + } + } + + public void WriteToOptionalParams( ref string optionalParams ) + { + optionalParams += TessellationOpHelper.TessSurfParam + Constants.OptionalParametersSep; + if ( m_phongEnabled ) + { + optionalParams += TessellationOpHelper.PhongStrengthParam + Constants.OptionalParametersSep; + } + } + + public void Reset() + { + m_hasCustomFunction = false; + m_customFunction = string.Empty; + + m_additionalData = string.Empty; + m_additionalDataDict.Clear(); + switch ( m_tessType ) + { + case 0: + { + m_customData[ 0 ] = TessUniformName; + m_customData[ 1 ] = TessMinUniformName; + m_customData[ 2 ] = TessMaxUniformName; + } + break; + case 1: + { + m_customData[ 0 ] = TessUniformName; + m_customData[ 1 ] = string.Empty; + m_customData[ 2 ] = string.Empty; + } + break; + case 2: + { + m_customData[ 0 ] = EdgeLengthTessUniformName; + m_customData[ 1 ] = string.Empty; + m_customData[ 2 ] = string.Empty; + } + break; + case 3: + { + m_customData[ 0 ] = EdgeLengthTessUniformName; + m_customData[ 1 ] = EdgeLengthTessMaxDispUniformName; + m_customData[ 2 ] = string.Empty; + } + break; + } + } + + public string GetCurrentTessellationFunction( ref MasterNodeDataCollector dataCollector ) + { + string finalTessFunctionOpen = string.Format( TessFunctionOpen , dataCollector.SurfaceVertexStructure ); + + if ( m_hasCustomFunction ) + { + return finalTessFunctionOpen + + m_customFunction + + TessFunctionClose; + } + + string tessFunction = string.Empty; + switch ( m_tessType ) + { + case 0: + { + tessFunction = finalTessFunctionOpen + + DistBasedTessFunctionBody + + TessFunctionClose; + } + break; + case 1: + { + tessFunction = FixedAmountTessFunctionOpen + + FixedAmountTessFunctionBody + + TessFunctionClose; + } + break; + case 2: + { + tessFunction = finalTessFunctionOpen + + EdgeLengthTessFunctionBody + + TessFunctionClose; + } + break; + case 3: + { + tessFunction = finalTessFunctionOpen + + EdgeLengthTessCullFunctionBody + + TessFunctionClose; + } + break; + } + return tessFunction; + } + + public void AddAdditionalData( string data ) + { + if ( !m_additionalDataDict.ContainsKey( data ) ) + { + m_additionalDataDict.Add( data, true ); + m_additionalData += data; + } + } + + public void AddCustomFunction( string returnData ) + { + m_hasCustomFunction = true; + m_customFunction = m_additionalData + string.Format( CustomFunctionBody, returnData ); + } + + public void Destroy() + { + m_additionalDataDict.Clear(); + m_additionalDataDict = null; + } + + public bool IsTessellationPort( int index ) + { + return index == m_masterNodeIndexPort; + } + + public bool EnableTesselation { get { return m_enabled; } } + + public int TessType { get { return m_tessType; } } + public int MasterNodeIndexPort + { + get { return m_masterNodeIndexPort; } + set { m_masterNodeIndexPort = value; } + } + public int VertexOffsetIndexPort + { + get { return m_vertexOffsetIndexPort; } + set { m_vertexOffsetIndexPort = value; } + } + + public StandardSurfaceOutputNode ParentSurface { get { return m_parentSurface; } set { m_parentSurface = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TessellationOpHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TessellationOpHelper.cs.meta new file mode 100644 index 0000000..c4400a8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/TessellationOpHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c6fbad94b0fc6b948be3a3dc61232c05 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/UsePassHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/UsePassHelper.cs new file mode 100644 index 0000000..d6e34ad --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/UsePassHelper.cs @@ -0,0 +1,360 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using UnityEditorInternal; + +namespace AmplifyShaderEditor +{ + public enum UsePassLocation + { + Above, + Below + } + + [Serializable] + public class UsePassItem : ScriptableObject + { + public UsePassLocation Location; + public string Value; + public UsePassItem() + { + Location = UsePassLocation.Above; + Value = string.Empty; + } + + public UsePassItem( UsePassLocation location, string name ) + { + Location = location; + Value = name; + } + + } + + [Serializable] + public class UsePassHelper : ScriptableObject + { + private const string UseGrabFormatNewLine = "UsePass \"{0}\"\n"; + private const string UseGrabFormat = "UsePass \"{0}\""; + private const float ShaderKeywordButtonLayoutWidth = 15; + private const string ShaderPoputContext = "CONTEXT/ShaderPopup"; + + [SerializeField] + private List m_items = new List(); + + [SerializeField] + private UndoParentNode m_owner = null; + + [SerializeField] + protected bool m_isDirty = false; + + [SerializeField] + protected string m_moduleName = string.Empty; + + private ReorderableList m_reordableList = null; + private ReordableAction m_actionType = ReordableAction.None; + private int m_actionIndex = 0; + private GUIStyle m_propertyAdjustment; + + private Material m_dummyMaterial; + private MenuCommand m_dummyCommand; + private int m_currentUsePassIdx = 0; + + public void Init( string moduleName ) + { + hideFlags = HideFlags.HideAndDontSave; + m_moduleName = moduleName; + } + + void DrawButtons() + { + EditorGUILayout.Separator(); + + // Add keyword + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + UsePassItem newItem = ScriptableObject.CreateInstance(); + newItem.hideFlags = HideFlags.HideAndDontSave; + m_items.Add( newItem ); + EditorGUI.FocusTextInControl( null ); + m_isDirty = true; + } + + //Remove keyword + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + if( m_items.Count > 0 ) + { + UsePassItem itemToDelete = m_items[ m_items.Count - 1 ]; + m_items.RemoveAt( m_items.Count - 1 ); + ScriptableObject.DestroyImmediate( itemToDelete ); + EditorGUI.FocusTextInControl( null ); + } + m_isDirty = true; + } + } + + public void Draw( UndoParentNode owner, bool style = true ) + { + if( m_owner == null ) + m_owner = owner; + + if( m_reordableList == null ) + { + m_reordableList = new ReorderableList( m_items, typeof( UsePassItem ), true, false, false, false ) + { + headerHeight = 0, + footerHeight = 0, + showDefaultBackground = false, + drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) => + { + if( m_items[ index ] != null ) + { + float labelWidthMultiplier; + float popUpWidth; + float shaderSelectorMultiplier; + float buttonPlusPosMultiplier; + if( style ) + { + rect.x -= 10; + labelWidthMultiplier = 0.9f; + popUpWidth = 0.31f; + shaderSelectorMultiplier = 1.01f; + buttonPlusPosMultiplier = 0.78f; + } + else + { + rect.x -= 1; + labelWidthMultiplier = 1.01f; + popUpWidth = 0.25f; + shaderSelectorMultiplier = 1.0f; + buttonPlusPosMultiplier = 0.55f; + } + + Rect popupPos = new Rect( rect.x, rect.y + 2, popUpWidth * rect.width, rect.height ); + Rect labelPos = new Rect( rect.x + popupPos.width * labelWidthMultiplier, rect.y, 0.59f * rect.width, rect.height ); + + Rect shaderSelectorPos = new Rect( labelPos.x + labelPos.width* shaderSelectorMultiplier, rect.y, 15, rect.height ); + + Rect buttonPlusPos = new Rect( shaderSelectorPos.x + shaderSelectorPos.width * buttonPlusPosMultiplier, rect.y, ShaderKeywordButtonLayoutWidth, rect.height ); + Rect buttonMinusPos = new Rect( buttonPlusPos.x + buttonPlusPos.width, rect.y, ShaderKeywordButtonLayoutWidth, rect.height ); + + EditorGUI.BeginChangeCheck(); + m_items[ index ].Location = (UsePassLocation)owner.EditorGUIEnumPopup( popupPos, m_items[ index ].Location ); + + if( EditorGUI.EndChangeCheck() && m_items[ index ].Location == UsePassLocation.Below && m_owner != null && m_owner.ContainerGraph.CurrentCanvasMode == NodeAvailability.TemplateShader ) + { + m_items[ index ].Location = UsePassLocation.Above; + UIUtils.ShowMessage( "Below option still not available on templates" ); + } + m_items[ index ].Value = owner.EditorGUITextField( labelPos, string.Empty, m_items[ index ].Value ); + + if( GUI.Button( shaderSelectorPos, string.Empty, UIUtils.InspectorPopdropdownFallback ) ) + { + EditorGUI.FocusTextInControl( null ); + GUI.FocusControl( null ); + m_currentUsePassIdx = index; + DisplayShaderContext( owner, GUILayoutUtility.GetRect( GUIContent.none, EditorStyles.popup ) ); + } + + if( GUI.Button( buttonPlusPos, string.Empty, UIUtils.PlusStyle ) ) + { + m_actionType = ReordableAction.Add; + m_actionIndex = index; + } + + if( GUI.Button( buttonMinusPos, string.Empty, UIUtils.MinusStyle ) ) + { + m_actionType = ReordableAction.Remove; + m_actionIndex = index; + } + } + } + }; + } + + if( m_actionType != ReordableAction.None ) + { + switch( m_actionType ) + { + case ReordableAction.Add: + UsePassItem newItem = ScriptableObject.CreateInstance(); + newItem.hideFlags = HideFlags.HideAndDontSave; + m_items.Insert( m_actionIndex + 1, newItem ); + break; + case ReordableAction.Remove: + UsePassItem itemToDelete = m_items[ m_actionIndex ]; + m_items.RemoveAt( m_actionIndex ); + ScriptableObject.DestroyImmediate( itemToDelete ); + break; + } + m_isDirty = true; + m_actionType = ReordableAction.None; + EditorGUI.FocusTextInControl( null ); + } + bool foldoutValue = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedUsePass; + if( style ) + { + NodeUtils.DrawPropertyGroup( ref foldoutValue, m_moduleName, DrawReordableList, DrawButtons ); + } + else + { + NodeUtils.DrawNestedPropertyGroup( ref foldoutValue, m_moduleName, DrawReordableList, DrawButtons ); + } + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedUsePass = foldoutValue; + } + + private void DisplayShaderContext( UndoParentNode node, Rect r ) + { + if( m_dummyCommand == null ) + m_dummyCommand = new MenuCommand( this, 0 ); + + if( m_dummyMaterial == null ) + m_dummyMaterial = new Material( Shader.Find( "Hidden/ASESShaderSelectorUnlit" ) ); + +#pragma warning disable 0618 + UnityEditorInternal.InternalEditorUtility.SetupShaderMenu( m_dummyMaterial ); +#pragma warning restore 0618 + EditorUtility.DisplayPopupMenu( r, ShaderPoputContext, m_dummyCommand ); + } + + private void OnSelectedShaderPopup( string command, Shader shader ) + { + if( shader != null ) + { + UIUtils.MarkUndoAction(); + Undo.RecordObject( m_owner, "Selected Use Pass shader" ); + m_items[ m_currentUsePassIdx ].Value = shader.name; + } + } + + void DrawReordableList() + { + if( m_reordableList != null ) + { + if( m_propertyAdjustment == null ) + { + m_propertyAdjustment = new GUIStyle(); + m_propertyAdjustment.padding.left = 17; + } + EditorGUILayout.Space(); + + if( m_items.Count == 0 ) + { + EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one.", MessageType.Info ); + } + else + { + m_reordableList.DoLayoutList(); + } + EditorGUILayout.Space(); + } + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + try + { + int count = Convert.ToInt32( nodeParams[ index++ ] ); + for( int i = 0; i < count; i++ ) + { + string locationValue = nodeParams[ index++ ]; + // REMOVE THIS TEST AFTER A COUPLE OF VERSIONS (curr v1.5.6 r02) + if( locationValue.Equals( "Bellow" ) ) locationValue = "Below"; + + UsePassLocation location = (UsePassLocation)Enum.Parse( typeof( UsePassLocation ), locationValue ); + string name = nodeParams[ index++ ]; + UsePassItem newItem = ScriptableObject.CreateInstance(); + newItem.hideFlags = HideFlags.HideAndDontSave; + newItem.Location = location; + newItem.Value = name; + m_items.Add( newItem ); + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_items.Count ); + for( int i = 0; i < m_items.Count; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_items[ i ].Location ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_items[ i ].Value ); + } + } + + public void BuildUsePassInfo( MasterNodeDataCollector dataCollector, ref string aboveItems, ref string bellowItems, string tabs) + { + int count = 0; + count = dataCollector.AboveUsePassesList.Count; + for( int i = 0; i < count; i++ ) + { + aboveItems += tabs + string.Format( UseGrabFormatNewLine, dataCollector.AboveUsePassesList[ i ].PropertyName ); + } + + count = dataCollector.BelowUsePassesList.Count; + for( int i = 0; i < count; i++ ) + { + bellowItems += tabs + string.Format( UseGrabFormatNewLine, dataCollector.BelowUsePassesList[ i ].PropertyName ); + } + + count = m_items.Count; + for( int i = 0; i < count; i++ ) + { + if( m_items[ i ].Location == UsePassLocation.Above ) + { + aboveItems += tabs + string.Format( UseGrabFormatNewLine, m_items[ i ].Value ); + } + else + { + bellowItems += tabs + string.Format( UseGrabFormatNewLine, m_items[ i ].Value ); + } + } + } + + public void BuildUsePassInfo( MasterNodeDataCollector dataCollector, ref List aboveItems, ref List bellowItems ) + { + int count = 0; + count = dataCollector.AboveUsePassesList.Count; + for( int i = 0; i < count; i++ ) + { + aboveItems.Add( new PropertyDataCollector( -1, string.Format( UseGrabFormat, dataCollector.AboveUsePassesList[ i ].PropertyName ) ) ); + } + + count = dataCollector.BelowUsePassesList.Count; + for( int i = 0; i < count; i++ ) + { + bellowItems.Add( new PropertyDataCollector( -1, string.Format( UseGrabFormat, dataCollector.BelowUsePassesList[ i ].PropertyName ) ) ); + } + + + count = m_items.Count; + for( int i = 0; i < count; i++ ) + { + if( m_items[ i ].Location == UsePassLocation.Above ) + { + aboveItems.Add( new PropertyDataCollector(-1,string.Format( UseGrabFormat, m_items[ i ].Value ))); + } + else + { + bellowItems.Add( new PropertyDataCollector( -1, string.Format( UseGrabFormat, m_items[ i ].Value ) ) ); + } + } + } + + //public string ModuleName { set { m_moduleName = value; } } + public void Destroy() + { + m_owner = null; + m_items.Clear(); + m_items = null; + m_reordableList = null; + m_dummyMaterial = null; + m_dummyCommand = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/UsePassHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/UsePassHelper.cs.meta new file mode 100644 index 0000000..ddf906c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/UsePassHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d818a147712609646b8d6f0f7c2ae731 +timeCreated: 1530179906 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ZBufferOpHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ZBufferOpHelper.cs new file mode 100644 index 0000000..73d3599 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ZBufferOpHelper.cs @@ -0,0 +1,272 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public enum ZWriteMode + { + On, + Off + } + + public enum ZTestMode + { + Less, + Greater, + LEqual, + GEqual, + Equal, + NotEqual, + Always + } + + [Serializable] + class ZBufferOpHelper + { + public static readonly string DepthParametersStr = " Depth"; + public static readonly string ZWriteModeStr = "ZWrite Mode"; + public static readonly string ZTestModeStr = "ZTest Mode"; + public static readonly string OffsetStr = "Offset"; + public static readonly string OffsetFactorStr = "Factor"; + public static readonly string OffsetUnitsStr = "Units"; + private const string ExtraDepthPassStr = "Extra Depth Pass"; + private const string DepthZTestStr = "Depth ZTest"; + + public static readonly string[] ZTestModeLabels = + { + "", + "Less", + "Greater", + "Less or Equal", + "Greater or Equal", + "Equal", + "Not Equal", + "Always" + }; + + public static readonly string[] ZTestModeValues = + { + "", + "Less", + "Greater", + "LEqual", + "GEqual", + "Equal", + "NotEqual", + "Always" + }; + + public static readonly string[] ZWriteModeValues = + { + "", + "On", + "Off" + }; + + public static readonly Dictionary ZTestModeDict = new Dictionary + { + {ZTestMode.Less,1 }, + {ZTestMode.Greater,2}, + {ZTestMode.LEqual,3}, + {ZTestMode.GEqual,4}, + {ZTestMode.Equal,5}, + {ZTestMode.NotEqual,6}, + {ZTestMode.Always,7} + }; + + public static readonly Dictionary ZWriteModeDict = new Dictionary + { + { ZWriteMode.On,1}, + { ZWriteMode.Off,2} + }; + + + [SerializeField] + private InlineProperty m_zTestMode = new InlineProperty(); + + [SerializeField] + private InlineProperty m_zWriteMode = new InlineProperty(); + [SerializeField] + private InlineProperty m_offsetFactor = new InlineProperty(); + + [SerializeField] + private InlineProperty m_offsetUnits = new InlineProperty(); + + [SerializeField] + private bool m_offsetEnabled; + + [SerializeField] + private bool m_extraDepthPass; + + [SerializeField] + private int m_extrazTestMode = 0; + + [SerializeField] + private StandardSurfaceOutputNode m_parentSurface; + + public string CreateDepthInfo( bool outlineZWrite, bool outlineZTest ) + { + string result = string.Empty; + if( m_zWriteMode.IntValue != 0 || m_zWriteMode.Active ) + { + MasterNode.AddRenderState( ref result, "ZWrite", m_zWriteMode.GetValueOrProperty( ZWriteModeValues[ m_zWriteMode.IntValue ] ) ); + } + else if( outlineZWrite ) + { + MasterNode.AddRenderState( ref result, "ZWrite", ZWriteModeValues[ 1 ] ); + } + + if( m_zTestMode.IntValue != 0 || m_zTestMode.Active ) + { + MasterNode.AddRenderState( ref result, "ZTest", m_zTestMode.GetValueOrProperty( ZTestModeValues[ m_zTestMode.IntValue ] ) ); + } + else if( outlineZTest ) + { + MasterNode.AddRenderState( ref result, "ZTest", ZTestModeValues[ 3 ] ); + } + + if( m_offsetEnabled ) + { + MasterNode.AddRenderState( ref result, "Offset ", m_offsetFactor.GetValueOrProperty() + " , " + m_offsetUnits.GetValueOrProperty() ); + } + + return result; + } + + public void Draw( UndoParentNode owner, GUIStyle toolbarstyle, bool customBlendAvailable ) + { + Color cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f ); + EditorGUILayout.BeginHorizontal( toolbarstyle ); + GUI.color = cachedColor; + EditorGUI.BeginChangeCheck(); + m_parentSurface.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDepth = owner.GUILayoutToggle( m_parentSurface.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDepth, DepthParametersStr, UIUtils.MenuItemToggleStyle ); + if( EditorGUI.EndChangeCheck() ) + { + EditorPrefs.SetBool( "ExpandedDepth", m_parentSurface.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDepth ); + } + EditorGUILayout.EndHorizontal(); + + if( m_parentSurface.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDepth ) + { + cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) ); + EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + GUI.color = cachedColor; + + EditorGUI.indentLevel++; + if( !customBlendAvailable ) + EditorGUILayout.HelpBox( "Depth Writing is only available for Opaque or Custom blend modes", MessageType.Warning ); + + EditorGUILayout.Separator(); + EditorGUI.BeginDisabledGroup( !customBlendAvailable ); + + m_zWriteMode.EnumTypePopup( ref owner, ZWriteModeStr, ZWriteModeValues ); + m_zTestMode.EnumTypePopup( ref owner, ZTestModeStr, ZTestModeLabels ); + //m_zWriteMode = owner.EditorGUILayoutPopup( ZWriteModeStr, m_zWriteMode, ZWriteModeValues ); + //m_zTestMode = owner.EditorGUILayoutPopup( ZTestModeStr, m_zTestMode, ZTestModeLabels ); + m_offsetEnabled = owner.EditorGUILayoutToggle( OffsetStr, m_offsetEnabled ); + if( m_offsetEnabled ) + { + EditorGUI.indentLevel++; + m_offsetFactor.FloatField( ref owner , OffsetFactorStr ); + m_offsetUnits.FloatField( ref owner , OffsetUnitsStr ); + EditorGUI.indentLevel--; + } + + m_extraDepthPass = owner.EditorGUILayoutToggle( ExtraDepthPassStr, m_extraDepthPass ); + if( m_extraDepthPass ) + { + EditorGUI.indentLevel++; + m_extrazTestMode = owner.EditorGUILayoutPopup( DepthZTestStr, m_extrazTestMode, ZTestModeLabels ); + EditorGUI.indentLevel--; + } + EditorGUILayout.Separator(); + EditorGUI.indentLevel--; + EditorGUI.EndDisabledGroup(); + EditorGUILayout.EndVertical(); + } + + EditorGUI.EndDisabledGroup(); + } + + public void DrawExtraDepthPass( ref string shaderBody ) + { + if( m_extraDepthPass ) + { + shaderBody += "\t\tPass\n"; + shaderBody += "\t\t{\n"; + shaderBody += "\t\t\tColorMask 0\n"; + if( m_extrazTestMode != 0 ) + shaderBody += "\t\t\tZTest " + ZTestModeValues[ m_extrazTestMode ] + "\n"; + shaderBody += "\t\t\tZWrite On\n"; + shaderBody += "\t\t}\n\n"; + } + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + if( UIUtils.CurrentShaderVersion() < 2502 ) + { + string zWriteMode = nodeParams[ index++ ]; + m_zWriteMode.IntValue = zWriteMode.Equals( "Off" ) ? 2 : 0; + + string zTestMode = nodeParams[ index++ ]; + for( int i = 0; i < ZTestModeValues.Length; i++ ) + { + if( zTestMode.Equals( ZTestModeValues[ i ] ) ) + { + m_zTestMode.IntValue = i; + break; + } + } + } + else + { + if( UIUtils.CurrentShaderVersion() > 14501 ) + { + m_zWriteMode.ReadFromString( ref index, ref nodeParams ); + m_zTestMode.ReadFromString( ref index, ref nodeParams ); + } + else + { + m_zWriteMode.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_zTestMode.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + } + m_offsetEnabled = Convert.ToBoolean( nodeParams[ index++ ] ); + + if( UIUtils.CurrentShaderVersion() > 15303 ) + { + m_offsetFactor.ReadFromString( ref index , ref nodeParams , false ); + m_offsetUnits.ReadFromString( ref index, ref nodeParams , false ); + } + else + { + m_offsetFactor.FloatValue = Convert.ToSingle( nodeParams[ index++ ] ); + m_offsetUnits.FloatValue = Convert.ToSingle( nodeParams[ index++ ] ); + } + + if( UIUtils.CurrentShaderVersion() > 14202 ) + { + m_extraDepthPass = Convert.ToBoolean( nodeParams[ index++ ] ); + m_extrazTestMode = Convert.ToInt32( nodeParams[ index++ ] ); + } + } + } + + public void WriteToString( ref string nodeInfo ) + { + m_zWriteMode.WriteToString( ref nodeInfo ); + m_zTestMode.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_offsetEnabled ); + m_offsetFactor.WriteToString( ref nodeInfo ); + m_offsetUnits.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_extraDepthPass ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_extrazTestMode ); + } + public bool IsActive { get { return m_zTestMode.IntValue != 0 || m_zWriteMode.IntValue != 0 || m_offsetEnabled || m_zTestMode.Active || m_zWriteMode.Active; } } + public StandardSurfaceOutputNode ParentSurface { get { return m_parentSurface; } set { m_parentSurface = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ZBufferOpHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ZBufferOpHelper.cs.meta new file mode 100644 index 0000000..edee7bf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/ZBufferOpHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f35a3e26a28596b4f9b54a1f2689db06 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc.meta new file mode 100644 index 0000000..ae40b7c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6371d71bb076e1d47a3854adc59fdb93 +folderAsset: yes +timeCreated: 1481126945 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/AppendNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/AppendNode.cs new file mode 100644 index 0000000..6318614 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/AppendNode.cs @@ -0,0 +1,254 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "[Old]Append", "Vector Operators", "Append channels to create a new component",null,KeyCode.V,true,true,"Append",typeof(DynamicAppendNode))] + public sealed class AppendNode : ParentNode + { + private const string OutputTypeStr = "Output type"; + + [SerializeField] + private WirePortDataType m_selectedOutputType = WirePortDataType.FLOAT4; + + [SerializeField] + private int m_selectedOutputTypeInt = 2; + + [SerializeField] + private float[] m_defaultValues = { 0, 0, 0, 0 }; + private string[] m_defaultValuesStr = { "[0]", "[1]", "[2]", "[3]" }; + + private readonly string[] m_outputValueTypes ={ "Vector2", + "Vector3", + "Vector4", + "Color"}; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "[0]" ); + AddInputPort( WirePortDataType.FLOAT, false, "[1]" ); + AddInputPort( WirePortDataType.FLOAT, false, "[2]" ); + AddInputPort( WirePortDataType.FLOAT, false, "[3]" ); + AddOutputPort( m_selectedOutputType, Constants.EmptyPortValue ); + m_textLabelWidth = 90; + m_autoWrapProperties = true; + m_previewShaderGUID = "d80ac81aabf643848a4eaa76f2f88d65"; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if ( m_dropdownEditing ) + { + EditorGUI.BeginChangeCheck(); + m_selectedOutputTypeInt = EditorGUIPopup( m_dropdownRect, m_selectedOutputTypeInt, m_outputValueTypes, UIUtils.PropertyPopUp ); + if ( EditorGUI.EndChangeCheck() ) + { + SetupPorts(); + DropdownEditing = false; + } + } + } + + void SetupPorts() + { + switch ( m_selectedOutputTypeInt ) + { + case 0: m_selectedOutputType = WirePortDataType.FLOAT2; break; + case 1: m_selectedOutputType = WirePortDataType.FLOAT3; break; + case 2: m_selectedOutputType = WirePortDataType.FLOAT4; break; + case 3: m_selectedOutputType = WirePortDataType.COLOR; break; + } + + UpdatePorts(); + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUILayout.BeginVertical(); + + EditorGUI.BeginChangeCheck(); + m_selectedOutputTypeInt = EditorGUILayoutPopup( OutputTypeStr, m_selectedOutputTypeInt, m_outputValueTypes ); + if ( EditorGUI.EndChangeCheck() ) + { + SetupPorts(); + } + + int count = 0; + switch ( m_selectedOutputType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + { + count = 4; + } + break; + case WirePortDataType.FLOAT3: + { + count = 3; + } + break; + case WirePortDataType.FLOAT2: + { + count = 2; + } + break; + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { } + break; + } + + for ( int i = 0; i < count; i++ ) + { + if ( !m_inputPorts[ i ].IsConnected ) + m_defaultValues[ i ] = EditorGUILayoutFloatField( m_defaultValuesStr[ i ], m_defaultValues[ i ] ); + } + + EditorGUILayout.EndVertical(); + } + void UpdatePorts() + { + m_sizeIsDirty = true; + ChangeOutputType( m_selectedOutputType, false ); + switch ( m_selectedOutputType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.OBJECT: + case WirePortDataType.COLOR: + { + m_inputPorts[ 0 ].Visible = true; + m_inputPorts[ 1 ].Visible = true; + m_inputPorts[ 2 ].Visible = true; + m_inputPorts[ 3 ].Visible = true; + } + break; + case WirePortDataType.FLOAT3: + { + m_inputPorts[ 0 ].Visible = true; + m_inputPorts[ 1 ].Visible = true; + m_inputPorts[ 2 ].Visible = true; + m_inputPorts[ 3 ].Visible = false; + if ( m_inputPorts[ 3 ].IsConnected ) + UIUtils.DeleteConnection( true, UniqueId, 3, false, true ); + } + break; + case WirePortDataType.FLOAT2: + { + m_inputPorts[ 0 ].Visible = true; + m_inputPorts[ 1 ].Visible = true; + m_inputPorts[ 2 ].Visible = false; + if ( m_inputPorts[ 2 ].IsConnected ) + UIUtils.DeleteConnection( true, UniqueId, 2, false, true ); + + m_inputPorts[ 3 ].Visible = false; + if ( m_inputPorts[ 3 ].IsConnected ) + UIUtils.DeleteConnection( true, UniqueId, 3, false, true ); + } + break; + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { } + break; + } + } + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string value = string.Empty; + switch ( m_selectedOutputType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.OBJECT: + case WirePortDataType.COLOR: + { + value = "float4( "; + for ( int i = 0; i < 4; i++ ) + { + value += m_inputPorts[ i ].IsConnected ? InputPorts[ i ].GenerateShaderForOutput( ref dataCollector, WirePortDataType.FLOAT, ignoreLocalVar, true ) : m_defaultValues[ i ].ToString(); + if ( i != 3 ) + value += " , "; + } + value += " )"; + } + break; + case WirePortDataType.FLOAT3: + { + value = "float3( "; + for ( int i = 0; i < 3; i++ ) + { + value += m_inputPorts[ i ].IsConnected ? InputPorts[ i ].GenerateShaderForOutput( ref dataCollector, WirePortDataType.FLOAT, ignoreLocalVar, true ) : m_defaultValues[ i ].ToString(); + if ( i != 2 ) + value += " , "; + } + value += " )"; + } + break; + case WirePortDataType.FLOAT2: + { + value = "float2( "; + for ( int i = 0; i < 2; i++ ) + { + value += m_inputPorts[ i ].IsConnected ? InputPorts[ i ].GenerateShaderForOutput( ref dataCollector, WirePortDataType.FLOAT, ignoreLocalVar, true ) : m_defaultValues[ i ].ToString(); + if ( i != 1 ) + value += " , "; + } + value += " )"; + } + break; + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { } + break; + } + + RegisterLocalVariable( 0, value, ref dataCollector, "appendResult" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedOutputType = ( WirePortDataType ) Enum.Parse( typeof( WirePortDataType ), GetCurrentParam( ref nodeParams ) ); + switch ( m_selectedOutputType ) + { + case WirePortDataType.FLOAT2: m_selectedOutputTypeInt = 0; break; + case WirePortDataType.FLOAT3: m_selectedOutputTypeInt = 1; break; + case WirePortDataType.FLOAT4: m_selectedOutputTypeInt = 2; break; + case WirePortDataType.COLOR: m_selectedOutputTypeInt = 3; break; + } + for ( int i = 0; i < m_defaultValues.Length; i++ ) + { + m_defaultValues[ i ] = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + } + UpdatePorts(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedOutputType ); + for ( int i = 0; i < m_defaultValues.Length; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultValues[ i ] ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/AppendNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/AppendNode.cs.meta new file mode 100644 index 0000000..bd51352 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/AppendNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 688412c534df41444ad49759fa2b6a62 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/BreakToComponentsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/BreakToComponentsNode.cs new file mode 100644 index 0000000..97340ff --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/BreakToComponentsNode.cs @@ -0,0 +1,290 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Split", "Vector Operators", "Formerly known as Break To Components. Breaks the input data into its individual components", null, KeyCode.B, tags: "split Break To Components" )] + public sealed class BreakToComponentsNode : ParentNode + { + private const string RenameInfo = "This node was formerly known as Break To Components and was renamed to Split to decrease its canvas size."; + private WirePortDataType m_currentType = WirePortDataType.FLOAT; + private readonly string[] ColorPortNames = { "R", "G", "B", "A" }; + private readonly string[] VectorPortNames = { "X", "Y", "Z", "W" }; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + for( int i = 0; i < 16; i++ ) + { + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_outputPorts[ i ].IndexPreviewOffset = 1; + if( i != 0 ) + { + m_outputPorts[ i ].Visible = false; + } + } + m_previewShaderGUID = "5f58f74a202ba804daddec838b75207d"; + } + + public override void RenderNodePreview() + { + //Runs at least one time + if( !m_initialized ) + { + // nodes with no preview don't update at all + PreviewIsDirty = false; + return; + } + + if( !PreviewIsDirty ) + return; + + SetPreviewInputs(); + if( !Preferences.GlobalDisablePreviews ) + { + int count = m_outputPorts.Count; + for( int i = 0 ; i < count ; i++ ) + { + RenderTexture temp = RenderTexture.active; + RenderTexture.active = m_outputPorts[ i ].OutputPreviewTexture; + Graphics.Blit( null , m_outputPorts[ i ].OutputPreviewTexture , PreviewMaterial , Mathf.Min( i , 3 ) ); + RenderTexture.active = temp; + } + } + PreviewIsDirty = m_continuousPreviewRefresh; + } + + public override RenderTexture PreviewTexture + { + get + { + return m_inputPorts[ 0 ].InputPreviewTexture( ContainerGraph ); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUILayout.HelpBox( RenameInfo, MessageType.Warning ); + } + + void UpdateOutputs( WirePortDataType newType ) + { + //this only happens when on initial load + if( newType == WirePortDataType.OBJECT ) + return; + + m_currentType = newType; + switch( newType ) + { + case WirePortDataType.OBJECT: + { + m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, WirePortDataType.OBJECT, false ); + m_outputPorts[ 0 ].Visible = true; + for( int i = 1; i < m_outputPorts.Count; i++ ) + { + m_outputPorts[ i ].Visible = false; + } + } + break; + case WirePortDataType.FLOAT: + { + m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, WirePortDataType.FLOAT, false ); + m_outputPorts[ 0 ].Visible = true; + for( int i = 1; i < m_outputPorts.Count; i++ ) + { + m_outputPorts[ i ].Visible = false; + } + } + break; + case WirePortDataType.FLOAT2: + { + for( int i = 0; i < 2; i++ ) + { + m_outputPorts[ i ].ChangeProperties( VectorPortNames[ i ], WirePortDataType.FLOAT, false ); + m_outputPorts[ i ].Visible = true; + } + for( int i = 2; i < m_outputPorts.Count; i++ ) + { + m_outputPorts[ i ].Visible = false; + } + } + break; + case WirePortDataType.FLOAT3: + { + for( int i = 0; i < 3; i++ ) + { + m_outputPorts[ i ].ChangeProperties( VectorPortNames[ i ], WirePortDataType.FLOAT, false ); + m_outputPorts[ i ].Visible = true; + } + for( int i = 3; i < m_outputPorts.Count; i++ ) + { + m_outputPorts[ i ].Visible = false; + } + } + break; + case WirePortDataType.FLOAT4: + { + for( int i = 0; i < 4; i++ ) + { + m_outputPorts[ i ].ChangeProperties( VectorPortNames[ i ], WirePortDataType.FLOAT, false ); + m_outputPorts[ i ].Visible = true; + } + for( int i = 4; i < m_outputPorts.Count; i++ ) + { + m_outputPorts[ i ].Visible = false; + } + } + break; + case WirePortDataType.FLOAT3x3: + { + for( int i = 0; i < 9; i++ ) + { + m_outputPorts[ i ].ChangeProperties( "[" + (int)( i / 3 ) + "][" + i % 3 + "]", WirePortDataType.FLOAT, false ); + m_outputPorts[ i ].Visible = true; + } + for( int i = 9; i < m_outputPorts.Count; i++ ) + { + m_outputPorts[ i ].Visible = false; + } + } + break; + case WirePortDataType.FLOAT4x4: + { + for( int i = 0; i < 16; i++ ) + { + m_outputPorts[ i ].ChangeProperties( "[" + (int)( i / 4 ) + "][" + i % 4 + "]", WirePortDataType.FLOAT, false ); + m_outputPorts[ i ].Visible = true; + } + } + break; + case WirePortDataType.COLOR: + { + for( int i = 0; i < 4; i++ ) + { + m_outputPorts[ i ].ChangeProperties( ColorPortNames[ i ], WirePortDataType.FLOAT, false ); + m_outputPorts[ i ].Visible = true; + } + for( int i = 4; i < m_outputPorts.Count; i++ ) + { + m_outputPorts[ i ].Visible = false; + } + } + break; + case WirePortDataType.INT: + { + m_outputPorts[ 0 ].Visible = true; + m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, WirePortDataType.INT, false ); + for( int i = 1; i < m_outputPorts.Count; i++ ) + { + m_outputPorts[ i ].Visible = false; + } + } + break; + } + m_sizeIsDirty = true; + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + + if( UIUtils.IsLoading || m_isNodeBeingCopied ) + return; + + m_inputPorts[ 0 ].MatchPortToConnection(); + UpdateOutputs( m_inputPorts[ 0 ].DataType ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + + if( UIUtils.IsLoading || m_isNodeBeingCopied ) + return; + + m_inputPorts[ 0 ].MatchPortToConnection(); + UpdateOutputs( m_inputPorts[ 0 ].DataType ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentType ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + UpdateOutputs( (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), GetCurrentParam( ref nodeParams ) ) ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + { + return ReturnByType( m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ), outputId ); + } + + string value = string.Empty; + value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + int channelsUsed = 0; + for( int i = 0; i < m_outputPorts.Count; i++ ) + { + if( m_outputPorts[ i ].IsConnected ) + channelsUsed++; + } + string varName = "break" + OutputId; + if( channelsUsed > 1 ) + { + //RegisterLocalVariable( 0, value, ref dataCollector, varName ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_inputPorts[ 0 ].DataType, varName, value ); + m_outputPorts[ 0 ].SetLocalValue( varName, dataCollector.PortCategory ); + + + value = varName; + } + + return ReturnByType( value, outputId ); + } + + private string ReturnByType( string value, int outputId ) + { + switch( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + { + return value; + } + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + { + return GetOutputVectorItem( 0, outputId + 1, value ); + } + case WirePortDataType.COLOR: + { + return GetOutputColorItem( 0, outputId + 1, value ); + } + case WirePortDataType.FLOAT3x3: + { + return value + "[ " + ( (int)( outputId / 3 ) ) + " ][ " + ( outputId % 3 ) + " ]"; + } + case WirePortDataType.FLOAT4x4: + { + return value + "[ " + ( (int)( outputId / 4 ) ) + " ][ " + ( outputId % 4 ) + " ]"; + } + } + return value; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/BreakToComponentsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/BreakToComponentsNode.cs.meta new file mode 100644 index 0000000..34381d1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/BreakToComponentsNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a74e2c0a9306c0048bfcc733cb7d154d +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/CustomExpressionNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/CustomExpressionNode.cs new file mode 100644 index 0000000..6f8a250 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/CustomExpressionNode.cs @@ -0,0 +1,1839 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using UnityEditorInternal; +using System.Text.RegularExpressions; + +namespace AmplifyShaderEditor +{ + public enum CustomExpressionMode + { + Create, + Call, + File + } + + [Serializable] + public class CustomExpressionInputItem + { + public PrecisionType Precision; + public VariableQualifiers Qualifier; + public WirePortDataType Type; + public bool IsSamplerState; + public bool IsTexture2DArray; + public string CustomType; + public bool IsVariable; + public bool FoldoutFlag; + public string FoldoutLabel; + + public CustomExpressionInputItem( PrecisionType precision , VariableQualifiers qualifier , string customType , bool isVariable , bool foldoutFlag , string foldoutLabel ) + { + Precision = precision; + Qualifier = qualifier; + CustomType = customType; + FoldoutFlag = foldoutFlag; + FoldoutLabel = foldoutLabel; + IsVariable = isVariable; + } + } + + [Serializable] + public class CustomExpressionDependency + { + public int DependencyArrayIdx; + public int DependencyNodeId; + public CustomExpressionDependency() { DependencyArrayIdx = DependencyNodeId = -1; } + public CustomExpressionDependency( string id ) { DependencyNodeId = Convert.ToInt32( id ); DependencyArrayIdx = -1; } + public void Reset() + { + DependencyArrayIdx = -1; + DependencyNodeId = -1; + } + } + + [Serializable] + [NodeAttributes( "Custom Expression" , "Miscellaneous" , "Creates a custom expression or function if return is detected in the written code." )] + public sealed class CustomExpressionNode : ParentNode + { + private const string WarningText = "Characters $ and @ are NOT allowed inside code since they are internally used as delimiters over the node meta.\nThey will be automatically removed when saving the shader."; + private const float AddRemoveButtonLayoutWidth = 15; + private const float LineAdjust = 1.15f; + private const float IdentationAdjust = 5f; + private const string CustomExpressionInfo = "Creates a custom expression or function according to how code is written on text area.\n\n" + + "- If a return function is detected on Code text area then a function will be created.\n" + + "Also in function mode a ; is expected on the end of each instruction line.\n\n" + + "- If no return function is detected then an expression will be generated and used directly on the vertex/frag body.\n" + + "On Expression mode a ; is not required on the end of an instruction line.\n\n" + + "- You can also call a function from an external file, just make sure to add the include file via the 'Additional Directives' group " + + "in the main property panel. Also works with shader functions."; + + private const string ReturnHelper = "return"; + private const double MaxTimestamp = 1; + private const string DefaultExpressionNameStr = "My Custom Expression"; + private const string DefaultInputNameStr = "In"; + private const string CodeTitleStr = "Code"; + private const string OutputTypeStr = "Output Type"; + private const string CustomTypeStr = " "; + private const string IsVariableStr = "Is Variable"; + private const string InputsStr = "Inputs"; + private const string InputNameStr = "Name"; + private const string InputTypeStr = "Type"; + private const string InputValueStr = "Value"; + private const string InputQualifierStr = "Qualifier"; + private const string ExpressionNameLabelStr = "Name"; + private const string FunctionCallModeStr = "Mode"; + private const string GenerateUniqueNameStr = "Set Unique"; + private const string AutoRegisterStr = "Auto-Register"; + private const string DependenciesStr = "Dependencies"; + + private const string VarRegexReplacer = @"\b{0}\b"; + private readonly string[] PrecisionLabelsExtraLocal = { "Float" , "Half" , "Inherit Local" }; + + private readonly string[] AvailableWireTypesStr = + { + "int", + "float", + "float2", + "float3", + "float4", + "float3x3", + "float4x4", + "sampler1D", + "sampler2D", + "sampler3D", + "samplerCUBE", + "sampler2Darray", + "samplerState", + "custom"}; + + private readonly string[] AvailableOutputWireTypesStr = + { + "int", + "float", + "float2", + "float3", + "float4", + "float3x3", + "float4x4", + "void", + }; + + private readonly string[] QualifiersStr = + { + "In", + "Out", + "InOut" + }; + + private readonly WirePortDataType[] AvailableWireTypes = + { + WirePortDataType.INT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4, + WirePortDataType.SAMPLER1D, + WirePortDataType.SAMPLER2D, + WirePortDataType.SAMPLER3D, + WirePortDataType.SAMPLERCUBE, + WirePortDataType.SAMPLER2DARRAY, + WirePortDataType.SAMPLERSTATE, + WirePortDataType.OBJECT + }; + + private readonly WirePortDataType[] AvailableOutputWireTypes = + { + WirePortDataType.INT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4, + WirePortDataType.OBJECT, + }; + + + private readonly Dictionary WireToIdx = new Dictionary + { + { WirePortDataType.INT, 0}, + { WirePortDataType.FLOAT, 1}, + { WirePortDataType.FLOAT2, 2}, + { WirePortDataType.FLOAT3, 3}, + { WirePortDataType.FLOAT4, 4}, + { WirePortDataType.FLOAT3x3, 5}, + { WirePortDataType.FLOAT4x4, 6}, + { WirePortDataType.SAMPLER1D, 7}, + { WirePortDataType.SAMPLER2D, 8}, + { WirePortDataType.SAMPLER3D, 9}, + { WirePortDataType.SAMPLERCUBE, 10}, + { WirePortDataType.SAMPLER2DARRAY, 11}, + { WirePortDataType.SAMPLERSTATE, 12}, + { WirePortDataType.OBJECT, 13} + }; + + [SerializeField] + private string m_customExpressionName = DefaultExpressionNameStr; + + [SerializeField] + private List m_items = new List(); + + [SerializeField] + private string m_code = " "; + + [SerializeField] + private int m_outputTypeIdx = 1; + + [SerializeField] + private bool m_visibleInputsFoldout = true; + + [SerializeField] + private CustomExpressionMode m_mode = CustomExpressionMode.Create; + + [SerializeField] + private string m_fileGUID = string.Empty; + + [SerializeField] + private TextAsset m_fileAsset = null; + + [SerializeField] + private bool m_precisionSuffix = false; + + [SerializeField] + private bool m_voidMode = false; + + [SerializeField] + private bool m_autoRegisterMode = false; + + [SerializeField] + private bool m_functionMode = false; + + [SerializeField] + private int m_firstAvailablePort = 0; + + [SerializeField] + private string m_uniqueName; + + [SerializeField] + private bool m_generateUniqueName = true; + + [SerializeField] + private bool m_dependenciesFoldout = false; + + [SerializeField] + private List m_dependencies = new List(); + + private const float ButtonLayoutWidth = 15; + + private bool m_repopulateNameDictionary = true; + private Dictionary m_usedNames = new Dictionary(); + + private double m_lastTimeNameModified = 0; + private bool m_nameModified = false; + + private double m_lastTimeCodeModified = 0; + private bool m_codeModified = false; + + //Title editing + private bool m_isEditing; + private bool m_stopEditing; + private bool m_startEditing; + private double m_clickTime; + private double m_doubleClickTime = 0.3; + private Rect m_titleClickArea; + + //Item Reordable List + private ReordableAction m_actionType = ReordableAction.None; + private int m_actionIndex = 0; + private int m_lastIndex = 0; + + private ReorderableList m_itemReordableList = null; + private ReorderableList m_dependenciesReordableList = null; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT , false , "In0" ); + m_items.Add( new CustomExpressionInputItem( PrecisionType.Inherit , VariableQualifiers.In , string.Empty , false , true , string.Empty/*"[0]"*/ ) ); + AddOutputPort( WirePortDataType.FLOAT , "Out" ); + m_textLabelWidth = 97; + m_customPrecision = true; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + + if( m_mode == CustomExpressionMode.Create ) + UIUtils.CurrentWindow.OutsideGraph.CustomExpressionOnFunctionMode.AddNode( this ); + + SetTitleText( m_customExpressionName ); + + if( m_nodeAttribs != null ) + m_uniqueName = m_nodeAttribs.Name + OutputId; + else + m_uniqueName = "CustomExpression" + OutputId; + } + + public override void OnInputPortConnected( int portId , int otherNodeId , int otherPortId , bool activateNode = true ) + { + base.OnInputPortConnected( portId , otherNodeId , otherPortId , activateNode ); + CheckPortConnection( portId ); + } + + public override void OnConnectedOutputNodeChanges( int portId , int otherNodeId , int otherPortId , string name , WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( portId , otherNodeId , otherPortId , name , type ); + CheckPortConnection( portId ); + } + + void CheckPortConnection( int portId ) + { + if( portId == 0 && ( m_mode == CustomExpressionMode.Call || m_voidMode ) ) + { + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType , false ); + } + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + if( m_nameModified ) + { + if( ( EditorApplication.timeSinceStartup - m_lastTimeNameModified ) > MaxTimestamp ) + { + m_nameModified = false; + m_sizeIsDirty = true; + m_repopulateNameDictionary = true; + } + } + + if( m_repopulateNameDictionary ) + { + m_repopulateNameDictionary = false; + m_usedNames.Clear(); + for( int i = 0 ; i < m_inputPorts.Count ; i++ ) + { + m_usedNames.Add( m_inputPorts[ i ].Name , i ); + } + } + + if( m_codeModified ) + { + if( ( EditorApplication.timeSinceStartup - m_lastTimeCodeModified ) > MaxTimestamp ) + { + m_codeModified = false; + bool functionMode = m_code.Contains( ReturnHelper ); + if( functionMode != m_functionMode ) + { + m_functionMode = functionMode; + CheckCallMode(); + } + } + } + } + + bool CheckCallMode() + { + if( m_functionMode && m_mode == CustomExpressionMode.Call ) + { + Mode = CustomExpressionMode.Create; + m_outputTypeIdx = ( AvailableOutputWireTypesStr.Length - 1 ); + //m_outputPorts[ 0 ].ChangeType( AvailableOutputWireTypes[ m_outputTypeIdx ], false ); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType , false ); + m_voidMode = true; + return true; + } + return false; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + if( !m_isEditing && ( ( !ContainerGraph.ParentWindow.MouseInteracted && drawInfo.CurrentEventType == EventType.MouseDown && m_titleClickArea.Contains( drawInfo.MousePosition ) ) ) ) + { + if( ( EditorApplication.timeSinceStartup - m_clickTime ) < m_doubleClickTime ) + m_startEditing = true; + else + GUI.FocusControl( null ); + m_clickTime = EditorApplication.timeSinceStartup; + } + else if( m_isEditing && ( ( drawInfo.CurrentEventType == EventType.MouseDown && !m_titleClickArea.Contains( drawInfo.MousePosition ) ) || !EditorGUIUtility.editingTextField ) ) + { + m_stopEditing = true; + } + + if( m_isEditing || m_startEditing ) + { + EditorGUI.BeginChangeCheck(); + GUI.SetNextControlName( m_uniqueName ); + m_customExpressionName = EditorGUITextField( m_titleClickArea , string.Empty , m_customExpressionName , UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + if( EditorGUI.EndChangeCheck() ) + { + SetTimedUpdate( 2 ); + SetTitleText( m_customExpressionName ); + m_sizeIsDirty = true; + m_isDirty = true; + } + + if( m_startEditing ) + EditorGUI.FocusTextInControl( m_uniqueName ); + } + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + if( m_startEditing ) + { + m_startEditing = false; + m_isEditing = true; + } + + if( m_stopEditing ) + { + m_stopEditing = false; + m_isEditing = false; + GUI.FocusControl( null ); + } + } + } + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + m_titleClickArea = m_titlePos; + m_titleClickArea.height = Constants.NODE_HEADER_HEIGHT; + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + if( !m_isVisible ) + return; + + // Fixed Title ( only renders when not editing ) + if( !m_isEditing && !m_startEditing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + GUI.Label( m_titleClickArea , m_content , UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + } + } + + public string GetFirstAvailableName() + { + string name = string.Empty; + for( int i = 0 ; i < m_inputPorts.Count + 1 ; i++ ) + { + name = DefaultInputNameStr + i; + if( !m_usedNames.ContainsKey( name ) ) + { + return name; + } + } + Debug.LogWarning( "Could not find valid name" ); + return string.Empty; + } + + public override void DrawProperties() + { + base.DrawProperties(); + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout , Constants.ParameterLabelStr , DrawBaseProperties ); + //NodeUtils.DrawPropertyGroup( ref m_visibleInputsFoldout, InputsStr, DrawInputs, DrawAddRemoveInputs ); + NodeUtils.DrawPropertyGroup( ref m_visibleInputsFoldout , InputsStr , DrawReordableInputs , DrawItemsAddRemoveInputs ); + + EditorGUILayout.HelpBox( CustomExpressionInfo , MessageType.Info ); + EditorGUILayout.HelpBox( WarningText , MessageType.Warning ); + } + + string WrapCodeInFunction( bool isTemplate , string functionName , bool expressionMode ) + { + //Hack to be used util indent is properly used + int currIndent = UIUtils.ShaderIndentLevel; + UIUtils.ShaderIndentLevel = isTemplate ? 0 : 1; + + if( !isTemplate ) UIUtils.ShaderIndentLevel++; + + //string functionName = UIUtils.RemoveInvalidCharacters( m_customExpressionName ); + string returnType = ( m_mode == CustomExpressionMode.Call || m_voidMode ) ? "void" : UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType , m_outputPorts[ 0 ].DataType ); + if( expressionMode ) + returnType = "inline " + returnType; + + string functionBody = UIUtils.ShaderIndentTabs + returnType + " " + functionName + "( "; + int count = m_inputPorts.Count - m_firstAvailablePort; + for( int i = 0 ; i < count ; i++ ) + { + int portIdx = i + m_firstAvailablePort; + string qualifier = m_items[ i ].Qualifier == VariableQualifiers.In ? string.Empty : UIUtils.QualifierToCg( m_items[ i ].Qualifier ) + " "; + PrecisionType precision = m_items[ i ].Precision; + if( precision == PrecisionType.Inherit ) + precision = CurrentPrecisionType; + //string dataType = ( m_inputPorts[ portIdx ].DataType == WirePortDataType.OBJECT ) ? m_items[ i ].CustomType : UIUtils.PrecisionWirePortToCgType( precision, m_inputPorts[ portIdx ].DataType ); + string declaration = string.Empty; + if( m_inputPorts[ portIdx ].DataType == WirePortDataType.OBJECT ) + declaration = m_items[ i ].CustomType + " " + m_inputPorts[ portIdx ].Name; + else + declaration = UIUtils.PrecisionWirePortToTypeValue( precision , m_inputPorts[ portIdx ].DataType , m_inputPorts[ portIdx ].Name ); + functionBody += qualifier + declaration; + //functionBody += qualifier + dataType + " " + m_inputPorts[ portIdx ].Name; + if( i < ( count - 1 ) ) + { + functionBody += ", "; + } + } + functionBody += " )\n" + UIUtils.ShaderIndentTabs + "{\n"; + UIUtils.ShaderIndentLevel++; + { + if( expressionMode ) + functionBody += UIUtils.ShaderIndentTabs + "return "; + + string[] codeLines = m_code.Split( IOUtils.LINE_TERMINATOR ); + for( int i = 0 ; i < codeLines.Length ; i++ ) + { + if( codeLines[ i ].Length > 0 ) + { + functionBody += ( ( i == 0 && expressionMode ) ? string.Empty : UIUtils.ShaderIndentTabs ) + codeLines[ i ] + ( ( ( i == codeLines.Length - 1 ) && expressionMode ) ? string.Empty : "\n" ); + } + } + if( expressionMode ) + functionBody += ";\n"; + } + UIUtils.ShaderIndentLevel--; + + functionBody += UIUtils.ShaderIndentTabs + "}\n"; + UIUtils.ShaderIndentLevel = currIndent; + return functionBody; + } + + void DrawBaseProperties() + { + EditorGUI.BeginChangeCheck(); + m_customExpressionName = EditorGUILayoutTextField( ExpressionNameLabelStr , m_customExpressionName ); + if( EditorGUI.EndChangeCheck() ) + { + SetTimedUpdate( 2 ); + SetTitleText( m_customExpressionName ); + } + + EditorGUI.BeginChangeCheck(); + Mode = (CustomExpressionMode)EditorGUILayoutEnumPopup( FunctionCallModeStr , m_mode ); + if( EditorGUI.EndChangeCheck() ) + { + if( CheckCallMode() ) + UIUtils.ShowMessage( UniqueId , "Call Mode cannot have return over is code.\nFalling back to Create Mode" ); + SetupCallMode(); + RecalculateInOutOutputPorts(); + } + + if( m_mode == CustomExpressionMode.File ) + { + m_fileAsset = EditorGUILayoutObjectField( "Source" , m_fileAsset , typeof( TextAsset ) , false ) as TextAsset; + m_precisionSuffix = EditorGUILayoutToggle( "Precision Suffix" , m_precisionSuffix ); + } + else + { + EditorGUILayout.LabelField( CodeTitleStr ); + EditorGUI.BeginChangeCheck(); + { + m_code = EditorGUILayoutTextArea( m_code , UIUtils.MainSkin.textArea ); + } + if( EditorGUI.EndChangeCheck() ) + { + m_codeModified = true; + m_lastTimeCodeModified = EditorApplication.timeSinceStartup; + } + } + if( m_mode == CustomExpressionMode.Create || m_mode == CustomExpressionMode.File ) + { + DrawPrecisionProperty(); + + bool guiEnabled = GUI.enabled; + + GUI.enabled = !AutoRegisterMode && Mode != CustomExpressionMode.File; + m_generateUniqueName = EditorGUILayoutToggle( GenerateUniqueNameStr , m_generateUniqueName ) && !AutoRegisterMode; + + GUI.enabled = !m_generateUniqueName; + AutoRegisterMode = EditorGUILayoutToggle( AutoRegisterStr , AutoRegisterMode ) && !m_generateUniqueName; + + GUI.enabled = guiEnabled; + + EditorGUI.BeginChangeCheck(); + m_outputTypeIdx = EditorGUILayoutPopup( OutputTypeStr , m_outputTypeIdx , AvailableOutputWireTypesStr ); + if( EditorGUI.EndChangeCheck() ) + { + bool oldVoidValue = m_voidMode; + UpdateVoidMode(); + if( oldVoidValue != m_voidMode ) + { + SetupCallMode(); + RecalculateInOutOutputPorts(); + } + else + { + m_outputPorts[ 0 ].ChangeType( AvailableOutputWireTypes[ m_outputTypeIdx ] , false ); + } + } + } + NodeUtils.DrawNestedPropertyGroup( ref m_dependenciesFoldout , "Dependencies" , DrawDependencies , DrawDependenciesAddRemoveInputs ); + } + + void UpdateVoidMode() + { + m_voidMode = ( m_outputTypeIdx == ( AvailableOutputWireTypesStr.Length - 1 ) ); + } + + void SetupCallMode() + { + if( m_mode == CustomExpressionMode.Call || m_voidMode ) + { + if( m_firstAvailablePort != 1 ) + { + m_firstAvailablePort = 1; + AddInputPortAt( 0 , WirePortDataType.FLOAT , false , DefaultInputNameStr ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT , false ); + } + } + else + { + if( m_firstAvailablePort != 0 ) + { + m_firstAvailablePort = 0; + if( m_inputPorts[ 0 ].IsConnected ) + { + m_containerGraph.DeleteConnection( true , UniqueId , m_inputPorts[ 0 ].PortId , false , true ); + } + DeleteInputPortByArrayIdx( 0 ); + m_outputPorts[ 0 ].ChangeType( AvailableOutputWireTypes[ m_outputTypeIdx ] , false ); + } + } + } + + void DrawItemsAddRemoveInputs() + { + if( m_inputPorts.Count == m_firstAvailablePort ) + m_visibleInputsFoldout = false; + + // Add new port + if( GUILayoutButton( string.Empty , UIUtils.PlusStyle , GUILayout.Width( ButtonLayoutWidth ) ) ) + { + AddPortAt( m_inputPorts.Count ); + m_visibleInputsFoldout = true; + EditorGUI.FocusTextInControl( null ); + } + + //Remove port + if( GUILayoutButton( string.Empty , UIUtils.MinusStyle , GUILayout.Width( ButtonLayoutWidth ) ) ) + { + RemovePortAt( m_inputPorts.Count - 1 ); + EditorGUI.FocusTextInControl( null ); + } + } + + void DrawDependenciesAddRemoveInputs() + { + // Add new port + if( GUILayoutButton( string.Empty , UIUtils.PlusStyle , GUILayout.Width( ButtonLayoutWidth ) ) ) + { + m_dependencies.Add( new CustomExpressionDependency() ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove port + if( GUILayoutButton( string.Empty , UIUtils.MinusStyle , GUILayout.Width( ButtonLayoutWidth ) ) ) + { + m_dependencies.RemoveAt( m_dependencies.Count - 1 ); + } + } + + void DrawDependencies() + { + if( m_dependenciesReordableList == null ) + { + m_dependenciesReordableList = new ReorderableList( m_dependencies , typeof( CustomExpressionDependency ) , true , false , false , false ) + { + headerHeight = 0 , + footerHeight = 0 , + showDefaultBackground = false , + drawElementCallback = ( Rect rect , int index , bool isActive , bool isFocused ) => + { + if( m_dependencies[ index ] != null ) + { + rect.xMin -= 1; + + Rect popupPos = new Rect( rect.x , rect.y , rect.width - 2 * Constants.PlusMinusButtonLayoutWidth , EditorGUIUtility.singleLineHeight ); + Rect buttonPlusPos = new Rect( rect.x + rect.width - 2 * Constants.PlusMinusButtonLayoutWidth , rect.y - 2 , Constants.PlusMinusButtonLayoutWidth , Constants.PlusMinusButtonLayoutWidth ); + Rect buttonMinusPos = new Rect( rect.x + rect.width - Constants.PlusMinusButtonLayoutWidth , rect.y - 2 , Constants.PlusMinusButtonLayoutWidth , Constants.PlusMinusButtonLayoutWidth ); + EditorGUI.BeginChangeCheck(); + m_dependencies[ index ].DependencyArrayIdx = EditorGUIPopup( popupPos , string.Empty , m_dependencies[ index ].DependencyArrayIdx , UIUtils.CurrentWindow.OutsideGraph.CustomExpressionOnFunctionMode.NodesArr ); + if( EditorGUI.EndChangeCheck() ) + { + m_dependencies[ index ].DependencyNodeId = UIUtils.CurrentWindow.OutsideGraph.CustomExpressionOnFunctionMode.GetNode( m_dependencies[ index ].DependencyArrayIdx ).UniqueId; + if( m_dependencies[ index ].DependencyNodeId == UniqueId ) + { + m_dependencies[ index ].Reset(); + } + } + + if( GUI.Button( buttonPlusPos , string.Empty , UIUtils.PlusStyle ) ) + { + m_actionType = ReordableAction.Add; + m_actionIndex = index; + } + + if( GUI.Button( buttonMinusPos , string.Empty , UIUtils.MinusStyle ) ) + { + m_actionType = ReordableAction.Remove; + m_actionIndex = index; + } + } + } + }; + } + + if( m_dependenciesReordableList != null ) + { + EditorGUILayout.Space(); + if( m_dependencies.Count == 0 ) + { + EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one." , MessageType.Info ); + } + else + { + m_dependenciesReordableList.DoLayoutList(); + } + EditorGUILayout.Space(); + } + + if( m_actionType != ReordableAction.None ) + { + switch( m_actionType ) + { + case ReordableAction.Add: + m_dependencies.Insert( m_actionIndex + 1 , new CustomExpressionDependency() ); + break; + case ReordableAction.Remove: + m_dependencies.RemoveAt( m_actionIndex ); + break; + } + m_isDirty = true; + m_actionType = ReordableAction.None; + EditorGUI.FocusTextInControl( null ); + } + } + + void DrawReordableInputs() + { + if( m_itemReordableList == null ) + { + m_itemReordableList = new ReorderableList( m_items , typeof( CustomExpressionInputItem ) , true , false , false , false ) + { + headerHeight = 0 , + footerHeight = 0 , + showDefaultBackground = false , + elementHeightCallback = ( int index ) => + { + float lineHeight = EditorGUIUtility.singleLineHeight * LineAdjust; + if( m_items[ index ].FoldoutFlag ) + { + float size = 7 * lineHeight; + + // Take Is Variable toggle into account + if( m_mode == CustomExpressionMode.Call ) + size += lineHeight; + + if( m_inputPorts[ m_firstAvailablePort + index ].DataType == WirePortDataType.OBJECT ) + size += lineHeight; + + if( !m_inputPorts[ m_firstAvailablePort + index ].IsConnected ) + { + switch( m_inputPorts[ m_firstAvailablePort + index ].DataType ) + { + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + size += 0;// lineHeight; + break; + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + size += lineHeight;//2 * lineHeight; + break; + case WirePortDataType.FLOAT3x3: + size += 5 * lineHeight;//6 * lineHeight; + break; + case WirePortDataType.FLOAT4x4: + size += 6 * lineHeight;//8 * lineHeight; + break; + + } + } + + return size; + } + else + { + return lineHeight; + } + } , + + onReorderCallback = ( ReorderableList list ) => + { + int realLastIndex = m_firstAvailablePort + m_lastIndex; + int realCurrIndex = m_firstAvailablePort + list.index; + + InputPort portA = m_inputPorts[ realLastIndex ]; + int originalOutputPortId = CreateOutputId( portA.PortId ); + + SwapInputPorts( realLastIndex , realCurrIndex ); + + if( m_outputPorts.Count > 1 ) + { + if( list.index > m_lastIndex ) + { + for( int i = m_lastIndex ; i <= list.index ; i++ ) + { + if( m_items[ i ].Qualifier != VariableQualifiers.In ) + { + int portIdx = i + m_firstAvailablePort; + int oldOutputPortId; + if( i < list.index ) + { + int oldinputPortId = m_inputPorts[ portIdx ].PortId + 1; + oldOutputPortId = CreateOutputId( oldinputPortId ); + } + else + { + oldOutputPortId = originalOutputPortId; + } + + m_outputPortsDict[ oldOutputPortId ].ChangePortId( CreateOutputId( m_inputPorts[ portIdx ].PortId ) ); + } + } + } + else + { + for( int i = list.index ; i <= m_lastIndex ; i++ ) + { + if( m_items[ i ].Qualifier != VariableQualifiers.In ) + { + int portIdx = i + m_firstAvailablePort; + int oldOutputPortId; + if( i > list.index ) + { + int oldinputPortId = m_inputPorts[ portIdx ].PortId - 1; + oldOutputPortId = CreateOutputId( oldinputPortId ); + } + else + { + oldOutputPortId = originalOutputPortId; + } + + m_outputPortsDict[ oldOutputPortId ].ChangePortId( CreateOutputId( m_inputPorts[ portIdx ].PortId ) ); + } + } + } + } + + + m_outputPorts.Sort( ( A , B ) => + { + return A.PortId.CompareTo( B.PortId ); + } ); + + m_outputPortsDict.Clear(); + for( int i = 0 ; i < m_outputPorts.Count ; i++ ) + { + m_outputPortsDict.Add( m_outputPorts[ i ].PortId , m_outputPorts[ i ] ); + } + + } , + onSelectCallback = ( ReorderableList list ) => + { + m_lastIndex = list.index; + } , + drawElementCallback = ( Rect rect , int index , bool isActive , bool isFocused ) => + { + if( m_items[ index ] != null ) + { + float lineHeight = EditorGUIUtility.singleLineHeight; + float lineSpacing = lineHeight * LineAdjust; + + rect.x -= IdentationAdjust; + rect.height = lineHeight; + int portIdx = index + m_firstAvailablePort; + Rect foldoutRect = rect; + if( !m_items[ index ].FoldoutFlag ) + { + foldoutRect.width -= 2 * AddRemoveButtonLayoutWidth; + } + m_items[ index ].FoldoutFlag = EditorGUIFoldout( foldoutRect , m_items[ index ].FoldoutFlag , /*m_items[ index ].FoldoutLabel + " - " +*/ m_inputPorts[ portIdx ].Name ); + if( m_items[ index ].FoldoutFlag ) + { + rect.x += IdentationAdjust; + + //Qualifier + rect.y += lineSpacing; + VariableQualifiers newQualifier = (VariableQualifiers)EditorGUIPopup( rect , InputQualifierStr , (int)m_items[ index ].Qualifier , QualifiersStr ); + if( newQualifier != m_items[ index ].Qualifier ) + { + VariableQualifiers oldQualifier = m_items[ index ].Qualifier; + m_items[ index ].Qualifier = newQualifier; + if( newQualifier == VariableQualifiers.In ) + { + RemoveOutputPort( CreateOutputId( m_inputPorts[ portIdx ].PortId ) , false ); + } + else if( oldQualifier == VariableQualifiers.In ) + { + int outputId = CreateOutputId( m_inputPorts[ portIdx ].PortId ); + AddOutputPort( m_inputPorts[ portIdx ].DataType , m_inputPorts[ portIdx ].Name , outputId ); + } + m_inputPorts[ portIdx ].Visible = newQualifier != VariableQualifiers.Out; + m_sizeIsDirty = true; + RecalculateInOutOutputPorts(); + } + + // Precision + rect.y += lineSpacing; + m_items[ index ].Precision = (PrecisionType)EditorGUIPopup( rect , PrecisionContent.text , (int)m_items[ index ].Precision , PrecisionLabelsExtraLocal ); + // Type + rect.y += lineSpacing; + int typeIdx = WireToIdx[ m_inputPorts[ portIdx ].DataType ]; + EditorGUI.BeginChangeCheck(); + typeIdx = EditorGUIPopup( rect , InputTypeStr , typeIdx , AvailableWireTypesStr ); + if( EditorGUI.EndChangeCheck() ) + { + // actual type is need in order for texture array and sampler state to fallback correctly + m_inputPorts[ portIdx ].ChangeType( AvailableWireTypes[ typeIdx ] , false ); + if( typeIdx == 5 || typeIdx == 6 ) + { + m_inputPorts[ portIdx ].Matrix4x4InternalData = Matrix4x4.identity; + } + + if( m_items[ index ].Qualifier != VariableQualifiers.In ) + { + OutputPort currOutPort = GetOutputPortByUniqueId( CreateOutputId( m_inputPorts[ portIdx ].PortId ) ); + currOutPort.ChangeType( AvailableWireTypes[ typeIdx ] , false ); + } + } + + if( AvailableWireTypes[ typeIdx ] == WirePortDataType.OBJECT ) + { + rect.y += lineSpacing; + m_items[ index ].CustomType = EditorGUITextField( rect , CustomTypeStr , m_items[ index ].CustomType ); + } + + //Name + rect.y += lineSpacing; + EditorGUI.BeginChangeCheck(); + { + m_inputPorts[ portIdx ].Name = EditorGUITextField( rect , InputNameStr , m_inputPorts[ portIdx ].Name ); + } + if( EditorGUI.EndChangeCheck() ) + { + m_nameModified = true; + m_lastTimeNameModified = EditorApplication.timeSinceStartup; + m_inputPorts[ portIdx ].Name = UIUtils.RemoveInvalidCharacters( m_inputPorts[ portIdx ].Name ); + if( string.IsNullOrEmpty( m_inputPorts[ portIdx ].Name ) ) + { + m_inputPorts[ portIdx ].Name = DefaultInputNameStr + index; + } + + if( m_items[ index ].Qualifier != VariableQualifiers.In ) + { + OutputPort currOutPort = GetOutputPortByUniqueId( CreateOutputId( m_inputPorts[ portIdx ].PortId ) ); + currOutPort.Name = m_inputPorts[ portIdx ].Name; + } + } + + if( m_mode == CustomExpressionMode.Call ) + { + //Is Unique + rect.y += lineSpacing; + m_items[ index ].IsVariable = EditorGUIToggle( rect , IsVariableStr , m_items[ index ].IsVariable ); + } + // Port Data + if( !m_inputPorts[ portIdx ].IsConnected ) + { + rect.y += lineSpacing; + m_inputPorts[ portIdx ].ShowInternalData( rect , this , true , InputValueStr ); + } + + //Buttons + rect.x += rect.width - 2 * AddRemoveButtonLayoutWidth; + rect.y += lineSpacing; + if( !m_inputPorts[ m_firstAvailablePort + index ].IsConnected ) + { + switch( m_inputPorts[ m_firstAvailablePort + index ].DataType ) + { + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + rect.y += 0;// lineSpacing; + break; + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + rect.y += lineSpacing;//2 * lineSpacing; + break; + case WirePortDataType.FLOAT3x3: + rect.y += 5 * lineSpacing;//6 * lineSpacing; + break; + case WirePortDataType.FLOAT4x4: + rect.y += 6 * lineSpacing;//8 * lineSpacing; + break; + + } + } + rect.width = AddRemoveButtonLayoutWidth; + if( GUI.Button( rect , string.Empty , UIUtils.PlusStyle ) ) + { + m_actionType = ReordableAction.Add; + m_actionIndex = index; + } + rect.x += AddRemoveButtonLayoutWidth; + if( GUI.Button( rect , string.Empty , UIUtils.MinusStyle ) ) + { + m_actionType = ReordableAction.Remove; + m_actionIndex = index; + } + + } + else + { + //Buttons + rect.x += IdentationAdjust + rect.width - 2 * AddRemoveButtonLayoutWidth; + rect.width = AddRemoveButtonLayoutWidth; + if( GUI.Button( rect , string.Empty , UIUtils.PlusStyle ) ) + { + m_actionType = ReordableAction.Add; + m_actionIndex = index; + } + rect.x += AddRemoveButtonLayoutWidth; + if( GUI.Button( rect , string.Empty , UIUtils.MinusStyle ) ) + { + m_actionType = ReordableAction.Remove; + m_actionIndex = index; + } + } + } + } + }; + } + + if( m_itemReordableList != null ) + { + EditorGUILayout.Space(); + if( m_items.Count == 0 ) + { + EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one." , MessageType.Info ); + } + else + { + m_itemReordableList.DoLayoutList(); + } + EditorGUILayout.Space(); + } + + if( m_actionType != ReordableAction.None ) + { + switch( m_actionType ) + { + case ReordableAction.Add: + AddPortAt( m_firstAvailablePort + m_actionIndex + 1 ); + break; + case ReordableAction.Remove: + RemovePortAt( m_firstAvailablePort + m_actionIndex ); + break; + } + m_isDirty = true; + m_actionType = ReordableAction.None; + EditorGUI.FocusTextInControl( null ); + } + } + + void RecalculateInOutOutputPorts() + { + m_outputPorts.Sort( ( x , y ) => x.PortId.CompareTo( y.PortId ) ); + + m_outputPortsDict.Clear(); + int count = m_inputPorts.Count - m_firstAvailablePort; + int outputId = 1; + for( int i = 0 ; i < count ; i++ ) + { + int idx = i + m_firstAvailablePort; + if( m_items[ i ].Qualifier != VariableQualifiers.In ) + { + m_outputPorts[ outputId ].ChangeProperties( m_inputPorts[ idx ].Name , m_inputPorts[ idx ].DataType , false ); + m_outputPorts[ outputId ].ChangePortId( CreateOutputId( m_inputPorts[ idx ].PortId ) ); + outputId++; + } + } + + int outCount = m_outputPorts.Count; + for( int i = 0 ; i < outCount ; i++ ) + { + m_outputPortsDict.Add( m_outputPorts[ i ].PortId , m_outputPorts[ i ] ); + } + } + + void AddPortAt( int idx ) + { + AddInputPortAt( idx , WirePortDataType.FLOAT , false , GetFirstAvailableName() ); + m_items.Insert( idx - m_firstAvailablePort , new CustomExpressionInputItem( PrecisionType.Inherit , VariableQualifiers.In , string.Empty , false , true , string.Empty/* "[" + idx + "]"*/ ) ); + m_repopulateNameDictionary = true; + RecalculateInOutOutputPorts(); + } + + void RemovePortAt( int idx ) + { + if( m_inputPorts.Count > m_firstAvailablePort ) + { + int varIdx = idx - m_firstAvailablePort; + if( m_items[ varIdx ].Qualifier != VariableQualifiers.In ) + { + int id = CreateOutputId( m_inputPorts[ idx ].PortId ); + RemoveOutputPort( id , false ); + } + + DeleteInputPortByArrayIdx( idx ); + m_items.RemoveAt( varIdx ); + + m_repopulateNameDictionary = true; + + RecalculateInOutOutputPorts(); + } + } + + public override void OnAfterDeserialize() + { + base.OnAfterDeserialize(); + m_repopulateNameDictionary = true; + } + + public string DealWithFileMode( int outputId , ref MasterNodeDataCollector dataCollector , bool ignoreLocalvar ) + { + OutputPort outputPort = GetOutputPortByUniqueId( outputId ); + if( outputPort.IsLocalValue( dataCollector.PortCategory ) ) + return outputPort.LocalValue( dataCollector.PortCategory ); + + if( m_fileAsset == null && !string.IsNullOrEmpty( m_fileGUID ) ) + { + m_fileAsset = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( m_fileGUID ) ); + } + + if( m_fileAsset != null ) + { + string path = AssetDatabase.GetAssetPath( m_fileAsset ); + dataCollector.AddToIncludes( UniqueId , path ); + + int dependenciesCount = m_dependencies.Count; + Dictionary examinedNodes = new Dictionary(); + for( int i = 0 ; i < dependenciesCount ; i++ ) + { + CustomExpressionNode node = m_containerGraph.GetNode( m_dependencies[ i ].DependencyNodeId ) as CustomExpressionNode; + if( node == null ) + { + node = UIUtils.CurrentWindow.OutsideGraph.GetNode( m_dependencies[ i ].DependencyNodeId ) as CustomExpressionNode; + } + + if( node != null ) + { + node.CheckDependencies( ref dataCollector , ref examinedNodes ); + } + } + + examinedNodes.Clear(); + examinedNodes = null; + + string expressionName = UIUtils.RemoveInvalidCharacters( m_customExpressionName ); + string localVarName = "local" + expressionName; + + localVarName += OutputId; + + int count = m_inputPorts.Count; + + if( m_voidMode ) + { + string mainData = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + RegisterLocalVariable( 0 , string.Format( Constants.CodeWrapper , mainData ) , ref dataCollector , localVarName ); + } + string precisionSuffix = string.Empty; + if( m_precisionSuffix ) + { + switch( CurrentPrecisionType ) + { + default: + case PrecisionType.Float: precisionSuffix = "_float"; break; + case PrecisionType.Half: precisionSuffix = "_half"; break; + } + } + + string functionCall = expressionName + precisionSuffix + "( "; + for( int i = m_firstAvailablePort ; i < count ; i++ ) + { + if( UIUtils.CurrentWindow.OutsideGraph.SamplingMacros && !UIUtils.CurrentWindow.OutsideGraph.IsSRP ) + { + // we don't know what kind of sampling the user will do so we add all of them + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector , m_inputPorts[ i ].DataType , MipType.Auto ); + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector , m_inputPorts[ i ].DataType , MipType.MipLevel ); + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector , m_inputPorts[ i ].DataType , MipType.MipBias ); + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector , m_inputPorts[ i ].DataType , MipType.Derivative ); + } + + string inputPortLocalVar = m_inputPorts[ i ].Name + OutputId; + int idx = i - m_firstAvailablePort; + if( m_inputPorts[ i ].DataType != WirePortDataType.OBJECT ) + { + string result = m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ); + dataCollector.AddLocalVariable( UniqueId , CurrentPrecisionType , m_inputPorts[ i ].DataType , inputPortLocalVar , result ); + } + else + { + string result = ( m_inputPorts[ i ].IsConnected ) ? m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ) : m_inputPorts[ i ].InternalData.ToString(); + string inputLocalVar = string.Format( Constants.CustomTypeLocalValueDecWithoutIdent , m_items[ idx ].CustomType , inputPortLocalVar , result ); + dataCollector.AddLocalVariable( UniqueId , inputLocalVar ); + } + + if( m_items[ idx ].Qualifier != VariableQualifiers.In ) + { + OutputPort currOutputPort = GetOutputPortByUniqueId( CreateOutputId( m_inputPorts[ i ].PortId ) ); + currOutputPort.SetLocalValue( inputPortLocalVar , dataCollector.PortCategory ); + } + functionCall += inputPortLocalVar; + if( i < ( count - 1 ) ) + { + functionCall += " , "; + } + } + functionCall += " )"; + + if( m_voidMode ) + { + dataCollector.AddLocalVariable( 0 , functionCall + ";" , true ); + } + else + { + RegisterLocalVariable( 0 , functionCall , ref dataCollector , localVarName ); + } + + return outputPort.LocalValue( dataCollector.PortCategory ); + + } + + return GenerateErrorValue( outputId ); + } + + public override string GenerateShaderForOutput( int outputId , ref MasterNodeDataCollector dataCollector , bool ignoreLocalvar ) + { + if( Mode == CustomExpressionMode.File ) + { + return DealWithFileMode( outputId , ref dataCollector , ignoreLocalvar ); + } + + if( string.IsNullOrEmpty( m_code ) ) + { + UIUtils.ShowMessage( UniqueId , string.Format( "Custom Expression \"{0}\" need to have code associated" , m_customExpressionName ) , MessageSeverity.Warning ); + return "0"; + } + + m_code = UIUtils.ForceLFLineEnding( m_code ); + + bool codeContainsReturn = m_code.Contains( ReturnHelper ); + + bool expressionMode = false; + if( !codeContainsReturn ) + { + string[] codeLines = m_code.Split( IOUtils.LINE_TERMINATOR ); + expressionMode = codeLines.Length == 1 && !m_voidMode; + } + + if( !expressionMode && + !codeContainsReturn && + m_mode == CustomExpressionMode.Create && !m_voidMode ) + { + UIUtils.ShowMessage( UniqueId , string.Format( "Custom Expression \"{0}\" has a non-void return type but no return instruction was detected" , m_customExpressionName ) , MessageSeverity.Error ); + + if( outputId != 0 ) + UIUtils.ShowMessage( UniqueId , string.Format( "Attempting to get value on Custom Expression \"{0}\" from inexisting \"{1}\" inout/out variable" , m_customExpressionName , m_outputPorts[ outputId ].Name ) , MessageSeverity.Error ); + + return "0"; + } + + int dependenciesCount = m_dependencies.Count; + Dictionary examinedNodes = new Dictionary(); + for( int i = 0 ; i < dependenciesCount ; i++ ) + { + CustomExpressionNode node = m_containerGraph.GetNode( m_dependencies[ i ].DependencyNodeId ) as CustomExpressionNode; + if( node == null ) + { + node = UIUtils.CurrentWindow.OutsideGraph.GetNode( m_dependencies[ i ].DependencyNodeId ) as CustomExpressionNode; + } + + if( node != null ) + { + node.CheckDependencies( ref dataCollector , ref examinedNodes ); + } + } + examinedNodes.Clear(); + examinedNodes = null; + + + OutputPort outputPort = GetOutputPortByUniqueId( outputId ); + if( outputPort.IsLocalValue( dataCollector.PortCategory ) ) + return outputPort.LocalValue( dataCollector.PortCategory ); + + string expressionName = UIUtils.RemoveInvalidCharacters( m_customExpressionName ); + string localVarName = "local" + expressionName; + + if( m_generateUniqueName ) + { + expressionName += OutputId; + } + localVarName += OutputId; + + int count = m_inputPorts.Count; + if( count > 0 ) + { + if( m_mode == CustomExpressionMode.Call || m_voidMode ) + { + string mainData = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + RegisterLocalVariable( 0 , string.Format( Constants.CodeWrapper , mainData ) , ref dataCollector , localVarName ); + } + + if( codeContainsReturn ) + { + string function = WrapCodeInFunction( dataCollector.IsTemplate , expressionName , false ); + string functionCall = expressionName + "( "; + for( int i = m_firstAvailablePort ; i < count ; i++ ) + { + if( UIUtils.CurrentWindow.OutsideGraph.SamplingMacros && !UIUtils.CurrentWindow.OutsideGraph.IsSRP ) + { + // we don't know what kind of sampling the user will do so we add all of them + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector , m_inputPorts[ i ].DataType , MipType.Auto ); + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector , m_inputPorts[ i ].DataType , MipType.MipLevel ); + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector , m_inputPorts[ i ].DataType , MipType.MipBias ); + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector , m_inputPorts[ i ].DataType , MipType.Derivative ); + } + + string inputPortLocalVar = m_inputPorts[ i ].Name + OutputId; + int idx = i - m_firstAvailablePort; + if( m_inputPorts[ i ].DataType != WirePortDataType.OBJECT ) + { + string result = m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ); + dataCollector.AddLocalVariable( UniqueId , CurrentPrecisionType , m_inputPorts[ i ].DataType , inputPortLocalVar , result ); + } + else + { + string result = ( m_inputPorts[ i ].IsConnected ) ? m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ) : m_inputPorts[ i ].InternalData.ToString(); + string inputLocalVar = string.Format( Constants.CustomTypeLocalValueDecWithoutIdent , m_items[ idx ].CustomType , inputPortLocalVar , result ); + dataCollector.AddLocalVariable( UniqueId , inputLocalVar ); + } + + if( m_items[ idx ].Qualifier != VariableQualifiers.In ) + { + OutputPort currOutputPort = GetOutputPortByUniqueId( CreateOutputId( m_inputPorts[ i ].PortId ) ); + currOutputPort.SetLocalValue( inputPortLocalVar , dataCollector.PortCategory ); + } + functionCall += inputPortLocalVar; + if( i < ( count - 1 ) ) + { + functionCall += " , "; + } + } + functionCall += " )"; + + if( m_mode == CustomExpressionMode.Call || m_voidMode ) + { + dataCollector.AddLocalVariable( 0 , functionCall + ";" , true ); + } + else + { + RegisterLocalVariable( 0 , functionCall , ref dataCollector , localVarName ); + } + + dataCollector.AddFunction( expressionName , function ); + } + else + { + + string localCode = m_code; + if( m_mode == CustomExpressionMode.Call || m_voidMode ) + { + for( int i = m_firstAvailablePort ; i < count ; i++ ) + { + int idx = i - m_firstAvailablePort; + if( !m_items[ idx ].IsVariable || + m_items[ idx ].Qualifier != VariableQualifiers.In || + !m_inputPorts[ i ].IsConnected + ) + { + string inputPortLocalVar = m_inputPorts[ i ].Name + OutputId; + string nameToReplaceRegex = string.Format( VarRegexReplacer , m_inputPorts[ i ].Name ); + localCode = Regex.Replace( localCode , nameToReplaceRegex , inputPortLocalVar , RegexOptions.Multiline ); + //localCode = localCode.Replace( m_inputPorts[ i ].Name, inputPortLocalVar ); + + if( m_inputPorts[ i ].IsConnected ) + { + string result = m_inputPorts[ i ].GenerateShaderForOutput( ref dataCollector , m_inputPorts[ i ].DataType , true , true ); + if( m_inputPorts[ i ].DataType == WirePortDataType.OBJECT ) + { + dataCollector.AddLocalVariable( UniqueId , m_items[ idx ].CustomType + " " + inputPortLocalVar , result + ";" ); + } + else + { + dataCollector.AddLocalVariable( UniqueId , CurrentPrecisionType , m_inputPorts[ i ].DataType , inputPortLocalVar , result ); + } + } + else + { + if( m_inputPorts[ i ].DataType == WirePortDataType.OBJECT ) + { + dataCollector.AddLocalVariable( UniqueId , m_items[ idx ].CustomType + " " + inputPortLocalVar , m_inputPorts[ i ].WrappedInternalData + ";" ); + } + else + { + dataCollector.AddLocalVariable( UniqueId , CurrentPrecisionType , m_inputPorts[ i ].DataType , inputPortLocalVar , m_inputPorts[ i ].WrappedInternalData ); + } + } + + if( m_items[ idx ].Qualifier != VariableQualifiers.In ) + { + OutputPort currOutputPort = GetOutputPortByUniqueId( CreateOutputId( m_inputPorts[ i ].PortId ) ); + currOutputPort.SetLocalValue( inputPortLocalVar , dataCollector.PortCategory ); + } + } + else + { + // Not Unique + string result = m_inputPorts[ i ].GenerateShaderForOutput( ref dataCollector , m_inputPorts[ i ].DataType , true , true ); + string nameToReplaceRegex = string.Format( VarRegexReplacer , m_inputPorts[ i ].Name ); + localCode = Regex.Replace( localCode , nameToReplaceRegex , result , RegexOptions.Multiline ); + //localCode = localCode.Replace( m_inputPorts[ i ].Name, result ); + } + } + localCode = string.Format( Constants.InlineCodeWrapper , localCode ); + string[] codeLines = localCode.Split( '\n' ); + for( int codeIdx = 0 ; codeIdx < codeLines.Length ; codeIdx++ ) + { + dataCollector.AddLocalVariable( 0 , codeLines[ codeIdx ] , true ); + } + } + else + { + string function = WrapCodeInFunction( dataCollector.IsTemplate , expressionName , true ); + + string functionCall = expressionName + "( "; + for( int i = m_firstAvailablePort ; i < count ; i++ ) + { + if( UIUtils.CurrentWindow.OutsideGraph.SamplingMacros && !UIUtils.CurrentWindow.OutsideGraph.IsSRP ) + { + // we don't know what kind of sampling the user will do so we add all of them + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector , m_inputPorts[ i ].DataType , MipType.Auto ); + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector , m_inputPorts[ i ].DataType , MipType.MipLevel ); + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector , m_inputPorts[ i ].DataType , MipType.MipBias ); + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector , m_inputPorts[ i ].DataType , MipType.Derivative ); + } + + string inputPortLocalVar = m_inputPorts[ i ].Name + OutputId; + int idx = i - m_firstAvailablePort; + if( m_inputPorts[ i ].DataType != WirePortDataType.OBJECT ) + { + string result = m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ); + dataCollector.AddLocalVariable( UniqueId , CurrentPrecisionType , m_inputPorts[ i ].DataType , inputPortLocalVar , result ); + } + else + { + string result = ( m_inputPorts[ i ].IsConnected ) ? m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ) : m_inputPorts[ i ].InternalData.ToString(); + string inputLocalVar = string.Format( Constants.CustomTypeLocalValueDecWithoutIdent , m_items[ idx ].CustomType , inputPortLocalVar , result ); + dataCollector.AddLocalVariable( UniqueId , inputLocalVar ); + } + + if( m_items[ idx ].Qualifier != VariableQualifiers.In ) + { + OutputPort currOutputPort = GetOutputPortByUniqueId( CreateOutputId( m_inputPorts[ i ].PortId ) ); + currOutputPort.SetLocalValue( inputPortLocalVar , dataCollector.PortCategory ); + } + functionCall += inputPortLocalVar; + if( i < ( count - 1 ) ) + { + functionCall += " , "; + } + } + functionCall += " )"; + RegisterLocalVariable( 0 , functionCall , ref dataCollector , localVarName ); + dataCollector.AddFunction( expressionName , function ); + } + } + + return outputPort.LocalValue( dataCollector.PortCategory ); + } + else + { + if( m_code.Contains( ReturnHelper ) ) + { + string function = WrapCodeInFunction( dataCollector.IsTemplate , expressionName , false ); + dataCollector.AddFunction( expressionName , function ); + string functionCall = expressionName + "()"; + RegisterLocalVariable( 0 , functionCall , ref dataCollector , localVarName ); + } + else + { + RegisterLocalVariable( 0 , string.Format( Constants.CodeWrapper , m_code ) , ref dataCollector , localVarName ); + } + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } + + int CreateOutputId( int inputId ) + { + return ( inputId + 1 ); + } + + int CreateInputId( int outputId ) + { + return outputId - 1; + } + + void UpdateOutputPorts() + { + int count = m_inputPorts.Count - m_firstAvailablePort; + for( int i = 0 ; i < count ; i++ ) + { + if( m_items[ i ].Qualifier != VariableQualifiers.In ) + { + int portIdx = i + m_firstAvailablePort; + int outputPortId = CreateOutputId( m_inputPorts[ portIdx ].PortId ); + AddOutputPort( m_inputPorts[ portIdx ].DataType , m_inputPorts[ portIdx ].Name , outputPortId ); + } + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + // This node is, by default, created with one input port + base.ReadFromString( ref nodeParams ); + m_code = GetCurrentParam( ref nodeParams ); + m_code = m_code.Replace( Constants.LineFeedSeparator , '\n' ); + m_code = m_code.Replace( Constants.SemiColonSeparator , ';' ); + m_outputTypeIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( m_outputTypeIdx >= AvailableWireTypes.Length ) + { + UIUtils.ShowMessage( UniqueId , "Sampler types were removed as a valid output custom expression type" ); + m_outputTypeIdx = 1; + } + UpdateVoidMode(); + m_outputPorts[ 0 ].ChangeType( AvailableWireTypes[ m_outputTypeIdx ] , false ); + + if( UIUtils.CurrentShaderVersion() > 12001 ) + { + if( UIUtils.CurrentShaderVersion() > 18901 ) + { + m_mode = (CustomExpressionMode)Enum.Parse( typeof( CustomExpressionMode ) , GetCurrentParam( ref nodeParams ) ); + } + else + { + bool mode = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_mode = mode ? CustomExpressionMode.Call : CustomExpressionMode.Create; + } + + if( m_mode == CustomExpressionMode.Call || m_voidMode ) + { + m_firstAvailablePort = 1; + AddInputPortAt( 0 , WirePortDataType.FLOAT , false , DefaultInputNameStr ); + } + } + + if( m_mode == CustomExpressionMode.Call || m_mode == CustomExpressionMode.File ) + UIUtils.CurrentWindow.OutsideGraph.CustomExpressionOnFunctionMode.RemoveNode( this ); + + int count = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( count == 0 ) + { + DeleteInputPortByArrayIdx( m_firstAvailablePort ); + m_items.Clear(); + } + else + { + for( int i = 0 ; i < count ; i++ ) + { + bool foldoutValue = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + string name = GetCurrentParam( ref nodeParams ); + WirePortDataType type = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ) , GetCurrentParam( ref nodeParams ) ); + string internalData = GetCurrentParam( ref nodeParams ); + VariableQualifiers qualifier = VariableQualifiers.In; + if( UIUtils.CurrentShaderVersion() > 12001 ) + { + qualifier = (VariableQualifiers)Enum.Parse( typeof( VariableQualifiers ) , GetCurrentParam( ref nodeParams ) ); + } + string customType = string.Empty; + if( UIUtils.CurrentShaderVersion() > 15311 ) + { + customType = GetCurrentParam( ref nodeParams ); + } + PrecisionType precision = PrecisionType.Float; + if( UIUtils.CurrentShaderVersion() > 15607 ) + { + precision = (PrecisionType)Enum.Parse( typeof( PrecisionType ) , GetCurrentParam( ref nodeParams ) ); + } + bool isVariable = false; + if( UIUtils.CurrentShaderVersion() > 16600 ) + { + isVariable = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + int portIdx = i + m_firstAvailablePort; + if( i == 0 ) + { + m_inputPorts[ portIdx ].ChangeProperties( name , type , false ); + m_inputPorts[ portIdx ].Visible = qualifier != VariableQualifiers.Out; + m_items[ 0 ].Qualifier = qualifier; + m_items[ 0 ].FoldoutFlag = foldoutValue; + m_items[ 0 ].CustomType = customType; + m_items[ 0 ].Precision = precision; + m_items[ 0 ].IsVariable = isVariable; + } + else + { + m_items.Add( new CustomExpressionInputItem( precision , qualifier , customType , isVariable , foldoutValue , string.Empty/*"[" + i + "]"*/ ) ); + AddInputPort( type , false , name ); + m_inputPorts[ m_inputPorts.Count - 1 ].Visible = qualifier != VariableQualifiers.Out; + } + m_inputPorts[ i ].InternalData = internalData; + } + } + + if( UIUtils.CurrentShaderVersion() > 7205 ) + { + m_customExpressionName = GetCurrentParam( ref nodeParams ); + SetTitleText( m_customExpressionName ); + } + + if( UIUtils.CurrentShaderVersion() > 14401 ) + { + m_generateUniqueName = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 15102 ) + { + m_autoRegisterMode = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 15403 ) + { + int dependencyCount = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + for( int i = 0 ; i < dependencyCount ; i++ ) + { + m_dependencies.Add( new CustomExpressionDependency( GetCurrentParam( ref nodeParams ) ) ); + } + } + + if( UIUtils.CurrentShaderVersion() > 18901 ) + { + m_fileGUID = GetCurrentParam( ref nodeParams ); + if( !string.IsNullOrEmpty( m_fileGUID ) ) + { + m_fileAsset = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( m_fileGUID ) ); + } + + m_precisionSuffix = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + if( m_mode == CustomExpressionMode.Create ) + { + UIUtils.CurrentWindow.OutsideGraph.CustomExpressionOnFunctionMode.AddNode( this ); + } + UpdateOutputPorts(); + + m_repopulateNameDictionary = true; + m_functionMode = m_code.Contains( ReturnHelper ); + CheckCallMode(); + + } + + public override void WriteToString( ref string nodeInfo , ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo , ref connectionsInfo ); + + m_code = m_code.Replace( Constants.LineFeedSeparator.ToString() , string.Empty ); + m_code = m_code.Replace( Constants.SemiColonSeparator.ToString() , string.Empty ); + m_code = UIUtils.ForceLFLineEnding( m_code ); + + string parsedCode = m_code.Replace( '\n' , Constants.LineFeedSeparator ); + parsedCode = parsedCode.Replace( ';' , Constants.SemiColonSeparator ); + + IOUtils.AddFieldValueToString( ref nodeInfo , parsedCode ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_outputTypeIdx ); + //IOUtils.AddFieldValueToString( ref nodeInfo, m_mode == CustomExpressionMode.Call ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_mode ); + + int count = m_inputPorts.Count - m_firstAvailablePort; + IOUtils.AddFieldValueToString( ref nodeInfo , count ); + for( int i = 0 ; i < count ; i++ ) + { + int portIdx = m_firstAvailablePort + i; + IOUtils.AddFieldValueToString( ref nodeInfo , m_items[ i ].FoldoutFlag ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_inputPorts[ portIdx ].Name ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_inputPorts[ portIdx ].DataType ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_inputPorts[ portIdx ].InternalData ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_items[ i ].Qualifier ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_items[ i ].CustomType ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_items[ i ].Precision ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_items[ i ].IsVariable ); + } + IOUtils.AddFieldValueToString( ref nodeInfo , m_customExpressionName ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_generateUniqueName ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_autoRegisterMode ); + count = m_dependencies.Count; + IOUtils.AddFieldValueToString( ref nodeInfo , count ); + for( int i = 0 ; i < count ; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo , m_dependencies[ i ].DependencyNodeId ); + } + + m_fileGUID = ( m_fileAsset == null ) ? string.Empty : + AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_fileAsset ) ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_fileGUID ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_precisionSuffix ); + } + + public override void Destroy() + { + base.Destroy(); + if( m_mode == CustomExpressionMode.Create ) + { + UIUtils.CurrentWindow.OutsideGraph.CustomExpressionOnFunctionMode.RemoveNode( this ); + } + m_items.Clear(); + m_items = null; + m_dependencies.Clear(); + m_dependencies = null; + m_itemReordableList = null; + } + + public void CheckDependencies( ref MasterNodeDataCollector dataCollector , ref Dictionary examinedNodes ) + { + if( !examinedNodes.ContainsKey( UniqueId ) && m_mode == CustomExpressionMode.Create && !m_generateUniqueName ) + { + int dependencyCount = m_dependencies.Count; + for( int d = 0 ; d < dependencyCount ; d++ ) + { + if( !examinedNodes.ContainsKey( m_dependencies[ d ].DependencyNodeId ) ) + { + CustomExpressionNode dNode = m_containerGraph.GetNode( m_dependencies[ d ].DependencyNodeId ) as CustomExpressionNode; + + if( dNode == null ) + { + dNode = UIUtils.CurrentWindow.OutsideGraph.GetNode( m_dependencies[ d ].DependencyNodeId ) as CustomExpressionNode; + } + + if( dNode != null ) + { + dNode.CheckDependencies( ref dataCollector , ref examinedNodes ); + } + } + } + dataCollector.AddFunction( ExpressionName , EncapsulatedCode( dataCollector.IsTemplate ) ); + examinedNodes.Add( UniqueId , this ); + } + } + + public string EncapsulatedCode( bool isTemplate ) + { + string functionName = UIUtils.RemoveInvalidCharacters( m_customExpressionName ); + if( m_generateUniqueName ) + { + functionName += OutputId; + } + return WrapCodeInFunction( isTemplate , functionName , false ); + } + + public CustomExpressionMode Mode + { + get { return m_mode; } + set + { + if( m_mode != value ) + { + m_mode = value; + if( m_mode == CustomExpressionMode.Call ) + { + AutoRegisterMode = false; + m_generateUniqueName = false; + UIUtils.CurrentWindow.OutsideGraph.CustomExpressionOnFunctionMode.RemoveNode( this ); + } + else if( m_mode == CustomExpressionMode.File ) + { + m_generateUniqueName = false; + UIUtils.CurrentWindow.OutsideGraph.CustomExpressionOnFunctionMode.RemoveNode( this ); + } + else if( m_mode == CustomExpressionMode.Create ) + { + UIUtils.CurrentWindow.OutsideGraph.CustomExpressionOnFunctionMode.AddNode( this ); + } + } + } + } + + public string ExpressionName + { + get + { + string expressionName = UIUtils.RemoveInvalidCharacters( m_customExpressionName ); + + if( m_generateUniqueName ) + { + expressionName += OutputId; + } + return expressionName; + } + } + public override string DataToArray { get { return m_customExpressionName; } } + public bool AutoRegisterMode + { + get { return m_autoRegisterMode; } + set + { + if( value != m_autoRegisterMode ) + { + m_autoRegisterMode = value; + } + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + int portCount = m_inputPorts.Count; + for( int i = 0 ; i < portCount ; i++ ) + { + if( m_inputPorts[ i ].DataType == WirePortDataType.COLOR ) + { + m_inputPorts[ i ].ChangeType( WirePortDataType.FLOAT4 , false ); ; + } + } + + int dependencyCount = m_dependencies.Count; + for( int i = 0 ; i < dependencyCount ; i++ ) + { + m_dependencies[ i ].DependencyArrayIdx = UIUtils.CurrentWindow.OutsideGraph.CustomExpressionOnFunctionMode.GetNodeRegisterIdx( m_dependencies[ i ].DependencyNodeId ); + } + //Fixing bug where user could set main output port as OBJECT + if( m_outputPorts[ 0 ].DataType == WirePortDataType.OBJECT && ( m_voidMode || m_mode == CustomExpressionMode.Call ) ) + { + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType , false ); + } + } + + public override void FireTimedUpdate() + { + UIUtils.CurrentWindow.OutsideGraph.CustomExpressionOnFunctionMode.UpdateDataOnNode( UniqueId , m_customExpressionName ); + } + + public List Dependencies { get { return m_dependencies; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/CustomExpressionNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/CustomExpressionNode.cs.meta new file mode 100644 index 0000000..bf37718 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/CustomExpressionNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f2507a764c07082458e350211d671334 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/DynamicAppendNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/DynamicAppendNode.cs new file mode 100644 index 0000000..64cc8eb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/DynamicAppendNode.cs @@ -0,0 +1,475 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + + public struct AppendData + { + public WirePortDataType PortType; + public int OldPortId; + public int NewPortId; + public AppendData( WirePortDataType portType, int oldPortId, int newPortId ) + { + PortType = portType; + OldPortId = oldPortId; + NewPortId = newPortId; + } + } + + [Serializable] + [NodeAttributes( "Append", "Vector Operators", "Append channels to create a new component", null, KeyCode.V, tags: "combine" )] + public sealed class DynamicAppendNode : ParentNode + { + private const string OutputTypeStr = "Output type"; + private const string OutputFormatStr = "({0}({1}))"; + + [SerializeField] + private WirePortDataType m_selectedOutputType = WirePortDataType.FLOAT4; + + [SerializeField] + private int m_selectedOutputTypeInt = 2; + + private readonly string[] m_outputValueTypes ={ "Vector2", + "Vector3", + "Vector4", + "Color"}; + + [SerializeField] + private int[] m_occupiedChannels = { -1, -1, -1, -1 }; + + [SerializeField] + private int m_maskId; + + [SerializeField] + private Vector4 m_maskValue = Vector4.one; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.ChannelNamesVector[ 0 ] ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.ChannelNamesVector[ 1 ] ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.ChannelNamesVector[ 2 ] ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.ChannelNamesVector[ 3 ] ); + AddOutputPort( m_selectedOutputType, Constants.EmptyPortValue ); + m_textLabelWidth = 90; + m_autoWrapProperties = true; + m_useInternalPortData = true; + m_hasLeftDropdown = true; + m_previewShaderGUID = "bfcd2919fe75bbf428fbbe583f463a9e"; + } + + public override void OnEnable() + { + base.OnEnable(); + m_maskId = Shader.PropertyToID( "_Mask" ); + } + + void NewUpdateBehaviorConn( int portId, bool onLoading ) + { + InputPort inputPort = GetInputPortByUniqueId( portId ); + int channelsRequired = UIUtils.GetChannelsAmount( onLoading ? inputPort.DataType : inputPort.ConnectionType( 0 ) ); + int availableChannels = UIUtils.GetChannelsAmount( m_selectedOutputType ); + + // Invalidate previously used channels + for( int i = 0; i < availableChannels; i++ ) + { + if( m_occupiedChannels[ i ] == portId ) + { + m_occupiedChannels[ i ] = -1; + m_inputPorts[ i ].Visible = true; + } + } + // Lock available channels to port + int len = Mathf.Min( portId + channelsRequired, availableChannels ); + + int channelsUsed = 0; + for( int i = portId; i < len; i++ ) + { + if( m_occupiedChannels[ i ] == -1 ) + { + m_occupiedChannels[ i ] = portId; + channelsUsed += 1; + } + else + { + break; + } + } + + if( !onLoading ) + inputPort.ChangeType( UIUtils.GetWireTypeForChannelAmount( channelsUsed ), false ); + + if( channelsUsed > 1 && portId < availableChannels - 1 ) + { + channelsUsed -= 1; + int i = portId + 1; + for( ; channelsUsed > 0; i++, --channelsUsed ) + { + m_inputPorts[ i ].Visible = false; + } + + } + m_sizeIsDirty = true; + } + + void NewUpdateBehaviorDisconn( int portId ) + { + int availableChannels = UIUtils.GetChannelsAmount( m_selectedOutputType ); + // Invalidate previously used channels + for( int i = 0; i < availableChannels; i++ ) + { + if( m_occupiedChannels[ i ] == portId ) + { + m_occupiedChannels[ i ] = -1; + m_inputPorts[ i ].Visible = true; + m_inputPorts[ i ].ChangeType( WirePortDataType.FLOAT, false ); + } + } + m_sizeIsDirty = true; + } + + void RenamePorts() + { + int channel = 0; + for( int i = 0; i < 4; i++ ) + { + if( m_inputPorts[ i ].Visible ) + { + string name = string.Empty; + int usedChannels = UIUtils.GetChannelsAmount( m_inputPorts[ i ].DataType ); + bool isColor = ( m_selectedOutputType == WirePortDataType.COLOR ); + for( int j = 0; j < usedChannels; j++ ) + { + if( channel < Constants.ChannelNamesVector.Length ) + name += isColor ? Constants.ChannelNamesColor[ channel++ ] : Constants.ChannelNamesVector[ channel++ ]; + } + m_inputPorts[ i ].Name = name; + } + } + + CalculatePreviewData(); + } + + void UpdatePortTypes() + { + ChangeOutputType( m_selectedOutputType, false ); + int availableChannels = UIUtils.GetChannelsAmount( m_selectedOutputType ); + int usedChannels = 0; + while( usedChannels < availableChannels ) + { + int channelsRequired = m_inputPorts[ usedChannels ].IsConnected ? UIUtils.GetChannelsAmount( m_inputPorts[ usedChannels ].DataType ) : 0; + if( channelsRequired > 0 ) + { + + if( ( usedChannels + channelsRequired ) < availableChannels ) + { + usedChannels += channelsRequired; + } + else + { + m_inputPorts[ usedChannels ].Visible = true; + WirePortDataType newType = UIUtils.GetWireTypeForChannelAmount( availableChannels - usedChannels ); + m_inputPorts[ usedChannels ].ChangeType( newType, false ); + usedChannels = availableChannels; + break; + } + } + else + { + m_occupiedChannels[ usedChannels ] = -1; + m_inputPorts[ usedChannels ].Visible = true; + m_inputPorts[ usedChannels ].ChangeType( WirePortDataType.FLOAT, false ); + usedChannels += 1; + } + } + + for( int i = usedChannels; i < availableChannels; i++ ) + { + m_occupiedChannels[ i ] = -1; + m_inputPorts[ i ].Visible = true; + m_inputPorts[ i ].ChangeType( WirePortDataType.FLOAT, false ); + } + + for( int i = availableChannels; i < 4; i++ ) + { + m_occupiedChannels[ i ] = -1; + m_inputPorts[ i ].Visible = false; + m_inputPorts[ i ].ChangeType( WirePortDataType.FLOAT, false ); + } + m_sizeIsDirty = true; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + + if( ( m_containerGraph.IsLoading || m_isNodeBeingCopied ) && UIUtils.CurrentShaderVersion() < 13206 ) + return; + + NewUpdateBehaviorConn( portId, ( UIUtils.IsLoading|| m_isNodeBeingCopied ) ); + RenamePorts(); + + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + + if( ( UIUtils.IsLoading || m_isNodeBeingCopied ) && UIUtils.CurrentShaderVersion() < 13206 ) + return; + + NewUpdateBehaviorDisconn( portId ); + RenamePorts(); + } + + public override void OnConnectedOutputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( portId, otherNodeId, otherPortId, name, type ); + + if( ( UIUtils.IsLoading || m_isNodeBeingCopied ) && UIUtils.CurrentShaderVersion() < 13206 ) + return; + + NewUpdateBehaviorConn( portId, ( UIUtils.IsLoading || m_isNodeBeingCopied ) ); + RenamePorts(); + } + + void SetupPorts() + { + switch( m_selectedOutputTypeInt ) + { + case 0: m_selectedOutputType = WirePortDataType.FLOAT2; break; + case 1: m_selectedOutputType = WirePortDataType.FLOAT3; break; + case 2: m_selectedOutputType = WirePortDataType.FLOAT4; break; + case 3: m_selectedOutputType = WirePortDataType.COLOR; break; + } + UpdatePortTypes(); + RenamePorts(); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( m_dropdownEditing ) + { + EditorGUI.BeginChangeCheck(); + m_selectedOutputTypeInt = EditorGUIPopup( m_dropdownRect, m_selectedOutputTypeInt, m_outputValueTypes, UIUtils.PropertyPopUp ); + if( EditorGUI.EndChangeCheck() ) + { + SetupPorts(); + DropdownEditing = false; + } + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUILayout.BeginVertical(); + + EditorGUI.BeginChangeCheck(); + m_selectedOutputTypeInt = EditorGUILayoutPopup( OutputTypeStr, m_selectedOutputTypeInt, m_outputValueTypes ); + if( EditorGUI.EndChangeCheck() ) + { + SetupPorts(); + } + + EditorGUILayout.EndVertical(); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + string result = string.Empty; + for( int i = 0; i < 4; i++ ) + { + if( m_inputPorts[ i ].Visible ) + { + if( i > 0 ) + { + result += " , "; + } + result += m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ); + } + } + + result = string.Format( OutputFormatStr, + UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_selectedOutputType ), + result ); + + RegisterLocalVariable( 0, result, ref dataCollector, "appendResult" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedOutputType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), GetCurrentParam( ref nodeParams ) ); + switch( m_selectedOutputType ) + { + case WirePortDataType.FLOAT2: m_selectedOutputTypeInt = 0; break; + case WirePortDataType.FLOAT3: m_selectedOutputTypeInt = 1; break; + case WirePortDataType.FLOAT4: m_selectedOutputTypeInt = 2; break; + case WirePortDataType.COLOR: m_selectedOutputTypeInt = 3; break; + } + } + + public override void ReadFromDeprecated( ref string[] nodeParams, Type oldType = null ) + { + m_selectedOutputType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), GetCurrentParam( ref nodeParams ) ); + switch( m_selectedOutputType ) + { + case WirePortDataType.FLOAT2: m_selectedOutputTypeInt = 0; break; + case WirePortDataType.FLOAT3: m_selectedOutputTypeInt = 1; break; + case WirePortDataType.FLOAT4: m_selectedOutputTypeInt = 2; break; + case WirePortDataType.COLOR: m_selectedOutputTypeInt = 3; break; + } + for( int i = 0; i < 4; i++ ) + { + m_inputPorts[i].FloatInternalData = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + + if( UIUtils.CurrentShaderVersion() < 13206 ) + { + //TODO: MAKE THIS LESS BRUTE FORCE + List reroutes = new List(); + int availableChannel = 0; + for( int i = 0; i < 4 && availableChannel < 4; i++ ) + { + int channelsAmount = UIUtils.GetChannelsAmount( m_inputPorts[ i ].DataType ); + if( m_inputPorts[ i ].IsConnected /*&& availableChannel != i*/ ) + { + reroutes.Add( new AppendData( m_inputPorts[ i ].DataType, i, availableChannel ) ); + } + + availableChannel += channelsAmount; + } + + if( reroutes.Count > 0 ) + { + for( int i = reroutes.Count - 1; i > -1; i-- ) + { + int nodeId = m_inputPorts[ reroutes[ i ].OldPortId ].ExternalReferences[ 0 ].NodeId; + int portId = m_inputPorts[ reroutes[ i ].OldPortId ].ExternalReferences[ 0 ].PortId; + + m_containerGraph.DeleteConnection( true, UniqueId, reroutes[ i ].OldPortId, false, false, false ); + m_containerGraph.CreateConnection( UniqueId, reroutes[ i ].NewPortId, nodeId, portId, false ); + NewUpdateBehaviorConn( reroutes[ i ].NewPortId, true ); + } + } + + availableChannel = UIUtils.GetChannelsAmount( m_selectedOutputType ); + int currChannelIdx = 0; + for( ; currChannelIdx < availableChannel; currChannelIdx++ ) + { + if( m_inputPorts[ currChannelIdx ].Visible ) + { + int channelsAmount = UIUtils.GetChannelsAmount( m_inputPorts[ currChannelIdx ].DataType ); + for( int j = currChannelIdx + 1; j < currChannelIdx + channelsAmount; j++ ) + { + m_inputPorts[ j ].Visible = false; + } + } + } + + for( ; currChannelIdx < 4; currChannelIdx++ ) + { + m_inputPorts[ currChannelIdx ].Visible = false; + } + } + SetupPorts(); + m_sizeIsDirty = true; + } + + + void CalculatePreviewData() + { + switch( m_outputPorts[ 0 ].DataType ) + { + default: m_maskValue = Vector4.zero; break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: m_maskValue = new Vector4( 1, 0, 0, 0 ); break; + case WirePortDataType.FLOAT2: m_maskValue = new Vector4( 1, 1, 0, 0 ); break; + case WirePortDataType.FLOAT3: m_maskValue = new Vector4( 1, 1, 1, 0 ); break; + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: m_maskValue = Vector4.one; break; + } + + m_previewMaterialPassId = -1; + switch( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + { + switch( m_inputPorts[ 1 ].DataType ) + { + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + { + if( m_inputPorts[ 2 ].DataType == WirePortDataType.FLOAT || + m_inputPorts[ 2 ].DataType == WirePortDataType.INT ) + { + m_previewMaterialPassId = 0; + } + else if( m_inputPorts[ 2 ].DataType == WirePortDataType.FLOAT2 ) + { + m_previewMaterialPassId = 1; + } + } + break; + case WirePortDataType.FLOAT2: m_previewMaterialPassId = 2; break; + case WirePortDataType.FLOAT3: m_previewMaterialPassId = 3; break; + } + + }; break; + case WirePortDataType.FLOAT2: + { + if( m_inputPorts[ 2 ].DataType == WirePortDataType.FLOAT || + m_inputPorts[ 2 ].DataType == WirePortDataType.INT ) + { + m_previewMaterialPassId = 4; + } + else if( m_inputPorts[ 2 ].DataType == WirePortDataType.FLOAT2 ) + { + m_previewMaterialPassId = 5; + } + }; break; + case WirePortDataType.FLOAT3: m_previewMaterialPassId = 6; break; + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: m_previewMaterialPassId = 7; break; + } + + if( m_previewMaterialPassId == -1 ) + { + m_previewMaterialPassId = 0; + if( DebugConsoleWindow.DeveloperMode ) + { + UIUtils.ShowMessage( UniqueId, "Could not find pass ID for append" , MessageSeverity.Error ); + } + } + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + PreviewMaterial.SetVector( m_maskId, m_maskValue ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedOutputType ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/DynamicAppendNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/DynamicAppendNode.cs.meta new file mode 100644 index 0000000..c442e36 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/DynamicAppendNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bc524cd13743b6f49a2e331767646448 +timeCreated: 1500632879 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/FresnelNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/FresnelNode.cs new file mode 100644 index 0000000..7cb2a32 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/FresnelNode.cs @@ -0,0 +1,393 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// http://kylehalladay.com/blog/tutorial/2014/02/18/Fresnel-Shaders-From-The-Ground-Up.html +// http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter07.html + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Fresnel", "Surface Data", "Simple Fresnel effect" )] + public sealed class FresnelNode : ParentNode + { + private const string FresnedFinalVar = "fresnelNode"; + + [SerializeField] + private ViewSpace m_normalSpace = ViewSpace.Tangent; + + enum FresnelType + { + Standard = 0, + Schlick, + SchlickIOR, + } + + enum NormalType + { + WorldNormal = 0, + TangentNormal, + HalfVector, + } + + enum ViewType + { + ViewDir = 0, + LightDir, + } + + [SerializeField] + private FresnelType m_fresnelType = FresnelType.Standard; + + [SerializeField] + private NormalType m_normalType = NormalType.WorldNormal; + + [SerializeField] + private ViewType m_viewType = ViewType.ViewDir; + + [SerializeField] + private bool m_normalizeVectors = false; + + [SerializeField] + private bool m_safePower = false; + + private InputPort m_normalVecPort; + private InputPort m_viewVecPort; + private InputPort m_biasPort; + private InputPort m_scalePort; + private InputPort m_powerPort; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "World Normal", -1, MasterNodePortCategory.Fragment, 0 ); + AddInputPort( WirePortDataType.FLOAT3, false, "View Dir", -1, MasterNodePortCategory.Fragment, 4 ); + AddInputPort( WirePortDataType.FLOAT, false, "Bias", -1, MasterNodePortCategory.Fragment, 1 ); + AddInputPort( WirePortDataType.FLOAT, false, "Scale", -1, MasterNodePortCategory.Fragment, 2 ); + AddInputPort( WirePortDataType.FLOAT, false, "Power", -1, MasterNodePortCategory.Fragment, 3 ); + AddOutputPort( WirePortDataType.FLOAT, "Out" ); + + m_normalVecPort = m_inputPorts[ 0 ]; + m_viewVecPort = m_inputPorts[ 1 ]; + m_biasPort = m_inputPorts[ 2 ]; + m_scalePort = m_inputPorts[ 3 ]; + m_powerPort = m_inputPorts[ 4 ]; + + m_biasPort.AutoDrawInternalData = true; + m_scalePort.AutoDrawInternalData = true; + m_powerPort.AutoDrawInternalData = true; + m_autoWrapProperties = true; + m_drawPreviewAsSphere = true; + m_normalVecPort.Vector3InternalData = Vector3.forward; + m_scalePort.FloatInternalData = 1; + m_powerPort.FloatInternalData = 5; + m_previewShaderGUID = "240145eb70cf79f428015012559f4e7d"; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + //m_mate + PreviewMaterial.SetInt( "_FresnelType", (int)m_fresnelType ); + + if( m_normalType == NormalType.TangentNormal && m_normalVecPort.IsConnected ) + m_previewMaterialPassId = 2; + else if( (m_normalType == NormalType.WorldNormal || m_normalType == NormalType.HalfVector ) && m_normalVecPort.IsConnected && !m_viewVecPort.IsConnected ) + m_previewMaterialPassId = 1; + else if( m_normalType == NormalType.HalfVector && !m_normalVecPort.IsConnected && !m_viewVecPort.IsConnected ) + m_previewMaterialPassId = 3; + else if( m_normalVecPort.IsConnected && m_viewVecPort.IsConnected ) + m_previewMaterialPassId = 4; + else if( !m_normalVecPort.IsConnected && !m_viewVecPort.IsConnected && m_viewType == ViewType.LightDir ) + m_previewMaterialPassId = 5; + else if( !m_normalVecPort.IsConnected && m_viewVecPort.IsConnected && m_normalType == NormalType.HalfVector ) + m_previewMaterialPassId = 7; + else if( !m_normalVecPort.IsConnected && m_viewVecPort.IsConnected ) + m_previewMaterialPassId = 6; + else + m_previewMaterialPassId = 0; + } + + public override void DrawProperties() + { + base.DrawProperties(); + + EditorGUI.BeginChangeCheck(); + m_fresnelType = (FresnelType)EditorGUILayoutEnumPopup( "Type", m_fresnelType ); + m_normalType = (NormalType)EditorGUILayoutEnumPopup( "Normal Vector", m_normalType ); + m_viewType = (ViewType)EditorGUILayoutEnumPopup( "View Vector", m_viewType ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePort(); + } + + if( !m_biasPort.IsConnected && m_biasPort.Visible ) + m_biasPort.FloatInternalData = EditorGUILayoutFloatField( m_biasPort.Name, m_biasPort.FloatInternalData ); + if( !m_scalePort.IsConnected && m_scalePort.Visible ) + m_scalePort.FloatInternalData = EditorGUILayoutFloatField( m_scalePort.Name, m_scalePort.FloatInternalData ); + if( !m_powerPort.IsConnected && m_powerPort.Visible ) + m_powerPort.FloatInternalData = EditorGUILayoutFloatField( m_powerPort.Name, m_powerPort.FloatInternalData ); + + m_normalizeVectors = EditorGUILayoutToggle( "Normalize Vectors", m_normalizeVectors ); + m_safePower = EditorGUILayoutToggle( PowerNode.SafePowerLabel, m_safePower ); + } + + private void UpdatePort() + { + switch( m_normalType ) + { + default: + case NormalType.WorldNormal: + m_normalVecPort.Name = "World Normal"; + break; + case NormalType.TangentNormal: + m_normalVecPort.Name = "Normal"; + break; + case NormalType.HalfVector: + m_normalVecPort.Name = "Half Vector"; + break; + } + + switch( m_viewType ) + { + default: + case ViewType.ViewDir: + m_viewVecPort.Name = "View Dir"; + break; + case ViewType.LightDir: + m_viewVecPort.Name = "Light Dir"; + break; + } + + switch( m_fresnelType ) + { + default: + case FresnelType.Standard: + m_biasPort.Visible = true; + m_biasPort.Name = "Bias"; + m_scalePort.Name = "Scale"; + m_scalePort.Visible = true; + m_powerPort.Visible = true; + break; + case FresnelType.Schlick: + m_biasPort.Visible = true; + m_biasPort.Name = "F0"; + m_scalePort.Visible = false; + m_powerPort.Visible = false; + break; + case FresnelType.SchlickIOR: + m_biasPort.Visible = false; + m_scalePort.Name = "IOR"; + m_scalePort.Visible = true; + m_powerPort.Visible = false; + break; + } + + m_sizeIsDirty = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + if( dataCollector.IsFragmentCategory ) + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_POS ); + + string viewdir = string.Empty; + if( m_viewType == ViewType.ViewDir ) + { + if( m_viewVecPort.IsConnected ) + viewdir = m_viewVecPort.GeneratePortInstructions( ref dataCollector ); + else + viewdir = GeneratorUtils.GenerateViewDirection( ref dataCollector, UniqueId, ViewSpace.World ); + } + else + { + if( m_viewVecPort.IsConnected ) + viewdir = m_viewVecPort.GeneratePortInstructions( ref dataCollector ); + else + viewdir = GeneratorUtils.GenerateWorldLightDirection( ref dataCollector, UniqueId, CurrentPrecisionType ); + } + + string normal = string.Empty; + if( m_normalType == NormalType.WorldNormal || m_normalType == NormalType.TangentNormal ) + { + if( m_normalVecPort.IsConnected ) + { + normal = m_normalVecPort.GeneratePortInstructions( ref dataCollector ); + + if( dataCollector.IsFragmentCategory ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + + if( m_normalType == NormalType.TangentNormal ) + { + if( dataCollector.IsTemplate ) + { + normal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( UniqueId, CurrentPrecisionType, normal, OutputId ); + } + else + { + normal = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId, CurrentPrecisionType, normal, OutputId ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + dataCollector.ForceNormal = true; + } + } + else + { + if( m_normalizeVectors ) + normal = string.Format( "normalize( {0} )", normal ); + } + } + else + { + if( m_normalType == NormalType.TangentNormal ) + { + string wtMatrix = GeneratorUtils.GenerateWorldToTangentMatrix( ref dataCollector, UniqueId, CurrentPrecisionType ); + normal = "mul( " + normal + "," + wtMatrix + " )"; + } + } + } + else + { + if( dataCollector.IsFragmentCategory ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + if( dataCollector.DirtyNormal ) + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + } + + if( dataCollector.IsTemplate ) + normal = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( CurrentPrecisionType, normalize: ( dataCollector.DirtyNormal && m_normalizeVectors ) ); + else + normal = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId, ( dataCollector.DirtyNormal && m_normalizeVectors ) ); + + if( dataCollector.DirtyNormal ) + { + dataCollector.ForceNormal = true; + } + } + } + else + { + // generate HV + if( !m_normalVecPort.IsConnected ) + { + string halfView = GeneratorUtils.GenerateViewDirection( ref dataCollector, UniqueId, ViewSpace.World ); + string halfLight = GeneratorUtils.GenerateWorldLightDirection( ref dataCollector, UniqueId, CurrentPrecisionType ); + normal = "halfVector" + OutputId; + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, normal, "normalize( " + halfView + " + " + halfLight + " )" ); + } + else + { + normal = m_normalVecPort.GeneratePortInstructions( ref dataCollector ); + if( m_normalizeVectors ) + normal = string.Format( "normalize( {0} )", normal ); + } + } + + string bias = m_biasPort.GeneratePortInstructions( ref dataCollector ); + string scale = m_scalePort.GeneratePortInstructions( ref dataCollector ); + string power = m_powerPort.GeneratePortInstructions( ref dataCollector ); + + string fresnelNDotVLocalValue = "dot( " + normal + ", " + viewdir + " )"; + string fresnelNDotVLocalVar = "fresnelNdotV" + OutputId; + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, fresnelNDotVLocalVar, fresnelNDotVLocalValue ); + + string fresnelFinalVar = FresnedFinalVar + OutputId; + + string result = string.Empty; + switch( m_fresnelType ) + { + default: + case FresnelType.Standard: + { + string powOp = m_safePower? string.Format( "pow( max( 1.0 - {0} , 0.0001 ), {1} )", fresnelNDotVLocalVar, power ): + string.Format( "pow( 1.0 - {0}, {1} )", fresnelNDotVLocalVar, power ); + result = string.Format( "( {0} + {1} * {2} )", bias, scale, powOp ); + } + break; + case FresnelType.Schlick: + { + string f0VarName = "f0" + OutputId; + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, f0VarName, bias ); + string powOp = m_safePower? string.Format( "pow( max( 1.0 - {0} , 0.0001 ), 5 )", fresnelNDotVLocalVar ) : + string.Format( "pow( 1.0 - {0}, 5 )", fresnelNDotVLocalVar ); + result = string.Format( "( {0} + ( 1.0 - {0} ) * {1} )", f0VarName, powOp ); + } + break; + case FresnelType.SchlickIOR: + { + string iorVarName = "ior" + OutputId; + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, iorVarName, scale ); + string iorPowOp = m_safePower? string.Format( "pow( max( ( 1 - {0} ) / ( 1 + {0} ) , 0.0001 ), 2 )", iorVarName ): + string.Format( "pow( ( 1 - {0} ) / ( 1 + {0} ), 2 )", iorVarName ); + + dataCollector.AddLocalVariable( UniqueId, iorVarName +" = "+ iorPowOp + ";"); + + string fresnelPowOp = m_safePower? string.Format( "pow( max( 1.0 - {0} , 0.0001 ), 5 )", fresnelNDotVLocalVar ): + string.Format( "pow( 1.0 - {0}, 5 )", fresnelNDotVLocalVar ); + result = string.Format( "( {0} + ( 1.0 - {0} ) * {1} )", iorVarName, fresnelPowOp ); + } + break; + } + + RegisterLocalVariable( 0, result, ref dataCollector, fresnelFinalVar ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + if( m_normalType == NormalType.TangentNormal && m_normalVecPort.IsConnected ) + dataCollector.DirtyNormal = true; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + + if( UIUtils.CurrentShaderVersion() > 15305 ) + { + m_fresnelType = (FresnelType)Enum.Parse( typeof( FresnelType ), GetCurrentParam( ref nodeParams ) ); + m_normalType = (NormalType)Enum.Parse( typeof( NormalType ), GetCurrentParam( ref nodeParams ) ); + m_viewType = (ViewType)Enum.Parse( typeof( ViewType ), GetCurrentParam( ref nodeParams ) ); + m_normalizeVectors = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 17502 ) + m_safePower = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + else + { + if( UIUtils.CurrentShaderVersion() >= 13202 ) + { + m_normalSpace = (ViewSpace)Enum.Parse( typeof( ViewSpace ), GetCurrentParam( ref nodeParams ) ); + } + else + { + m_normalSpace = ViewSpace.World; + } + + if( m_normalSpace == ViewSpace.World ) + m_normalType = NormalType.WorldNormal; + else + m_normalType = NormalType.TangentNormal; + } + UpdatePort(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + + IOUtils.AddFieldValueToString( ref nodeInfo, m_fresnelType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_viewType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalizeVectors ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_safePower ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/FresnelNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/FresnelNode.cs.meta new file mode 100644 index 0000000..54876f8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/FresnelNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 91955bc593b0dc14d90b10cb3eb25355 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/GetLocalVarNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/GetLocalVarNode.cs new file mode 100644 index 0000000..42fb540 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/GetLocalVarNode.cs @@ -0,0 +1,430 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Get Local Var", "Miscellaneous", "Use a registered local variable", null, KeyCode.G )] + public class GetLocalVarNode : ParentNode + { + [SerializeField] + private int m_referenceId = -1; + + [SerializeField] + private float m_referenceWidth = -1; + + [SerializeField] + private int m_nodeId = -1; + + [SerializeField] + private RegisterLocalVarNode m_currentSelected = null; + + [SerializeField] + private string m_registerLocalVarName = string.Empty; + + private int m_cachedPropertyId = -1; + + private string m_previousLabel = string.Empty; + + private bool m_refSelect = false; + private int m_prevReferenceId = -1; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputPort( WirePortDataType.OBJECT, Constants.EmptyPortValue ); + + // This is needed for infinite loop detection + AddInputPort( WirePortDataType.OBJECT, false, Constants.EmptyPortValue ); + m_inputPorts[ 0 ].Visible = false; + + m_outputPorts[ 0 ].Locked = true; + m_textLabelWidth = 80; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + m_previewShaderGUID = "f21a6e44c7d7b8543afacd19751d24c6"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + + if( UniqueId > -1 ) + m_containerGraph.LocalVarNodes.OnReorderEventComplete += OnReorderEventComplete; + } + + private void OnReorderEventComplete() + { + if( m_currentSelected != null ) + { + m_referenceId = m_containerGraph.LocalVarNodes.GetNodeRegisterIdx( m_currentSelected.UniqueId ); + } + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_currentSelected != null ) + { + if( m_drawPreviewAsSphere != m_currentSelected.SpherePreview ) + { + m_drawPreviewAsSphere = m_currentSelected.SpherePreview; + OnNodeChange(); + } + //CheckSpherePreview(); + + if( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_A" ); + + PreviewMaterial.SetTexture( m_cachedPropertyId, m_currentSelected.OutputPorts[ 0 ].OutputPreviewTexture ); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUILayout.BeginHorizontal(); + EditorGUI.BeginChangeCheck(); + m_referenceId = EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceId, UIUtils.LocalVarNodeArr() ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromSelected(); + } + + if( GUILayout.Button( "\u25C4", "minibutton", GUILayout.Width( 17 ) ) && m_currentSelected ) + { + UIUtils.FocusOnNode( m_currentSelected, 0, false ); + } + EditorGUILayout.EndHorizontal(); + //EditorGUILayout.LabelField( ConnStatus.ToString() + " " + m_activeConnections ); + } + + public override void Destroy() + { + base.Destroy(); + CurrentSelected = null; + if( UniqueId > -1 ) + m_containerGraph.LocalVarNodes.OnReorderEventComplete -= OnReorderEventComplete; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( m_dropdownEditing ) + { + EditorGUI.BeginChangeCheck(); + m_referenceId = EditorGUIPopup( m_dropdownRect, m_referenceId, UIUtils.LocalVarNodeArr(), UIUtils.PropertyPopUp ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromSelected(); + DropdownEditing = false; + } + } + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + UpdateLocalVar(); + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + + if( m_isVisible && m_refSelect && !m_selected ) + { + GUI.color = Constants.SpecialGetLocalVarSelectionColor; + GUI.Label( m_globalPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ) ); + GUI.color = m_colorBuffer; + } + } + + void CheckForLoops() + { + if( CurrentSelected != null && UIUtils.DetectNodeLoopsFrom( CurrentSelected, new Dictionary() ) ) + { + CurrentSelected = UIUtils.GetLocalVarNode( m_prevReferenceId ); + if( CurrentSelected == null || UIUtils.DetectNodeLoopsFrom( CurrentSelected, new Dictionary() ) ) + { + m_referenceId = -1; + m_prevReferenceId = -1; + CurrentSelected = null; + m_outputPorts[ 0 ].Locked = true; + SetAdditonalTitleText( "" ); + UIUtils.ShowMessage( "Infinite Loop detected, disabled selection" ); + } + else + { + m_referenceId = m_prevReferenceId; + UIUtils.ShowMessage( "Infinite Loop detected, reverted to previous selection" ); + } + } + } + + void UpdateFromSelected() + { + CurrentSelected = UIUtils.GetLocalVarNode( m_referenceId ); + CheckForLoops(); + + if( m_currentSelected != null ) + { + m_nodeId = m_currentSelected.UniqueId; + m_outputPorts[ 0 ].Locked = false; + m_outputPorts[ 0 ].ChangeType( m_currentSelected.OutputPorts[ 0 ].DataType, false ); + m_drawPreviewAsSphere = m_currentSelected.SpherePreview; + CheckSpherePreview(); + + m_previousLabel = m_currentSelected.DataToArray; + SetAdditonalTitleText( string.Format( Constants.SubTitleVarNameFormatStr, m_currentSelected.DataToArray ) ); + m_referenceWidth = m_currentSelected.Position.width; + } + + m_sizeIsDirty = true; + m_isDirty = true; + m_prevReferenceId = m_referenceId; + } + + public void UpdateLocalVar() + { + m_refSelect = false; + if( m_referenceId > -1 ) + { + ParentNode newNode = UIUtils.GetLocalVarNode( m_referenceId ); + if( newNode != null ) + { + if( newNode.UniqueId != m_nodeId ) + { + CurrentSelected = null; + int count = UIUtils.LocalVarNodeAmount(); + for( int i = 0; i < count; i++ ) + { + ParentNode node = UIUtils.GetLocalVarNode( i ); + if( node.UniqueId == m_nodeId ) + { + CurrentSelected = node as RegisterLocalVarNode; + m_referenceId = i; + break; + } + } + } + } + + if( m_currentSelected != null ) + { + if( m_currentSelected.OutputPorts[ 0 ].DataType != m_outputPorts[ 0 ].DataType ) + { + m_outputPorts[ 0 ].Locked = false; + m_outputPorts[ 0 ].ChangeType( m_currentSelected.OutputPorts[ 0 ].DataType, false ); + } + + if( !m_previousLabel.Equals( m_currentSelected.DataToArray ) ) + { + m_previousLabel = m_currentSelected.DataToArray; + SetAdditonalTitleText( string.Format( Constants.SubTitleVarNameFormatStr, m_currentSelected.DataToArray ) ); + } + + if( m_referenceWidth != m_currentSelected.Position.width ) + { + m_referenceWidth = m_currentSelected.Position.width; + m_sizeIsDirty = true; + } + + if( m_currentSelected.Selected ) + m_refSelect = true; + } + else + { + ResetReference(); + } + } + } + + public void ResetReference() + { + m_outputPorts[ 0 ].Locked = true; + m_currentSelected = null; + m_inputPorts[ 0 ].DummyClear(); + m_nodeId = -1; + m_referenceId = -1; + m_referenceWidth = -1; + SetAdditonalTitleText( string.Empty ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_currentSelected != null ) + { + return m_currentSelected.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + else + { + UIUtils.ShowMessage( UniqueId, "Get Local Var node without reference. Attempting to access inexistant local variable.", MessageSeverity.Error ); + + return m_outputPorts[ 0 ].ErrorValue; + } + } + + + //public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + //{ + // base.PropagateNodeData( nodeData, ref dataCollector ); + // if( m_currentSelected != null ) + // { + // m_currentSelected.PropagateNodeData( nodeData, ref dataCollector ); + // } + //} + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 15 ) + { + m_nodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_outputPorts[ 0 ].Locked = ( m_nodeId < 0 ); + if( UIUtils.CurrentShaderVersion() > 15500 ) + { + m_registerLocalVarName = GetCurrentParam( ref nodeParams ); + } + } + else + { + m_referenceId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_outputPorts[ 0 ].Locked = ( m_referenceId < 0 ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + if( m_currentSelected != null ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentSelected.UniqueId ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentSelected.DataToArray ); + } + else + { + IOUtils.AddFieldValueToString( ref nodeInfo, -1 ); + IOUtils.AddFieldValueToString( ref nodeInfo, string.Empty ); + } + + } + + public override void OnNodeDoubleClicked( Vector2 currentMousePos2D ) + { + if( m_currentSelected != null ) + { + UIUtils.FocusOnNode( m_currentSelected, 0, true ); + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( UIUtils.CurrentShaderVersion() > 15 ) + { + CurrentSelected = UIUtils.GetNode( m_nodeId ) as RegisterLocalVarNode; + m_referenceId = UIUtils.GetLocalVarNodeRegisterId( m_nodeId ); + if( CurrentSelected == null && UIUtils.CurrentShaderVersion() > 15500 && !string.IsNullOrEmpty( m_registerLocalVarName ) ) + { + CurrentSelected = m_containerGraph.LocalVarNodes.GetNodeByDataToArray( m_registerLocalVarName ); + if( CurrentSelected != null ) + { + m_nodeId = CurrentSelected.UniqueId; + m_referenceId = UIUtils.GetLocalVarNodeRegisterId( m_nodeId ); + } + } + } + else + { + CurrentSelected = UIUtils.GetLocalVarNode( m_referenceId ); + if( m_currentSelected != null ) + { + m_nodeId = m_currentSelected.UniqueId; + } + } + + CheckForLoops(); + + if( m_currentSelected != null ) + { + m_outputPorts[ 0 ].Locked = false; + m_outputPorts[ 0 ].ChangeType( m_currentSelected.OutputPorts[ 0 ].DataType, false ); + } + else + { + m_outputPorts[ 0 ].Locked = true; + } + } + + public override void ActivateNode( int signalGenNodeId, int signalGenPortId, System.Type signalGenNodeType ) + { + base.ActivateNode( signalGenNodeId, signalGenPortId, signalGenNodeType ); + if( m_activeConnections == 1 ) + { + if( m_currentSelected != null ) + { + m_currentSelected.ActivateNode( signalGenNodeId, signalGenPortId, signalGenNodeType ); + } + } + } + + public override void DeactivateNode( int deactivatedPort, bool forceComplete ) + { + forceComplete = forceComplete || ( m_activeConnections == 1 ); + base.DeactivateNode( deactivatedPort, forceComplete ); + if( forceComplete && m_currentSelected != null ) + { + m_currentSelected.DeactivateNode( deactivatedPort, false ); + } + } + + public override void OnNodeSelected( bool value ) + { + base.OnNodeSelected( value ); + if( m_currentSelected != null ) + { + m_currentSelected.CheckReferenceSelection(); + } + } + + public RegisterLocalVarNode CurrentSelected + { + get { return m_currentSelected; } + set + { + // This is needed for infinite loop detection + if( m_inputPorts != null ) + m_inputPorts[ 0 ].DummyClear(); + + if( m_currentSelected != null ) + { + m_currentSelected.UnregisterGetLocalVar( this ); + + //if( m_currentSelected != value ) + m_currentSelected.DeactivateNode( 0, false ); + } + + if( value != null ) + { + value.RegisterGetLocalVar( this ); + if( IsConnected && value != m_currentSelected ) + value.ActivateNode( UniqueId, 0, m_activeType ); + + // This is needed for infinite loop detection + m_inputPorts[ 0 ].DummyAdd( value.UniqueId, 0 ); ; + } + + m_currentSelected = value; + + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/GetLocalVarNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/GetLocalVarNode.cs.meta new file mode 100644 index 0000000..9b80add --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/GetLocalVarNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: efce529ed3c74854b9d0cece836991c3 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LayeredBlendNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LayeredBlendNode.cs new file mode 100644 index 0000000..21589b0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LayeredBlendNode.cs @@ -0,0 +1,61 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Layered Blend", "Miscellaneous", "Mix all channels through interpolation factors", null, KeyCode.None, true )] + public sealed class LayeredBlendNode : WeightedAvgNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 1 ].Name = "Layer Base"; + AddInputPort( WirePortDataType.FLOAT, false, string.Empty ); + for ( int i = 2; i < m_inputPorts.Count; i++ ) + { + m_inputPorts[ i ].Name = AmountsStr[ i - 2 ]; + } + m_inputData = new string[ 6 ]; + m_minimumSize = 2; + UpdateConnection( 0 ); + m_previewShaderGUID = "48faca2f6506fc44c97adb1e2b79c37d"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + GetInputData( ref dataCollector, ignoreLocalvar ); + + string result = string.Empty; + string localVarName = "layeredBlendVar" + OutputId; + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_inputPorts[ 0 ].DataType, localVarName, m_inputData[ 0 ] ); + + if ( m_activeCount == 1 ) + { + result = m_inputData[ 0 ]; + } + else if ( m_activeCount == 2 ) + { + result += "lerp( " + m_inputData[ 1 ] + "," + m_inputData[ 2 ] + " , " + localVarName + " )"; + } + else + { + result = m_inputData[ 1 ]; + for ( int i = 1; i < m_activeCount; i++ ) + { + result = "lerp( " + result + " , " + m_inputData[ i + 1 ] + " , " + localVarName + Constants.VectorSuffixes[ i - 1 ] + " )"; + } + } + result = UIUtils.AddBrackets( result ); + RegisterLocalVariable( 0, result, ref dataCollector, "layeredBlend" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LayeredBlendNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LayeredBlendNode.cs.meta new file mode 100644 index 0000000..bcfcd29 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LayeredBlendNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 90801da82a0b4f74cae2f9387bd5ad92 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LinearDepthNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LinearDepthNode.cs new file mode 100644 index 0000000..5e84c3a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LinearDepthNode.cs @@ -0,0 +1,109 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Linear Depth", "Miscellaneous", "Converts depth values given on logarithmic space to linear" )] + public sealed class LinearDepthNode : ParentNode + { + private readonly string[] LinearModeLabels = { "Eye Space", "0-1 Space" }; + + private const string LinearEyeFuncFormat = "LinearEyeDepth({0})"; + private const string Linear01FuncFormat = "Linear01Depth({0})"; + + private const string LinearEyeFuncSRPFormat = "LinearEyeDepth({0},_ZBufferParams)"; + private const string Linear01FuncSRPFormat = "Linear01Depth({0},_ZBufferParams)"; + + private const string LinerValName = "depthToLinear"; + private const string ViewSpaceLabel = "View Space"; + + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + [SerializeField] + private int m_currentOption = 0; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + m_previewShaderGUID = "2b0785cc8b854974ab4e45419072705a"; + UpdateFromOption(); + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + void UpdateFromOption() + { + m_previewMaterialPassId = m_currentOption; + SetAdditonalTitleText( string.Format( Constants.SubTitleSpaceFormatStr, LinearModeLabels[ m_currentOption ] ) ); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_currentOption = m_upperLeftWidget.DrawWidget( this, m_currentOption, LinearModeLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromOption(); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_currentOption = EditorGUILayoutPopup( ViewSpaceLabel, m_currentOption, LinearModeLabels ); + if( EditorGUI.EndChangeCheck() ) + { + SetAdditonalTitleText( string.Format( Constants.SubTitleSpaceFormatStr, LinearModeLabels[ m_currentOption ] ) ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + if( dataCollector.IsSRP ) + { + value = string.Format( ( ( m_currentOption == 0 ) ? LinearEyeFuncSRPFormat : Linear01FuncSRPFormat ), value ); + } + else + { + value = string.Format( ( ( m_currentOption == 0 ) ? LinearEyeFuncFormat : Linear01FuncFormat ), value ); + } + RegisterLocalVariable( 0, value, ref dataCollector, LinerValName + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentOption ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + int.TryParse( GetCurrentParam( ref nodeParams ), out m_currentOption ); + UpdateFromOption(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LinearDepthNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LinearDepthNode.cs.meta new file mode 100644 index 0000000..490856d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/LinearDepthNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8b8af65130c9ed64f95976ec67ac1adf +timeCreated: 1546438982 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/MatrixFromVectors.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/MatrixFromVectors.cs new file mode 100644 index 0000000..af6325b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/MatrixFromVectors.cs @@ -0,0 +1,215 @@ +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Matrix From Vectors", "Matrix Operators", "Matrix From Vectors" )] + public sealed class MatrixFromVectors : ParentNode + { + private const string RowFromVector = "Input to Row"; + [SerializeField] + private WirePortDataType m_selectedOutputType = WirePortDataType.FLOAT3x3; + + [SerializeField] + private int m_selectedOutputTypeInt = 0; + + [SerializeField] + private Vector3[] m_defaultValuesV3 = { Vector3.zero, Vector3.zero, Vector3.zero }; + + [SerializeField] + private Vector4[] m_defaultValuesV4 = { Vector4.zero, Vector4.zero, Vector4.zero, Vector4.zero }; + + [SerializeField] + private bool m_rowsFromVector = true; + + private string[] m_defaultValuesStr = { "[0]", "[1]", "[2]", "[3]" }; + + private readonly string[] _outputValueTypes ={ "Matrix3X3", + "Matrix4X4"}; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT4, false, "[0]" ); + AddInputPort( WirePortDataType.FLOAT4, false, "[1]" ); + AddInputPort( WirePortDataType.FLOAT4, false, "[2]" ); + AddInputPort( WirePortDataType.FLOAT4, false, "[3]" ); + AddOutputPort( m_selectedOutputType, Constants.EmptyPortValue ); + m_textLabelWidth = 90; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + UpdatePorts(); + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_selectedOutputTypeInt = m_upperLeftWidget.DrawWidget( this, m_selectedOutputTypeInt, _outputValueTypes ); + if( EditorGUI.EndChangeCheck() ) + { + switch( m_selectedOutputTypeInt ) + { + case 0: m_selectedOutputType = WirePortDataType.FLOAT3x3; break; + case 1: m_selectedOutputType = WirePortDataType.FLOAT4x4; break; + } + + UpdatePorts(); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + + EditorGUI.BeginChangeCheck(); + m_selectedOutputTypeInt = EditorGUILayoutPopup( "Output type", m_selectedOutputTypeInt, _outputValueTypes ); + if( EditorGUI.EndChangeCheck() ) + { + switch( m_selectedOutputTypeInt ) + { + case 0: m_selectedOutputType = WirePortDataType.FLOAT3x3; break; + case 1: m_selectedOutputType = WirePortDataType.FLOAT4x4; break; + } + + UpdatePorts(); + } + + int count = 0; + switch( m_selectedOutputType ) + { + case WirePortDataType.FLOAT3x3: + count = 3; + for( int i = 0; i < count; i++ ) + { + if( !m_inputPorts[ i ].IsConnected ) + m_defaultValuesV3[ i ] = EditorGUILayoutVector3Field( m_defaultValuesStr[ i ], m_defaultValuesV3[ i ] ); + } + break; + case WirePortDataType.FLOAT4x4: + count = 4; + for( int i = 0; i < count; i++ ) + { + if( !m_inputPorts[ i ].IsConnected ) + m_defaultValuesV4[ i ] = EditorGUILayoutVector4Field( m_defaultValuesStr[ i ], m_defaultValuesV4[ i ] ); + } + break; + } + m_rowsFromVector = EditorGUILayoutToggle( RowFromVector, m_rowsFromVector ); + } + + void UpdatePorts() + { + m_sizeIsDirty = true; + ChangeOutputType( m_selectedOutputType, false ); + switch( m_selectedOutputType ) + { + case WirePortDataType.FLOAT3x3: + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ 1 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ 2 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ 3 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_inputPorts[ 3 ].Visible = false; + break; + case WirePortDataType.FLOAT4x4: + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_inputPorts[ 1 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_inputPorts[ 2 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_inputPorts[ 3 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_inputPorts[ 3 ].Visible = true; + break; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + string result = ""; + switch( m_selectedOutputType ) + { + case WirePortDataType.FLOAT3x3: + if( m_rowsFromVector ) + { + result = "float3x3(" + m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) + ", " + + m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ) + ", " + + m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ) + ")"; + } + else + { + string vec0 = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string vec1 = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string vec2 = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + result = string.Format( "float3x3({0}.x,{1}.x,{2}.x,{0}.y,{1}.y,{2}.y,{0}.z,{1}.z,{2}.z )", vec0, vec1, vec2 ); + } + break; + case WirePortDataType.FLOAT4x4: + if( m_rowsFromVector ) + { + result = "float4x4(" + m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) + ", " + + m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ) + ", " + + m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ) + ", " + + m_inputPorts[ 3 ].GeneratePortInstructions( ref dataCollector ) + ")"; + } + else + { + string vec0 = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string vec1 = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string vec2 = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + string vec3 = m_inputPorts[ 3 ].GeneratePortInstructions( ref dataCollector ); + result = string.Format( "float4x4( {0}.x,{1}.x,{2}.x,{3}.x,{0}.y,{1}.y,{2}.y,{3}.y,{0}.z,{1}.z,{2}.z,{3}.z,{0}.w,{1}.w,{2}.w,{3}.w )", vec0, vec1, vec2, vec3 ); + } + break; + } + + return result; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedOutputType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 15310 ) + { + m_rowsFromVector = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + switch( m_selectedOutputType ) + { + case WirePortDataType.FLOAT3x3: + m_selectedOutputTypeInt = 0; + break; + case WirePortDataType.FLOAT4x4: + m_selectedOutputTypeInt = 1; + break; + } + UpdatePorts(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedOutputType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_rowsFromVector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/MatrixFromVectors.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/MatrixFromVectors.cs.meta new file mode 100644 index 0000000..2523184 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/MatrixFromVectors.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a313774cf0e4d1e4289d7395e8e49067 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/PosFromTransformMatrix.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/PosFromTransformMatrix.cs new file mode 100644 index 0000000..41a1478 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/PosFromTransformMatrix.cs @@ -0,0 +1,34 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Position From Transform", "Matrix Operators", "Gets the position vector from a transformation matrix" )] + public sealed class PosFromTransformMatrix : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT4x4, true, Constants.EmptyPortValue ); + AddOutputPort( WirePortDataType.FLOAT4, "XYZW" ); + AddOutputPort( WirePortDataType.FLOAT, "X" ); + AddOutputPort( WirePortDataType.FLOAT, "Y" ); + AddOutputPort( WirePortDataType.FLOAT, "Z" ); + AddOutputPort( WirePortDataType.FLOAT, "W" ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string result = string.Format( "float4( {0},{1},{2},{3})", value + "[3][0]", value + "[3][1]", value + "[3][2]", value + "[3][3]" ); + RegisterLocalVariable( 0, result, ref dataCollector, "matrixToPos" + OutputId ); + + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/PosFromTransformMatrix.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/PosFromTransformMatrix.cs.meta new file mode 100644 index 0000000..568be07 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/PosFromTransformMatrix.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7c7321a370f1f1b499d4655cc25f457b +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RegisterLocalVarNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RegisterLocalVarNode.cs new file mode 100644 index 0000000..6a7ab5e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RegisterLocalVarNode.cs @@ -0,0 +1,352 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Register Local Var", "Miscellaneous", "Forces a local variable to be written with the given name. Can then be fetched at any place with a Get Local Var node.", null, KeyCode.R )] + public sealed class RegisterLocalVarNode : ParentNode + { + private const double MaxEditingTimestamp = 1; + + private const string LocalDefaultNameStr = "myVarName"; + private const string LocalVarNameStr = "Var Name"; + private const string OrderIndexStr = "Order Index"; + private const string AutoOrderIndexStr = "Auto Order"; + private const string ReferencesStr = "References"; + + private const string GetLocalVarLabel = "( {0} ) Get Local Var"; + private string m_oldName = string.Empty; + private bool m_reRegisterName = false; + private int m_autoOrderIndex = int.MaxValue; + private bool m_forceUpdate = true; + private bool m_refSelect = false; + + private bool m_referencesVisible = false; + + [SerializeField] + private string m_variableName = LocalDefaultNameStr; + + [SerializeField] + private int m_orderIndex = -1; + + [SerializeField] + private bool m_autoIndexActive = true; + + [SerializeField] + private List m_registeredGetLocalVars = new List(); + + [NonSerialized] + private double m_editingTimestamp; + + [NonSerialized] + private bool m_editingTimestampFlag; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_inputPorts[ 0 ].SetFreeForAll(); + m_textLabelWidth = 85; + m_customPrecision = true; + + if( m_containerGraph != null ) + m_variableName += m_containerGraph.LocalVarNodes.NodesList.Count; + + m_oldName = m_variableName; + UpdateTitle(); + m_previewShaderGUID = "5aaa1d3ea9e1fa64781647e035a82334"; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_containerGraph.LocalVarNodes.AddNode( this ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + + for( int i = 0 ; i < m_registeredGetLocalVars.Count ; i++ ) + { + m_registeredGetLocalVars[ i ].UpdateLocalVar(); + } + } + + void UpdateTitle() + { + SetAdditonalTitleText( string.Format( Constants.SubTitleVarNameFormatStr, m_variableName ) ); + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + if( m_editingTimestampFlag && ( EditorApplication.timeSinceStartup - m_editingTimestamp ) > MaxEditingTimestamp ) + { + m_editingTimestampFlag = false; + CheckAndChangeName(); + } + } + + void DrawMainProperties() + { + EditorGUI.BeginChangeCheck(); + m_variableName = EditorGUILayoutTextField( LocalVarNameStr, m_variableName ); + if( EditorGUI.EndChangeCheck() ) + { + m_editingTimestampFlag = true; + m_editingTimestamp = EditorApplication.timeSinceStartup; + //CheckAndChangeName(); + } + + DrawPrecisionProperty(); + } + + public override void AfterDuplication() + { + base.AfterDuplication(); + CheckAndChangeName(); + } + + void CheckAndChangeName() + { + m_variableName = UIUtils.RemoveInvalidCharacters( m_variableName ); + if( string.IsNullOrEmpty( m_variableName ) ) + { + m_variableName = LocalDefaultNameStr + OutputId; + } + bool isNumericName = UIUtils.IsNumericName( m_variableName ); + bool isLocalVarNameAvailable = m_containerGraph.ParentWindow.DuplicatePrevBufferInstance.IsLocalvariableNameAvailable( m_variableName ); + if( !isNumericName && isLocalVarNameAvailable ) + { + m_containerGraph.ParentWindow.DuplicatePrevBufferInstance.ReleaseLocalVariableName( UniqueId, m_oldName ); + m_containerGraph.ParentWindow.DuplicatePrevBufferInstance.RegisterLocalVariableName( UniqueId, m_variableName ); + m_oldName = m_variableName; + m_containerGraph.LocalVarNodes.UpdateDataOnNode( UniqueId, m_variableName ); + UpdateTitle(); + m_forceUpdate = true; + } + else + { + if( isNumericName ) + { + UIUtils.ShowMessage( UniqueId, string.Format( "Local variable name '{0}' cannot start or be numerical values. Reverting back to '{1}'.", m_variableName, m_oldName ), MessageSeverity.Warning ); + } + else if( !isLocalVarNameAvailable ) + { + UIUtils.ShowMessage( UniqueId, string.Format( "Local variable name '{0}' already being used. Reverting back to '{1}'.", m_variableName, m_oldName ), MessageSeverity.Warning ); + } + + m_variableName = m_oldName; + m_containerGraph.LocalVarNodes.UpdateDataOnNode( UniqueId, m_variableName ); + } + } + + void DrawReferences() + { + int count = m_registeredGetLocalVars.Count; + if( m_registeredGetLocalVars.Count > 0 ) + { + for( int i = 0; i < count; i++ ) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField( string.Format( GetLocalVarLabel, m_registeredGetLocalVars[ i ].UniqueId ) ); + if( GUILayout.Button( "\u25BA", "minibutton", GUILayout.Width( 17 ) ) ) + { + m_containerGraph.ParentWindow.FocusOnNode( m_registeredGetLocalVars[ i ], 0, false ); + } + EditorGUILayout.EndHorizontal(); + } + + if( GUILayout.Button( "Back" ) ) + { + m_containerGraph.ParentWindow.FocusOnNode( this, 0, false ); + } + } + else + { + EditorGUILayout.HelpBox( "This node is not being referenced by any Get Local Var.", MessageType.Info ); + } + } + + public override void DrawProperties() + { + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr, DrawMainProperties ); + NodeUtils.DrawPropertyGroup( ref m_referencesVisible, ReferencesStr, DrawReferences ); + //EditorGUILayout.LabelField(ConnStatus.ToString()+" "+m_activeConnections); + } + + public override void OnEnable() + { + base.OnEnable(); + m_reRegisterName = true; + } + + public void CheckReferenceSelection() + { + m_refSelect = false; + int count = m_registeredGetLocalVars.Count; + for( int i = 0; i < count; i++ ) + { + if( m_registeredGetLocalVars[ i ].Selected ) + m_refSelect = true; + } + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + if( m_isVisible && m_refSelect && !m_selected ) + { + GUI.color = Constants.SpecialRegisterLocalVarSelectionColor; + GUI.Label( m_globalPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ) ); + GUI.color = m_colorBuffer; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + + base.Draw( drawInfo ); + if( m_reRegisterName ) + { + m_reRegisterName = false; + m_containerGraph.ParentWindow.DuplicatePrevBufferInstance.RegisterLocalVariableName( UniqueId, m_variableName ); + } + + if( m_forceUpdate ) + { + m_forceUpdate = false; + UpdateTitle(); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + { + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + string result = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + if( m_inputPorts[ 0 ].DataType == WirePortDataType.OBJECT ) + m_outputPorts[ 0 ].SetLocalValue( result, dataCollector.PortCategory ); + else + RegisterLocalVariable( 0, result, ref dataCollector, m_variableName + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_variableName = GetCurrentParam( ref nodeParams ); + m_oldName = m_variableName; + if( UIUtils.CurrentShaderVersion() > 14 ) + m_orderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + + if( UIUtils.CurrentShaderVersion() > 3106 ) + { + m_autoIndexActive = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + else + { + m_autoIndexActive = false; + } + if( !m_isNodeBeingCopied ) + { + m_containerGraph.LocalVarNodes.UpdateDataOnNode( UniqueId, m_variableName ); + m_containerGraph.ParentWindow.DuplicatePrevBufferInstance.ReleaseLocalVariableName( UniqueId, m_oldName ); + m_containerGraph.ParentWindow.DuplicatePrevBufferInstance.RegisterLocalVariableName( UniqueId, m_variableName ); + } + m_forceUpdate = true; + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_variableName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_orderIndex ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_autoIndexActive ); + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + if( m_autoOrderIndex < nodeData.OrderIndex ) + { + nodeData.OrderIndex = m_autoOrderIndex - 1; + } + else + { + m_autoOrderIndex = nodeData.OrderIndex; + nodeData.OrderIndex -= 1; + } + + base.PropagateNodeData( nodeData, ref dataCollector ); + } + + public override void ResetNodeData() + { + base.ResetNodeData(); + m_autoOrderIndex = int.MaxValue; + } + + public void RegisterGetLocalVar( GetLocalVarNode node ) + { + if( !m_registeredGetLocalVars.Contains( node ) ) + { + m_registeredGetLocalVars.Add( node ); + CheckReferenceSelection(); + } + } + + public void UnregisterGetLocalVar( GetLocalVarNode node ) + { + if( m_registeredGetLocalVars.Contains( node ) ) + { + m_registeredGetLocalVars.Remove( node ); + CheckReferenceSelection(); + } + } + + public override void Destroy() + { + base.Destroy(); + m_containerGraph.LocalVarNodes.RemoveNode( this ); + m_containerGraph.ParentWindow.DuplicatePrevBufferInstance.ReleaseLocalVariableName( UniqueId, m_variableName ); + + int count = m_registeredGetLocalVars.Count; + for( int i = 0; i < count; i++ ) + { + //GetLocalVarNode node = m_containerGraph.GetNode( m_registeredGetLocalVars[ i ] ) as GetLocalVarNode; + if( m_registeredGetLocalVars[ i ] != null ) + m_registeredGetLocalVars[ i ].ResetReference(); + } + m_registeredGetLocalVars.Clear(); + m_registeredGetLocalVars = null; + + m_containerGraph.LocalVarNodes.RemoveNode( this ); + } + + public override void ActivateNode( int signalGenNodeId, int signalGenPortId, Type signalGenNodeType ) + { + base.ActivateNode( signalGenNodeId, signalGenPortId, signalGenNodeType ); + } + public override string DataToArray { get { return m_variableName; } } + public List NodeReferences { get { return m_registeredGetLocalVars; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RegisterLocalVarNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RegisterLocalVarNode.cs.meta new file mode 100644 index 0000000..9cda9e5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RegisterLocalVarNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ebd1a3b3014ccdd40b8fa805b4281c6f +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RelayNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RelayNode.cs new file mode 100644 index 0000000..ab6df69 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RelayNode.cs @@ -0,0 +1,38 @@ +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Relay", "Miscellaneous", "Relay" )] + public sealed class RelayNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.OBJECT, false, Constants.EmptyPortValue ); + AddOutputPort( WirePortDataType.OBJECT, Constants.EmptyPortValue ); + m_previewShaderGUID = "74e4d859fbdb2c0468de3612145f4929"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + return m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, m_inputPorts[ 0 ].DataType, ignoreLocalvar ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RelayNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RelayNode.cs.meta new file mode 100644 index 0000000..378c204 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RelayNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ef679ba7cdeda594aa3e5c02b25e66df +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RotateAboutAxisNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RotateAboutAxisNode.cs new file mode 100644 index 0000000..b9b0a6c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RotateAboutAxisNode.cs @@ -0,0 +1,95 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Rotate About Axis", "Vector Operators", "Rotates a vector around a normalized axis" )] + public class RotateAboutAxisNode : ParentNode + { + private const string FunctionHeader = "float3 RotateAroundAxis( float3 center, float3 original, float3 u, float angle )"; + private const string FunctionCall = "RotateAroundAxis( {0}, {1}, {2}, {3} )"; + private readonly string[] FunctionBody = + { + "float3 RotateAroundAxis( float3 center, float3 original, float3 u, float angle )\n", + "{\n", + "\toriginal -= center;\n", + "\tfloat C = cos( angle );\n", + "\tfloat S = sin( angle );\n", + "\tfloat t = 1 - C;\n", + "\tfloat m00 = t * u.x * u.x + C;\n", + "\tfloat m01 = t * u.x * u.y - S * u.z;\n", + "\tfloat m02 = t * u.x * u.z + S * u.y;\n", + "\tfloat m10 = t * u.x * u.y + S * u.z;\n", + "\tfloat m11 = t * u.y * u.y + C;\n", + "\tfloat m12 = t * u.y * u.z - S * u.x;\n", + "\tfloat m20 = t * u.x * u.z - S * u.y;\n", + "\tfloat m21 = t * u.y * u.z + S * u.x;\n", + "\tfloat m22 = t * u.z * u.z + C;\n", + "\tfloat3x3 finalMatrix = float3x3( m00, m01, m02, m10, m11, m12, m20, m21, m22 );\n", + "\treturn mul( finalMatrix, original ) + center;\n", + "}\n" + }; + + private const string NormalizeAxisLabel = "Rotation Axis"; + private const string NonNormalizeAxisLabel = "Normalized Rotation Axis"; + private const string NormalizeAxisStr = "Normalize Axis"; + + [UnityEngine.SerializeField] + private bool m_normalizeAxis = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, m_normalizeAxis? NormalizeAxisLabel: NonNormalizeAxisLabel ); + AddInputPort( WirePortDataType.FLOAT, false, "Rotation Angle" ); + AddInputPort( WirePortDataType.FLOAT3, false, "Pivot Point" ); + AddInputPort( WirePortDataType.FLOAT3, false, "Position" ); + AddOutputPort( WirePortDataType.FLOAT3, Constants.EmptyPortValue ); + m_useInternalPortData = true; + m_autoWrapProperties = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_normalizeAxis = EditorGUILayoutToggle( NormalizeAxisStr, m_normalizeAxis ); + if( EditorGUI.EndChangeCheck() ) + { + m_inputPorts[ 0 ].Name = (m_normalizeAxis ? NormalizeAxisLabel : NonNormalizeAxisLabel); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string normalizeRotAxis = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + if( m_normalizeAxis ) + { + normalizeRotAxis = string.Format( "normalize( {0} )", normalizeRotAxis ); + } + string rotationAngle = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string pivotPoint = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + string position = m_inputPorts[ 3 ].GeneratePortInstructions( ref dataCollector ); + dataCollector.AddFunction( FunctionHeader, FunctionBody, false ); + RegisterLocalVariable( 0, string.Format( FunctionCall, pivotPoint, position, normalizeRotAxis, rotationAngle ), ref dataCollector, "rotatedValue" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_normalizeAxis = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalizeAxis ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RotateAboutAxisNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RotateAboutAxisNode.cs.meta new file mode 100644 index 0000000..f5af5b8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/RotateAboutAxisNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6190b6c1a4cd29b48bfd36ff9b2ea773 +timeCreated: 1513184612 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SummedBlendNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SummedBlendNode.cs new file mode 100644 index 0000000..735bcd9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SummedBlendNode.cs @@ -0,0 +1,56 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Summed Blend", "Miscellaneous", "Mix all channels through weighted sum", null, KeyCode.None, true )] + public sealed class SummedBlendNode : WeightedAvgNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputData = new string[ 6 ]; + m_previewShaderGUID = "eda18b96e13f78b49bbdaa4da3fead19"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + GetInputData( ref dataCollector, ignoreLocalvar ); + + string result = string.Empty; + string localVarName = "weightedBlendVar" + OutputId; + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_inputPorts[ 0 ].DataType, localVarName, m_inputData[ 0 ] ); + + if ( m_activeCount == 0 ) + { + result = m_inputData[ 0 ]; + } + else if ( m_activeCount == 1 ) + { + result += localVarName + "*" + m_inputData[ 1 ]; + } + else + { + for ( int i = 0; i < m_activeCount; i++ ) + { + result += localVarName + Constants.VectorSuffixes[ i ] + "*" + m_inputData[ i + 1 ]; + if ( i != ( m_activeCount - 1 ) ) + { + result += " + "; + } + } + } + + result = UIUtils.AddBrackets( result ); + RegisterLocalVariable( 0, result, ref dataCollector, "weightedBlend" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SummedBlendNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SummedBlendNode.cs.meta new file mode 100644 index 0000000..102a6f1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SummedBlendNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: da71cf021d98a7f468319e56eaefe6f1 +timeCreated: 1484229430 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwitchNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwitchNode.cs new file mode 100644 index 0000000..ae3d410 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwitchNode.cs @@ -0,0 +1,230 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Debug Switch", "Logical Operators", "Hard Switch between any of its input ports" )] + public class SwitchNode : ParentNode + { + private const string Info = "This is a Debug node which only generates the source for the selected port. This means that no properties are generated for other ports and information might be lost."; + private const string InputPortName = "In "; + + private const string CurrSelectedStr = "Current"; + private const string MaxAmountStr = "Max Amount"; + private const int MaxAllowedAmount = 8; + + [SerializeField] + private string[] m_availableInputsLabels = { "In 0", "In 1" }; + + [SerializeField] + private int[] m_availableInputsValues = { 0, 1 }; + + [SerializeField] + private int m_currentSelectedInput = 0; + + [SerializeField] + private int m_maxAmountInputs = 2; + + private int m_cachedPropertyId = -1; + + private GUIContent m_popContent; + + private Rect m_varRect; + private Rect m_imgRect; + private bool m_editing; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + for( int i = 0; i < MaxAllowedAmount; i++ ) + { + AddInputPort( WirePortDataType.FLOAT, false, InputPortName + i ); + m_inputPorts[ i ].Visible = ( i < 2 ); + } + AddOutputPort( WirePortDataType.FLOAT, " " ); + + m_popContent = new GUIContent(); + m_popContent.image = UIUtils.PopupIcon; + + m_insideSize.Set( 50, 25 ); + m_textLabelWidth = 100; + m_autoWrapProperties = false; + m_previewShaderGUID = "a58e46feaa5e3d14383bfeac24d008bc"; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_Current" ); + + PreviewMaterial.SetInt( m_cachedPropertyId, m_currentSelectedInput ); + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + m_inputPorts[ inputPortId ].MatchPortToConnection(); + if( inputPortId == m_currentSelectedInput ) + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ inputPortId ].DataType, false ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ portId ].MatchPortToConnection(); + if( portId == m_currentSelectedInput ) + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ portId ].DataType, false ); + } + + public void UpdateLabels() + { + m_availableInputsLabels = new string[ m_maxAmountInputs ]; + m_availableInputsValues = new int[ m_maxAmountInputs ]; + + for( int i = 0; i < m_maxAmountInputs; i++ ) + { + m_availableInputsLabels[ i ] = InputPortName + i; + m_availableInputsValues[ i ] = i; + } + } + + //void UpdateOutput() + //{ + // m_outputPorts[ 0 ].ChangeProperties( m_inputPorts[ m_currentSelectedInput ].Name, m_inputPorts[ m_currentSelectedInput ].DataType, false ); + // m_sizeIsDirty = true; + //} + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_varRect = m_remainingBox; + m_varRect.width = 50 * drawInfo.InvertedZoom; + m_varRect.height = 16 * drawInfo.InvertedZoom; + m_varRect.x = m_remainingBox.xMax - m_varRect.width; + //m_varRect.x += m_remainingBox.width * 0.5f - m_varRect.width * 0.5f; + m_varRect.y += 1 * drawInfo.InvertedZoom; + + m_imgRect = m_varRect; + m_imgRect.x = m_varRect.xMax - 16 * drawInfo.InvertedZoom; + m_imgRect.width = 16 * drawInfo.InvertedZoom; + m_imgRect.height = m_imgRect.width; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if( drawInfo.CurrentEventType != EventType.MouseDown ) + return; + + if( m_varRect.Contains( drawInfo.MousePosition ) ) + { + m_editing = true; + } + else if( m_editing ) + { + m_editing = false; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( m_editing ) + { + EditorGUI.BeginChangeCheck(); + m_currentSelectedInput = EditorGUIIntPopup( m_varRect, m_currentSelectedInput, m_availableInputsLabels, m_availableInputsValues, UIUtils.GraphDropDown ); + if( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + m_editing = false; + } + } + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + + if( !m_isVisible ) + return; + + if( !m_editing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + { + GUI.Label( m_varRect, m_availableInputsLabels[ m_currentSelectedInput ], UIUtils.GraphDropDown ); + GUI.Label( m_imgRect, m_popContent, UIUtils.GraphButtonIcon ); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr, DrawDebugOptions ); + + EditorGUILayout.HelpBox( Info, MessageType.Warning ); + } + + void DrawDebugOptions() + { + EditorGUI.BeginChangeCheck(); + m_maxAmountInputs = EditorGUILayoutIntSlider( MaxAmountStr, m_maxAmountInputs, 2, MaxAllowedAmount ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < MaxAllowedAmount; i++ ) + { + m_inputPorts[ i ].Visible = ( i < m_maxAmountInputs ); + } + + if( m_currentSelectedInput >= m_maxAmountInputs ) + { + m_currentSelectedInput = m_maxAmountInputs - 1; + } + + UpdateLabels(); + m_sizeIsDirty = true; + } + + m_currentSelectedInput = EditorGUILayoutIntPopup( CurrSelectedStr, m_currentSelectedInput, m_availableInputsLabels, m_availableInputsValues ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + return m_inputPorts[ m_currentSelectedInput ].GeneratePortInstructions( ref dataCollector ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_currentSelectedInput = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_maxAmountInputs = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + + for( int i = 0; i < MaxAllowedAmount; i++ ) + { + m_inputPorts[ i ].Visible = ( i < m_maxAmountInputs ); + } + + if( m_currentSelectedInput >= m_maxAmountInputs ) + { + m_currentSelectedInput = m_maxAmountInputs - 1; + } + + UpdateLabels(); + m_sizeIsDirty = true; + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentSelectedInput ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_maxAmountInputs ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwitchNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwitchNode.cs.meta new file mode 100644 index 0000000..246aa75 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwitchNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ad88ed9f1b6010a4bb17685dec17a585 +timeCreated: 1483956795 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwizzleNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwizzleNode.cs new file mode 100644 index 0000000..ec83951 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwizzleNode.cs @@ -0,0 +1,441 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Swizzle +// Donated by Tobias Pott - @ Tobias Pott +// www.tobiaspott.de + +using System; +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Swizzle", "Vector Operators", "Swizzle components of vector types", null, KeyCode.Z, true, false, null, null, "Tobias Pott - @TobiasPott" )] + public sealed class SwizzleNode : SingleInputOp + { + + private const string OutputTypeStr = "Output type"; + + [SerializeField] + private WirePortDataType m_selectedOutputType = WirePortDataType.FLOAT4; + + [SerializeField] + private int m_selectedOutputTypeInt = 3; + + [SerializeField] + private int[] m_selectedOutputSwizzleTypes = new int[] { 0, 1, 2, 3 }; + + [SerializeField] + private int m_maskId; + + [SerializeField] + private Vector4 m_maskValue = Vector4.one; + + private readonly string[] SwizzleVectorChannels = { "x", "y", "z", "w" }; + private readonly string[] SwizzleColorChannels = { "r", "g", "b", "a" }; + private readonly string[] SwizzleChannelLabels = { "Channel 0", "Channel 1", "Channel 2", "Channel 3" }; + + private readonly string[] m_outputValueTypes ={ "Float", + "Vector 2", + "Vector 3", + "Vector 4"}; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + + + m_inputPorts[ 0 ].DataType = WirePortDataType.FLOAT4; + m_outputPorts[ 0 ].DataType = m_selectedOutputType; + m_textLabelWidth = 90; + m_autoWrapProperties = true; + m_autoUpdateOutputPort = false; + m_hasLeftDropdown = true; + m_previewShaderGUID = "d20531704ce28b14bafb296f291f6608"; + SetAdditonalTitleText( "Value( XYZW )" ); + CalculatePreviewData(); + } + + public override void OnEnable() + { + base.OnEnable(); + m_maskId = Shader.PropertyToID( "_Mask" ); + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + PreviewMaterial.SetVector( m_maskId, m_maskValue ); + } + + void CalculatePreviewData() + { + switch( m_outputPorts[ 0 ].DataType ) + { + default: m_maskValue = Vector4.zero; break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: m_maskValue = new Vector4( 1, 0, 0, 0 ); break; + case WirePortDataType.FLOAT2: m_maskValue = new Vector4( 1, 1, 0, 0 ); break; + case WirePortDataType.FLOAT3: m_maskValue = new Vector4( 1, 1, 1, 0 ); break; + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: m_maskValue = Vector4.one; break; + } + + int inputMaxChannelId = 0; + switch( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + inputMaxChannelId = 3; + break; + case WirePortDataType.FLOAT3: + inputMaxChannelId = 2; + break; + case WirePortDataType.FLOAT2: + inputMaxChannelId = 1; + break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + inputMaxChannelId = 0; + break; + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + break; + } + + m_previewMaterialPassId = -1; + float passValue = 0; + for( int i = 3; i > -1; i-- ) + { + int currentSwizzle = Mathf.Min( inputMaxChannelId, m_selectedOutputSwizzleTypes[ i ] ); + if( currentSwizzle > 0 ) + { + passValue += Mathf.Pow( 4, 3 - i ) * currentSwizzle; + } + } + + m_previewMaterialPassId = (int)passValue; + + if( m_previewMaterialPassId == -1 ) + { + m_previewMaterialPassId = 0; + if( DebugConsoleWindow.DeveloperMode ) + { + UIUtils.ShowMessage( UniqueId, "Could not find pass ID for swizzle", MessageSeverity.Error ); + } + } + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + + if ( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if ( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + UpdatePorts(); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdatePorts(); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + UpdatePorts(); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if ( m_dropdownEditing ) + { + EditorGUI.BeginChangeCheck(); + m_selectedOutputTypeInt = EditorGUIPopup( m_dropdownRect, m_selectedOutputTypeInt, m_outputValueTypes, UIUtils.PropertyPopUp ); + if ( EditorGUI.EndChangeCheck() ) + { + switch ( m_selectedOutputTypeInt ) + { + case 0: m_selectedOutputType = WirePortDataType.FLOAT; break; + case 1: m_selectedOutputType = WirePortDataType.FLOAT2; break; + case 2: m_selectedOutputType = WirePortDataType.FLOAT3; break; + case 3: m_selectedOutputType = WirePortDataType.FLOAT4; break; + } + + UpdatePorts(); + DropdownEditing = false; + } + } + } + + public override void DrawProperties() + { + + EditorGUILayout.BeginVertical(); + EditorGUI.BeginChangeCheck(); + m_selectedOutputTypeInt = EditorGUILayoutPopup( OutputTypeStr, m_selectedOutputTypeInt, m_outputValueTypes ); + if ( EditorGUI.EndChangeCheck() ) + { + switch ( m_selectedOutputTypeInt ) + { + case 0: m_selectedOutputType = WirePortDataType.FLOAT; break; + case 1: m_selectedOutputType = WirePortDataType.FLOAT2; break; + case 2: m_selectedOutputType = WirePortDataType.FLOAT3; break; + case 3: m_selectedOutputType = WirePortDataType.FLOAT4; break; + } + + UpdatePorts(); + } + EditorGUILayout.EndVertical(); + + // Draw base properties + base.DrawProperties(); + + EditorGUILayout.BeginVertical(); + + int count = 0; + + switch ( m_selectedOutputType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + count = 4; + break; + case WirePortDataType.FLOAT3: + count = 3; + break; + case WirePortDataType.FLOAT2: + count = 2; + break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + count = 1; + break; + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + break; + } + + EditorGUI.BeginChangeCheck(); + if ( m_inputPorts[ 0 ].DataType == WirePortDataType.COLOR ) + { + for ( int i = 0; i < count; i++ ) + { + m_selectedOutputSwizzleTypes[ i ] = EditorGUILayoutPopup( SwizzleChannelLabels[ i ], m_selectedOutputSwizzleTypes[ i ], SwizzleColorChannels ); + } + } + else + { + for ( int i = 0; i < count; i++ ) + { + m_selectedOutputSwizzleTypes[ i ] = EditorGUILayoutPopup( SwizzleChannelLabels[ i ], m_selectedOutputSwizzleTypes[ i ], SwizzleVectorChannels ); + } + } + if ( EditorGUI.EndChangeCheck() ) + { + UpdatePorts(); + } + + EditorGUILayout.EndVertical(); + + } + + void UpdatePorts() + { + ChangeOutputType( m_selectedOutputType, false ); + + int count = 0; + switch ( m_selectedOutputType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + count = 4; + break; + case WirePortDataType.FLOAT3: + count = 3; + break; + case WirePortDataType.FLOAT2: + count = 2; + break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + count = 1; + break; + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + break; + } + + int inputMaxChannelId = 0; + switch ( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + inputMaxChannelId = 3; + break; + case WirePortDataType.FLOAT3: + inputMaxChannelId = 2; + break; + case WirePortDataType.FLOAT2: + inputMaxChannelId = 1; + break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + inputMaxChannelId = 0; + break; + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + break; + } + + //for ( int i = 0; i < count; i++ ) + //{ + //m_selectedOutputSwizzleTypes[ i ] = Mathf.Clamp( m_selectedOutputSwizzleTypes[ i ], 0, inputMaxChannelId ); + //} + + // Update Title + string additionalText = string.Empty; + for ( int i = 0; i < count; i++ ) + { + int currentSwizzle = Mathf.Min( inputMaxChannelId, m_selectedOutputSwizzleTypes[ i ] ); + additionalText += GetSwizzleComponentForChannel( currentSwizzle ).ToUpper(); + } + + if ( additionalText.Length > 0 ) + SetAdditonalTitleText( "Value( " + additionalText + " )" ); + else + SetAdditonalTitleText( string.Empty ); + + CalculatePreviewData(); + m_sizeIsDirty = true; + } + + public string GetSwizzleComponentForChannel( int channel ) + { + if ( m_inputPorts[ 0 ].DataType == WirePortDataType.COLOR ) + { + return SwizzleColorChannels[ channel ]; + } + else + { + return SwizzleVectorChannels[ channel ]; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string value = string.Format( "({0}).", m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) ); + + int inputMaxChannelId = 0; + switch( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + inputMaxChannelId = 3; + break; + case WirePortDataType.FLOAT3: + inputMaxChannelId = 2; + break; + case WirePortDataType.FLOAT2: + inputMaxChannelId = 1; + break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + inputMaxChannelId = 0; + break; + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + break; + } + + int count = 0; + switch ( m_selectedOutputType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + count = 4; + break; + case WirePortDataType.FLOAT3: + count = 3; + break; + case WirePortDataType.FLOAT2: + count = 2; + break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + count = 1; + break; + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + break; + } + + for ( int i = 0; i < count; i++ ) + { + int currentSwizzle = Mathf.Min( inputMaxChannelId, m_selectedOutputSwizzleTypes[ i ] ); + value += GetSwizzleComponentForChannel( currentSwizzle ); + } + + return CreateOutputLocalVariable( 0, value, ref dataCollector ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedOutputType = ( WirePortDataType ) Enum.Parse( typeof( WirePortDataType ), GetCurrentParam( ref nodeParams ) ); + switch ( m_selectedOutputType ) + { + case WirePortDataType.FLOAT: m_selectedOutputTypeInt = 0; break; + case WirePortDataType.FLOAT2: m_selectedOutputTypeInt = 1; break; + case WirePortDataType.FLOAT3: m_selectedOutputTypeInt = 2; break; + case WirePortDataType.COLOR: + case WirePortDataType.FLOAT4: m_selectedOutputTypeInt = 3; break; + } + for ( int i = 0; i < m_selectedOutputSwizzleTypes.Length; i++ ) + { + m_selectedOutputSwizzleTypes[ i ] = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + UpdatePorts(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedOutputType ); + for ( int i = 0; i < m_selectedOutputSwizzleTypes.Length; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedOutputSwizzleTypes[ i ] ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwizzleNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwizzleNode.cs.meta new file mode 100644 index 0000000..5049f92 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/SwizzleNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3bb41488b4b3e034d838c73c2eb471f5 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/ToggleSwitchNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/ToggleSwitchNode.cs new file mode 100644 index 0000000..fddc5b6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/ToggleSwitchNode.cs @@ -0,0 +1,311 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Toggle Switch", "Logical Operators", "Switch between any of its input ports" )] + public class ToggleSwitchNode : PropertyNode + { + private const string InputPortName = "In "; + private const string CurrSelectedStr = "Toggle Value"; + private const string GenerateKeywordStr = "Generate Keyword"; + //private const string LerpOp = "lerp({0},{1},{2})"; + private const string LerpOp = "(( {2} )?( {1} ):( {0} ))"; + + [SerializeField] + private string[] AvailableInputsLabels = { "In 0", "In 1" }; + + [SerializeField] + private int[] AvailableInputsValues = { 0, 1 }; + + [SerializeField] + private int m_currentSelectedInput = 0; + + [SerializeField] + private WirePortDataType m_mainDataType = WirePortDataType.FLOAT; + + [SerializeField] + private bool m_generateKeyword = true; + + private int m_cachedPropertyId = -1; + + private GUIContent m_popContent; + + private Rect m_varRect; + private Rect m_imgRect; + private bool m_editing; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( m_mainDataType, false, InputPortName + "0" ); + AddInputPort( m_mainDataType, false, InputPortName + "1" ); + + AddOutputPort( m_mainDataType, " " ); + m_insideSize.Set( 80, 25 ); + m_currentParameterType = PropertyType.Property; + m_customPrefix = "Toggle Switch"; + + m_popContent = new GUIContent(); + m_popContent.image = UIUtils.PopupIcon; + + m_availableAttribs.Clear(); + //Need to maintain this because of retrocompatibility reasons + m_availableAttribs.Add( new PropertyAttributes( "Toggle", "[Toggle]" ) ); + + m_drawAttributes = false; + m_freeType = false; + m_useVarSubtitle = true; + m_useInternalPortData = true; + m_previewShaderGUID = "beeb138daeb592a4887454f81dba2b3f"; + + m_allowPropertyDuplicates = true; + m_showAutoRegisterUI = false; + + m_srpBatcherCompatible = true; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + UIUtils.RegisterPropertyNode( this ); + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if ( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_Current" ); + + PreviewMaterial.SetInt( m_cachedPropertyId, m_currentSelectedInput ); + } + + public override void OnConnectedOutputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( portId, otherNodeId, otherPortId, name, type ); + UpdateConnection(); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnection(); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + UpdateConnection(); + } + + void UpdateConnection() + { + WirePortDataType type1 = WirePortDataType.FLOAT; + if( m_inputPorts[ 0 ].IsConnected ) + type1 = m_inputPorts[ 0 ].GetOutputConnection( 0 ).DataType; + + WirePortDataType type2 = WirePortDataType.FLOAT; + if( m_inputPorts[ 1 ].IsConnected ) + type2 = m_inputPorts[ 1 ].GetOutputConnection( 0 ).DataType; + + m_mainDataType = UIUtils.GetPriority( type1 ) > UIUtils.GetPriority( type2 ) ? type1 : type2; + + m_inputPorts[ 0 ].ChangeType( m_mainDataType, false ); + m_inputPorts[ 1 ].ChangeType( m_mainDataType, false ); + + + //m_outputPorts[ 0 ].ChangeProperties( m_out, m_mainDataType, false ); + m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_varRect = m_remainingBox; + m_varRect.width = 50 * drawInfo.InvertedZoom; + m_varRect.height = 16 * drawInfo.InvertedZoom; + m_varRect.x = m_remainingBox.xMax - m_varRect.width; + m_varRect.y += 1 * drawInfo.InvertedZoom; + + m_imgRect = m_varRect; + m_imgRect.x = m_varRect.xMax - 16 * drawInfo.InvertedZoom; + m_imgRect.width = 16 * drawInfo.InvertedZoom; + m_imgRect.height = m_imgRect.width; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if ( drawInfo.CurrentEventType != EventType.MouseDown ) + return; + + if ( m_varRect.Contains( drawInfo.MousePosition ) ) + { + m_editing = true; + } + else if ( m_editing ) + { + m_editing = false; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( m_editing ) + { + EditorGUI.BeginChangeCheck(); + m_currentSelectedInput = EditorGUIIntPopup( m_varRect, m_currentSelectedInput, AvailableInputsLabels, AvailableInputsValues, UIUtils.SwitchNodePopUp ); + if ( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + UpdateConnection(); + m_requireMaterialUpdate = true; + m_editing = false; + } + } + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + + if ( !m_isVisible ) + return; + + if ( !m_editing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + { + GUI.Label( m_varRect, AvailableInputsLabels[ m_currentSelectedInput ], UIUtils.GraphDropDown ); + GUI.Label( m_imgRect, m_popContent, UIUtils.GraphButtonIcon ); + } + } + + public override void DrawMainPropertyBlock() + { + EditorGUILayout.BeginVertical(); + { + ShowPropertyInspectorNameGUI(); + ShowPropertyNameGUI( true ); + ShowVariableMode(); + ShowHybridInstanced(); + ShowAutoRegister(); + ShowPrecision(); + m_generateKeyword = EditorGUILayoutToggle( GenerateKeywordStr, m_generateKeyword ); + ShowToolbar(); + } + EditorGUILayout.EndVertical(); + + EditorGUILayout.Separator(); + EditorGUI.BeginChangeCheck(); + m_currentSelectedInput = EditorGUILayoutIntPopup( CurrSelectedStr, m_currentSelectedInput, AvailableInputsLabels, AvailableInputsValues ); + if ( EditorGUI.EndChangeCheck() ) + { + UpdateConnection(); + m_requireMaterialUpdate = true; + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + NodeUtils.DrawPropertyGroup( ref m_visibleCustomAttrFoldout, CustomAttrStr, DrawCustomAttributes, DrawCustomAttrAddRemoveButtons ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + m_precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ); + + string resultA = m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, m_mainDataType, ignoreLocalvar, true ); + string resultB = m_inputPorts[ 1 ].GenerateShaderForOutput( ref dataCollector, m_mainDataType, ignoreLocalvar, true ); + return string.Format( LerpOp, resultA, resultB, m_propertyName ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_currentSelectedInput = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 18806 ) + { + m_generateKeyword = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentSelectedInput ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_generateKeyword ); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + m_selectedAttribs.Clear(); + UpdateConnection(); + } + public override string GetPropertyValue() + { +#if UNITY_2018_1_OR_NEWER + string toggleAttribute = ( m_generateKeyword ) ? "[Toggle]":"[ToggleUI]"; +#else + string toggleAttribute = ( m_generateKeyword ) ? "[Toggle]": "[NoKeywordToggle]"; +#endif + return PropertyAttributes + toggleAttribute + m_propertyName + "(\"" + m_propertyInspectorName + "\", Float) = " + m_currentSelectedInput; + } + + public override string GetUniformValue() + { + int index = m_containerGraph.IsSRP ? 1 : 0; + return string.Format( Constants.UniformDec[ index ], UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, WirePortDataType.FLOAT ), m_propertyName ); + } + + public override bool GetUniformData( out string dataType, out string dataName, ref bool fullValue ) + { + dataType = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, WirePortDataType.FLOAT ); + dataName = m_propertyName; + return true; + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if ( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction ) + { + mat.SetFloat( m_propertyName, ( float ) m_currentSelectedInput ); + } + } + + public override void SetMaterialMode( Material mat , bool fetchMaterialValues ) + { + base.SetMaterialMode( mat , fetchMaterialValues ); + if ( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) && mat.HasProperty( m_propertyName ) ) + { + m_currentSelectedInput = ( int ) mat.GetFloat( m_propertyName ); + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( m_propertyName ) ) + { + m_currentSelectedInput = (int)material.GetFloat( m_propertyName ); + PreviewIsDirty = true; + } + } + + public override string GetPropertyValStr() + { + return PropertyName; //return m_currentSelectedInput.ToString(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/ToggleSwitchNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/ToggleSwitchNode.cs.meta new file mode 100644 index 0000000..54b2075 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/ToggleSwitchNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c7f6ffd9a8c958e449321777764784de +timeCreated: 1484213504 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation.meta new file mode 100644 index 0000000..3dcf03f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2505ed67ae6a9d647a25755a065e350e +folderAsset: yes +timeCreated: 1488205900 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ObjectToWorldTransfNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ObjectToWorldTransfNode.cs new file mode 100644 index 0000000..48de5fb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ObjectToWorldTransfNode.cs @@ -0,0 +1,30 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Object To World", "Object Transform", "Transforms input to World Space" )] + public sealed class ObjectToWorldTransfNode : ParentTransfNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_matrixName = "unity_ObjectToWorld"; + m_matrixHDName = "GetObjectToWorldMatrix()"; + m_matrixLWName = "GetObjectToWorldMatrix()"; + m_previewShaderGUID = "a4044ee165813654486d0cecd0de478c"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + string result = base.GenerateShaderForOutput( 0, ref dataCollector, ignoreLocalvar ); + if( dataCollector.IsTemplate && dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD && !string.IsNullOrEmpty( m_matrixHDName ) ) + { + dataCollector.AddLocalVariable( UniqueId, string.Format( "{0}.xyz", result ), string.Format( "GetAbsolutePositionWS(({0}).xyz);", result ) ); + } + + return GetOutputVectorItem( 0, outputId, result ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ObjectToWorldTransfNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ObjectToWorldTransfNode.cs.meta new file mode 100644 index 0000000..40b45c8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ObjectToWorldTransfNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 545417ad304cea84b9f625a3b6ad4e56 +timeCreated: 1488205951 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ParentTransfNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ParentTransfNode.cs new file mode 100644 index 0000000..5781e11 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ParentTransfNode.cs @@ -0,0 +1,53 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + public class ParentTransfNode : ParentNode + { + protected string m_matrixName; + protected string m_matrixHDName; + protected string m_matrixLWName; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT4, false, string.Empty ); + AddOutputVectorPorts( WirePortDataType.FLOAT4, "XYZW" ); + m_useInternalPortData = true; + m_inputPorts[ 0 ].Vector4InternalData = new UnityEngine.Vector4( 0, 0, 0, 1 ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string matrixName = string.Empty; + if( dataCollector.IsTemplate ) + { + if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD && !string.IsNullOrEmpty( m_matrixHDName ) ) + { + matrixName = m_matrixHDName; + } + else if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.Lightweight && !string.IsNullOrEmpty( m_matrixLWName ) ) + { + matrixName = m_matrixLWName; + } + else + { + matrixName = m_matrixName; + } + } + else + { + matrixName = m_matrixName; + } + + RegisterLocalVariable( 0, string.Format( "mul({0},{1})", matrixName, value ),ref dataCollector,"transform"+ OutputId ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ParentTransfNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ParentTransfNode.cs.meta new file mode 100644 index 0000000..5a714ba --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/ParentTransfNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 11f04432b7f1ffb43b584adb226614c6 +timeCreated: 1488206086 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/WorldToObjectTransfNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/WorldToObjectTransfNode.cs new file mode 100644 index 0000000..ccc5781 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/WorldToObjectTransfNode.cs @@ -0,0 +1,54 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "World To Object", "Object Transform", "Transforms input to Object Space" )] + public sealed class WorldToObjectTransfNode : ParentTransfNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_matrixName = "unity_WorldToObject"; + m_matrixHDName = "GetWorldToObjectMatrix()"; + m_matrixLWName = "GetWorldToObjectMatrix()"; + m_previewShaderGUID = "79a5efd1e3309f54d8ba3e7fdf5e459b"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string matrixName = string.Empty; + if( dataCollector.IsTemplate ) + { + if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD && !string.IsNullOrEmpty( m_matrixHDName ) ) + { + string varName = "localWorldVar" + OutputId; + dataCollector.AddLocalVariable( UniqueId, PrecisionType.Float, WirePortDataType.FLOAT4, varName, value ); + dataCollector.AddLocalVariable( UniqueId, string.Format( "({0}).xyz", varName ), string.Format( "GetCameraRelativePositionWS(({0}).xyz);", varName ) ); + value = varName; + matrixName = m_matrixHDName; + } + else if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.Lightweight && !string.IsNullOrEmpty( m_matrixLWName ) ) + { + matrixName = m_matrixLWName; + } + else + { + matrixName = m_matrixName; + } + } + else + { + matrixName = m_matrixName; + } + + RegisterLocalVariable( 0, string.Format( "mul({0},{1})", matrixName, value ), ref dataCollector, "transform" + OutputId ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/WorldToObjectTransfNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/WorldToObjectTransfNode.cs.meta new file mode 100644 index 0000000..8ad85ca --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/Transformation/WorldToObjectTransfNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8a25ccf8973bfae46ae3df2823f58229 +timeCreated: 1488205986 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/VectorFromMatrixNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/VectorFromMatrixNode.cs new file mode 100644 index 0000000..1095df4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/VectorFromMatrixNode.cs @@ -0,0 +1,131 @@ +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public enum eVectorFromMatrixMode + { + Row, + Column + } + + [Serializable] + [NodeAttributes( "Vector From Matrix", "Matrix Operators", "Retrieve vector data from a matrix" )] + public sealed class VectorFromMatrixNode : ParentNode + { + private const string IndexStr = "Index"; + private const string ModeStr = "Mode"; + + [SerializeField] + private eVectorFromMatrixMode m_mode = eVectorFromMatrixMode.Row; + + [SerializeField] + private int m_index = 0; + + [SerializeField] + private int m_maxIndex = 3; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT4x4, false, Constants.EmptyPortValue ); + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.FLOAT3x3, WirePortDataType.FLOAT4x4 ); + AddOutputVectorPorts( WirePortDataType.FLOAT4, "XYZW" ); + m_useInternalPortData = true; + m_autoWrapProperties = true; + } + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdatePorts(); + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + UpdatePorts(); + } + + void UpdatePorts() + { + m_inputPorts[ 0 ].MatchPortToConnection(); + + if ( m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT3x3 ) + { + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_outputPorts[ 0 ].Name = "XYZ"; + m_maxIndex = 2; + m_outputPorts[ 4 ].Visible = false; + } + else + { + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_outputPorts[ 0 ].Name = "XYZW"; + m_maxIndex = 3; + m_outputPorts[ 4 ].Visible = true; + } + m_sizeIsDirty = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + if ( m_inputPorts[ 0 ].DataType != WirePortDataType.FLOAT4x4 && + m_inputPorts[ 0 ].DataType != WirePortDataType.FLOAT3x3 ) + { + value = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), value, m_inputPorts[ 0 ].DataType, WirePortDataType.FLOAT4x4, value ); + } + if ( m_mode == eVectorFromMatrixMode.Row ) + { + value += "[" + m_index + "]"; + } + else + { + string formatStr = value + "[{0}]" + "[" + m_index + "]"; + int count = 4; + if ( m_inputPorts[ 0 ].DataType != WirePortDataType.FLOAT3x3 ) + { + value = "float4( "; + } + else + { + count = 3; + value = "float3( "; + } + + for ( int i = 0; i < count; i++ ) + { + value += string.Format( formatStr, i ); + if ( i != ( count - 1 ) ) + { + value += ","; + } + } + value += " )"; + } + return GetOutputVectorItem( 0, outputId, value ); + } + + public override void DrawProperties() + { + m_mode = (eVectorFromMatrixMode)EditorGUILayoutEnumPopup( ModeStr, m_mode ); + m_index = EditorGUILayoutIntSlider( IndexStr, m_index, 0, m_maxIndex ); + base.DrawProperties(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_mode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_index ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_mode = ( eVectorFromMatrixMode ) Enum.Parse( typeof( eVectorFromMatrixMode ), GetCurrentParam( ref nodeParams ) ); + m_index = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/VectorFromMatrixNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/VectorFromMatrixNode.cs.meta new file mode 100644 index 0000000..c2e6a9f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/VectorFromMatrixNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 31c07015a5f2aa44297aa7cfb80ffdd5 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedAvgNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedAvgNode.cs new file mode 100644 index 0000000..c9329ff --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedAvgNode.cs @@ -0,0 +1,182 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; +using UnityEditor; +namespace AmplifyShaderEditor +{ + [Serializable] + + public class WeightedAvgNode : ParentNode + { + protected string[] AmountsStr = { "Layer 1", "Layer 2", "Layer 3", "Layer 4" }; + + [SerializeField] + protected int m_minimumSize = 1; + + [SerializeField] + protected WirePortDataType m_mainDataType = WirePortDataType.FLOAT; + + [SerializeField] + protected string[] m_inputData; + [SerializeField] + protected int m_activeCount = 0; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "Weights" ); + AddInputPort( WirePortDataType.FLOAT, false, AmountsStr[ 0 ] ); + AddInputPort( WirePortDataType.FLOAT, false, AmountsStr[ 1 ] ); + AddInputPort( WirePortDataType.FLOAT, false, AmountsStr[ 2 ] ); + AddInputPort( WirePortDataType.FLOAT, false, AmountsStr[ 3 ] ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + m_inputPorts[ i ].AddPortForbiddenTypes( WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4, + WirePortDataType.SAMPLER1D, + WirePortDataType.SAMPLER2D, + WirePortDataType.SAMPLER3D, + WirePortDataType.SAMPLERCUBE, + WirePortDataType.SAMPLER2DARRAY, + WirePortDataType.SAMPLERSTATE ); + } + UpdateConnection( 0 ); + m_useInternalPortData = true; + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + UpdateConnection( inputPortId ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnection( portId ); + } + + void UpdateInputPorts( int activePorts ) + { + int idx = 1; + for ( ; idx < m_minimumSize + activePorts; idx++ ) + { + m_inputPorts[ idx ].Visible = true; + } + + m_activeCount = idx - 1; + + for ( ; idx < m_inputPorts.Count; idx++ ) + { + m_inputPorts[ idx ].Visible = false; + } + } + + protected void UpdateConnection( int portId ) + { + if ( portId == 0 ) + { + if( m_inputPorts[ portId ].IsConnected ) + m_inputPorts[ portId ].MatchPortToConnection(); + + switch ( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + { + UpdateInputPorts( 1 ); + m_previewMaterialPassId = 0; + } + break; + case WirePortDataType.FLOAT2: + { + UpdateInputPorts( 2 ); + m_previewMaterialPassId = 1; + } + break; + case WirePortDataType.FLOAT3: + { + UpdateInputPorts( 3 ); + m_previewMaterialPassId = 2; + } + break; + case WirePortDataType.COLOR: + case WirePortDataType.FLOAT4: + { + UpdateInputPorts( 4 ); + m_previewMaterialPassId = 3; + } + break; + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + for ( int i = 1; i < m_inputPorts.Count; i++ ) + { + m_inputPorts[ i ].Visible = false; + } + m_activeCount = 0; + } + break; + } + } + //else + //{ + // SetMainOutputType(); + //} + + SetMainOutputType(); + m_sizeIsDirty = true; + } + + protected void SetMainOutputType() + { + m_mainDataType = WirePortDataType.OBJECT; + int count = m_inputPorts.Count; + for ( int i = 1; i < count; i++ ) + { + if ( m_inputPorts[ i ].Visible ) + { + WirePortDataType portType = m_inputPorts[ i ].IsConnected ? m_inputPorts[ i ].ConnectionType() : WirePortDataType.FLOAT; + if ( m_mainDataType != portType && + UIUtils.GetPriority( portType ) > UIUtils.GetPriority( m_mainDataType ) ) + { + m_mainDataType = portType; + } + } + } + + for( int i = 1; i < count; i++ ) + { + if( m_inputPorts[ i ].Visible ) + { + m_inputPorts[ i ].ChangeType( m_mainDataType, false ); + } + } + + m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + } + + protected void GetInputData( ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + m_inputData[ 0 ] = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + for ( int i = 1; i < m_inputPorts.Count; i++ ) + { + if ( m_inputPorts[ i ].Visible ) + { + m_inputData[ i ] = m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ); + } + } + } + + public override void ReadInputDataFromString( ref string[] nodeParams ) + { + base.ReadInputDataFromString( ref nodeParams ); + UpdateConnection( 0 ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedAvgNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedAvgNode.cs.meta new file mode 100644 index 0000000..1faefae --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedAvgNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 35c70c67524c86049a25b7ebd0de6ae3 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedBlendNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedBlendNode.cs new file mode 100644 index 0000000..dc5fc1b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedBlendNode.cs @@ -0,0 +1,58 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Weighted Blend", "Miscellaneous", "Mix all channels through weighted average sum", null, KeyCode.None, true )] + public sealed class WeightedBlendNode : WeightedAvgNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputData = new string[ 6 ]; + m_previewShaderGUID = "6076cbeaa41ebb14c85ff81b58df7d88"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + GetInputData( ref dataCollector, ignoreLocalvar ); + + string result = string.Empty; + string avgSum = string.Empty; + + string localVarName = "weightedBlendVar" + OutputId; + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_inputPorts[ 0 ].DataType, localVarName, m_inputData[ 0 ] ); + + if ( m_activeCount < 2 ) + { + return CreateOutputLocalVariable( 0, m_inputData[ 1 ], ref dataCollector ); + } + else + { + for ( int i = 0; i < m_activeCount; i++ ) + { + result += localVarName + Constants.VectorSuffixes[ i ] + "*" + m_inputData[ i + 1 ]; + avgSum += localVarName + Constants.VectorSuffixes[ i ]; + if ( i != ( m_activeCount - 1 ) ) + { + result += " + "; + avgSum += " + "; + } + } + } + + result = UIUtils.AddBrackets( result ) + "/" + UIUtils.AddBrackets( avgSum ); + result = UIUtils.AddBrackets( result ); + RegisterLocalVariable( 0, result, ref dataCollector, "weightedAvg" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedBlendNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedBlendNode.cs.meta new file mode 100644 index 0000000..744bfd0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WeightedBlendNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b91b2aefbfad5b444b25320e9ed53cac +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WireNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WireNode.cs new file mode 100644 index 0000000..4bcc500 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WireNode.cs @@ -0,0 +1,484 @@ +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Wire Node", "Miscellaneous", "Wire Node", null, KeyCode.None, false )] + public sealed class WireNode : ParentNode + { + private bool m_markedToDelete = false; + + [SerializeField] + private WirePortDataType m_visualDataType = WirePortDataType.FLOAT; + + bool m_forceVisualDataUpdate = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.OBJECT, false, string.Empty ); + AddOutputPort( WirePortDataType.OBJECT, Constants.EmptyPortValue ); + m_tooltipText = string.Empty; + m_drawPreview = false; + m_drawPreviewExpander = false; + m_canExpand = false; + m_previewShaderGUID = "fa1e3e404e6b3c243b5527b82739d682"; + } + + public WirePortDataType GetLastInputDataTypeRecursively() + { + if( m_outputPorts[ 0 ].ExternalReferences.Count > 0 ) + { + WireNode rightWire = m_outputPorts[ 0 ].GetInputNode( 0 ) as WireNode; + if( rightWire != null ) + return rightWire.GetLastInputDataTypeRecursively(); + else + { + return m_outputPorts[ 0 ].GetInputConnection( 0 ).DataType; + } + } + + if( m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid ) + return m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.DataType; + else + return m_visualDataType; + } + + public override WirePortDataType GetInputPortVisualDataTypeByArrayIdx( int portArrayIdx ) + { + return m_visualDataType; + } + + public override WirePortDataType GetOutputPortVisualDataTypeById( int portId ) + { + return m_visualDataType; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + + m_forceVisualDataUpdate = true; + } + + public override void OnOutputPortConnected( int portId, int otherNodeId, int otherPortId ) + { + base.OnOutputPortConnected( portId, otherNodeId, otherPortId ); + + if( m_outputPorts[ portId ].ConnectionCount > 1 ) + { + for( int i = 0; i < m_outputPorts[ portId ].ExternalReferences.Count; i++ ) + { + if( m_outputPorts[ portId ].ExternalReferences[ i ].PortId != otherPortId ) + { + UIUtils.DeleteConnection( true, m_outputPorts[ portId ].ExternalReferences[ i ].NodeId, m_outputPorts[ portId ].ExternalReferences[ i ].PortId, false, true ); + } + } + } + + m_inputPorts[ 0 ].NotifyExternalRefencesOnChange(); + m_forceVisualDataUpdate = true; + } + + public override void OnConnectedInputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedInputNodeChanges( portId, otherNodeId, otherPortId, name, type ); + + m_inputPorts[ 0 ].NotifyExternalRefencesOnChange(); + m_forceVisualDataUpdate = true; + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + + m_forceVisualDataUpdate = true; + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + TestIfValid(); + + m_forceVisualDataUpdate = true; + m_outputPorts[ 0 ].NotifyExternalRefencesOnChange(); + } + + public override void OnOutputPortDisconnected( int portId ) + { + base.OnOutputPortDisconnected( portId ); + TestIfValid(); + + m_forceVisualDataUpdate = true; + m_inputPorts[ 0 ].NotifyExternalRefencesOnChange(); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + return m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + } + + public override void DrawProperties() + { + if( m_markedToDelete ) + return; + + base.DrawProperties(); + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + if( m_firstDraw ) + { + m_firstDraw = false; + AfterCommonInit(); + OnNodeChange(); + } + + if( m_forceVisualDataUpdate ) + { + m_forceVisualDataUpdate = false; + m_visualDataType = GetLastInputDataTypeRecursively(); + } + + if( m_repopulateDictionaries ) + { + m_repopulateDictionaries = false; + + m_inputPortsDict.Clear(); + int inputCount = m_inputPorts.Count; + for( int i = 0; i < inputCount; i++ ) + { + m_inputPortsDict.Add( m_inputPorts[ i ].PortId, m_inputPorts[ i ] ); + } + + m_outputPortsDict.Clear(); + int outputCount = m_outputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + m_outputPortsDict.Add( m_outputPorts[ i ].PortId, m_outputPorts[ i ] ); + } + } + + if( m_sizeIsDirty ) + { + m_sizeIsDirty = false; + m_extraSize.Set( 20f, 20f ); + m_position.width = m_extraSize.x + UIUtils.PortsSize.x; + m_position.height = m_extraSize.y + UIUtils.PortsSize.y; + + Vec2Position -= Position.size * 0.5f; + if( OnNodeChangeSizeEvent != null ) + { + OnNodeChangeSizeEvent( this ); + } + + ChangeSizeFinished(); + //ChangeSize(); + } + + CalculatePositionAndVisibility( drawInfo ); + + // Input Ports + { + m_currInputPortPos = m_globalPosition; + m_currInputPortPos.width = drawInfo.InvertedZoom * UIUtils.PortsSize.x; + m_currInputPortPos.height = drawInfo.InvertedZoom * UIUtils.PortsSize.y; + m_currInputPortPos.position = m_globalPosition.center - m_currInputPortPos.size * 0.5f; + int inputCount = m_inputPorts.Count; + + for( int i = 0; i < inputCount; i++ ) + { + if( m_inputPorts[ i ].Visible ) + { + // Button + m_inputPorts[ i ].Position = m_currInputPortPos; + + if( !m_inputPorts[ i ].Locked ) + { + float overflow = 2; + float scaledOverflow = 3 * drawInfo.InvertedZoom; + m_auxRect = m_currInputPortPos; + m_auxRect.yMin -= scaledOverflow + overflow; + m_auxRect.yMax += scaledOverflow + overflow; + m_auxRect.xMin -= Constants.PORT_INITIAL_X * drawInfo.InvertedZoom + scaledOverflow + overflow; + m_auxRect.xMax += m_inputPorts[ i ].LabelSize.x + Constants.PORT_TO_LABEL_SPACE_X * drawInfo.InvertedZoom + scaledOverflow + overflow; + m_inputPorts[ i ].ActivePortArea = m_auxRect; + } + m_currInputPortPos.y += drawInfo.InvertedZoom * ( m_fontHeight + Constants.INPUT_PORT_DELTA_Y ); + } + } + } + + // Output Ports + { + m_currOutputPortPos = m_globalPosition; + m_currOutputPortPos.width = drawInfo.InvertedZoom * UIUtils.PortsSize.x; + m_currOutputPortPos.height = drawInfo.InvertedZoom * UIUtils.PortsSize.y; + m_currOutputPortPos.position = m_globalPosition.center - m_currOutputPortPos.size * 0.5f; + //m_currOutputPortPos.x += ( m_globalPosition.width - drawInfo.InvertedZoom * ( Constants.PORT_INITIAL_X + m_anchorAdjust ) ); + //m_currOutputPortPos.y += drawInfo.InvertedZoom * Constants.PORT_INITIAL_Y;// + m_extraHeaderHeight * drawInfo.InvertedZoom; + int outputCount = m_outputPorts.Count; + + for( int i = 0; i < outputCount; i++ ) + { + if( m_outputPorts[ i ].Visible ) + { + //Button + m_outputPorts[ i ].Position = m_currOutputPortPos; + + if( !m_outputPorts[ i ].Locked ) + { + float overflow = 2; + float scaledOverflow = 3 * drawInfo.InvertedZoom; + m_auxRect = m_currOutputPortPos; + m_auxRect.yMin -= scaledOverflow + overflow; + m_auxRect.yMax += scaledOverflow + overflow; + m_auxRect.xMin -= m_outputPorts[ i ].LabelSize.x + Constants.PORT_TO_LABEL_SPACE_X * drawInfo.InvertedZoom + scaledOverflow + overflow; + m_auxRect.xMax += Constants.PORT_INITIAL_X * drawInfo.InvertedZoom + scaledOverflow + overflow; + m_outputPorts[ i ].ActivePortArea = m_auxRect; + } + m_currOutputPortPos.y += drawInfo.InvertedZoom * ( m_fontHeight + Constants.INPUT_PORT_DELTA_Y ); + } + } + } + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + //base.OnRepaint( drawInfo ); + //return; + if( !m_isVisible ) + return; + + m_colorBuffer = GUI.color; + + // Output Ports + int outputCount = m_outputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + if( m_outputPorts[ i ].Visible ) + { + // Output Port Icon + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + { + if( m_outputPorts[ i ].Locked ) + GUI.color = Constants.LockedPortColor; + else if( ContainerGraph.ParentWindow.Options.ColoredPorts ) + GUI.color = UIUtils.GetColorForDataType( m_visualDataType, false, false ); + else + GUI.color = m_outputPorts[ i ].HasCustomColor ? m_outputPorts[ i ].CustomColor : UIUtils.GetColorForDataType( m_visualDataType, true, false ); + + GUIStyle style = m_outputPorts[ i ].IsConnected ? UIUtils.GetCustomStyle( CustomStyle.PortFullIcon ) : UIUtils.GetCustomStyle( CustomStyle.PortEmptyIcon ); + GUI.Label( m_outputPorts[ i ].Position, string.Empty, style ); + + GUI.color = m_colorBuffer; + } + + // Output Port Label + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + if( m_outputPorts[ i ].Locked ) + { + GUI.color = Constants.PortLockedTextColor; + GUI.Label( m_outputPorts[ i ].LabelPosition, m_outputPorts[ i ].Name, UIUtils.OutputPortLabel ); + GUI.color = m_colorBuffer; + } + else + { + GUI.Label( m_outputPorts[ i ].LabelPosition, m_outputPorts[ i ].Name, UIUtils.OutputPortLabel ); + } + } + } + } + + // Selection Box + if( m_selected ) + { + Rect selectionBox = m_globalPosition; + selectionBox.size = Vector2.one * 16 * drawInfo.InvertedZoom + Vector2.one * 4; + selectionBox.center = m_globalPosition.center; + GUI.DrawTexture( selectionBox, UIUtils.WireNodeSelection ); + GUI.color = m_colorBuffer; + } + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + //base.DrawGUIControls( drawInfo ); + } + + public override void Draw( DrawInfo drawInfo ) + { + if( m_markedToDelete ) + return; + + if( drawInfo.CurrentEventType == EventType.Repaint ) + OnNodeRepaint( drawInfo ); + //base.Draw( drawInfo ); + + if( drawInfo.CurrentEventType == EventType.Repaint ) + TestIfValid(); + } + + bool TestIfValid() + { + if( !Alive ) + return false; + + bool result = true; + if( !m_inputPorts[ 0 ].IsConnected ) + { + if( !m_containerGraph.ParentWindow.WireReferenceUtils.InputPortReference.IsValid || m_containerGraph.ParentWindow.WireReferenceUtils.InputPortReference.IsValid && m_containerGraph.ParentWindow.WireReferenceUtils.InputPortReference.NodeId != UniqueId ) + { + ContainerGraph.MarkWireNodeSequence( this, true ); + result = false; + } + } + + if( !m_outputPorts[ 0 ].IsConnected ) + { + if( !m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid || m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid && m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.NodeId != UniqueId ) + { + ContainerGraph.MarkWireNodeSequence( this, false ); + result = false; + } + } + return result; + } + + public Vector3 TangentDirection + { + get + { + ParentNode otherInputNode = null; + ParentNode otherOutputNode = null; + + //defaults to itself so it can still calculate tangents + WirePort otherInputPort = m_outputPorts[ 0 ]; + WirePort otherOutputPort = m_inputPorts[ 0 ]; + + if( m_outputPorts[ 0 ].ConnectionCount > 0 ) + { + otherInputNode = m_containerGraph.GetNode( m_outputPorts[ 0 ].ExternalReferences[ 0 ].NodeId ); + otherInputPort = otherInputNode.GetInputPortByUniqueId( m_outputPorts[ 0 ].ExternalReferences[ 0 ].PortId ); + } + + if( m_inputPorts[ 0 ].ConnectionCount > 0 ) + { + otherOutputNode = m_containerGraph.GetNode( m_inputPorts[ 0 ].ExternalReferences[ 0 ].NodeId ); + otherOutputPort = otherOutputNode.GetOutputPortByUniqueId( m_inputPorts[ 0 ].ExternalReferences[ 0 ].PortId ); + } + + //TODO: it still generates crooked lines if wire nodes get too close to non-wire nodes (the fix would be to calculate the non-wire nodes magnitude properly) + float mag = Constants.HORIZONTAL_TANGENT_SIZE * ContainerGraph.ParentWindow.CameraDrawInfo.InvertedZoom; + + Vector2 outPos; + if( otherOutputNode != null && otherOutputNode.GetType() != typeof( WireNode ) ) + outPos = otherOutputPort.Position.position + Vector2.right * mag * 0.66f; + else + outPos = otherOutputPort.Position.position; + + Vector2 inPos; + if( otherInputNode != null && otherInputNode.GetType() != typeof( WireNode ) ) + inPos = otherInputPort.Position.position - Vector2.right * mag * 0.66f; + else + inPos = otherInputPort.Position.position; + + Vector2 tangent = ( outPos - inPos ).normalized; + return new Vector3( tangent.x, tangent.y ); + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + + m_extraSize.Set( 20f, 20f ); + m_position.width = m_extraSize.x + UIUtils.PortsSize.x; + m_position.height = m_extraSize.y + UIUtils.PortsSize.y; + + Vec2Position += Position.size * 0.5f; + } + + public override void OnAfterDeserialize() + { + base.OnAfterDeserialize(); + m_sizeIsDirty = false; + } + + public WireReference FindNewValidInputNode( WireNode current ) + { + if( current.InputPorts[ 0 ].IsConnected ) + { + ParentNode node = m_containerGraph.GetNode( current.InputPorts[ 0 ].ExternalReferences[ 0 ].NodeId ); + if( node != null ) + { + WireNode wireNode = node as WireNode; + if( wireNode != null && wireNode.MarkToDelete ) + { + return FindNewValidInputNode( wireNode ); + } + else + { + return current.InputPorts[ 0 ].ExternalReferences[ 0 ]; + } + } + } + return null; + } + + public WireReference FindNewValidOutputNode( WireNode current ) + { + if( current.OutputPorts[ 0 ].IsConnected ) + { + ParentNode node = m_containerGraph.GetNode( current.OutputPorts[ 0 ].ExternalReferences[ 0 ].NodeId ); + + if( node != null ) + { + WireNode wireNode = node as WireNode; + if( wireNode != null && wireNode.MarkToDelete ) + { + return FindNewValidOutputNode( wireNode ); + } + else + { + return current.OutputPorts[ 0 ].ExternalReferences[ 0 ]; + } + } + } + return null; + } + + public override void Rewire() + { + //if ( m_inputPorts[ 0 ].ExternalReferences != null && m_inputPorts[ 0 ].ExternalReferences.Count > 0 ) + //{ + //WireReference backPort = m_inputPorts[ 0 ].ExternalReferences[ 0 ]; + //for ( int i = 0; i < m_outputPorts[ 0 ].ExternalReferences.Count; i++ ) + //{ + // UIUtils.CurrentWindow.ConnectInputToOutput( m_outputPorts[ 0 ].ExternalReferences[ i ].NodeId, m_outputPorts[ 0 ].ExternalReferences[ i ].PortId, backPort.NodeId, backPort.PortId ); + //} + //} + MarkToDelete = true; + WireReference outputReference = FindNewValidInputNode( this ); + WireReference inputReference = FindNewValidOutputNode( this ); + if( outputReference != null && inputReference != null ) + { + ContainerGraph.ParentWindow.ConnectInputToOutput( inputReference.NodeId, inputReference.PortId, outputReference.NodeId, outputReference.PortId ); + } + } + + public bool MarkToDelete + { + get { return m_markedToDelete; } + set { m_markedToDelete = value; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WireNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WireNode.cs.meta new file mode 100644 index 0000000..ab597cb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Misc/WireNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7a566d6bf220cd74b8385a91f690b683 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeAttributes.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeAttributes.cs new file mode 100644 index 0000000..91e441e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeAttributes.cs @@ -0,0 +1,97 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public enum NodeAvailability + { + SurfaceShader = 1 << 0, + ShaderFunction = 1 << 1, + CustomLighting = 1 << 2, + TemplateShader = 1 << 3 + } + + + [AttributeUsage( AttributeTargets.Class )] + public class NodeAttributes : Attribute + { + + public string Name; + public string Description; + public string Category; + public KeyCode ShortcutKey; + public bool Available; + public System.Type[] CastType; // Type that will be converted to AttribType if dropped on the canvas ... p.e. dropping a texture2d on the canvas will generate a sampler2d node + public bool Deprecated; + public string DeprecatedAlternative; + public System.Type DeprecatedAlternativeType; + public bool FromCommunity; + public string CustomCategoryColor; // Color created via a string containing its hexadecimal representation + public int SortOrderPriority; // to be used when name comparing on sorting + public int NodeAvailabilityFlags;// used to define where this node can be used + private string m_nodeUrl; + public string Community; + public string Tags; + public NodeAttributes( string name, string category, string description, System.Type castType = null, KeyCode shortcutKey = KeyCode.None, bool available = true, bool deprecated = false, string deprecatedAlternative = null, System.Type deprecatedAlternativeType = null, string community = null, string customCategoryColor = null, int sortOrderPriority = -1, int nodeAvailabilityFlags = int.MaxValue, string tags = null ) + { + Name = name; + Description = description; + Category = category; + if( castType != null ) + CastType = new System.Type[] { castType }; + + ShortcutKey = shortcutKey; + Available = available; + Deprecated = deprecated; + DeprecatedAlternative = deprecatedAlternative; + Community = community; + if( string.IsNullOrEmpty( Community ) ) + Community = string.Empty; + else + FromCommunity = true; + + if( !string.IsNullOrEmpty( customCategoryColor ) ) + CustomCategoryColor = customCategoryColor; + + DeprecatedAlternativeType = deprecatedAlternativeType; + SortOrderPriority = sortOrderPriority; + NodeAvailabilityFlags = nodeAvailabilityFlags; + Tags = tags; + if( string.IsNullOrEmpty( tags ) ) + Tags = string.Empty; + //m_nodeUrl = ( FromCommunity ? Constants.CommunityNodeCommonUrl : Constants.NodeCommonUrl ) + UIUtils.UrlReplaceInvalidStrings( Name ); + } + + public NodeAttributes( string name, string category, string description, KeyCode shortcutKey, bool available, int sortOrderPriority, int nodeAvailabilityFlags, params System.Type[] castTypes ) + { + Name = name; + Description = description; + Category = category; + if( castTypes != null && castTypes.Length > 0 ) + { + CastType = castTypes; + } + + ShortcutKey = shortcutKey; + Available = available; + SortOrderPriority = sortOrderPriority; + NodeAvailabilityFlags = nodeAvailabilityFlags; + //m_nodeUrl = ( FromCommunity ? Constants.CommunityNodeCommonUrl : Constants.NodeCommonUrl ) + UIUtils.UrlReplaceInvalidStrings( Name ); + } + + public string NodeUrl + { + get + { + if( string.IsNullOrEmpty( m_nodeUrl ) ) + { + m_nodeUrl = ( FromCommunity ? Constants.CommunityNodeCommonUrl : Constants.NodeCommonUrl ) + UIUtils.UrlReplaceInvalidStrings( Name ); + } + return m_nodeUrl; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeAttributes.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeAttributes.cs.meta new file mode 100644 index 0000000..c7a076f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeAttributes.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ec3cfdc3a4d1a7a4cb24c1c079e1750a +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeRestrictions.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeRestrictions.cs new file mode 100644 index 0000000..d68d8eb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeRestrictions.cs @@ -0,0 +1,119 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +namespace AmplifyShaderEditor +{ + public class NodeRestrictionsData + { + private bool m_allPorts; + private Dictionary m_portRestrictions; + public NodeRestrictionsData() + { + m_portRestrictions = new Dictionary(); + } + + public NodeRestrictionsData( int port ) + { + m_portRestrictions = new Dictionary(); + m_portRestrictions.Add( port, true ); + } + + public void SetAllPortRestiction( bool value ) + { + m_allPorts = value; + } + + public void AddRestriction( int port ) + { + if ( !m_portRestrictions.ContainsKey( port ) ) + m_portRestrictions.Add( port, true ); + else + m_portRestrictions[ port ] = true; + } + + public void RemoveRestriction( int port ) + { + if ( m_portRestrictions.ContainsKey( port ) ) + m_portRestrictions[ port ] = true; + } + + public bool IsPortRestricted( int port ) + { + if ( m_portRestrictions.ContainsKey( port ) ) + return m_portRestrictions[ port ]; + return false; + } + + public void Destroy() + { + m_portRestrictions.Clear(); + m_portRestrictions = null; + } + + public bool AllPortsRestricted + { + get + { + return m_allPorts; + } + } + } + + public class NodeRestrictions + { + private Dictionary m_restrictions; + + public NodeRestrictions() + { + m_restrictions = new Dictionary(); + } + + public void AddTypeRestriction( System.Type type ) + { + if ( !m_restrictions.ContainsKey( type ) ) + m_restrictions.Add( type, new NodeRestrictionsData() ); + + m_restrictions[ type ].SetAllPortRestiction( true ); + + } + + public void AddPortRestriction( System.Type type, int port ) + { + if ( !m_restrictions.ContainsKey( type ) ) + m_restrictions.Add( type, new NodeRestrictionsData( port ) ); + else + { + m_restrictions[ type ].AddRestriction( port ); + } + } + + public bool GetRestiction( System.Type type, int port ) + { + if ( m_restrictions.Count == 0 || type == null ) + return false; + + if ( m_restrictions.ContainsKey( type ) ) + { + if ( m_restrictions[ type ].AllPortsRestricted ) + return true; + + return m_restrictions[ type ].IsPortRestricted( port ); + } + + return false; + } + + public void Destroy() + { + foreach ( KeyValuePair pair in m_restrictions ) + { + pair.Value.Destroy(); + } + + m_restrictions.Clear(); + m_restrictions = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeRestrictions.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeRestrictions.cs.meta new file mode 100644 index 0000000..dccb7b3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeRestrictions.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bd1aff8475f370d4380918491184aef5 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUsageRegister.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUsageRegister.cs new file mode 100644 index 0000000..944ce81 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUsageRegister.cs @@ -0,0 +1,203 @@ +using System; +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] public class UsageListSamplerNodes : NodeUsageRegister { } + [Serializable] public class UsageListFloatIntNodes : NodeUsageRegister { } + [Serializable] public class UsageListTexturePropertyNodes : NodeUsageRegister { } + [Serializable] public class UsageListTextureArrayNodes : NodeUsageRegister { } + [Serializable] public class UsageListPropertyNodes : NodeUsageRegister { } + [Serializable] public class UsageListScreenColorNodes : NodeUsageRegister { } + [Serializable] public class UsageListRegisterLocalVarNodes : NodeUsageRegister { } + [Serializable] public class UsageListFunctionInputNodes : NodeUsageRegister { } + [Serializable] public class UsageListFunctionNodes : NodeUsageRegister { } + [Serializable] public class UsageListFunctionOutputNodes : NodeUsageRegister { } + [Serializable] public class UsageListFunctionSwitchNodes : NodeUsageRegister { } + [Serializable] public class UsageListFunctionSwitchCopyNodes : NodeUsageRegister { } + [Serializable] public class UsageListTemplateMultiPassMasterNodes : NodeUsageRegister { } + [Serializable] public class UsageListCustomExpressionsOnFunctionMode : NodeUsageRegister { } + [Serializable] public class UsageListGlobalArrayNodes : NodeUsageRegister { } + [Serializable] public class UsageListStaticSwitchNodes : NodeUsageRegister { } + + [Serializable] + public class NodeUsageRegister where T : ParentNode + { + public delegate void ReorderEvent(); + public event ReorderEvent OnReorderEventComplete; + + [SerializeField] + public bool ReorderOnChange = false; + + // Sampler Nodes registry + [SerializeField] + private List m_nodes; + + [SerializeField] + private string[] m_nodesArr; + + [SerializeField] + private int[] m_nodeIDs; + + [SerializeField] + ParentGraph m_containerGraph; + + public NodeUsageRegister() + { + m_nodesArr = new string[ 0 ]; + m_nodeIDs = new int[ 0 ]; + m_nodes = new List(); + } + + public void Destroy() + { + m_nodes.Clear(); + m_nodes = null; + m_nodesArr = null; + m_nodeIDs = null; + } + + public void Clear() + { + m_nodes.Clear(); + } + + public int AddNode( T node ) + { + if( node == null ) + return -1; + + if( !m_nodes.Contains( node ) ) + { + if( m_containerGraph != null ) + { + Undo.RegisterCompleteObjectUndo( m_containerGraph.ParentWindow, Constants.UndoRegisterNodeId ); + Undo.RegisterCompleteObjectUndo( m_containerGraph, Constants.UndoRegisterNodeId ); + } + m_nodes.Add( node ); + ReorderNodes(); + UpdateNodeArr(); + return m_nodes.Count - 1; + } + else if( node.UniqueId > -1 ) + { + UpdateNodeArr(); + } + + return -1; + } + + public bool HasNode( int uniqueId ) + { + return m_nodes.FindIndex( x => x.UniqueId == uniqueId ) > -1 ? true : false; + } + + public void RemoveNode( T node ) + { + if( node == null ) + return; + + if( m_nodes.Contains( node ) ) + { + if( m_containerGraph != null ) + { + Undo.RegisterCompleteObjectUndo( m_containerGraph.ParentWindow, Constants.UndoUnregisterNodeId ); + Undo.RegisterCompleteObjectUndo( m_containerGraph, Constants.UndoUnregisterNodeId ); + } + + m_nodes.Remove( node ); + ReorderNodes(); + UpdateNodeArr(); + } + } + + public void ReorderNodes() + { + if( ReorderOnChange ) + { + m_nodes.Sort( ( x, y ) => ( x.DataToArray.CompareTo( y.DataToArray ) ) ); + if( OnReorderEventComplete != null ) + { + OnReorderEventComplete(); + } + } + } + + public void UpdateNodeArr() + { + int nodeCount = m_nodes.Count; + if( nodeCount != m_nodesArr.Length ) + { + m_nodesArr = new string[ nodeCount ]; + m_nodeIDs = new int[ nodeCount ]; + } + + for( int i = 0; i < nodeCount; i++ ) + { + m_nodesArr[ i ] = m_nodes[ i ].DataToArray; + m_nodeIDs[ i ] = m_nodes[ i ].UniqueId; + } + } + + public T GetNode( int idx ) + { + if( idx > -1 && idx < m_nodes.Count ) + { + return m_nodes[ idx ]; + } + return null; + } + + public T GetNodeByUniqueId( int uniqueId ) + { + return m_nodes.Find( x => x.UniqueId == uniqueId ); + } + + public T GetNodeByDataToArray( string data ) + { + return m_nodes.Find( x => x.DataToArray.Equals( data )); + } + + public int GetNodeRegisterIdx( int uniqueId ) + { + return m_nodes.FindIndex( x => x.UniqueId == uniqueId ); + } + + public void UpdateDataOnNode( int uniqueId, string data ) + { + if( ReorderOnChange ) + { + ReorderNodes(); + UpdateNodeArr(); + } + else + { + int index = m_nodes.FindIndex( x => x.UniqueId == uniqueId ); + if( index > -1 ) + { + m_nodesArr[ index ] = data; + m_nodeIDs[ index ] = uniqueId; + } + } + } + + public void Dump() + { + string data = string.Empty; + + for( int i = 0; i < m_nodesArr.Length; i++ ) + { + data += m_nodesArr[ i ] + " " + m_nodeIDs[ i ] + '\n'; + } + Debug.Log( data ); + } + + public string[] NodesArr { get { return m_nodesArr; } } + public int[] NodeIds { get { return m_nodeIDs; } } + public List NodesList { get { return m_nodes; } } + public int Count { get { return m_nodes.Count; } } + public ParentGraph ContainerGraph { get { return m_containerGraph; } set { m_containerGraph = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUsageRegister.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUsageRegister.cs.meta new file mode 100644 index 0000000..9f7511e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUsageRegister.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2aa06a21e7f64094c91da5dd60ef35cf +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUtils.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUtils.cs new file mode 100644 index 0000000..81219dd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUtils.cs @@ -0,0 +1,293 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public class NodeUtils + { + + public delegate void DrawPropertySection(); + + public static void DrawPropertyGroup( string sectionName, DrawPropertySection DrawSection ) + { + Color cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f ); + EditorGUILayout.BeginHorizontal( UIUtils.MenuItemToolbarStyle ); + GUI.color = cachedColor; + + GUILayout.Label( sectionName, UIUtils.MenuItemToggleStyle ); + + EditorGUILayout.EndHorizontal(); + + + cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) ); + EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + GUI.color = cachedColor; + DrawSection(); + EditorGUILayout.Separator(); + EditorGUILayout.EndVertical(); + } + + + public static void DrawNestedPropertyGroup( ref bool foldoutValue, string sectionName, DrawPropertySection DrawSection, int horizontalSpacing = 15 ) + { + GUILayout.BeginHorizontal(); + { + GUILayout.Space( horizontalSpacing ); + EditorGUILayout.BeginVertical( EditorStyles.helpBox ); + { + Color cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f ); + EditorGUILayout.BeginHorizontal(); + { + GUI.color = cachedColor; + bool value = GUILayout.Toggle( foldoutValue, sectionName, UIUtils.MenuItemToggleStyle ); + if( Event.current.button == Constants.FoldoutMouseId ) + { + foldoutValue = value; + } + } + EditorGUILayout.EndHorizontal(); + EditorGUI.indentLevel--; + if( foldoutValue ) + { + cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) ); + { + EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + { + GUI.color = cachedColor; + DrawSection(); + } + EditorGUILayout.EndVertical(); + EditorGUILayout.Separator(); + } + } + EditorGUI.indentLevel++; + } + EditorGUILayout.EndVertical(); + } + GUILayout.EndHorizontal(); + } + + public static void DrawNestedPropertyGroup( ref bool foldoutValue, Rect rect, string sectionName, DrawPropertySection DrawSection, int horizontalSpacing = 15 ) + { + var box = rect; + box.height -= 2; + GUI.Label( box, string.Empty, EditorStyles.helpBox ); + + var tog = rect; +#if UNITY_2019_3_OR_NEWER + tog.y -= ( tog.height - ( EditorGUIUtility.singleLineHeight + 5 ) ) * 0.5f; +#endif + tog.xMin += 2; + tog.xMax -= 2; + tog.yMin += 2; + bool value = GUI.Toggle( tog, foldoutValue, sectionName, UIUtils.MenuItemToggleStyle ); + if( Event.current.button == Constants.FoldoutMouseId ) + { + foldoutValue = value; + } + + if( foldoutValue ) + { + DrawSection(); + } + } + + + public static void DrawNestedPropertyGroup( ref bool foldoutValue, string sectionName, DrawPropertySection DrawSection, DrawPropertySection HeaderSection ) + { + GUILayout.BeginHorizontal(); + { + GUILayout.Space( 15 ); + EditorGUILayout.BeginVertical( EditorStyles.helpBox ); + Color cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f ); + EditorGUILayout.BeginHorizontal(); + GUI.color = cachedColor; + + bool value = GUILayout.Toggle( foldoutValue, sectionName, UIUtils.MenuItemToggleStyle ); + if( Event.current.button == Constants.FoldoutMouseId ) + { + foldoutValue = value; + } + HeaderSection(); + EditorGUILayout.EndHorizontal(); + EditorGUI.indentLevel--; + if( foldoutValue ) + { + cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) ); + EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + GUI.color = cachedColor; + DrawSection(); + EditorGUILayout.EndVertical(); + EditorGUILayout.Separator(); + } + EditorGUI.indentLevel++; + EditorGUILayout.EndVertical(); + } + GUILayout.EndHorizontal(); + } + + public static void DrawNestedPropertyGroup( UndoParentNode owner, ref bool foldoutValue, ref bool enabledValue, string sectionName, DrawPropertySection DrawSection ) + { + GUILayout.BeginHorizontal(); + { + GUILayout.Space( 15 ); + EditorGUILayout.BeginVertical( EditorStyles.helpBox ); + Color cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f ); + EditorGUILayout.BeginHorizontal(); + GUI.color = cachedColor; + + bool value = GUILayout.Toggle( foldoutValue, sectionName, UIUtils.MenuItemToggleStyle ); + if( Event.current.button == Constants.FoldoutMouseId ) + { + foldoutValue = value; + } + + value = ( (object)owner != null ) ? owner.GUILayoutToggle( enabledValue, string.Empty,UIUtils.MenuItemEnableStyle, GUILayout.Width( 16 ) ) : + GUILayout.Toggle( enabledValue, string.Empty, UIUtils.MenuItemEnableStyle, GUILayout.Width( 16 ) ); + if( Event.current.button == Constants.FoldoutMouseId ) + { + enabledValue = value; + } + + + EditorGUILayout.EndHorizontal(); + EditorGUI.indentLevel--; + if( foldoutValue ) + { + cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) ); + EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + GUI.color = cachedColor; + DrawSection(); + EditorGUILayout.EndVertical(); + EditorGUILayout.Separator(); + } + EditorGUI.indentLevel++; + EditorGUILayout.EndVertical(); + } + GUILayout.EndHorizontal(); + } + + + public static void DrawPropertyGroup( ref bool foldoutValue, string sectionName, DrawPropertySection DrawSection ) + { + Color cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f ); + EditorGUILayout.BeginHorizontal( UIUtils.MenuItemToolbarStyle ); + GUI.color = cachedColor; + + bool value = GUILayout.Toggle( foldoutValue, sectionName, UIUtils.MenuItemToggleStyle ); + if( Event.current.button == Constants.FoldoutMouseId ) + { + foldoutValue = value; + } + EditorGUILayout.EndHorizontal(); + + if( foldoutValue ) + { + cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) ); + EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + { + GUI.color = cachedColor; + EditorGUI.indentLevel++; + DrawSection(); + EditorGUI.indentLevel--; + EditorGUILayout.Separator(); + } + EditorGUILayout.EndVertical(); + } + } + + public static void DrawPropertyGroup( ref bool foldoutValue, string sectionName, DrawPropertySection DrawSection, DrawPropertySection HeaderSection ) + { + Color cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f ); + EditorGUILayout.BeginHorizontal( UIUtils.MenuItemToolbarStyle ); + GUI.color = cachedColor; + + bool value = GUILayout.Toggle( foldoutValue, sectionName, UIUtils.MenuItemToggleStyle ); + if( Event.current.button == Constants.FoldoutMouseId ) + { + foldoutValue = value; + } + HeaderSection(); + EditorGUILayout.EndHorizontal(); + + if( foldoutValue ) + { + cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) ); + EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + { + GUI.color = cachedColor; + EditorGUI.indentLevel++; + DrawSection(); + EditorGUI.indentLevel--; + EditorGUILayout.Separator(); + } + EditorGUILayout.EndVertical(); + } + } + + + public static bool DrawPropertyGroup( UndoParentNode owner, ref bool foldoutValue, ref bool enabledValue, string sectionName, DrawPropertySection DrawSection ) + { + bool enableChanged = false; + Color cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, 0.5f ); + EditorGUILayout.BeginHorizontal( UIUtils.MenuItemToolbarStyle ); + GUI.color = cachedColor; + bool value = GUILayout.Toggle( foldoutValue, sectionName, UIUtils.MenuItemToggleStyle, GUILayout.ExpandWidth( true ) ); + if( Event.current.button == Constants.FoldoutMouseId ) + { + foldoutValue = value; + } + EditorGUI.BeginChangeCheck(); + value = ( (object)owner != null ) ? owner.EditorGUILayoutToggle( string.Empty, enabledValue, UIUtils.MenuItemEnableStyle, GUILayout.Width( 16 ) ) : + EditorGUILayout.Toggle( string.Empty, enabledValue, UIUtils.MenuItemEnableStyle, GUILayout.Width( 16 ) ); + if( Event.current.button == Constants.FoldoutMouseId ) + { + enabledValue = value; + } + if( EditorGUI.EndChangeCheck() ) + { + enableChanged = true; + } + + EditorGUILayout.EndHorizontal(); + + if( foldoutValue ) + { + cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) ); + EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + GUI.color = cachedColor; + + EditorGUILayout.Separator(); + EditorGUI.BeginDisabledGroup( !enabledValue ); + + EditorGUI.indentLevel += 1; + + DrawSection(); + + EditorGUI.indentLevel -= 1; + EditorGUI.EndDisabledGroup(); + EditorGUILayout.Separator(); + EditorGUILayout.EndVertical(); + } + + return enableChanged; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUtils.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUtils.cs.meta new file mode 100644 index 0000000..f60220a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/NodeUtils.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9eb57a68790e6e343affe131e8a0f860 +timeCreated: 1487688956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators.meta new file mode 100644 index 0000000..6d6fbea --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f2a66c410f1e56b418ec994b6f57c2eb +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ACosOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ACosOpNode.cs new file mode 100644 index 0000000..32fff2c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ACosOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "ACos", "Trigonometry Operators", "Arccosine of scalars and vectors" )] + public sealed class ACosOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "acos"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + m_previewShaderGUID = "710f3c0bbd7ba0c4aada6d7dfadd49c2"; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ACosOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ACosOpNode.cs.meta new file mode 100644 index 0000000..74fdc7a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ACosOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8238f389c28938544b56035531b3f1be +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ASinOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ASinOpNode.cs new file mode 100644 index 0000000..936e1d1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ASinOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "ASin", "Trigonometry Operators", "Arcsine of scalars and vectors" )] + public sealed class ASinOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "asin"; + m_previewShaderGUID = "2b016c135284add4cb3364d4a0bd0638"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ASinOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ASinOpNode.cs.meta new file mode 100644 index 0000000..0e1aa0a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ASinOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 268ebf76d03c2e84f8c80a375773b46c +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATan2OpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATan2OpNode.cs new file mode 100644 index 0000000..70f9fb7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATan2OpNode.cs @@ -0,0 +1,28 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "ATan2", "Trigonometry Operators", "Arctangent of y/x" )] + public sealed class ATan2OpNode : DynamicTypeNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_dynamicOutputType = true; + m_useInternalPortData = true; + m_previewShaderGUID = "02e3ff61784e38840af6313936b6a730"; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + string result = "atan2( " + m_inputA + " , " + m_inputB + " )"; + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATan2OpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATan2OpNode.cs.meta new file mode 100644 index 0000000..9109fe7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATan2OpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f5957d9ac2cc12146bc862cd0c92815a +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATanOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATanOpNode.cs new file mode 100644 index 0000000..c36c599 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATanOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "ATan", "Trigonometry Operators", "Arctangent of scalars and vectors" )] + public sealed class ATanOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "atan"; + m_previewShaderGUID = "7d7f3331a98831241b017364e80625ea"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATanOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATanOpNode.cs.meta new file mode 100644 index 0000000..a382707 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ATanOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d84f7e90e793aaa4891b4c1fe400dc4c +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/AbsOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/AbsOpNode.cs new file mode 100644 index 0000000..18adcbd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/AbsOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Abs", "Math Operators", "Absolute value of scalars and vectors" )] + public sealed class AbsOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "abs"; + m_previewShaderGUID = "cd6d6dfa3df214a479f68a490e177db6"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/AbsOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/AbsOpNode.cs.meta new file mode 100644 index 0000000..50ca8f5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/AbsOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 46aea6c13d71ec74da7f23abba3704d6 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CeilOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CeilOpNode.cs new file mode 100644 index 0000000..6767231 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CeilOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Ceil", "Math Operators", "Smallest integer not less than a scalar or each vector component" )] + public sealed class CeilOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "ceil"; + m_previewShaderGUID = "ce0588227a766a245a85291977c1f222"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CeilOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CeilOpNode.cs.meta new file mode 100644 index 0000000..aba3589 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CeilOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 555db3754f84db947846519630ea303b +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClampOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClampOpNode.cs new file mode 100644 index 0000000..fe15a01 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClampOpNode.cs @@ -0,0 +1,103 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Clamp", "Math Operators", "Value clamped to the range [min,max]" )] + public sealed class ClampOpNode : ParentNode + { + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + AddInputPort( WirePortDataType.FLOAT, false, "Min" ); + AddInputPort( WirePortDataType.FLOAT, false, "Max" ); + m_inputPorts[ m_inputPorts.Count - 1 ].FloatInternalData = 1; + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_useInternalPortData = true; + m_textLabelWidth = 55; + m_previewShaderGUID = "ab6163c4b10bfc84da8e3c486520490a"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + if ( portId == 0 ) + { + m_inputPorts[ 0 ].MatchPortToConnection(); + m_inputPorts[ 1 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + m_inputPorts[ 2 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + //else + //{ + // _inputPorts[ portId ].MatchPortToConnection(); + //} + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + if ( outputPortId == 0 ) + { + m_inputPorts[ 0 ].MatchPortToConnection(); + m_inputPorts[ 1 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + m_inputPorts[ 2 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + WirePortDataType valueType = m_inputPorts[ 0 ].ConnectionType(); + WirePortDataType minType = m_inputPorts[ 1 ].ConnectionType(); + WirePortDataType maxType = m_inputPorts[ 2 ].ConnectionType(); + + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string min = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + if ( minType != valueType ) + { + min = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), null, m_inputPorts[ 1 ].DataType, m_inputPorts[ 0 ].DataType, min ); + } + + string max = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + if ( maxType != valueType ) + { + max = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), null, m_inputPorts[ 2 ].DataType, m_inputPorts[ 0 ].DataType, max ); + } + + string result = string.Empty; + switch ( valueType ) + { + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.INT: + case WirePortDataType.COLOR: + case WirePortDataType.OBJECT: + { + result = "clamp( " + value + " , " + min + " , " + max + " )"; + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + return UIUtils.InvalidParameter( this ); + } + } + + RegisterLocalVariable( 0, result, ref dataCollector, "clampResult" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClampOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClampOpNode.cs.meta new file mode 100644 index 0000000..dd3c8f7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClampOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5d7101830aa0c524f9519fef95c90dc3 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClipNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClipNode.cs new file mode 100644 index 0000000..606cb82 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClipNode.cs @@ -0,0 +1,123 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Clip", "Miscellaneous", "Conditionally kill a pixel before output" )] + public sealed class ClipNode : ParentNode + { + private const string ClipOpFormat = "clip( {0} );"; + private const string ClipSubOpFormat = "clip( {0} - {1});"; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + AddInputPort( WirePortDataType.FLOAT, false, "Alpha" ); + AddInputPort( WirePortDataType.FLOAT, false, "Threshold" ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_useInternalPortData = true; + + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + + m_previewShaderGUID = "1fca7774f364aee4d8c64e8634ef4be4"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ portId ].MatchPortToConnection(); + UpdatePortConnection( portId ); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ outputPortId ].MatchPortToConnection(); + UpdatePortConnection( outputPortId ); + } + + void UpdatePortConnection( int portId ) + { + if( portId == 0 ) + { + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + else + { + int otherPortId = portId == 1 ? 2 : 1; + if( m_inputPorts[ otherPortId ].IsConnected ) + { + WirePortDataType type1 = m_inputPorts[ portId ].DataType; + WirePortDataType type2 = m_inputPorts[ otherPortId ].DataType; + + WirePortDataType mainType = UIUtils.GetPriority( type1 ) > UIUtils.GetPriority( type2 ) ? type1 : type2; + + m_inputPorts[ portId ].ChangeType( mainType, false ); + m_inputPorts[ otherPortId ].ChangeType( mainType , false ); + } + else + { + m_inputPorts[ otherPortId ].ChangeType( m_inputPorts[ portId ].DataType,false ); + } + } + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + if( portId == 0 ) + return; + int otherPortId = portId == 1 ? 2 : 1; + if( m_inputPorts[ otherPortId ].IsConnected ) + { + m_inputPorts[ portId ].ChangeType( m_inputPorts[ otherPortId ].DataType, false ); + } + else + { + m_inputPorts[ portId ].ChangeType( WirePortDataType.FLOAT, false ); + m_inputPorts[ otherPortId ].ChangeType( WirePortDataType.FLOAT, false ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || + dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + UIUtils.ShowMessage( UniqueId, "Clip can only be used in fragment functions", MessageSeverity.Warning ); + return GenerateErrorValue(); + } + + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string alpha = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + if( m_inputPorts[ 2 ].IsConnected ) + { + string threshold = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + dataCollector.AddLocalVariable( UniqueId, string.Format( ClipSubOpFormat, alpha , threshold) ); + } + else + { + if( m_inputPorts[ 2 ].IsZeroInternalData ) + { + dataCollector.AddLocalVariable( UniqueId, string.Format( ClipOpFormat, alpha ) ); + } + else + { + string threshold = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + dataCollector.AddLocalVariable( UniqueId, string.Format( ClipSubOpFormat, alpha, threshold ) ); + } + } + + return value; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClipNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClipNode.cs.meta new file mode 100644 index 0000000..0d24e6e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ClipNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 78e9954f4d587b74fa38ae1dd9922d77 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ComponentMaskNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ComponentMaskNode.cs new file mode 100644 index 0000000..3ed727c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ComponentMaskNode.cs @@ -0,0 +1,382 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Component Mask", "Vector Operators", "Mask certain channels from vectors/color components", null, KeyCode.K )] + public sealed class ComponentMaskNode : ParentNode + { + private const string OutputLocalVarName = "componentMask"; + [SerializeField] + private bool[] m_selection = { true, true, true, true }; + + [SerializeField] + private int m_outputPortCount = 4; + + [SerializeField] + private string[] m_labels; + + private int m_cachedOrderId = -1; + private int m_cachedSingularId = -1; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT4, false, Constants.EmptyPortValue ); + AddOutputPort( WirePortDataType.FLOAT4, Constants.EmptyPortValue ); + m_useInternalPortData = true; + m_autoWrapProperties = true; + m_selectedLocation = PreviewLocation.TopCenter; + m_labels = new string[] { "X", "Y", "Z", "W" }; + m_previewShaderGUID = "b78e2b295c265cd439c80d218fb3e88e"; + SetAdditonalTitleText( "Value( XYZW )" ); + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + Vector4 order = new Vector4(-1,-1,-1,-1); + int lastIndex = 0; + int singularId = -1; + var datatype = m_inputPorts[ 0 ].DataType; + + if( m_selection[ 0 ] ) + { + order.Set( lastIndex, order.y, order.z, order.w ); + lastIndex++; + singularId = 0; + } + if( m_selection[ 1 ] && datatype >= WirePortDataType.FLOAT2 ) + { + order.Set( order.x, lastIndex, order.z, order.w ); + lastIndex++; + singularId = 1; + } + if( m_selection[ 2 ] && datatype >= WirePortDataType.FLOAT3 ) + { + order.Set( order.x, order.y, lastIndex, order.w ); + lastIndex++; + singularId = 2; + } + if( m_selection[ 3 ] && ( datatype == WirePortDataType.FLOAT4 || datatype == WirePortDataType.COLOR ) ) + { + order.Set( order.x, order.y, order.z, lastIndex ); + lastIndex++; + singularId = 3; + } + + if ( lastIndex != 1 ) + singularId = -1; + + if ( m_cachedOrderId == -1 ) + m_cachedOrderId = Shader.PropertyToID( "_Order" ); + + if ( m_cachedSingularId == -1 ) + m_cachedSingularId = Shader.PropertyToID( "_Singular" ); + + PreviewMaterial.SetVector( m_cachedOrderId, order ); + PreviewMaterial.SetFloat( m_cachedSingularId, singularId ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdatePorts(); + UpdateTitle(); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + UpdatePorts(); + UpdateTitle(); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + UpdateTitle(); + } + + void UpdatePorts() + { + m_inputPorts[ 0 ].MatchPortToConnection(); + int count = 0; + switch ( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.OBJECT: + case WirePortDataType.COLOR: + { + count = 4; + } + break; + case WirePortDataType.FLOAT3: + { + count = 3; + } + break; + case WirePortDataType.FLOAT2: + { + count = 2; + } + break; + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { } + break; + } + + int activeCount = 0; + if ( count > 0 ) + { + for ( int i = 0; i < count; i++ ) + { + if ( m_selection[ i ] ) + activeCount += 1; + } + } + + m_outputPortCount = activeCount; + switch ( activeCount ) + { + case 0: ChangeOutputType( m_inputPorts[ 0 ].DataType, false ); break; + case 1: ChangeOutputType( WirePortDataType.FLOAT, false ); break; + case 2: ChangeOutputType( WirePortDataType.FLOAT2, false ); break; + case 3: ChangeOutputType( WirePortDataType.FLOAT3, false ); break; + case 4: ChangeOutputType( m_inputPorts[ 0 ].DataType, false ); break; + } + + } + + private void UpdateTitle() + { + int count = 0; + string additionalText = string.Empty; + switch ( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.OBJECT: + case WirePortDataType.COLOR: + { + count = 4; + } + break; + case WirePortDataType.FLOAT3: + { + count = 3; + } + break; + case WirePortDataType.FLOAT2: + { + count = 2; + } + break; + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + { + count = 0; + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { } + break; + } + + if ( count > 0 ) + { + for ( int i = 0; i < count; i++ ) + { + if ( m_selection[ i ] ) + { + additionalText += UIUtils.GetComponentForPosition( i, m_inputPorts[ 0 ].DataType ).ToUpper(); + } + } + } + + if ( additionalText.Length > 0 ) + SetAdditonalTitleText( "Value( " + additionalText + " )" ); + else + SetAdditonalTitleText( string.Empty ); + } + + public override void DrawProperties() + { + base.DrawProperties(); + + EditorGUILayout.BeginVertical(); + + int count = 0; + switch ( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.OBJECT: + case WirePortDataType.COLOR: + { + count = 4; + } + break; + case WirePortDataType.FLOAT3: + { + count = 3; + } + break; + case WirePortDataType.FLOAT2: + { + count = 2; + } + break; + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { } + break; + } + + int activeCount = 0; + if ( count > 0 ) + { + for ( int i = 0; i < count; i++ ) + { + m_selection[ i ] = EditorGUILayoutToggleLeft( m_labels[i], m_selection[ i ] ); + m_labels[ i ] = UIUtils.GetComponentForPosition( i, m_inputPorts[ 0 ].DataType ).ToUpper(); + if ( m_selection[ i ] ) + { + activeCount += 1; + } + } + } + + if ( activeCount != m_outputPortCount ) + { + m_outputPortCount = activeCount; + switch ( activeCount ) + { + case 0: ChangeOutputType( m_inputPorts[ 0 ].DataType, false ); break; + case 1: ChangeOutputType( WirePortDataType.FLOAT, false ); break; + case 2: ChangeOutputType( WirePortDataType.FLOAT2, false ); break; + case 3: ChangeOutputType( WirePortDataType.FLOAT3, false ); break; + case 4: ChangeOutputType( m_inputPorts[ 0 ].DataType, false ); break; + } + UpdateTitle(); + SetSaveIsDirty(); + } + + EditorGUILayout.EndVertical(); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + int count = 0; + switch ( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.FLOAT4: + case WirePortDataType.OBJECT: + case WirePortDataType.COLOR: + { + count = 4; + } + break; + case WirePortDataType.FLOAT3: + { + count = 3; + } + break; + case WirePortDataType.FLOAT2: + { + count = 2; + } + break; + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + { + count = 0; + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { } + break; + } + + if ( count > 0 ) + { + bool firstElement = true; + value = string.Format("({0})",value); + for ( int i = 0; i < count; i++ ) + { + if ( m_selection[ i ] ) + { + if( firstElement ) + { + firstElement = false; + value += "."; + } + value += UIUtils.GetComponentForPosition( i, m_inputPorts[ 0 ].DataType ); + } + } + } + + return CreateOutputLocalVariable( 0, value, ref dataCollector ); + } + + public string GetComponentForPosition( int i ) + { + switch ( i ) + { + case 0: + { + return ( ( m_outputPorts[ 0 ].DataType == WirePortDataType.COLOR ) ? "r" : "x" ); + } + case 1: + { + return ( ( m_outputPorts[ 0 ].DataType == WirePortDataType.COLOR ) ? "g" : "y" ); + } + case 2: + { + return ( ( m_outputPorts[ 0 ].DataType == WirePortDataType.COLOR ) ? "b" : "z" ); + } + case 3: + { + return ( ( m_outputPorts[ 0 ].DataType == WirePortDataType.COLOR ) ? "a" : "w" ); + } + } + return string.Empty; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + for ( int i = 0; i < 4; i++ ) + { + m_selection[ i ] = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + UpdateTitle(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + for ( int i = 0; i < 4; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_selection[ i ] ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ComponentMaskNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ComponentMaskNode.cs.meta new file mode 100644 index 0000000..fd1be0b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ComponentMaskNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 85082b6932d1c9a4f8b64605534ef118 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CosOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CosOpNode.cs new file mode 100644 index 0000000..a7f799f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CosOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Cos", "Trigonometry Operators", "Cosine of scalars and vectors" )] + public sealed class CosOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "cos"; + m_previewShaderGUID = "3dde9e80389196f459eb94137268de4a"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CosOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CosOpNode.cs.meta new file mode 100644 index 0000000..132f1bf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CosOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ee9c446e7e41d524f8b4c93e6a8886c5 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CoshOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CoshOpNode.cs new file mode 100644 index 0000000..24b6205 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CoshOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Cosh", "Trigonometry Operators", "Hyperbolic cosine of scalars and vectors" )] + public sealed class CoshOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "cosh"; + m_previewShaderGUID = "154a4c85fe88657489a54a02416402c0"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CoshOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CoshOpNode.cs.meta new file mode 100644 index 0000000..46ec817 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CoshOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2b50a187f488a004aaa2dabbe558ab3a +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CrossProductOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CrossProductOpNode.cs new file mode 100644 index 0000000..354db0d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CrossProductOpNode.cs @@ -0,0 +1,35 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Cross", "Vector Operators", "Cross product of two three-component vectors ( A x B )", null, KeyCode.X )] + public sealed class CrossProductOpNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "Lhs" ); + AddInputPort( WirePortDataType.FLOAT3, false, "Rhs" ); + AddOutputPort( WirePortDataType.FLOAT3, "Out" ); + m_useInternalPortData = true; + m_previewShaderGUID = "65a9be5cc7037654db8e148d669f03ee"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + string lhsStr = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string rhsStr = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + string result = "cross( " + lhsStr + " , " + rhsStr + " )"; + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CrossProductOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CrossProductOpNode.cs.meta new file mode 100644 index 0000000..61758de --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/CrossProductOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 283bc0645ce925346b33c024ff5a7dad +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdxOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdxOpNode.cs new file mode 100644 index 0000000..53b8821 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdxOpNode.cs @@ -0,0 +1,32 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "DDX", "Math Operators", "Approximate partial derivative with respect to window-space X" )] + public sealed class DdxOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "ddx"; + m_previewShaderGUID = "b54ea73d5568b3540977557813eb9c3c"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsFragmentCategory ) + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + else + return m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdxOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdxOpNode.cs.meta new file mode 100644 index 0000000..d83171e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdxOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2e14c4a7c0be9f146ac912130c280b15 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdyOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdyOpNode.cs new file mode 100644 index 0000000..604a341 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdyOpNode.cs @@ -0,0 +1,32 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "DDY", "Math Operators", "Approximate partial derivative with respect to window-space Y" )] + public sealed class DdyOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "ddy"; + m_previewShaderGUID = "197dcc7f05339da47b6b0e681c475c5e"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsFragmentCategory ) + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + else + return m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdyOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdyOpNode.cs.meta new file mode 100644 index 0000000..d32275f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DdyOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 722a2ad531fefdc4d8782d5c7cdfd012 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DegreesOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DegreesOpNode.cs new file mode 100644 index 0000000..97afc8b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DegreesOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Degrees", "Trigonometry Operators", "Converts values of scalars and vectors from radians to degrees" )] + public sealed class DegreesOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "degrees"; + m_previewShaderGUID = "2a8eebb5566830c4a9d7c4b9021bb743"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DegreesOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DegreesOpNode.cs.meta new file mode 100644 index 0000000..93e8abe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DegreesOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3d88a21f3ece742408c7748897a21c79 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DeterminantOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DeterminantOpNode.cs new file mode 100644 index 0000000..d48f775 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DeterminantOpNode.cs @@ -0,0 +1,25 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Determinant", "Matrix Operators", "Scalar determinant of a square matrix" )] + public sealed class DeterminantOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "determinant"; + m_drawPreview = false; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4 ); + + m_autoUpdateOutputPort = false; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4x4, false ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT, false ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DeterminantOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DeterminantOpNode.cs.meta new file mode 100644 index 0000000..16d62ce --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DeterminantOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e5cded78687f09442895bc96cc5b683d +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DistanceOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DistanceOpNode.cs new file mode 100644 index 0000000..8e3a6db --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DistanceOpNode.cs @@ -0,0 +1,32 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Distance", "Vector Operators", "Euclidean distance between two points" )] + public sealed class DistanceOpNode : DynamicTypeNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_inputPorts[ 1 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT, false ); + m_dynamicOutputType = false; + m_useInternalPortData = true; + m_previewShaderGUID = "3be9a95031c0cb740ae982e465dfc242"; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + string result = "distance( " + m_inputA + " , " + m_inputB + " )"; + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DistanceOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DistanceOpNode.cs.meta new file mode 100644 index 0000000..3d28c02 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DistanceOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4b8bd7fecbc728f4b89d398cef86ada8 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DotProductOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DotProductOpNode.cs new file mode 100644 index 0000000..892ae53 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DotProductOpNode.cs @@ -0,0 +1,34 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Dot", "Vector Operators", "Scalar dot product of two vectors ( A . B )", null, KeyCode.Period )] + public sealed class DotProductOpNode : DynamicTypeNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_inputPorts[ 1 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_dynamicOutputType = false; + m_useInternalPortData = true; + m_allowMatrixCheck = true; + m_previewShaderGUID = "85f11fd5cb9bb954c8615a45c57a3784"; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + string result = "dot( " + m_inputA + " , " + m_inputB + " )"; + RegisterLocalVariable( 0, result, ref dataCollector, "dotResult" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DotProductOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DotProductOpNode.cs.meta new file mode 100644 index 0000000..a84594f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/DotProductOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c2bf0375fb75ce245b2f30857a111972 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Exp2OpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Exp2OpNode.cs new file mode 100644 index 0000000..b94d561 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Exp2OpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Exp2", "Math Operators", "Base-2 exponential of scalars and vectors" )] + public sealed class Exp2OpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "exp2"; + m_previewShaderGUID = "ceb70ed5423a36647a504a41de7dbfe6"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Exp2OpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Exp2OpNode.cs.meta new file mode 100644 index 0000000..edea0de --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Exp2OpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a9881734e0217bc45bb422dc83f6ee1a +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ExpOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ExpOpNode.cs new file mode 100644 index 0000000..29bded7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ExpOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Exp", "Math Operators", "Base-e exponential of scalars and vectors" )] + public sealed class ExpOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "exp"; + m_previewShaderGUID = "6416ff506137d97479a7ebde790b45e5"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ExpOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ExpOpNode.cs.meta new file mode 100644 index 0000000..f598976 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ExpOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 81ef96bc69f897d4e8bc21e2731e065f +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FWidthOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FWidthOpNode.cs new file mode 100644 index 0000000..75ee9f4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FWidthOpNode.cs @@ -0,0 +1,38 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "FWidth", "Math Operators", "Sum of approximate window-space partial derivatives magnitudes (Only valid on Fragment type ports)" )] + public sealed class FWidthOpNode : SingleInputOp + { + private const string FWidthErrorMsg = "Attempting to connect an FWidth to a {0} type port. It is only valid on Fragment type ports"; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "fwidth"; + m_previewShaderGUID = "81ea481faaef9c8459a555479ba64df7"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + //m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || + dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + UIUtils.ShowMessage( UniqueId, string.Format( FWidthErrorMsg, dataCollector.PortCategory ), MessageSeverity.Error ); + return GenerateErrorValue(); + } + + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FWidthOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FWidthOpNode.cs.meta new file mode 100644 index 0000000..f97901e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FWidthOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2e17448829221b04bb3185bef727b19f +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FloorOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FloorOpNode.cs new file mode 100644 index 0000000..5fe190e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FloorOpNode.cs @@ -0,0 +1,24 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Floor", "Math Operators", "Largest integer not greater than a scalar or each vector component" )] + public sealed class FloorOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "floor"; + m_previewShaderGUID = "46ae4a72a9a38de40a2d8f20cfccc67d"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FloorOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FloorOpNode.cs.meta new file mode 100644 index 0000000..bd8bbdb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FloorOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 176154e86c6c3544fab0d67e098c645d +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FmodOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FmodOpNode.cs new file mode 100644 index 0000000..698e370 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FmodOpNode.cs @@ -0,0 +1,36 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Fmod", "Math Operators", "Floating point remainder of x/y with the same sign as x" )] + public sealed class FmodOpNode : DynamicTypeNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_previewShaderGUID = "65083930f9d7812479fd6ff203ad2992"; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + if( m_inputPorts[ 0 ].DataType == WirePortDataType.INT ) + m_inputA = "(float)" + m_inputA; + + + if( m_inputPorts[ 1 ].DataType == WirePortDataType.INT ) + m_inputB = "(float)" + m_inputB; + + + string result = "fmod( " + m_inputA + " , " + m_inputB + " )"; + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FmodOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FmodOpNode.cs.meta new file mode 100644 index 0000000..c4d07b8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FmodOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 599ae67e52ac45f46acc0efd9285b97c +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FractNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FractNode.cs new file mode 100644 index 0000000..62c54dc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FractNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Fract", "Math Operators", "Fractional portion of a scalar or each vector component" )] + public sealed class FractNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "frac"; + m_previewShaderGUID = "53a335f8f18d4694b8d94e8aee21fdca"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FractNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FractNode.cs.meta new file mode 100644 index 0000000..004f9c6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/FractNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: fd6da00dbcdf3d04cb35a61cda01ae77 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/GradientSampleNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/GradientSampleNode.cs new file mode 100644 index 0000000..258dae3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/GradientSampleNode.cs @@ -0,0 +1,207 @@ +using System; +using UnityEngine; +using UnityEditor; +using System.Collections; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Gradient Sample", "Miscellaneous", "Samples a gradient" )] + public sealed class GradientSampleNode : ParentNode + { + private string m_functionHeader = "SampleGradient( {0}, {1} )"; + private string m_functionBody = string.Empty; + + private GradientNode m_gradientNode = null; + private InputPort m_gradPort; + + private Gradient m_blankGrandient = new Gradient(); + + private int m_cachedTimeId = -1; + private int m_cachedTypeId = -1; + private int m_cachedColorNumId = -1; + private int m_cachedAlphaNumId = -1; + + private Vector4 m_auxVec4 = Vector4.zero; + + private string m_functionHeaderStruct = "Gradient( {0} )"; + private string m_functionBodyStruct = string.Empty; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.OBJECT, true, Constants.EmptyPortValue ); + AddInputPort( WirePortDataType.FLOAT, false, "Time" ); + AddOutputColorPorts( "RGBA", true ); + m_gradPort = m_inputPorts[ 0 ]; + m_useInternalPortData = true; + m_autoDrawInternalPortData = true; + m_drawPreviewExpander = false; + m_drawPreview = true; + m_showPreview = true; + m_selectedLocation = PreviewLocation.TopCenter; + m_previewShaderGUID = "8a09124cd6e4aa54a996e7487ec16b90"; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_cachedTypeId == -1 ) + m_cachedTypeId = Shader.PropertyToID( "_GType" ); + + if( m_cachedTimeId == -1 ) + m_cachedTimeId = Shader.PropertyToID( "_GTime" ); + + if( m_cachedColorNumId == -1 ) + m_cachedColorNumId = Shader.PropertyToID( "_GColorNum" ); + + if( m_cachedAlphaNumId == -1 ) + m_cachedAlphaNumId = Shader.PropertyToID( "_GAlphaNum" ); + + PreviewMaterial.SetTexture( m_cachedTimeId, m_inputPorts[ 1 ].InputPreviewTexture( ContainerGraph ) ); + + Gradient curGrad = m_blankGrandient; + if( m_gradientNode != null ) + curGrad = m_gradientNode.Gradient; + + PreviewMaterial.SetInt( m_cachedTypeId, (int)curGrad.mode ); + PreviewMaterial.SetInt( m_cachedColorNumId, curGrad.colorKeys.Length ); + PreviewMaterial.SetInt( m_cachedAlphaNumId, curGrad.alphaKeys.Length ); + + for( int i = 0; i < 8; i++ ) + { + if( i < curGrad.colorKeys.Length ) + { + m_auxVec4.x = curGrad.colorKeys[ i ].color.r; + m_auxVec4.y = curGrad.colorKeys[ i ].color.g; + m_auxVec4.z = curGrad.colorKeys[ i ].color.b; + m_auxVec4.w = curGrad.colorKeys[ i ].time; + PreviewMaterial.SetVector( "_Col" + i, m_auxVec4 ); + } + else + { + PreviewMaterial.SetVector( "_Col" + i, Vector4.zero ); + } + } + + for( int i = 0; i < 8; i++ ) + { + if( i < curGrad.alphaKeys.Length ) + { + m_auxVec4.x = curGrad.alphaKeys[ i ].alpha; + m_auxVec4.y = curGrad.alphaKeys[ i ].time; + PreviewMaterial.SetVector( "_Alp" + i, m_auxVec4 ); + } + else + { + PreviewMaterial.SetVector( "_Alp" + i, Vector4.zero ); + } + } + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + + if( m_gradPort.IsConnected ) + { + m_gradientNode = RecursiveBackCheck( m_gradPort.GetOutputNode( 0 ) ); + } + else + { + m_gradientNode = null; + } + } + + GradientNode RecursiveBackCheck( ParentNode node ) + { + if( node is GradientNode ) + { + return node as GradientNode; + } + else + { + if( node is RelayNode || node is WireNode || node is RegisterLocalVarNode ) + { + return RecursiveBackCheck( node.InputPorts[ 0 ].GetOutputNode( 0 ) ); + } + else if( node is GetLocalVarNode) + { + var gnode = node as GetLocalVarNode; + if( gnode.CurrentSelected != null ) + return RecursiveBackCheck( gnode.CurrentSelected ); + else + return null; + } + else + { + return null; + } + } + + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + m_functionBodyStruct = string.Empty; + if( !dataCollector.IsSRP ) + { + GradientNode.GenerateGradientStruct( ref m_functionBodyStruct ); + dataCollector.AddFunctions( m_functionHeaderStruct, m_functionBodyStruct, "0" ); + } + else + { + dataCollector.AddToIncludes( UniqueId, "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl" ); + } + + GenerateGradientSampler( dataCollector.IsSRP ); + + string gradient = "(Gradient)0"; + if( m_inputPorts[ 0 ].IsConnected && m_gradientNode != null ) + gradient = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string time = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + string functionResult = dataCollector.AddFunctions( m_functionHeader, m_functionBody, gradient, time ); + return GetOutputVectorItem( 0, outputId, functionResult ); + } + + void GenerateGradientSampler( bool isSrp ) + { + m_functionBody = string.Empty; + IOUtils.AddFunctionHeader( ref m_functionBody, "float4 SampleGradient( Gradient gradient, float time )" ); + IOUtils.AddFunctionLine( ref m_functionBody, "float3 color = gradient.colors[0].rgb;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "UNITY_UNROLL" ); + IOUtils.AddFunctionLine( ref m_functionBody, "for (int c = 1; c < 8; c++)" ); + IOUtils.AddFunctionLine( ref m_functionBody, "{" ); + if( isSrp ) + IOUtils.AddFunctionLine( ref m_functionBody, "float colorPos = saturate((time - gradient.colors[c-1].w) / ( 0.00001 + (gradient.colors[c].w - gradient.colors[c-1].w)) * step(c, gradient.colorsLength-1));" ); + else + IOUtils.AddFunctionLine( ref m_functionBody, "float colorPos = saturate((time - gradient.colors[c-1].w) / ( 0.00001 + (gradient.colors[c].w - gradient.colors[c-1].w)) * step(c, (float)gradient.colorsLength-1));" ); + IOUtils.AddFunctionLine( ref m_functionBody, "color = lerp(color, gradient.colors[c].rgb, lerp(colorPos, step(0.01, colorPos), gradient.type));" ); + IOUtils.AddFunctionLine( ref m_functionBody, "}" ); + + IOUtils.AddFunctionLine( ref m_functionBody, "#ifndef UNITY_COLORSPACE_GAMMA" ); + if( isSrp ) + IOUtils.AddFunctionLine( ref m_functionBody, "color = SRGBToLinear(color);" ); + else + IOUtils.AddFunctionLine( ref m_functionBody, "color = half3(GammaToLinearSpaceExact(color.r), GammaToLinearSpaceExact(color.g), GammaToLinearSpaceExact(color.b));" ); + IOUtils.AddFunctionLine( ref m_functionBody, "#endif" ); + + IOUtils.AddFunctionLine( ref m_functionBody, "float alpha = gradient.alphas[0].x;" ); + IOUtils.AddFunctionLine( ref m_functionBody, "UNITY_UNROLL" ); + IOUtils.AddFunctionLine( ref m_functionBody, "for (int a = 1; a < 8; a++)" ); + IOUtils.AddFunctionLine( ref m_functionBody, "{" ); + if( isSrp ) + IOUtils.AddFunctionLine( ref m_functionBody, "float alphaPos = saturate((time - gradient.alphas[a-1].y) / ( 0.00001 + (gradient.alphas[a].y - gradient.alphas[a-1].y)) * step(a, gradient.alphasLength-1));" ); + else + IOUtils.AddFunctionLine( ref m_functionBody, "float alphaPos = saturate((time - gradient.alphas[a-1].y) / ( 0.00001 + (gradient.alphas[a].y - gradient.alphas[a-1].y)) * step(a, (float)gradient.alphasLength-1));" ); + IOUtils.AddFunctionLine( ref m_functionBody, "alpha = lerp(alpha, gradient.alphas[a].x, lerp(alphaPos, step(0.01, alphaPos), gradient.type));" ); + IOUtils.AddFunctionLine( ref m_functionBody, "}" ); + IOUtils.AddFunctionLine( ref m_functionBody, "return float4(color, alpha);" ); + IOUtils.CloseFunctionBody( ref m_functionBody ); + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/GradientSampleNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/GradientSampleNode.cs.meta new file mode 100644 index 0000000..51d0b9e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/GradientSampleNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b90e416e2fa93a249952fabc78f659c8 +timeCreated: 1562847602 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/InverseOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/InverseOpNode.cs new file mode 100644 index 0000000..178fc54 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/InverseOpNode.cs @@ -0,0 +1,138 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// 4x4 Invert by DBN in +// http://answers.unity3d.com/questions/218333/shader-inversefloat4x4-function.html?childToView=641391#answer-641391 + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Inverse", "Matrix Operators", "Inverse matrix of a matrix" )] + public sealed class InverseOpNode : SingleInputOp + { + private string Inverse4x4Header = "Inverse4x4( {0} )"; + + //4x4 + private string[] Inverse4x4Function = + { + "{0}4x4 Inverse4x4({0}4x4 input)\n", + "{\n", + "\t#define minor(a,b,c) determinant({0}3x3(input.a, input.b, input.c))\n", + "\t{0}4x4 cofactors = {0}4x4(\n", + "\tminor( _22_23_24, _32_33_34, _42_43_44 ),\n", + "\t-minor( _21_23_24, _31_33_34, _41_43_44 ),\n", + "\tminor( _21_22_24, _31_32_34, _41_42_44 ),\n", + "\t-minor( _21_22_23, _31_32_33, _41_42_43 ),\n", + "\n", + "\t-minor( _12_13_14, _32_33_34, _42_43_44 ),\n", + "\tminor( _11_13_14, _31_33_34, _41_43_44 ),\n", + "\t-minor( _11_12_14, _31_32_34, _41_42_44 ),\n", + "\tminor( _11_12_13, _31_32_33, _41_42_43 ),\n", + "\n", + "\tminor( _12_13_14, _22_23_24, _42_43_44 ),\n", + "\t-minor( _11_13_14, _21_23_24, _41_43_44 ),\n", + "\tminor( _11_12_14, _21_22_24, _41_42_44 ),\n", + "\t-minor( _11_12_13, _21_22_23, _41_42_43 ),\n", + "\n", + "\t-minor( _12_13_14, _22_23_24, _32_33_34 ),\n", + "\tminor( _11_13_14, _21_23_24, _31_33_34 ),\n", + "\t-minor( _11_12_14, _21_22_24, _31_32_34 ),\n", + "\tminor( _11_12_13, _21_22_23, _31_32_33 ));\n", + "\t#undef minor\n", + "\treturn transpose( cofactors ) / determinant( input );\n", + "}\n" + }; + + private bool[] Inverse4x4FunctionFlags = + { + true, + false, + true, + true, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false + }; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "inverse"; + m_drawPreview = false; + + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4 ); + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4x4, false ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4x4, false ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, WirePortDataType.FLOAT ); + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + if ( m_outputPorts[ 0 ].DataType == WirePortDataType.FLOAT3x3 ) + { + GeneratorUtils.Add3x3InverseFunction( ref dataCollector, precisionString ); + RegisterLocalVariable( 0, string.Format( GeneratorUtils.Inverse3x3Header, value ), ref dataCollector, "invertVal" + OutputId ); + } + else + { + if ( !dataCollector.HasFunction( Inverse4x4Header ) ) + { + //Hack to be used util indent is properly used + int currIndent = UIUtils.ShaderIndentLevel; + + if ( dataCollector.IsTemplate ) + { + UIUtils.ShaderIndentLevel = 0; + } + else + { + UIUtils.ShaderIndentLevel = 1; + UIUtils.ShaderIndentLevel++; + } + + string finalFunction = string.Empty; + for ( int i = 0; i < Inverse4x4Function.Length; i++ ) + { + finalFunction += UIUtils.ShaderIndentTabs + ( Inverse4x4FunctionFlags[ i ] ? string.Format( Inverse4x4Function[ i ], precisionString ) : Inverse4x4Function[ i ] ); + } + + + UIUtils.ShaderIndentLevel = currIndent; + + dataCollector.AddFunction( Inverse4x4Header, finalFunction ); + } + + RegisterLocalVariable( 0, string.Format( Inverse4x4Header, value ), ref dataCollector, "invertVal" + OutputId ); + } + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/InverseOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/InverseOpNode.cs.meta new file mode 100644 index 0000000..bc47ad0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/InverseOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 785830160e033d24280df9c5b4cec368 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LengthOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LengthOpNode.cs new file mode 100644 index 0000000..c67f26b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LengthOpNode.cs @@ -0,0 +1,41 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Length", "Vector Operators", "Scalar Euclidean length of a vector" )] + public sealed class LengthOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "length"; + m_previewShaderGUID = "1c1f6d6512b758942a8b9dd1bea12f34"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_autoUpdateOutputPort = false; + } + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + switch( m_inputPorts[0].DataType ) + { + case WirePortDataType.OBJECT: + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + case WirePortDataType.UINT:m_previewMaterialPassId = 0;break; + case WirePortDataType.FLOAT2:m_previewMaterialPassId = 1;break; + case WirePortDataType.FLOAT3:m_previewMaterialPassId = 2;break; + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR:m_previewMaterialPassId = 3;break; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LengthOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LengthOpNode.cs.meta new file mode 100644 index 0000000..c13dd4f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LengthOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bb3fd570e41cfa24d93b53e80eac02d5 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LerpOp.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LerpOp.cs new file mode 100644 index 0000000..1ec7199 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LerpOp.cs @@ -0,0 +1,116 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Lerp", "Math Operators", "Linear interpolation of two scalars or vectors based on a weight", null, KeyCode.L )] + public sealed class LerpOp : ParentNode + { + private const string LertOpFormat = "lerp( {0} , {1} , {2})"; + + [UnityEngine.SerializeField] + private WirePortDataType m_mainDataType = WirePortDataType.FLOAT; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_textLabelWidth = 55; + AddInputPort( WirePortDataType.FLOAT, false, "A" ); + AddInputPort( WirePortDataType.FLOAT, false, "B" ); + AddInputPort( WirePortDataType.FLOAT, false, "Alpha" ); + AddOutputPort( WirePortDataType.FLOAT,Constants.EmptyPortValue); + m_useInternalPortData = true; + m_previewShaderGUID = "34d9c4cdcf1fadb49af2de3f90bbc57d"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnection( portId ); + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + UpdateConnection( inputPortId ); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + UpdateConnection( portId ); + } + + void UpdateConnection( int portId ) + { + WirePortDataType type1 = WirePortDataType.FLOAT; + if( m_inputPorts[ 0 ].IsConnected ) + type1 = m_inputPorts[ 0 ].GetOutputConnection( 0 ).DataType; + + WirePortDataType type2 = WirePortDataType.FLOAT; + if( m_inputPorts[ 1 ].IsConnected ) + type2 = m_inputPorts[ 1 ].GetOutputConnection( 0 ).DataType; + + WirePortDataType typealpha = WirePortDataType.FLOAT; + if( m_inputPorts[ 2 ].IsConnected ) + typealpha = m_inputPorts[ 2 ].GetOutputConnection( 0 ).DataType; + + m_mainDataType = UIUtils.GetPriority( type1 ) > UIUtils.GetPriority( type2 ) ? type1 : type2; + + if( !m_inputPorts[ 0 ].IsConnected && !m_inputPorts[ 1 ].IsConnected && m_inputPorts[ 2 ].IsConnected ) + m_mainDataType = m_inputPorts[ 2 ].GetOutputConnection( 0 ).DataType; + + m_inputPorts[ 0 ].ChangeType( m_mainDataType, false ); + + m_inputPorts[ 1 ].ChangeType( m_mainDataType, false ); + if( m_inputPorts[ 2 ].IsConnected && ( typealpha == WirePortDataType.FLOAT || typealpha == WirePortDataType.INT ) ) + m_inputPorts[ 2 ].ChangeType( WirePortDataType.FLOAT, false ); + else + m_inputPorts[ 2 ].ChangeType( m_mainDataType, false ); + + m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + } + + //void UpdateDisconnection( int portId ) + //{ + // int otherPortId = ( portId + 1 ) % 2; + // if ( m_inputPorts[ otherPortId ].IsConnected ) + // { + // m_mainDataType = m_inputPorts[ otherPortId ].DataType; + // m_inputPorts[ portId ].ChangeType( m_mainDataType, false ); + // m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + // } + //} + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string aValue = m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, m_mainDataType, ignoreLocalVar, true ); + string bValue = m_inputPorts[ 1 ].GenerateShaderForOutput( ref dataCollector, m_mainDataType, ignoreLocalVar, true ); + string interp = string.Empty; + if( m_inputPorts[ 2 ].DataType == WirePortDataType.FLOAT ) + interp = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + else + interp = m_inputPorts[ 2 ].GenerateShaderForOutput( ref dataCollector, m_mainDataType, ignoreLocalVar,true ); + string result = string.Format( LertOpFormat, aValue,bValue,interp); + + RegisterLocalVariable( 0, result, ref dataCollector, "lerpResult"+OutputId ); + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + //public override void RefreshExternalReferences() + //{ + // if ( m_inputPorts[ 2 ].DataType != WirePortDataType.FLOAT ) + // { + // m_inputPorts[ 2 ].ChangeType( WirePortDataType.FLOAT, false ); + // } + //} + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LerpOp.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LerpOp.cs.meta new file mode 100644 index 0000000..22b8eec --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LerpOp.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1e38abf6e3c7dfa409a5fe40d2ce8a19 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log10OpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log10OpNode.cs new file mode 100644 index 0000000..35914c3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log10OpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Log10", "Math Operators", "Base-10 logarithm of scalars and vectors" )] + public sealed class Log10OpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "log10"; + m_previewShaderGUID = "9e7cfa357dd261f499d0ba8637ff2614"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log10OpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log10OpNode.cs.meta new file mode 100644 index 0000000..e9ae3c3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log10OpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: be47a76f1f42fbe47bf2568584c31196 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log2OpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log2OpNode.cs new file mode 100644 index 0000000..614a82a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log2OpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Log2", "Math Operators", "Base-2 logarithm of scalars and vectors" )] + public sealed class Log2OpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "log2"; + m_previewShaderGUID = "5975a154432d4c64cacd78d015ed08ba"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log2OpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log2OpNode.cs.meta new file mode 100644 index 0000000..9511991 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/Log2OpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b9489308aad1f794982afc1faf646013 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LogOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LogOpNode.cs new file mode 100644 index 0000000..ff7d786 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LogOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Log", "Math Operators", "Natural logarithm of scalars and vectors" )] + public sealed class LogOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "log"; + m_previewShaderGUID = "a3293e0a73834b24682775f5d8ee1e7c"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LogOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LogOpNode.cs.meta new file mode 100644 index 0000000..7aab4f7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/LogOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1ed2c12cea61a8c4fa67eebdc10d2a2a +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/MultipleInputOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/MultipleInputOpNode.cs new file mode 100644 index 0000000..9cb64e9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/MultipleInputOpNode.cs @@ -0,0 +1,3 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// Deprecated file diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/MultipleInputOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/MultipleInputOpNode.cs.meta new file mode 100644 index 0000000..597824c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/MultipleInputOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8804c7e5888738547b5a704f788fc18b +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NegateNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NegateNode.cs new file mode 100644 index 0000000..00c174d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NegateNode.cs @@ -0,0 +1,46 @@ +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Negate", "Math Operators", "Negate or invert an input value" )] + public sealed class NegateNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_useInternalPortData = true; + m_previewShaderGUID = "b035bc40da1ac7c4eafad4116382ec79"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + string result = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + if ( result.StartsWith( "-" ) ) + { + return result.Remove( 0, 1 ); + } + else + { + return "-" + result; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NegateNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NegateNode.cs.meta new file mode 100644 index 0000000..83f5922 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NegateNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 01c91005470f6b94eba168a127cecd6c +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NormalizeNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NormalizeNode.cs new file mode 100644 index 0000000..7faddb4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NormalizeNode.cs @@ -0,0 +1,87 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Normalize", "Vector Operators", "Normalizes a vector", null, KeyCode.N )] + public sealed class NormalizeNode : SingleInputOp + { + [SerializeField] + private bool m_safeNormalize = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_selectedLocation = PreviewLocation.TopCenter; + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.FLOAT, WirePortDataType.FLOAT2, WirePortDataType.FLOAT3, WirePortDataType.FLOAT4, WirePortDataType.COLOR, WirePortDataType.OBJECT, WirePortDataType.INT ); + + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4 , false ); + + m_previewShaderGUID = "a51b11dfb6b32884e930595e5f9defa8"; + m_autoWrapProperties = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_safeNormalize = EditorGUILayoutToggle( "Safe Normalize" , m_safeNormalize ); + EditorGUILayout.HelpBox( Constants.SafeNormalizeInfoStr , MessageType.Info ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string result = string.Empty; + switch ( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.OBJECT: + case WirePortDataType.COLOR: + { + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + result = GeneratorUtils.NormalizeValue( ref dataCollector , m_safeNormalize , m_inputPorts[ 0 ].DataType, value ); + } + break; + case WirePortDataType.INT: + { + return m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + } + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + result = UIUtils.InvalidParameter( this ); + } + break; + } + RegisterLocalVariable( 0, result, ref dataCollector, "normalizeResult" + OutputId ); + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 18814 ) + { + m_safeNormalize = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo , ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo , ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_safeNormalize ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NormalizeNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NormalizeNode.cs.meta new file mode 100644 index 0000000..8bec377 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/NormalizeNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: fa6682c371754094f88b3c2a7e96ae26 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/OneMinusNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/OneMinusNode.cs new file mode 100644 index 0000000..1079211 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/OneMinusNode.cs @@ -0,0 +1,45 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "One Minus", "Math Operators", "1 - input value", null, KeyCode.O )] + public sealed class OneMinusNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_useInternalPortData = true; + m_previewShaderGUID = "bed5300b92e7bb0419d0f4accb853312"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( InputPorts[ 0 ].DataType, false ); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( InputPorts[ 0 ].DataType, false ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string result = "( 1.0 - " + m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) + " )"; + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/OneMinusNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/OneMinusNode.cs.meta new file mode 100644 index 0000000..ff94c53 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/OneMinusNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 727743b66e17d7b4f9c2fbe7dde98bd9 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/PowerNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/PowerNode.cs new file mode 100644 index 0000000..82357b6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/PowerNode.cs @@ -0,0 +1,93 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Power", "Math Operators", "Base to the Exp-th power of scalars and vectors", null, KeyCode.E )] + public sealed class PowerNode : ParentNode + { + public const string SafePowerStr = "max( {0} , 0.0001 )"; + public const string SafePowerLabel = "Safe Power"; + + [SerializeField] + private bool m_safePower = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "Base" ); + AddInputPort( WirePortDataType.FLOAT, false, "Exp" ); + m_inputPorts[ 1 ].FloatInternalData = 1; + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_useInternalPortData = true; + m_autoWrapProperties = true; + m_textLabelWidth = 85; + m_previewShaderGUID = "758cc2f8b537b4e4b93d9833075d138c"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnections( portId ); + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + UpdateConnections( inputPortId ); + } + + void UpdateConnections( int inputPort ) + { + m_inputPorts[ inputPort ].MatchPortToConnection(); + if ( inputPort == 0 ) + { + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_safePower = EditorGUILayoutToggle( SafePowerLabel, m_safePower ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string x = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + if( m_safePower ) + { + string safePowerName = "saferPower" + OutputId; + string safePowerValue = string.Format( SafePowerStr, x ); + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_inputPorts[ 0 ].DataType, safePowerName, safePowerValue ); + x = safePowerName; + } + + string y = m_inputPorts[ 1 ].GenerateShaderForOutput( ref dataCollector, m_inputPorts[ 0 ].DataType, ignoreLocalvar, true ); + string result = "pow( " + x + " , " + y + " )"; + + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 17502 ) + m_safePower = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_safePower ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/PowerNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/PowerNode.cs.meta new file mode 100644 index 0000000..bedc464 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/PowerNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 520a55839e863ce47b3558be612f4691 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RSqrtOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RSqrtOpNode.cs new file mode 100644 index 0000000..659c86c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RSqrtOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Rsqrt", "Math Operators", "Reciprocal square root of scalars and vectors" )] + public sealed class RSqrtOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "rsqrt"; + m_previewShaderGUID = "c58c17cb1f7f6e6429a2c7a6cdaef87d"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RSqrtOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RSqrtOpNode.cs.meta new file mode 100644 index 0000000..e124e47 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RSqrtOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 513de50bd4766d0448bb471ca272608f +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RadiansOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RadiansOpNode.cs new file mode 100644 index 0000000..19f478f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RadiansOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Radians", "Trigonometry Operators", "Converts values of scalars and vectors from degrees to radians" )] + public sealed class RadiansOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "radians"; + m_previewShaderGUID = "d27d189eaf6eeb04fae9913d9617ece5"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RadiansOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RadiansOpNode.cs.meta new file mode 100644 index 0000000..f90ec87 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RadiansOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b6ca01d5c16f73c42996318c140eddb7 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ReflectOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ReflectOpNode.cs new file mode 100644 index 0000000..1488cb1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ReflectOpNode.cs @@ -0,0 +1,33 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Reflect", "Vector Operators", "Reflection vector given an incidence vector and a normal vector" )] + public sealed class ReflectOpNode : DynamicTypeNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].ChangeProperties( "Incident", WirePortDataType.FLOAT4, false ); + m_inputPorts[ 1 ].ChangeProperties( "Normal", WirePortDataType.FLOAT4, false ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + + m_textLabelWidth = 67; + m_previewShaderGUID = "fb520f2145c0fa0409320a9e6d720758"; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + string result = "reflect( " + m_inputA + " , " + m_inputB + " )"; + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ReflectOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ReflectOpNode.cs.meta new file mode 100644 index 0000000..2b7f085 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ReflectOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bcd77715f8db1564abc96d502312d476 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RefractOpVec.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RefractOpVec.cs new file mode 100644 index 0000000..ba59e2c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RefractOpVec.cs @@ -0,0 +1,92 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Refract", "Vector Operators", "Computes a refraction vector" )] + public sealed class RefractOpVec : ParentNode + { + [UnityEngine.SerializeField] + private WirePortDataType m_mainDataType = WirePortDataType.FLOAT; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT4, false , "Incident" ); + AddInputPort( WirePortDataType.FLOAT4, false , "Normal" ); + AddInputPort( WirePortDataType.FLOAT, false, "Eta" ); + AddOutputPort( WirePortDataType.FLOAT4, Constants.EmptyPortValue ); + m_textLabelWidth = 67; + m_previewShaderGUID = "5ab44ca484bed8b4884b03b1c00fdc3d"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnection( portId ); + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + UpdateConnection( inputPortId ); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + UpdateConnection( portId ); + } + + void UpdateConnection( int portId ) + { + if( portId == 2 ) + return; + + bool hasConnection = false; + + WirePortDataType type1 = WirePortDataType.FLOAT; + if( m_inputPorts[ 0 ].IsConnected ) + { + type1 = m_inputPorts[ 0 ].GetOutputConnection( 0 ).DataType; + hasConnection = true; + } + WirePortDataType type2 = WirePortDataType.FLOAT; + if( m_inputPorts[ 1 ].IsConnected ) + { + type2 = m_inputPorts[ 1 ].GetOutputConnection( 0 ).DataType; + hasConnection = true; + } + + if( hasConnection ) + { + m_mainDataType = UIUtils.GetPriority( type1 ) > UIUtils.GetPriority( type2 ) ? type1 : type2; + } + else + { + m_mainDataType = WirePortDataType.FLOAT4; + } + + m_inputPorts[ 0 ].ChangeType( m_mainDataType, false ); + m_inputPorts[ 1 ].ChangeType( m_mainDataType, false ); + m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string incident = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string normal = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string interp = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + string result = "refract( " + incident + " , " + normal + " , " + interp + " )"; + + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RefractOpVec.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RefractOpVec.cs.meta new file mode 100644 index 0000000..58b705a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RefractOpVec.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c5bb608b83cdc894cab572c72baa5f84 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RoundOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RoundOpNode.cs new file mode 100644 index 0000000..95b1dd8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RoundOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Round", "Math Operators", "Rounded value of scalars or vectors" )] + public sealed class RoundOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "round"; + m_previewShaderGUID = "554d561417b207c4bb3cd4a0c86b6907"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RoundOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RoundOpNode.cs.meta new file mode 100644 index 0000000..9b3740d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/RoundOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f7b5f29bc7f6bb844ae4ea698404adc3 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SaturateNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SaturateNode.cs new file mode 100644 index 0000000..ed91f4d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SaturateNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Saturate", "Math Operators", "Saturate clamps the input values into the [0,1] range" )] + public sealed class SaturateNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "saturate"; + m_previewShaderGUID = "d9e53418dc8b9d34fb395e3ea3c75985"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SaturateNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SaturateNode.cs.meta new file mode 100644 index 0000000..e199e9c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SaturateNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9d56f68d94c889443af651140ef86948 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleAndOffsetNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleAndOffsetNode.cs new file mode 100644 index 0000000..0d79fe8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleAndOffsetNode.cs @@ -0,0 +1,78 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Scale And Offset", "Math Operators", "Scales and offsets an input value\n( ( Value * Scale ) + Offset )" )] + public sealed class ScaleAndOffsetNode : ParentNode + { + private const string ScaleOffsetOpStr = "({0}*{1} + {2})"; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + AddInputPort( WirePortDataType.FLOAT, false, "Scale" ); + m_inputPorts[ 1 ].FloatInternalData = 1; + AddInputPort( WirePortDataType.FLOAT, false, "Offset" ); + AddOutputPort( WirePortDataType.FLOAT, " " ); + m_useInternalPortData = true; + m_previewShaderGUID = "a1f1053d4d9c3be439e0382038b74771"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnection( portId ); + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + UpdateConnection( inputPortId ); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + m_inputPorts[ portId ].ChangeType( WirePortDataType.FLOAT, false ); + if( portId == 0 ) + { + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT, false ); + } + } + + void UpdateConnection( int portId ) + { + if( portId == 0 ) + { + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + else + { + WirePortDataType newDataType = m_inputPorts[ portId ].ConnectionType() == WirePortDataType.FLOAT ? WirePortDataType.FLOAT : m_outputPorts[ 0 ].DataType; + m_inputPorts[ portId ].ChangeType( newDataType, false ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + // If scale or offset ports are floats then there's no need to cast them to any other type since they can be multiplied with everything + WirePortDataType scaleType = ( m_inputPorts[ 1 ].ConnectionType() == WirePortDataType.FLOAT ) ? WirePortDataType.FLOAT : m_outputPorts[ 0 ].DataType; + string scale = m_inputPorts[ 1 ].GenerateShaderForOutput( ref dataCollector, scaleType, ignoreLocalvar , true ); + + WirePortDataType offsetType = ( m_inputPorts[ 2 ].ConnectionType() == WirePortDataType.FLOAT ) ? WirePortDataType.FLOAT : m_outputPorts[ 0 ].DataType; + string offset = m_inputPorts[ 2 ].GenerateShaderForOutput( ref dataCollector, offsetType, ignoreLocalvar, true ); + + string result = string.Format( ScaleOffsetOpStr, value, scale, offset ); + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleAndOffsetNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleAndOffsetNode.cs.meta new file mode 100644 index 0000000..4a508a8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleAndOffsetNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b594feaa69ad03449b563f834fe0c18e +timeCreated: 1484582091 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleNode.cs new file mode 100644 index 0000000..7445a10 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleNode.cs @@ -0,0 +1,152 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Scale", "Math Operators", "Scales input value by a float factor" )] + public sealed class ScaleNode : ParentNode + { + private const string ScaleFactorStr = "Scale"; + + [SerializeField] + private float m_scaleFactor = 1; + + private int m_cachedPropertyId = -1; + + private const float LabelWidth = 8; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, " " ); + AddOutputPort( WirePortDataType.FLOAT, " " ); + m_insideSize.Set( 50, 10 ); + m_autoWrapProperties = true; + m_previewShaderGUID = "6d8ec9d9dab62c44aa2dcc0e3987760d"; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if ( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_ScaleFloat" ); + + PreviewMaterial.SetFloat( m_cachedPropertyId, m_scaleFactor ); + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_scaleFactor = EditorGUILayoutFloatField( ScaleFactorStr, m_scaleFactor ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_outputPorts[ 0 ].ChangeType( InputPorts[ 0 ].DataType, false ); + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_propertyDrawPos.x = m_remainingBox.x + Constants.FLOAT_WIDTH_SPACING * drawInfo.InvertedZoom * 0.5f; + m_propertyDrawPos.y = m_remainingBox.y + Constants.INPUT_PORT_DELTA_Y * drawInfo.InvertedZoom * 0.5f; + m_propertyDrawPos.width = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_WIDTH_FIELD_SIZE; + m_propertyDrawPos.height = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if ( drawInfo.CurrentEventType != EventType.MouseDown ) + return; + + Rect hitBox = m_remainingBox; + hitBox.xMin -= LabelWidth * drawInfo.InvertedZoom; + bool insideBox = hitBox.Contains( drawInfo.MousePosition ); + + if ( insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = true; + } + else if ( m_isEditingFields && !insideBox ) + { + GUI.FocusControl( null ); + m_isEditingFields = false; + } + } + + private bool m_isEditingFields; + private float m_previousValue; + private string m_fieldText = "0"; + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if ( !m_isVisible ) + return; + + if ( m_isEditingFields ) + { + UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref m_scaleFactor, LabelWidth ); + } + else if ( drawInfo.CurrentEventType == EventType.Repaint ) + { + Rect fakeField = m_propertyDrawPos; + fakeField.xMin += LabelWidth * drawInfo.InvertedZoom; + Rect fakeLabel = m_propertyDrawPos; + fakeLabel.xMax = fakeField.xMin; + EditorGUIUtility.AddCursorRect( fakeLabel, MouseCursor.SlideArrow ); + EditorGUIUtility.AddCursorRect( fakeField, MouseCursor.Text ); + + if ( m_previousValue != m_scaleFactor ) + { + m_previousValue = m_scaleFactor; + m_fieldText = m_scaleFactor.ToString(); + } + + GUI.Label( fakeField, m_fieldText, UIUtils.MainSkin.textField ); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string portResult = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string result = "( " + portResult + " * " + m_scaleFactor + " )"; + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_scaleFactor ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_scaleFactor = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleNode.cs.meta new file mode 100644 index 0000000..49bd4b8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/ScaleNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ec926b11f9c698c458f746e4e55fd7df +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SignOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SignOpNode.cs new file mode 100644 index 0000000..90f83dc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SignOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Sign", "Math Operators", "Sign of scalar or each vector component" )] + public sealed class SignOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "sign"; + m_previewShaderGUID = "3aca80b49aadf5046b7133730818e18f"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT , + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR , + WirePortDataType.INT); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SignOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SignOpNode.cs.meta new file mode 100644 index 0000000..1a1d0ff --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SignOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 429f407c2b590df45b215f0edfa49b97 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SimplifiedFModOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SimplifiedFModOpNode.cs new file mode 100644 index 0000000..4726b84 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SimplifiedFModOpNode.cs @@ -0,0 +1,32 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Simplified Fmod", "Math Operators", "Floating point remainder of x/y" )] + public sealed class SimplifiedFModOpNode : DynamicTypeNode + { + private const string FmodCustomOp = "frac({0}/{1})*{1}"; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_previewShaderGUID = "2688236fb4f37ce47b81cc818c53321d"; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + { + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + RegisterLocalVariable( 0, string.Format( FmodCustomOp, m_inputA, m_inputB ), ref dataCollector, ( "fmodResult" + OutputId ) ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SimplifiedFModOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SimplifiedFModOpNode.cs.meta new file mode 100644 index 0000000..77efda8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SimplifiedFModOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f186e1b03a8ee2b4b9e45918576e8cf6 +timeCreated: 1484731588 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinOpNode.cs new file mode 100644 index 0000000..6d0d363 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Sin", "Trigonometry Operators", "Sine of scalars and vectors" )] + public sealed class SinOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "sin"; + m_previewShaderGUID = "bcd9f8749ddd3ac4f94f4c2071c1d0d4"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinOpNode.cs.meta new file mode 100644 index 0000000..24e23e6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: be2a11b08ee8cbb458dbcc4c1a61ad1b +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SingleInputOp.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SingleInputOp.cs new file mode 100644 index 0000000..4af0cba --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SingleInputOp.cs @@ -0,0 +1,67 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; + + +namespace AmplifyShaderEditor +{ + [Serializable] + public class SingleInputOp : ParentNode + { + + [SerializeField] + protected string m_opName; + //[SerializeField] + //protected int m_validTypes; + + protected bool m_autoUpdateOutputPort = true; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + //m_validTypes = 0; + m_useInternalPortData = true; + + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ 0 ].MatchPortToConnection(); + if ( m_autoUpdateOutputPort ) + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ 0 ].MatchPortToConnection(); + if ( m_autoUpdateOutputPort ) + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string result = "0"; + if ( m_inputPorts[ 0 ].IsConnected ) + { + ParentNode node = m_inputPorts[ 0 ].GetOutputNode(); + int localOutputId = m_inputPorts[ 0 ].ExternalReferences[ 0 ].PortId; + result = m_opName + "( " + node.GenerateShaderForOutput( localOutputId, ref dataCollector, ignoreLocalvar ) + " )"; + } + else + { + result = m_opName + "( " + m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) + " )"; + } + + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SingleInputOp.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SingleInputOp.cs.meta new file mode 100644 index 0000000..751db40 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SingleInputOp.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ed03e964ff9aa274cbf392769b61170b +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinhOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinhOpNode.cs new file mode 100644 index 0000000..f38a192 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinhOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Sinh", "Trigonometry Operators", "Hyperbolic sine of scalars and vectors" )] + public sealed class SinhOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "sinh"; + m_previewShaderGUID = "4e9c00e6dceb4024f80d4e3d7786abad"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinhOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinhOpNode.cs.meta new file mode 100644 index 0000000..292ae67 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SinhOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 52092e3985c556943895f86c585bcd25 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SmoothstepOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SmoothstepOpNode.cs new file mode 100644 index 0000000..09d86cb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SmoothstepOpNode.cs @@ -0,0 +1,122 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Smoothstep", "Math Operators", "Returns a smooth Hermite interpolation between 0 and 1, if input is in the range [min, max]." )] + public sealed class SmoothstepOpNode : ParentNode + { + //[UnityEngine.SerializeField] + //private WirePortDataType m_mainDataType = WirePortDataType.FLOAT; + + private int m_alphaPortId = 0; + private int m_minPortId = 0; + private int m_maxPortId = 0; + private const string SmoothstepOpFormat = "smoothstep( {0} , {1} , {2})";//min max alpha + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue, -1, MasterNodePortCategory.Fragment, 0 ); + m_alphaPortId = m_inputPorts.Count - 1; + AddInputPort( WirePortDataType.FLOAT, false, "Min", -1, MasterNodePortCategory.Fragment, 1 ); + m_minPortId = m_inputPorts.Count - 1; + AddInputPort( WirePortDataType.FLOAT, false, "Max", -1, MasterNodePortCategory.Fragment, 2 ); + m_maxPortId = m_inputPorts.Count - 1; + + GetInputPortByUniqueId( m_maxPortId ).FloatInternalData = 1; + + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_useInternalPortData = true; + m_textLabelWidth = 55; + m_previewShaderGUID = "954cdd40a7a528344a0a4d3ff1db5176"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + if( portId == 0 ) + { + m_inputPorts[ 0 ].MatchPortToConnection(); + m_inputPorts[ 1 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + m_inputPorts[ 2 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + if( outputPortId == 0 ) + { + m_inputPorts[ 0 ].MatchPortToConnection(); + m_inputPorts[ 1 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + m_inputPorts[ 2 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + } + + //public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + //{ + // base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + // UpdateConnection( portId ); + //} + + //public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + //{ + // base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + // UpdateConnection( inputPortId ); + //} + + //public override void OnInputPortDisconnected( int portId ) + //{ + // base.OnInputPortDisconnected( portId ); + // UpdateConnection( portId ); + //} + + //void UpdateConnection( int portId ) + //{ + // WirePortDataType type1 = WirePortDataType.FLOAT; + // if( m_inputPorts[ m_minPortId ].IsConnected ) + // type1 = m_inputPorts[ m_minPortId ].GetOutputConnection( 0 ).DataType; + + // WirePortDataType type2 = WirePortDataType.FLOAT; + // if( m_inputPorts[ m_maxPortId ].IsConnected ) + // type2 = m_inputPorts[ m_maxPortId ].GetOutputConnection( 0 ).DataType; + + // m_mainDataType = UIUtils.GetPriority( type1 ) > UIUtils.GetPriority( type2 ) ? type1 : type2; + + // if( !m_inputPorts[ m_minPortId ].IsConnected && !m_inputPorts[ m_maxPortId ].IsConnected && m_inputPorts[ m_alphaPortId ].IsConnected ) + // m_mainDataType = m_inputPorts[ m_alphaPortId ].GetOutputConnection( 0 ).DataType; + + // m_inputPorts[ m_minPortId ].ChangeType( m_mainDataType, false ); + + // m_inputPorts[ m_maxPortId ].ChangeType( m_mainDataType, false ); + // if( m_inputPorts[ m_alphaPortId ].IsConnected && m_inputPorts[ m_alphaPortId ].GetOutputConnection( 0 ).DataType == WirePortDataType.FLOAT ) + // m_inputPorts[ m_alphaPortId ].ChangeType( WirePortDataType.FLOAT, false ); + // else + // m_inputPorts[ m_alphaPortId ].ChangeType( m_mainDataType, false ); + + // m_outputPorts[ 0 ].ChangeType( m_mainDataType, false ); + //} + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string aValue = m_inputPorts[ m_minPortId ].GeneratePortInstructions( ref dataCollector ); + string bValue = m_inputPorts[ m_maxPortId ].GeneratePortInstructions( ref dataCollector ); + string interp = m_inputPorts[ m_alphaPortId ].GeneratePortInstructions( ref dataCollector ); + + string result = string.Format( SmoothstepOpFormat, aValue, bValue, interp ); + + RegisterLocalVariable( 0, result, ref dataCollector, "smoothstepResult" + OutputId ); + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SmoothstepOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SmoothstepOpNode.cs.meta new file mode 100644 index 0000000..98387eb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SmoothstepOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0f64eb769f843a349a0d249beacc6fc3 +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SqrtOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SqrtOpNode.cs new file mode 100644 index 0000000..e35c1b2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SqrtOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Sqrt", "Math Operators", "Square root of scalars and vectors" )] + public sealed class SqrtOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "sqrt"; + m_previewShaderGUID = "1791e2fbf36af084da7ecfc289e89b6e"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SqrtOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SqrtOpNode.cs.meta new file mode 100644 index 0000000..164b7c5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/SqrtOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4820b591b73a7fe4ab13261deebf76f7 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/StepOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/StepOpNode.cs new file mode 100644 index 0000000..ab1a1b8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/StepOpNode.cs @@ -0,0 +1,24 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Step", "Math Operators", "Step function returning either zero or one" )] + public sealed class StepOpNode : DynamicTypeNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_previewShaderGUID = "2c757add7f97ecd4abd9ce6ec4659697"; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + return "step( " + m_inputA + " , " + m_inputB + " )"; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/StepOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/StepOpNode.cs.meta new file mode 100644 index 0000000..5215554 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/StepOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c4305e64271097249a198b2e8aed3046 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TFHCRemapNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TFHCRemapNode.cs new file mode 100644 index 0000000..dc010aa --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TFHCRemapNode.cs @@ -0,0 +1,74 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Remap +// Donated by The Four Headed Cat - @fourheadedcat +using UnityEngine; +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Remap", "Math Operators", "Remap value from old min - max range to new min - max range", null, KeyCode.None, true, false, null, null, "The Four Headed Cat - @fourheadedcat" )] + public sealed class TFHCRemapNode : DynamicTypeNode + { + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].Name = Constants.EmptyPortValue; + m_inputPorts[ 1 ].Name = "Min Old"; + AddInputPort( WirePortDataType.FLOAT, false, "Max Old" ); + m_inputPorts[ 2 ].FloatInternalData = 1; + m_inputPorts[ 2 ].Vector2InternalData = Vector2.one; + m_inputPorts[ 2 ].Vector3InternalData = Vector3.one; + m_inputPorts[ 2 ].Vector4InternalData = Vector4.one; + m_inputPorts[ 2 ].ColorInternalData = Color.white; + + AddInputPort( WirePortDataType.FLOAT, false, "Min New" ); + AddInputPort( WirePortDataType.FLOAT, false, "Max New" ); + m_inputPorts[ 4 ].FloatInternalData = 1; + m_inputPorts[ 4 ].Vector2InternalData = Vector2.one; + m_inputPorts[ 4 ].Vector3InternalData = Vector3.one; + m_inputPorts[ 4 ].Vector4InternalData = Vector4.one; + m_inputPorts[ 4 ].ColorInternalData = Color.white; + + m_textLabelWidth = 100; + m_useInternalPortData = true; + m_previewShaderGUID = "72dd1cbea889fa047b929d5191e360c0"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnections(); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + UpdateConnections(); + } + + void UpdateConnections() + { + m_inputPorts[ 0 ].MatchPortToConnection(); + m_inputPorts[ 1 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + m_inputPorts[ 2 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + m_inputPorts[ 3 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + m_inputPorts[ 4 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + m_outputPorts[ 0 ].ChangeType( m_inputPorts[ 0 ].DataType, false ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string oldMin = m_inputPorts[ 1 ].GenerateShaderForOutput( ref dataCollector, m_inputPorts[ 0 ].DataType, ignoreLocalvar, true ); + string oldMax = m_inputPorts[ 2 ].GenerateShaderForOutput( ref dataCollector, m_inputPorts[ 0 ].DataType, ignoreLocalvar, true ); + string newMin = m_inputPorts[ 3 ].GenerateShaderForOutput( ref dataCollector, m_inputPorts[ 0 ].DataType, ignoreLocalvar, true ); + string newMax = m_inputPorts[ 4 ].GenerateShaderForOutput( ref dataCollector, m_inputPorts[ 0 ].DataType, ignoreLocalvar, true ); + string strout = "(" + newMin + " + (" + value + " - " + oldMin + ") * (" + newMax + " - " + newMin + ") / (" + oldMax + " - " + oldMin + "))"; + + return CreateOutputLocalVariable( 0, strout, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TFHCRemapNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TFHCRemapNode.cs.meta new file mode 100644 index 0000000..e255ee6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TFHCRemapNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 637508d44a97b5449a3d7223c461e58c +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanOpNode.cs new file mode 100644 index 0000000..409937e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Tan", "Trigonometry Operators", "Tangent of scalars and vectors" )] + public sealed class TanOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "tan"; + m_previewShaderGUID = "312e291832cac5749a3626547dfc8607"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanOpNode.cs.meta new file mode 100644 index 0000000..e78333f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 535b4367719ca2146bb7ddac217dad94 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanhOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanhOpNode.cs new file mode 100644 index 0000000..e9f88fa --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanhOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Tanh", "Trigonometry Operators", "Hyperbolic tangent of scalars and vectors" )] + public sealed class TanhOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "tanh"; + m_previewShaderGUID = "52f78d3a1c66d1c489cd63b0a9300b38"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanhOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanhOpNode.cs.meta new file mode 100644 index 0000000..e2a2ef7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TanhOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 792e48b83a6387a4d826d6445417372f +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransformVectorOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransformVectorOpNode.cs new file mode 100644 index 0000000..72d3612 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransformVectorOpNode.cs @@ -0,0 +1,160 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public enum CoordinateSpaces + { + Tangent, + Local, + World, + View, + Clip, + Screen + } + + [Serializable] + [NodeAttributes( "Transform Vector", "Math Operators", "Transforma a vector into another", null, KeyCode.None, false )] + public sealed class TransformVectorOpNode : ParentNode + { + [SerializeField] + private CoordinateSpaces m_source = CoordinateSpaces.Tangent; + [SerializeField] + private CoordinateSpaces m_destination = CoordinateSpaces.World; + + private const string InputTangentrStr = "float4 tangent: TANGENT"; + private const string ColorValueStr = ".tangent"; + + private const string InputNormalStr = "float3 normal : NORMAL"; + private const string NormalValueStr = ".normal"; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT4, false, Constants.EmptyPortValue ); + AddOutputPort( WirePortDataType.FLOAT4, Constants.EmptyPortValue ); + m_useInternalPortData = true; + } + + void AddTangentInfo( ref MasterNodeDataCollector dataCollector ) + { + dataCollector.AddToInput( UniqueId, InputTangentrStr, true ); + dataCollector.AddToInput( UniqueId, InputTangentrStr, true ); + dataCollector.AddToInput( UniqueId, InputNormalStr, true ); + dataCollector.AddToFragmentLocalVariables( UniqueId, "float3 binormal = cross( normalize( v.normal ), normalize( v.tangent.xyz ) ) * v.tangent.w;" ); + dataCollector.AddToFragmentLocalVariables( UniqueId, "float3x3 rotation = float3x3( v.tangent.xyz, binormal, v.normal );" ); + + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + + //if ( !InputPorts[ 0 ].IsConnected ) + //{ + // return UIUtils.NoConnection( this ); + //} + + string value = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + dataCollector.AddToIncludes( UniqueId, Constants.UnityShaderVariables ); + + + + switch ( m_source ) + { + case CoordinateSpaces.Tangent: + { + AddTangentInfo( ref dataCollector ); + switch ( m_destination ) + { + case CoordinateSpaces.Tangent: + { + return value; + } + //case eCoordinateSpaces.Local: + //{ + //} + //case eCoordinateSpaces.World: + //{ + //} + //case eCoordinateSpaces.View: + //{ + //} + } + } + break; + case CoordinateSpaces.Local: + { + switch ( m_destination ) + { + case CoordinateSpaces.Tangent: + { + AddTangentInfo( ref dataCollector ); + return "float4(mul( rotation , " + value + ".xyz ),1)"; + } + case CoordinateSpaces.Local: + { + return value; + } + case CoordinateSpaces.World: + { + return "mul( _Object2World , " + value + " )"; + } + case CoordinateSpaces.View: + { + return "mul( UNITY_MATRIX_MV , " + value + " )"; + } + } + } + break; + case CoordinateSpaces.World: + { + switch ( m_destination ) + { + //case eCoordinateSpaces.Tangent: + //{ + //} + case CoordinateSpaces.Local: + { + return "mul( _World2Object , " + value + " )"; + } + case CoordinateSpaces.World: + { + return value; + } + case CoordinateSpaces.View: + { + return "mul( UNITY_MATRIX_V , " + value + " )"; + } + } + } + break; + case CoordinateSpaces.View: + { + UIUtils.ShowMessage( UniqueId, "View as Source is not supported", MessageSeverity.Warning ); + return value; + } + } + + return UIUtils.UnknownError( this ); + } + + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_source = ( CoordinateSpaces ) Enum.Parse( typeof( CoordinateSpaces ), GetCurrentParam( ref nodeParams ) ); + m_destination = ( CoordinateSpaces ) Enum.Parse( typeof( CoordinateSpaces ), GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_source ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_destination ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransformVectorOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransformVectorOpNode.cs.meta new file mode 100644 index 0000000..3169b4e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransformVectorOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 928c21155a9c1a74b953da2d24269035 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransposeOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransposeOpNode.cs new file mode 100644 index 0000000..6e83e51 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransposeOpNode.cs @@ -0,0 +1,23 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Transpose", "Matrix Operators", "Transpose matrix of a matrix" )] + public sealed class TransposeOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "transpose"; + m_drawPreview = false; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4 ); + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4x4, false ); + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4x4, false ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransposeOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransposeOpNode.cs.meta new file mode 100644 index 0000000..1df556e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TransposeOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ba1613dad4af0da4b9f4619b90916cbf +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TruncOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TruncOpNode.cs new file mode 100644 index 0000000..f190b0c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TruncOpNode.cs @@ -0,0 +1,26 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Trunc", "Math Operators", "Largest integer not greater than a scalar or each vector component" )] + public sealed class TruncOpNode : SingleInputOp + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_opName = "trunc"; + m_previewShaderGUID = "c717aaa68f4ac9e469b15763e82933e1"; + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.INT ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TruncOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TruncOpNode.cs.meta new file mode 100644 index 0000000..9b87310 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/TruncOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5f78e9a796a94d54482caa15d4971feb +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/VariablePortTypeOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/VariablePortTypeOpNode.cs new file mode 100644 index 0000000..f561089 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/VariablePortTypeOpNode.cs @@ -0,0 +1,76 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + public class VariablePortTypeOpNode : ParentNode + { + private const string InputTypeStr = "Input type"; + + [SerializeField] + protected WirePortDataType m_selectedType = WirePortDataType.FLOAT; + + [SerializeField] + protected WirePortDataType m_lastSelectedType = WirePortDataType.FLOAT; + + [SerializeField] + protected int _inputAmount = 1; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddPorts(); + } + + void AddPorts() + { + for ( int i = 0; i < _inputAmount; i++ ) + { + AddInputPort( m_selectedType, true, i.ToString() ); + } + AddOutputPort( m_selectedType, Constants.EmptyPortValue ); + m_sizeIsDirty = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUILayout.BeginVertical(); + { + EditorGUILayout.LabelField( InputTypeStr ); + m_selectedType = ( WirePortDataType ) EditorGUILayoutEnumPopup( m_selectedType ); + } + EditorGUILayout.EndVertical(); + if ( m_selectedType != m_lastSelectedType ) + { + m_lastSelectedType = m_selectedType; + + DeleteAllInputConnections( true ); + DeleteAllOutputConnections( true ); + + AddPorts(); + + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedType ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedType = ( WirePortDataType ) Enum.Parse( typeof( WirePortDataType ), GetCurrentParam( ref nodeParams ) ); + m_lastSelectedType = m_selectedType; + DeleteAllInputConnections( true ); + DeleteAllOutputConnections( true ); + AddPorts(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/VariablePortTypeOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/VariablePortTypeOpNode.cs.meta new file mode 100644 index 0000000..f0328b0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Operators/VariablePortTypeOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 97be7adea7b8ae44c9bebb753277e0c2 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs new file mode 100644 index 0000000..4974759 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs @@ -0,0 +1,3801 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public enum PreviewLocation + { + Auto, + TopCenter, + BottomCenter, + Left, + Right + } + + public enum NodeMessageType + { + Error, + Warning, + Info + } + + [Serializable] + public class ParentNode : UndoParentNode, ISerializationCallbackReceiver + { + + protected readonly string[] PrecisionLabels = { "Float", "Half" }; + protected readonly string[] PrecisionLabelsExtra = { "Float", "Half", "Inherit" }; + + private const double NodeClickTime = 0.2; + protected GUIContent PrecisionContent = new GUIContent( "Precision", "Changes the precision of internal calculations, using lower types saves some performance\nDefault: Float" ); + private const int MoveCountBuffer = 3;// When testing for stopped movement we need to take Layout and Repaint into account for them not to interfere with tests + private const float MinInsideBoxWidth = 20; + private const float MinInsideBoxHeight = 10; + + private const string WikiLinkStr = "online reference"; + + public delegate void OnNodeEvent( ParentNode node, bool testOnlySelected, InteractionMode interactionMode ); + public delegate void OnNodeGenericEvent( ParentNode node ); + public delegate void OnNodeReOrder( ParentNode node, int index ); + public delegate void DrawPropertySection(); + public delegate void OnSRPAction( int outputId, ref MasterNodeDataCollector dataCollector ); + + [SerializeField] + protected PrecisionType m_currentPrecisionType = PrecisionType.Inherit; + + [SerializeField] + protected bool m_customPrecision = false; + + [SerializeField] + protected InteractionMode m_defaultInteractionMode = InteractionMode.Other; + + public event OnNodeEvent OnNodeStoppedMovingEvent; + public OnNodeGenericEvent OnNodeChangeSizeEvent; + public OnNodeGenericEvent OnNodeDestroyedEvent; + public event OnNodeReOrder OnNodeReOrderEvent; + public OnSRPAction OnLightweightAction; + public OnSRPAction OnHDAction; + + [SerializeField] + private int m_uniqueId; + + [SerializeField] + protected Rect m_position; + + [SerializeField] + protected Rect m_unpreviewedPosition; + + [SerializeField] + protected GUIContent m_content; + + [SerializeField] + protected GUIContent m_additionalContent; + + [SerializeField] + protected bool m_initialized; + + [SerializeField] + protected NodeConnectionStatus m_connStatus; + protected bool m_selfPowered = false; + + [SerializeField] + protected int m_activeConnections; + + [SerializeField] + protected System.Type m_activeType; + + [SerializeField] + protected int m_activePort; + + [SerializeField] + protected int m_activeNode; + + protected NodeRestrictions m_restrictions; + + [SerializeField] + protected Color m_statusColor; + + [SerializeField] + protected Rect m_propertyDrawPos; + + // Ports + [SerializeField] + protected List m_inputPorts = new List(); + + protected Dictionary m_inputPortsDict = new Dictionary(); + + [SerializeField] + protected List m_outputPorts = new List(); + + protected Dictionary m_outputPortsDict = new Dictionary(); + + [SerializeField] + protected Rect m_globalPosition; + + [SerializeField] + protected Rect m_headerPosition; + + //private Vector2 m_tooltipOffset; + + [SerializeField] + protected bool m_sizeIsDirty = false; + + [SerializeField] + protected Vector2 m_extraSize; + + [SerializeField] + protected Vector2 m_insideSize; + + [SerializeField] + protected float m_fontHeight; + + // Editor State save on Play Button + [SerializeField] + protected bool m_isDirty; + + [SerializeField] + private int m_isMoving = 0; + [SerializeField] + private Rect m_lastPosition; + + // Live Shader Gen + [SerializeField] + private bool m_saveIsDirty; + + [SerializeField] + protected bool m_requireMaterialUpdate = false; + + [SerializeField] + protected int m_commentaryParent = -1; + + [SerializeField] + protected int m_depth = -1; + + [SerializeField] + protected bool m_materialMode = false; + + [SerializeField] + protected bool m_showPreview = false; + + [SerializeField] + protected int m_previewMaterialPassId = -1; + + protected bool m_useSquareNodeTitle = false; + + [SerializeField] + protected bool m_continuousPreviewRefresh = false; + private bool m_previewIsDirty = true; + + // Error Box Messages + private Rect m_errorBox; + private bool m_previousErrorMessage = false; + protected bool m_showErrorMessage = false; + protected NodeMessageType m_errorMessageTypeIsError = NodeMessageType.Error; + protected string m_errorMessageTooltip = string.Empty; + + private GUIContent m_errorIcon = new GUIContent(); + private GUIContent m_errorMessage = new GUIContent(); + private GUIStyle m_errorCurrentStyle; + + private const string ErrorTitle = "ERROR"; + private const string WarningTitle = "WARNING"; + private const string InfoTitle = "INFO"; + + // Drawing Node + protected PreviewLocation m_selectedLocation = PreviewLocation.Auto; + private int m_extraHeaderHeight = 0; + protected bool m_isVisible; + protected bool m_selected = false; + protected bool m_rmbIgnore; + protected GUIContent m_sizeContentAux; + + protected uint m_currentReadParamIdx = 1; + protected bool m_reorderLocked = false; + + protected Rect m_cachedPos; + protected Vector2 m_accumDelta = Vector2.zero; + + private bool m_isOnGrid = false; + protected bool m_useInternalPortData = false; + protected bool m_autoDrawInternalPortData = true; + protected DrawOrder m_drawOrder = DrawOrder.Default; + + protected bool m_movingInFrame = false; + protected float m_anchorAdjust = -1; + + protected Color m_headerColor; + + [SerializeField] // needs to be serialized because of Undo + protected Color m_headerColorModifier = Color.white; + + protected bool m_infiniteLoopDetected = false; + protected int m_textLabelWidth = -1; + + private bool m_linkVisibility = false; + [SerializeField] + protected bool m_hasTooltipLink = true; + + protected int m_category = 0; + + protected double m_lastTimeSelected; + private double m_tooltipTimestamp; + protected string m_tooltipText; + + protected Rect m_unscaledRemainingBox; + protected Rect m_remainingBox; + + private int m_visibleInputs = 0; + private int m_visibleOutputs = 0; + + private double m_doubleClickTimestamp; + private const double DoubleClickTime = 0.25; + + protected bool m_canExpand = true; + + protected bool m_firstDraw = true; + + protected int m_matrixId = -1; + + private float m_paddingTitleLeft = 0; + private float m_paddingTitleRight = 0; + + // Preview Fields + private Material m_previewMaterial = null; + private Shader m_previewShader = null; + protected string m_previewShaderGUID = string.Empty; + protected float m_marginPreviewLeft = 0; + protected bool m_globalShowPreview = false; + protected Rect m_unscaledPreviewRect; + protected Rect m_previewRect; + protected bool m_drawPreviewMaskButtons = true; + private int m_channelNumber = 0; + protected bool m_firstPreviewDraw = true; + [SerializeField] + protected bool m_drawPreview = true; + protected bool m_drawPreviewExpander = true; + private bool m_spherePreview = false; + protected bool m_drawPreviewAsSphere = false; + protected bool m_forceDrawPreviewAsPlane = false; + private bool m_finishPreviewRender = false; + + private int m_cachedMainTexId = -1; + private int m_cachedMaskTexId = -1; + private int m_cachedPortsId = -1; + private int m_cachedPortId = -1; + + private int m_cachedDrawSphereId = -1; + private int m_cachedInvertedZoomId = -1; + //private int m_cachedIsLinearId = -1; + + private bool[] m_previewChannels = { true, true, true, false }; + + // Others + protected bool m_hasSubtitle = false; + protected bool m_showSubtitle = true; + protected bool m_hasLeftDropdown = false; + protected bool m_autoWrapProperties = false; + protected bool m_internalDataFoldout = true; + protected bool m_propertiesFoldout = true; + protected bool m_repopulateDictionaries = true; + + protected Vector2 m_lastInputBottomRight = Vector2.zero; + protected Vector2 m_lastOutputBottomLeft = Vector2.zero; + + private Vector4 m_portMask = Vector4.zero; + + private Vector2 m_auxVector2 = Vector4.zero; + protected Rect m_auxRect; + + protected PreviewLocation m_autoLocation; + protected Rect m_titlePos; + protected Rect m_addTitlePos; + protected Rect m_expandRect; + protected Rect m_dropdownRect; + protected Rect m_currInputPortPos; + protected Rect m_currOutputPortPos; + protected Color m_colorBuffer; + + [SerializeField] + protected bool m_docking = false; + + [SerializeField] + protected int m_visiblePorts = 0; + + protected int m_graphDepth = 0; + + protected int m_oldInputCount = -1; + + protected bool m_dropdownEditing = false; + + protected bool m_isNodeBeingCopied = false; + + protected string m_previousTitle = string.Empty; + + protected string m_previousAdditonalTitle = string.Empty; + + private bool m_alive = true; + + private bool m_wasDeprecated = false; + + private double m_timedUpdateInitialValue; + private double m_timedUpdateInterval; + private bool m_fireTimedUpdateRequest = false; + + public ParentNode() + { + m_position = new Rect( 0, 0, 0, 0 ); + m_content = new GUIContent( GUIContent.none ); + m_additionalContent = new GUIContent( GUIContent.none ); + CommonInit( -1 ); + } + + public ParentNode( int uniqueId, float x, float y, float width, float height ) + { + m_position = new Rect( x, y, width, height ); + m_content = new GUIContent( GUIContent.none ); + m_additionalContent = new GUIContent( GUIContent.none ); + CommonInit( uniqueId ); + } + + public virtual void OnEnable() + { + hideFlags = HideFlags.HideAndDontSave; + if( m_nodeAttribs != null ) + { + if( UIUtils.HasColorCategory( m_nodeAttribs.Category ) ) + { + m_headerColor = UIUtils.GetColorFromCategory( m_nodeAttribs.Category ); + } + else + { + if( !string.IsNullOrEmpty( m_nodeAttribs.CustomCategoryColor ) ) + { + m_headerColor = UIUtils.AddColorCategory( m_nodeAttribs.Category, m_nodeAttribs.CustomCategoryColor ); + } + } + } + + m_tooltipTimestamp = Time.realtimeSinceStartup; + hideFlags = HideFlags.DontSave; + } + + protected virtual void CommonInit( int uniqueId ) + { + m_uniqueId = uniqueId; + + m_isOnGrid = false; + ConnStatus = NodeConnectionStatus.Not_Connected; + m_inputPorts = new List(); + m_inputPortsDict = new Dictionary(); + + m_outputPorts = new List(); + m_outputPortsDict = new Dictionary(); + + System.Reflection.MemberInfo info = this.GetType(); + m_nodeAttribs = info.GetCustomAttributes( true )[ 0 ] as NodeAttributes; + if( m_nodeAttribs != null ) + { + m_content.text = m_nodeAttribs.Name; + //m_content.tooltip = m_nodeAttribs.Description; + m_tooltipText = m_nodeAttribs.Description; + m_selected = false; + } + + m_sizeContentAux = new GUIContent(); + m_extraSize = new Vector2( 0, 0 ); + m_insideSize = new Vector2( 0, 0 ); + m_sizeIsDirty = true; + m_initialized = true; + m_restrictions = new NodeRestrictions(); + + m_propertyDrawPos = new Rect(); + } + + public virtual void AfterCommonInit() + { + if( PreviewShader && !HasPreviewShader ) + { + m_drawPreview = false; + m_drawPreviewExpander = false; + m_canExpand = false; + } + + if( m_drawPreviewExpander || m_hasLeftDropdown ) + { + m_paddingTitleRight += Constants.PreviewExpanderWidth + Constants.IconsLeftRightMargin; + m_paddingTitleLeft = Constants.PreviewExpanderWidth + Constants.IconsLeftRightMargin; + } + } + + public virtual void Destroy() + { + m_alive = false; + if( OnNodeDestroyedEvent != null ) + { + OnNodeDestroyedEvent( this ); + OnNodeDestroyedEvent = null; + } + + OnLightweightAction = null; + OnHDAction = null; + + OnNodeStoppedMovingEvent = null; + OnNodeChangeSizeEvent = null; + OnNodeReOrderEvent = null; + if( m_restrictions != null ) + m_restrictions.Destroy(); + m_restrictions = null; + + if( m_inputPorts != null ) + { + int inputCount = m_inputPorts.Count; + for( int i = 0; i < inputCount; i++ ) + { + m_inputPorts[ i ].Destroy(); + } + m_inputPorts.Clear(); + m_inputPorts = null; + } + + if( m_outputPorts != null ) + { + int outputCount = m_outputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + m_outputPorts[ i ].Destroy(); + } + m_outputPorts.Clear(); + m_outputPorts = null; + } + + if( m_inputPortsDict != null ) + m_inputPortsDict.Clear(); + + m_inputPortsDict = null; + + if( m_outputPortsDict != null ) + m_outputPortsDict.Clear(); + + m_outputPortsDict = null; + + if( m_previewMaterial != null ) + DestroyImmediate( m_previewMaterial ); + m_previewMaterial = null; + + m_previewShader = null; + //m_containerGraph = null; + } + + public virtual void Move( Vector2 delta ) + { + if( m_docking ) + return; + + Move( delta, false ); + } + + public virtual void Move( Vector2 delta, bool snap ) + { + if( m_docking ) + return; + + if( m_isMoving == 0 ) + { + m_cachedPos = m_position; + m_accumDelta = Vector2.zero; + } + + m_isMoving = MoveCountBuffer; + m_accumDelta += delta; + + if( snap ) + { + m_position.x = Mathf.Round( ( m_cachedPos.x + m_accumDelta.x ) / 16 ) * 16; + m_position.y = Mathf.Round( ( m_cachedPos.y + m_accumDelta.y ) / 16 ) * 16; + } + else + { + m_position.x += delta.x; + m_position.y += delta.y; + } + //if(Event.current.type == EventType.Layout) + m_movingInFrame = true; + } + + public virtual void UpdateMaterial( Material mat ) + { + m_requireMaterialUpdate = false; + } + + public virtual void SetMaterialMode( Material mat, bool fetchMaterialValues ) + { + m_materialMode = ( mat != null ); + } + + public virtual bool UpdateShaderDefaults( ref Shader shader, ref TextureDefaultsDataColector defaultCol ) { return false; } + public virtual void ForceUpdateFromMaterial( Material material ) { } + public void SetSaveIsDirty() + { + if( m_connStatus == NodeConnectionStatus.Connected ) + { + SaveIsDirty = true; + } + } + + public void ActivateNodeReordering( int index ) + { + if( OnNodeReOrderEvent != null ) + OnNodeReOrderEvent( this, index ); + } + + void RecalculateInputPortIdx() + { + m_inputPortsDict.Clear(); + int count = m_inputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + int nodeId = m_inputPorts[ i ].ExternalReferences[ 0 ].NodeId; + int portId = m_inputPorts[ i ].ExternalReferences[ 0 ].PortId; + ParentNode node = UIUtils.GetNode( nodeId ); + if( node != null ) + { + OutputPort outputPort = node.GetOutputPortByUniqueId( portId ); + int outputCount = outputPort.ExternalReferences.Count; + for( int j = 0; j < outputCount; j++ ) + { + if( outputPort.ExternalReferences[ j ].NodeId == m_uniqueId && + outputPort.ExternalReferences[ j ].PortId == m_inputPorts[ i ].PortId ) + { + outputPort.ExternalReferences[ j ].PortId = i; + } + } + } + } + m_inputPorts[ i ].PortId = i; + m_inputPortsDict.Add( i, m_inputPorts[ i ] ); + } + } + + public void SwapInputPorts( int fromIdx, int toIdx ) + { + InputPort port = m_inputPorts[ fromIdx ]; + //if( toIdx > fromIdx ) + // toIdx--; + m_inputPorts.Remove( port ); + m_inputPorts.Insert( toIdx, port ); + RecalculateInputPortIdx(); + SetSaveIsDirty(); + } + + public void RemoveInputPort( int idx ) + { + if( idx < m_inputPorts.Count ) + { + m_inputPortsDict.Remove( m_inputPorts[ idx ].PortId ); + m_inputPorts.RemoveAt( idx ); + SetSaveIsDirty(); + m_sizeIsDirty = true; + } + } + + public void RemoveOutputPort( string name ) + { + int count = m_outputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_outputPorts[ i ].Name.Equals( name ) ) + { + if( m_outputPorts[ i ].IsConnected ) + { + m_containerGraph.DeleteConnection( false, m_uniqueId, m_outputPorts[ i ].PortId, false, true ); + m_outputPortsDict.Remove( m_outputPorts[ i ].PortId ); + m_outputPorts.RemoveAt( i ); + SetSaveIsDirty(); + m_sizeIsDirty = true; + } + } + } + } + + public void RemoveOutputPort( int idx, bool isArrayIndex = true ) + { + if( isArrayIndex ) + { + // idx represents a position on the output port array + if( idx < m_outputPorts.Count ) + { + if( m_outputPorts[ idx ].IsConnected ) + { + m_containerGraph.DeleteConnection( false, m_uniqueId, m_outputPorts[ idx ].PortId, false, true ); + } + + m_outputPortsDict.Remove( m_outputPorts[ idx ].PortId ); + m_outputPorts.RemoveAt( idx ); + SetSaveIsDirty(); + m_sizeIsDirty = true; + } + } + else + { + // idx represents a port unique id + int count = m_outputPorts.Count; + int arrIdx = -1; + for( int i = 0; i < count; i++ ) + { + if( m_outputPorts[ i ].PortId == idx ) + { + arrIdx = i; + break; + } + } + + if( arrIdx >= 0 ) + { + if( m_outputPorts[ arrIdx ].IsConnected ) + { + m_containerGraph.DeleteConnection( false, m_uniqueId, idx, false, true ); + } + + m_outputPortsDict.Remove( idx ); + m_outputPorts.RemoveAt( arrIdx ); + SetSaveIsDirty(); + m_sizeIsDirty = true; + } + } + } + + // Manually add Ports + public InputPort AddInputPort( WirePortDataType type, bool typeLocked, string name, int orderId = -1, MasterNodePortCategory category = MasterNodePortCategory.Fragment, int uniquePortId = -1 ) + { + InputPort port = new InputPort( m_uniqueId, ( uniquePortId < 0 ? m_inputPorts.Count : uniquePortId ), type, name, typeLocked, ( orderId >= 0 ? orderId : m_inputPorts.Count ), category ); + m_inputPorts.Add( port ); + m_inputPortsDict.Add( port.PortId, port ); + SetSaveIsDirty(); + m_sizeIsDirty = true; + return port; + } + + public InputPort AddInputPort( WirePortDataType type, bool typeLocked, string name, string dataName, int orderId = -1, MasterNodePortCategory category = MasterNodePortCategory.Fragment, int uniquePortId = -1 ) + { + InputPort port = new InputPort( m_uniqueId, ( uniquePortId < 0 ? m_inputPorts.Count : uniquePortId ), type, name, dataName, typeLocked, ( orderId >= 0 ? orderId : m_inputPorts.Count ), category ); + m_inputPorts.Add( port ); + m_inputPortsDict.Add( port.PortId, port ); + SetSaveIsDirty(); + m_sizeIsDirty = true; + return port; + } + + public InputPort AddInputPortAt( int idx, WirePortDataType type, bool typeLocked, string name, int orderId = -1, MasterNodePortCategory category = MasterNodePortCategory.Fragment, int uniquePortId = -1 ) + { + InputPort port = new InputPort( m_uniqueId, ( uniquePortId < 0 ? m_inputPorts.Count : uniquePortId ), type, name, typeLocked, ( orderId >= 0 ? orderId : m_inputPorts.Count ), category ); + m_inputPorts.Insert( idx, port ); + m_inputPortsDict.Add( port.PortId, port ); + SetSaveIsDirty(); + m_sizeIsDirty = true; + RecalculateInputPortIdx(); + return port; + } + + public void AddOutputPort( WirePortDataType type, string name, int uniquePortId = -1 ) + { + m_outputPorts.Add( new OutputPort( this, m_uniqueId, ( uniquePortId < 0 ? m_outputPorts.Count : uniquePortId ), type, name ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + SetSaveIsDirty(); + m_sizeIsDirty = true; + } + + public void AddOutputPortAt( int idx, WirePortDataType type, string name, int uniquePortId = -1 ) + { + OutputPort port = new OutputPort( this, m_uniqueId, ( uniquePortId < 0 ? m_outputPorts.Count : uniquePortId ), type, name ); + m_outputPorts.Insert( idx, port ); + m_outputPortsDict.Add( port.PortId, port ); + SetSaveIsDirty(); + m_sizeIsDirty = true; + } + + public void AddOutputVectorPorts( WirePortDataType type, string name ) + { + m_sizeIsDirty = true; + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, type, name ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + + switch( type ) + { + case WirePortDataType.FLOAT2: + { + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "X" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "Y" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + } + break; + case WirePortDataType.FLOAT3: + { + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "X" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "Y" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "Z" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + } + break; + case WirePortDataType.FLOAT4: + { + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "X" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "Y" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "Z" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "W" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + } + break; + } + SetSaveIsDirty(); + } + + public void SetPreviewDirtyFromOutputs() + { + PreviewIsDirty = true; + } + + public string GetOutputVectorItem( int vectorPortId, int currentPortId, string result ) + { + if( m_outputPorts[ 0 ].DataType == WirePortDataType.COLOR ) + { + switch( currentPortId - vectorPortId ) + { + case 1: result += ".r"; break; + case 2: result += ".g"; break; + case 3: result += ".b"; break; + case 4: result += ".a"; break; + } + } + else + { + switch( currentPortId - vectorPortId ) + { + case 1: result += ".x"; break; + case 2: result += ".y"; break; + case 3: result += ".z"; break; + case 4: result += ".w"; break; + } + } + return result; + } + + public void AddOutputColorPorts( string name, bool addAlpha = true ) + { + m_sizeIsDirty = true; + //Main port + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, addAlpha ? WirePortDataType.COLOR : WirePortDataType.FLOAT3, name ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + + //Color components port + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "R" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + m_outputPorts[ m_outputPorts.Count - 1 ].CustomColor = Color.red; + + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "G" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + m_outputPorts[ m_outputPorts.Count - 1 ].CustomColor = Color.green; + + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "B" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + m_outputPorts[ m_outputPorts.Count - 1 ].CustomColor = Color.blue; + + if( addAlpha ) + { + m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "A" ) ); + m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] ); + m_outputPorts[ m_outputPorts.Count - 1 ].CustomColor = Color.white; + } + } + + public void ConvertFromVectorToColorPorts() + { + m_outputPorts[ 0 ].ChangeType( WirePortDataType.COLOR, false ); + + m_outputPorts[ 1 ].Name = "R"; + m_outputPorts[ 1 ].CustomColor = Color.red; + + m_outputPorts[ 2 ].Name = "G"; + m_outputPorts[ 2 ].CustomColor = Color.green; + + m_outputPorts[ 3 ].Name = "B"; + m_outputPorts[ 3 ].CustomColor = Color.blue; + + m_outputPorts[ 4 ].Name = "A"; + m_outputPorts[ 4 ].CustomColor = Color.white; + } + + + public string GetOutputColorItem( int vectorPortId, int currentPortId, string result ) + { + switch( currentPortId - vectorPortId ) + { + case 1: result += ".r"; break; + case 2: result += ".g"; break; + case 3: result += ".b"; break; + case 4: result += ".a"; break; + } + return result; + } + + public void ChangeOutputType( WirePortDataType type, bool invalidateConnections ) + { + int outputCount = m_outputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + m_outputPorts[ i ].ChangeType( type, invalidateConnections ); + } + } + + public void ChangeInputType( WirePortDataType type, bool invalidateConnections ) + { + int inputCount = m_inputPorts.Count; + for( int i = 0; i < inputCount; i++ ) + { + m_inputPorts[ i ].ChangeType( type, invalidateConnections ); + } + } + + public void ChangeOutputProperties( int outputID, string newName, WirePortDataType newType, bool invalidateConnections = true ) + { + if( outputID < m_outputPorts.Count ) + { + m_outputPorts[ outputID ].ChangeProperties( newName, newType, invalidateConnections ); + IsDirty = true; + m_sizeIsDirty = true; + SetSaveIsDirty(); + } + } + + public void ChangeOutputName( int outputArrayIdx, string newName ) + { + if( outputArrayIdx < m_outputPorts.Count ) + { + m_outputPorts[ outputArrayIdx ].Name = newName; + IsDirty = true; + m_sizeIsDirty = true; + } + } + + public InputPort CheckInputPortAt( Vector3 pos ) + { + int count = m_inputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_inputPorts[ i ].InsideActiveArea( pos ) ) + return m_inputPorts[ i ]; + } + return null; + } + + public InputPort GetFirstInputPortOfType( WirePortDataType dataType, bool countObjectTypeAsValid ) + { + int count = m_inputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( ( m_inputPorts[ i ].CheckValidType( dataType ) ) || ( countObjectTypeAsValid && m_inputPorts[ i ].DataType == WirePortDataType.OBJECT ) ) + return m_inputPorts[ i ]; + } + return null; + } + + public OutputPort CheckOutputPortAt( Vector3 pos ) + { + int count = m_outputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_outputPorts[ i ].InsideActiveArea( pos ) ) + return m_outputPorts[ i ]; + } + return null; + } + + public OutputPort GetFirstOutputPortOfType( WirePortDataType dataType, bool checkForCasts ) + { + int count = m_outputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( ( m_outputPorts[ i ].CheckValidType( dataType ) ) || ( checkForCasts && UIUtils.CanCast( dataType, m_outputPorts[ i ].DataType ) ) ) + return m_outputPorts[ i ]; + } + return null; + } + + virtual protected void ChangeSizeFinished() { m_firstPreviewDraw = true; /*MarkForPreviewUpdate();*/ } + protected void ChangeSize() + { + m_cachedPos = m_position; + //UIUtils.ResetMainSkin(); + + Vector2 inSize = Vector2.zero; + int inputCount = 0; + int inputSize = m_inputPorts.Count; + for( int i = 0; i < inputSize; i++ ) + { + if( m_inputPorts[ i ].Visible ) + { + if( m_inputPorts[ i ].DirtyLabelSize || m_inputPorts[ i ].LabelSize == Vector2.zero ) + { + m_inputPorts[ i ].DirtyLabelSize = false; + m_sizeContentAux.text = m_inputPorts[ i ].Name; + m_inputPorts[ i ].UnscaledLabelSize = UIUtils.UnZoomedInputPortStyle.CalcSize( m_sizeContentAux ); + } + + inSize.x = Mathf.Max( inSize.x, m_inputPorts[ i ].UnscaledLabelSize.x ); + inSize.y = Mathf.Max( inSize.y, m_inputPorts[ i ].UnscaledLabelSize.y ); + inputCount += 1; + } + } + if( inSize.x > 0 ) + inSize.x += UIUtils.PortsSize.x + Constants.PORT_TO_LABEL_SPACE_X * 2; + inSize.x += m_marginPreviewLeft; + inSize.y = Mathf.Max( inSize.y, UIUtils.PortsSize.y ); + + + Vector2 outSize = Vector2.zero; + int outputCount = 0; + int outputSize = m_outputPorts.Count; + for( int i = 0; i < outputSize; i++ ) + { + if( m_outputPorts[ i ].Visible ) + { + if( m_outputPorts[ i ].DirtyLabelSize || m_outputPorts[ i ].LabelSize == Vector2.zero ) + { + m_outputPorts[ i ].DirtyLabelSize = false; + m_sizeContentAux.text = m_outputPorts[ i ].Name; + m_outputPorts[ i ].UnscaledLabelSize = UIUtils.UnZoomedOutputPortPortStyle.CalcSize( m_sizeContentAux ); + } + + outSize.x = Mathf.Max( outSize.x, m_outputPorts[ i ].UnscaledLabelSize.x ); + outSize.y = Mathf.Max( outSize.y, m_outputPorts[ i ].UnscaledLabelSize.y ); + outputCount += 1; + } + } + if( outSize.x > 0 ) + outSize.x += UIUtils.PortsSize.x + Constants.PORT_TO_LABEL_SPACE_X * 2; + outSize.y = Mathf.Max( outSize.y, UIUtils.PortsSize.y ); + + if( m_additionalContent.text.Length > 0 ) + { + m_extraHeaderHeight = (int)Constants.NODE_HEADER_EXTRA_HEIGHT; + m_hasSubtitle = true && m_showSubtitle; + } + else + { + m_extraHeaderHeight = 0; + m_hasSubtitle = false; + } + + float headerWidth = Mathf.Max( UIUtils.UnZoomedNodeTitleStyle.CalcSize( m_content ).x + m_paddingTitleLeft + m_paddingTitleRight, UIUtils.UnZoomedPropertyValuesTitleStyle.CalcSize( m_additionalContent ).x + m_paddingTitleLeft + m_paddingTitleRight ); + m_position.width = Mathf.Max( headerWidth, Mathf.Max( MinInsideBoxWidth, m_insideSize.x ) + inSize.x + outSize.x ) + Constants.NODE_HEADER_LEFTRIGHT_MARGIN * 2; + //m_position.width += m_extraSize.x; + + m_fontHeight = Mathf.Max( inSize.y, outSize.y ); + + m_position.height = Mathf.Max( inputCount, outputCount ) * ( m_fontHeight + Constants.INPUT_PORT_DELTA_Y );// + Constants.INPUT_PORT_DELTA_Y; + m_position.height = Mathf.Max( m_position.height, Mathf.Max( MinInsideBoxHeight, m_insideSize.y ) ); + m_position.height += UIUtils.HeaderMaxHeight + m_extraHeaderHeight + Constants.INPUT_PORT_DELTA_Y;// + m_extraSize.y; + if( m_showErrorMessage ) + m_position.height += 24; + + m_unpreviewedPosition = m_position; + //UIUtils.CurrentWindow.CameraDrawInfo.InvertedZoom = cachedZoom; + if( OnNodeChangeSizeEvent != null ) + { + OnNodeChangeSizeEvent( this ); + } + ChangeSizeFinished(); + } + + public virtual void Reset() { } + public virtual void OnOutputPortConnected( int portId, int otherNodeId, int otherPortId ) { } + + public virtual void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + InputPort port = GetInputPortByUniqueId( portId ); + if( activateNode && m_connStatus == NodeConnectionStatus.Connected ) + { + port.GetOutputNode().ActivateNode( m_activeNode, m_activePort, m_activeType ); + } + + PreviewIsDirty = true; + OnNodeChange(); + SetSaveIsDirty(); + } + + public virtual void OnInputPortDisconnected( int portId ) { PreviewIsDirty = true; OnNodeChange(); } + public virtual void OnOutputPortDisconnected( int portId ) { } + + public virtual void OnNodeChange() + { + CheckSpherePreview(); + int count = m_outputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_outputPorts[ i ].IsConnected ) + { + for( int f = 0; f < m_outputPorts[ i ].ExternalReferences.Count; f++ ) + { + ContainerGraph.GetNode( m_outputPorts[ i ].ExternalReferences[ f ].NodeId ).OnNodeChange(); + } + } + } + } + + public virtual void ActivateNode( int signalGenNodeId, int signalGenPortId, System.Type signalGenNodeType ) + { + if( m_selfPowered ) + return; + + ConnStatus = m_restrictions.GetRestiction( signalGenNodeType, signalGenPortId ) ? NodeConnectionStatus.Error : NodeConnectionStatus.Connected; + m_activeConnections += 1; + + if( m_activeConnections == 1 ) + { + m_activeType = signalGenNodeType; + m_activeNode = signalGenNodeId; + m_activePort = signalGenPortId; + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + m_inputPorts[ i ].GetOutputNode().ActivateNode( signalGenNodeId, signalGenPortId, signalGenNodeType ); + } + } + } + // saveisdirty might be needed, gonna leave this here for now + // SetSaveIsDirty(); + } + + public virtual void DeactivateInputPortNode( int deactivatedPort, bool forceComplete ) + { + GetInputPortByUniqueId( deactivatedPort ).GetOutputNode().DeactivateNode( deactivatedPort, false ); + } + + public virtual void DeactivateNode( int deactivatedPort, bool forceComplete ) + { + if( m_selfPowered ) + return; + + // saveisdirty might be needed, gonna leave this here for now + // SetSaveIsDirty(); + m_activeConnections -= 1; + if( forceComplete || m_activeConnections <= 0 ) + { + m_activeConnections = 0; + ConnStatus = NodeConnectionStatus.Not_Connected; + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + ParentNode node = m_inputPorts[ i ].GetOutputNode(); + if( node != null ) + node.DeactivateNode( deactivatedPort == -1 ? m_inputPorts[ i ].PortId : deactivatedPort, false ); + } + } + } + } + + public Rect GlobalToLocalPosition( DrawInfo drawInfo ) + { + float width = m_globalPosition.width / drawInfo.InvertedZoom; + float height = m_globalPosition.height / drawInfo.InvertedZoom; + + float x = m_globalPosition.x / drawInfo.InvertedZoom - drawInfo.CameraOffset.x; + float y = m_globalPosition.y / drawInfo.InvertedZoom - drawInfo.CameraOffset.y; + return new Rect( x, y, width, height ); + } + + protected void CalculatePositionAndVisibility( DrawInfo drawInfo ) + { + //m_movingInFrame = false; + m_globalPosition = m_position; + m_globalPosition.x = drawInfo.InvertedZoom * ( m_globalPosition.x + drawInfo.CameraOffset.x ); + m_globalPosition.y = drawInfo.InvertedZoom * ( m_globalPosition.y + drawInfo.CameraOffset.y ); + m_globalPosition.width *= drawInfo.InvertedZoom; + m_globalPosition.height *= drawInfo.InvertedZoom; + + m_isVisible = ( m_globalPosition.x + m_globalPosition.width > 0 ) && + ( m_globalPosition.x < drawInfo.CameraArea.width ) && + ( m_globalPosition.y + m_globalPosition.height > 0 ) && + ( m_globalPosition.y < drawInfo.CameraArea.height ); + + if( m_isMoving > 0 && drawInfo.CurrentEventType != EventType.MouseDrag ) + { + float deltaX = Mathf.Abs( m_lastPosition.x - m_position.x ); + float deltaY = Mathf.Abs( m_lastPosition.y - m_position.y ); + if( deltaX < 0.01f && deltaY < 0.01f ) + { + m_isMoving -= 1; + if( m_isMoving == 0 ) + { + OnSelfStoppedMovingEvent(); + } + } + else + { + m_isMoving = MoveCountBuffer; + } + m_lastPosition = m_position; + } + } + + public void FireStoppedMovingEvent( bool testOnlySelected, InteractionMode interactionMode ) + { + if( OnNodeStoppedMovingEvent != null ) + OnNodeStoppedMovingEvent( this, testOnlySelected, interactionMode ); + } + + public virtual void OnSelfStoppedMovingEvent() + { + FireStoppedMovingEvent( true, m_defaultInteractionMode ); + } + + protected void DrawPrecisionProperty( bool withInherit = true ) + { + if( withInherit ) + m_currentPrecisionType = (PrecisionType)EditorGUILayoutPopup( PrecisionContent.text, (int)m_currentPrecisionType, PrecisionLabelsExtra ); + else + m_currentPrecisionType = (PrecisionType)EditorGUILayoutPopup( PrecisionContent.text, (int)m_currentPrecisionType, PrecisionLabels ); + } + + public virtual void DrawTitle( Rect titlePos ) + { + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + GUI.Label( titlePos, m_content, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + } + } + + public virtual void DrawPreview( DrawInfo drawInfo, Rect rect ) + { + //if ( !m_drawPreview ) + // return; + + if( m_cachedDrawSphereId == -1 ) + m_cachedDrawSphereId = Shader.PropertyToID( "_DrawSphere" ); + + if( m_cachedInvertedZoomId == -1 ) + m_cachedInvertedZoomId = Shader.PropertyToID( "_InvertedZoom" ); + + m_channelNumber = 0; + Vector4 mask = Vector4.one; + if( m_outputPorts.Count > 0 ) + { + switch( m_outputPorts[ 0 ].DataType ) + { + case WirePortDataType.FLOAT: + m_channelNumber = 1; + mask.Set( 1, 1, 1, 0 ); + break; + case WirePortDataType.FLOAT2: + m_channelNumber = 2; + mask.Set( m_previewChannels[ 0 ] ? 1 : 0, m_previewChannels[ 1 ] ? 1 : 0, 1, 0 ); + break; + case WirePortDataType.COLOR: + case WirePortDataType.FLOAT4: + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + m_channelNumber = 4; + mask.Set( m_previewChannels[ 0 ] ? 1 : 0, m_previewChannels[ 1 ] ? 1 : 0, m_previewChannels[ 2 ] ? 1 : 0, m_previewChannels[ 3 ] ? 1 : 0 ); + break; + default: + m_channelNumber = 3; + mask.Set( m_previewChannels[ 0 ] ? 1 : 0, m_previewChannels[ 1 ] ? 1 : 0, m_previewChannels[ 2 ] ? 1 : 0, 0 ); + break; + } + } + + UIUtils.LinearMaterial.SetFloat( m_cachedDrawSphereId, ( SpherePreview ? 1 : 0 ) ); + UIUtils.LinearMaterial.SetFloat( m_cachedInvertedZoomId, drawInfo.InvertedZoom ); + UIUtils.LinearMaterial.SetVector( "_Mask", mask ); + + bool cached = GL.sRGBWrite; + GL.sRGBWrite = true; + //EditorGUI.DrawPreviewTexture( rect, PreviewTexture, UIUtils.LinearMaterial ); + int pass = 0; + if( SpherePreview ) + { + if( mask.w == 1 ) + pass = 3; + else + pass = 1; + } + else if( mask.w == 1 ) + pass = 2; + + Graphics.DrawTexture( rect, PreviewTexture, UIUtils.LinearMaterial, pass ); + GL.sRGBWrite = cached; + //Preview buttons + if( m_drawPreviewMaskButtons ) + DrawPreviewMaskButtonsRepaint( drawInfo, rect ); + } + + protected void DrawPreviewMaskButtonsLayout( DrawInfo drawInfo, Rect rect ) + { + if( rect.Contains( drawInfo.MousePosition ) && m_channelNumber > 1 && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + { + Rect buttonRect = rect; + buttonRect.height = 14 * drawInfo.InvertedZoom; + buttonRect.y = rect.yMax - buttonRect.height; + buttonRect.width = 14 * drawInfo.InvertedZoom; + + if( m_channelNumber == 2 ) + { + m_previewChannels[ 0 ] = GUI.Toggle( buttonRect, m_previewChannels[ 0 ], string.Empty, GUIStyle.none ); + buttonRect.x += 14 * drawInfo.InvertedZoom; + m_previewChannels[ 1 ] = GUI.Toggle( buttonRect, m_previewChannels[ 1 ], string.Empty, GUIStyle.none ); + } + else if( m_channelNumber == 3 ) + { + m_previewChannels[ 0 ] = GUI.Toggle( buttonRect, m_previewChannels[ 0 ], string.Empty, GUIStyle.none ); + buttonRect.x += 14 * drawInfo.InvertedZoom; + m_previewChannels[ 1 ] = GUI.Toggle( buttonRect, m_previewChannels[ 1 ], string.Empty, GUIStyle.none ); + buttonRect.x += 14 * drawInfo.InvertedZoom; + m_previewChannels[ 2 ] = GUI.Toggle( buttonRect, m_previewChannels[ 2 ], string.Empty, GUIStyle.none ); + } + else if( m_channelNumber == 4 ) + { + m_previewChannels[ 0 ] = GUI.Toggle( buttonRect, m_previewChannels[ 0 ], string.Empty, GUIStyle.none ); + buttonRect.x += 14 * drawInfo.InvertedZoom; + m_previewChannels[ 1 ] = GUI.Toggle( buttonRect, m_previewChannels[ 1 ], string.Empty, GUIStyle.none ); + buttonRect.x += 14 * drawInfo.InvertedZoom; + m_previewChannels[ 2 ] = GUI.Toggle( buttonRect, m_previewChannels[ 2 ], string.Empty, GUIStyle.none ); + buttonRect.x += 14 * drawInfo.InvertedZoom; + m_previewChannels[ 3 ] = GUI.Toggle( buttonRect, m_previewChannels[ 3 ], string.Empty, GUIStyle.none ); + } + } + } + + protected void DrawPreviewMaskButtonsRepaint( DrawInfo drawInfo, Rect rect ) + { + if( drawInfo.CurrentEventType == EventType.Repaint && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 && rect.Contains( drawInfo.MousePosition ) && m_channelNumber > 1 ) + { + Rect buttonRect = rect; + buttonRect.height = 14 * drawInfo.InvertedZoom; + buttonRect.y = rect.yMax - buttonRect.height; + buttonRect.width = 14 * drawInfo.InvertedZoom; + + if( m_channelNumber == 2 ) + { + UIUtils.MiniButtonTopMid.Draw( buttonRect, "R", false, false, m_previewChannels[ 0 ], false ); + buttonRect.x += 14 * drawInfo.InvertedZoom; + UIUtils.MiniButtonTopRight.Draw( buttonRect, "G", false, false, m_previewChannels[ 1 ], false ); + } + else if( m_channelNumber == 3 ) + { + UIUtils.MiniButtonTopMid.Draw( buttonRect, "R", false, false, m_previewChannels[ 0 ], false ); + buttonRect.x += 14 * drawInfo.InvertedZoom; + UIUtils.MiniButtonTopMid.Draw( buttonRect, "G", false, false, m_previewChannels[ 1 ], false ); + buttonRect.x += 14 * drawInfo.InvertedZoom; + UIUtils.MiniButtonTopRight.Draw( buttonRect, "B", false, false, m_previewChannels[ 2 ], false ); + } + else if( m_channelNumber == 4 ) + { + UIUtils.MiniButtonTopMid.Draw( buttonRect, "R", false, false, m_previewChannels[ 0 ], false ); + buttonRect.x += 14 * drawInfo.InvertedZoom; + UIUtils.MiniButtonTopMid.Draw( buttonRect, "G", false, false, m_previewChannels[ 1 ], false ); + buttonRect.x += 14 * drawInfo.InvertedZoom; + UIUtils.MiniButtonTopMid.Draw( buttonRect, "B", false, false, m_previewChannels[ 2 ], false ); + buttonRect.x += 14 * drawInfo.InvertedZoom; + UIUtils.MiniButtonTopRight.Draw( buttonRect, "A", false, false, m_previewChannels[ 3 ], false ); + } + } + } + + public void SetTimedUpdate( double timerInterval ) + { + m_timedUpdateInitialValue = EditorApplication.timeSinceStartup; + m_timedUpdateInterval = timerInterval; + m_fireTimedUpdateRequest = true; + } + + public virtual void FireTimedUpdate() { } + /// + /// + /// + /// + public virtual void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + if( m_fireTimedUpdateRequest && ( EditorApplication.timeSinceStartup - m_timedUpdateInitialValue ) > m_timedUpdateInterval ) + { + m_fireTimedUpdateRequest = false; + FireTimedUpdate(); + } + + if( m_repopulateDictionaries ) + { + m_repopulateDictionaries = false; + + m_inputPortsDict.Clear(); + int inputCount = m_inputPorts.Count; + for( int i = 0; i < inputCount; i++ ) + { + m_inputPortsDict.Add( m_inputPorts[ i ].PortId, m_inputPorts[ i ] ); + } + + m_outputPortsDict.Clear(); + int outputCount = m_outputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + m_outputPortsDict.Add( m_outputPorts[ i ].PortId, m_outputPorts[ i ] ); + } + } + } + + /// + /// This method should only be called to calculate layouts of elements to be draw later, only runs once per frame and before wires are drawn + /// + /// + public virtual void OnNodeLayout( DrawInfo drawInfo ) + { + + if( ContainerGraph.ChangedLightingModel ) + { + m_sizeIsDirty = true; + m_firstPreviewDraw = true; + } + + if( m_firstDraw ) + { + m_firstDraw = false; + AfterCommonInit(); + OnNodeChange(); + } + + if( m_previousErrorMessage != m_showErrorMessage ) + { + m_sizeIsDirty = true; + } + + if( m_sizeIsDirty ) + { + m_sizeIsDirty = false; + ChangeSize(); + } + + CalculatePositionAndVisibility( drawInfo ); + + m_unscaledRemainingBox = m_position; + m_remainingBox = m_globalPosition; + + m_lastInputBottomRight = m_position.position; + m_lastOutputBottomLeft = m_position.position; + m_lastOutputBottomLeft.x += m_position.width; + + m_visibleInputs = 0; + m_visibleOutputs = 0; + + if( m_hasSubtitle ) + m_extraHeaderHeight = (int)Constants.NODE_HEADER_EXTRA_HEIGHT; + else + m_extraHeaderHeight = 0; + + m_lastInputBottomRight.y += UIUtils.HeaderMaxHeight + m_extraHeaderHeight; + m_lastOutputBottomLeft.y += UIUtils.HeaderMaxHeight + m_extraHeaderHeight; + m_unscaledRemainingBox.y += UIUtils.HeaderMaxHeight + m_extraHeaderHeight; + + if( m_isVisible ) + { + // Header + m_headerPosition = m_globalPosition; + m_headerPosition.height = UIUtils.CurrentHeaderHeight + m_extraHeaderHeight * drawInfo.InvertedZoom; + + // Title + m_titlePos = m_globalPosition; + m_titlePos.height = m_headerPosition.height; + if( m_hasSubtitle ) + m_titlePos.yMin += ( 4 * drawInfo.InvertedZoom ); + else + m_titlePos.yMin += ( 7 * drawInfo.InvertedZoom ); + m_titlePos.width -= ( m_paddingTitleLeft + m_paddingTitleRight ) * drawInfo.InvertedZoom; + m_titlePos.x += m_paddingTitleLeft * drawInfo.InvertedZoom; + + // Additional Title + if( m_hasSubtitle ) + { + m_addTitlePos = m_titlePos; + m_addTitlePos.y = m_globalPosition.y; + m_addTitlePos.yMin += ( 19 * drawInfo.InvertedZoom ); + } + + // Left Dropdown + if( m_hasLeftDropdown && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + { + m_dropdownRect = m_headerPosition; + m_dropdownRect.width = Constants.NodeButtonSizeX * drawInfo.InvertedZoom; + m_dropdownRect.x = m_globalPosition.x + ( Constants.IconsLeftRightMargin + 1 ) * drawInfo.InvertedZoom; + m_dropdownRect.height = Constants.NodeButtonSizeY * drawInfo.InvertedZoom; + m_dropdownRect.y = m_globalPosition.y + m_headerPosition.height * 0.5f - 14 * drawInfo.InvertedZoom * 0.5f; + } + + // Expander + if( m_drawPreviewExpander && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + { + m_expandRect = m_globalPosition; + m_expandRect.width = Constants.PreviewExpanderWidth * drawInfo.InvertedZoom; + m_expandRect.x = m_globalPosition.x + m_globalPosition.width - ( Constants.IconsLeftRightMargin + Constants.PreviewExpanderWidth ) * drawInfo.InvertedZoom; //titlePos.x + titlePos.width; + m_expandRect.height = Constants.PreviewExpanderHeight * drawInfo.InvertedZoom; + m_expandRect.y = m_globalPosition.y + m_headerPosition.height * 0.5f - Constants.PreviewExpanderHeight * drawInfo.InvertedZoom * 0.5f; + } + } + + if( m_anchorAdjust < 0 ) + { + m_anchorAdjust = UIUtils.GetCustomStyle( CustomStyle.PortEmptyIcon ).normal.background.width; + } + + m_unscaledRemainingBox.y += Constants.INPUT_PORT_DELTA_Y; + m_lastOutputBottomLeft.y += Constants.INPUT_PORT_DELTA_Y; + m_lastInputBottomRight.y += Constants.INPUT_PORT_DELTA_Y; + + // Input Ports + { + m_currInputPortPos = m_globalPosition; + m_currInputPortPos.width = drawInfo.InvertedZoom * UIUtils.PortsSize.x; + m_currInputPortPos.height = drawInfo.InvertedZoom * UIUtils.PortsSize.y; + + m_currInputPortPos.x += drawInfo.InvertedZoom * Constants.PORT_INITIAL_X; + m_currInputPortPos.y += drawInfo.InvertedZoom * Constants.PORT_INITIAL_Y + m_extraHeaderHeight * drawInfo.InvertedZoom; + int inputCount = m_inputPorts.Count; + + float initialX = m_lastInputBottomRight.x; + + for( int i = 0; i < inputCount; i++ ) + { + if( m_inputPorts[ i ].Visible ) + { + m_visibleInputs++; + // Button + m_inputPorts[ i ].Position = m_currInputPortPos; + + // Label + m_inputPorts[ i ].LabelPosition = m_currInputPortPos; + float deltaX = 1f * drawInfo.InvertedZoom * ( UIUtils.PortsSize.x + Constants.PORT_TO_LABEL_SPACE_X ); + m_auxRect = m_inputPorts[ i ].LabelPosition; + m_auxRect.x += deltaX; + m_inputPorts[ i ].LabelPosition = m_auxRect; + + //if( m_inputPorts[ i ].DirtyLabelSize || m_inputPorts[ i ].LabelSize == Vector2.zero ) + //{ + // m_inputPorts[ i ].DirtyLabelSize = false; + // m_sizeContentAux.text = m_inputPorts[ i ].Name; + // m_inputPorts[ i ].UnscaledLabelSize = UIUtils.UnZoomedInputPortStyle.CalcSize( m_sizeContentAux ); + //} + + m_inputPorts[ i ].LabelSize = m_inputPorts[ i ].UnscaledLabelSize * drawInfo.InvertedZoom; + + m_lastInputBottomRight.x = Mathf.Max( m_lastInputBottomRight.x, initialX + m_inputPorts[ i ].UnscaledLabelSize.x + Constants.PORT_INITIAL_X + Constants.PORT_TO_LABEL_SPACE_X + UIUtils.PortsSize.x ); + + if( !m_inputPorts[ i ].Locked ) + { + float overflow = 2; + float scaledOverflow = 4 * drawInfo.InvertedZoom; + m_auxRect = m_currInputPortPos; + m_auxRect.yMin -= scaledOverflow + overflow; + m_auxRect.yMax += scaledOverflow + overflow; + m_auxRect.xMin -= Constants.PORT_INITIAL_X * drawInfo.InvertedZoom + scaledOverflow + overflow; + if( m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid ) + m_auxRect.xMax += m_inputPorts[ i ].LabelSize.x + Constants.PORT_TO_LABEL_SPACE_X * drawInfo.InvertedZoom + scaledOverflow + overflow; + else + m_auxRect.xMax += Constants.PORT_TO_LABEL_SPACE_X * drawInfo.InvertedZoom + scaledOverflow + overflow; + m_inputPorts[ i ].ActivePortArea = m_auxRect; + } + m_currInputPortPos.y += drawInfo.InvertedZoom * ( m_fontHeight + Constants.INPUT_PORT_DELTA_Y ); + //GUI.Label( m_inputPorts[ i ].ActivePortArea, string.Empty, UIUtils.Box ); + } + } + if( m_visibleInputs > 0 ) + m_lastInputBottomRight.y += m_fontHeight * m_visibleInputs + Constants.INPUT_PORT_DELTA_Y * ( m_visibleInputs - 1 ); + } + + // Output Ports + { + m_currOutputPortPos = m_globalPosition; + m_currOutputPortPos.width = drawInfo.InvertedZoom * UIUtils.PortsSize.x; + m_currOutputPortPos.height = drawInfo.InvertedZoom * UIUtils.PortsSize.y; + + m_currOutputPortPos.x += ( m_globalPosition.width - drawInfo.InvertedZoom * ( Constants.PORT_INITIAL_X + m_anchorAdjust ) ); + m_currOutputPortPos.y += drawInfo.InvertedZoom * Constants.PORT_INITIAL_Y + m_extraHeaderHeight * drawInfo.InvertedZoom; + int outputCount = m_outputPorts.Count; + + float initialX = m_lastOutputBottomLeft.x; + + for( int i = 0; i < outputCount; i++ ) + { + if( m_outputPorts[ i ].Visible ) + { + m_visibleOutputs++; + //Button + m_outputPorts[ i ].Position = m_currOutputPortPos; + + // Label + m_outputPorts[ i ].LabelPosition = m_currOutputPortPos; + float deltaX = 1f * drawInfo.InvertedZoom * ( UIUtils.PortsSize.x + Constants.PORT_TO_LABEL_SPACE_X ); + m_auxRect = m_outputPorts[ i ].LabelPosition; + m_auxRect.x -= deltaX; + m_outputPorts[ i ].LabelPosition = m_auxRect; + + m_outputPorts[ i ].LabelSize = m_outputPorts[ i ].UnscaledLabelSize * drawInfo.InvertedZoom; + + m_lastOutputBottomLeft.x = Mathf.Min( m_lastOutputBottomLeft.x, initialX - m_outputPorts[ i ].UnscaledLabelSize.x - Constants.PORT_INITIAL_X - Constants.PORT_TO_LABEL_SPACE_X - UIUtils.PortsSize.x ); + + if( !m_outputPorts[ i ].Locked ) + { + float overflow = 2; + float scaledOverflow = 4 * drawInfo.InvertedZoom; + m_auxRect = m_currOutputPortPos; + m_auxRect.yMin -= scaledOverflow + overflow; + m_auxRect.yMax += scaledOverflow + overflow; + if( m_containerGraph.ParentWindow.WireReferenceUtils.InputPortReference.IsValid ) + m_auxRect.xMin -= m_outputPorts[ i ].LabelSize.x + Constants.PORT_TO_LABEL_SPACE_X * drawInfo.InvertedZoom + scaledOverflow + overflow; + else + m_auxRect.xMin -= Constants.PORT_TO_LABEL_SPACE_X * drawInfo.InvertedZoom + scaledOverflow + overflow; + m_auxRect.xMax += Constants.PORT_INITIAL_X * drawInfo.InvertedZoom + scaledOverflow + overflow; + m_outputPorts[ i ].ActivePortArea = m_auxRect; + } + m_currOutputPortPos.y += drawInfo.InvertedZoom * ( m_fontHeight + Constants.INPUT_PORT_DELTA_Y ); + //GUI.Label( m_outputPorts[ i ].ActivePortArea, string.Empty, UIUtils.Box ); + } + } + if( m_visibleOutputs > 0 ) + m_lastOutputBottomLeft.y += m_fontHeight * m_visibleOutputs + Constants.INPUT_PORT_DELTA_Y * ( m_visibleOutputs - 1 ); + } + + m_lastInputBottomRight.x += m_marginPreviewLeft; + + //Vector2 scaledLastOutputBottomLeft = ( m_lastOutputBottomLeft + drawInfo.CameraOffset ) * drawInfo.InvertedZoom; + //GUI.Label( new Rect( scaledLastOutputBottomLeft, Vector2.one * 2 ), string.Empty, UIUtils.CurrentWindow.CustomStylesInstance.Box ); + + m_unscaledRemainingBox.xMin = m_lastInputBottomRight.x; + //m_unscaledRemainingBox.yMin = m_lastInputBottomRight.y; + m_unscaledRemainingBox.xMax = m_lastOutputBottomLeft.x; + m_unscaledRemainingBox.yMax = Mathf.Max( m_lastOutputBottomLeft.y, m_lastInputBottomRight.y ); + + m_remainingBox.position = ( m_unscaledRemainingBox.position + drawInfo.CameraOffset ) * drawInfo.InvertedZoom; + m_remainingBox.size = m_unscaledRemainingBox.size * drawInfo.InvertedZoom; + + //GUI.Label( m_remainingBox, string.Empty, UIUtils.Box ); + + if( m_visibleInputs == 0 ) + { + m_remainingBox.x += Constants.PORT_INITIAL_X * drawInfo.InvertedZoom; + m_remainingBox.width -= Constants.PORT_INITIAL_X * drawInfo.InvertedZoom; + } + + if( m_visibleOutputs == 0 ) + { + m_remainingBox.width -= Constants.PORT_INITIAL_X * drawInfo.InvertedZoom; + } + + if( ContainerGraph.ParentWindow.GlobalPreview != m_globalShowPreview ) + { + m_globalShowPreview = ContainerGraph.ParentWindow.GlobalPreview; + m_sizeIsDirty = true; + ContainerGraph.ParentWindow.RequestRepaint(); + } + + // Generate Proper Preview Rect + float marginAround = 10; + float scaledMarginAround = marginAround * drawInfo.InvertedZoom; + float previewSize = 128; + PreviewLocation m_autoLocation = m_selectedLocation; + if( m_selectedLocation == PreviewLocation.Auto ) + { + if( m_visibleOutputs > m_visibleInputs ) + { + m_autoLocation = PreviewLocation.Left; + } + else if( m_visibleOutputs < m_visibleInputs ) + { + m_autoLocation = PreviewLocation.Right; + } + else if( m_unscaledRemainingBox.width > previewSize ) + { + m_autoLocation = PreviewLocation.TopCenter; + } + else + { + m_autoLocation = PreviewLocation.BottomCenter; + } + } + + if( m_canExpand && ( m_showPreview || m_globalShowPreview ) ) + { + if( m_autoLocation == PreviewLocation.TopCenter ) + { + m_unscaledPreviewRect.y = m_unscaledRemainingBox.y; + m_unscaledPreviewRect.x = m_unscaledRemainingBox.center.x - 0.5f * ( previewSize + 2 * marginAround ); + } + else if( m_autoLocation == PreviewLocation.BottomCenter ) + { + m_unscaledPreviewRect.y = Mathf.Max( m_lastOutputBottomLeft.y, m_lastInputBottomRight.y ); + m_unscaledPreviewRect.x = m_position.x + 0.5f * m_position.width - 0.5f * ( previewSize + 2 * marginAround ); + } + else if( m_autoLocation == PreviewLocation.Left ) + { + m_unscaledPreviewRect.y = m_lastInputBottomRight.y; + m_unscaledPreviewRect.x = m_position.x; + } + else if( m_autoLocation == PreviewLocation.Right ) + { + m_unscaledPreviewRect.y = m_lastOutputBottomLeft.y; + m_unscaledPreviewRect.x = m_lastInputBottomRight.x; + } + if( m_autoLocation == PreviewLocation.BottomCenter ) + m_unscaledPreviewRect.height = previewSize + 2 * marginAround; + else if( m_autoLocation == PreviewLocation.TopCenter ) + m_unscaledPreviewRect.height = previewSize + marginAround; + else + m_unscaledPreviewRect.height = previewSize + ( m_visibleInputs > 0 && m_visibleOutputs > 0 ? 2 * marginAround : marginAround ); + m_unscaledPreviewRect.width = previewSize + 2 * marginAround; + + m_previewRect = m_unscaledPreviewRect; + m_previewRect.position = ( m_previewRect.position + drawInfo.CameraOffset ) * drawInfo.InvertedZoom; + m_auxVector2.Set( previewSize * drawInfo.InvertedZoom, previewSize * drawInfo.InvertedZoom ); + m_previewRect.size = m_auxVector2; + + if( m_autoLocation == PreviewLocation.BottomCenter ) + { + m_auxVector2.Set( m_previewRect.position.x + scaledMarginAround, m_previewRect.position.y + scaledMarginAround ); + m_previewRect.position = m_auxVector2; + } + else if( m_autoLocation == PreviewLocation.TopCenter ) + { + m_auxVector2.Set( m_previewRect.position.x + scaledMarginAround, m_previewRect.position.y ); + m_previewRect.position = m_auxVector2; + } + else + { + m_previewRect.position += new Vector2( scaledMarginAround, ( m_visibleInputs > 0 && m_visibleOutputs > 0 ? scaledMarginAround : 0 ) ); + } + } + + // Adjust node rect after preview + if( m_firstPreviewDraw ) + { + m_firstPreviewDraw = false; + ContainerGraph.ParentWindow.RequestRepaint(); + if( m_canExpand && ( m_showPreview || m_globalShowPreview ) ) + { + if( m_autoLocation == PreviewLocation.TopCenter ) + { + float fillWidth = m_unscaledRemainingBox.width - m_unscaledPreviewRect.width; + m_extraSize.x = Mathf.Max( -fillWidth, 0 ); + float fillHeight = m_position.yMax - m_unscaledPreviewRect.yMax; + m_extraSize.y = Mathf.Max( -fillHeight, 0 ); + } + if( m_autoLocation == PreviewLocation.BottomCenter ) + { + float fillWidth = m_position.width - m_unscaledPreviewRect.width; + m_extraSize.x = Mathf.Max( -fillWidth, 0 ); + float fillHeight = m_position.yMax - m_unscaledPreviewRect.yMax; + m_extraSize.y = Mathf.Max( -fillHeight, 0 ); + } + else if( m_autoLocation == PreviewLocation.Left ) + { + float fillWidth = m_lastOutputBottomLeft.x - m_unscaledPreviewRect.xMax; + m_extraSize.x = Mathf.Max( -fillWidth, 0 ); + float fillHeight = m_position.yMax - m_unscaledPreviewRect.yMax; + m_extraSize.y = Mathf.Max( -fillHeight, 0 ); + } + else if( m_autoLocation == PreviewLocation.Right ) + { + float fillWidth = m_position.xMax - m_unscaledPreviewRect.xMax; + m_extraSize.x = Mathf.Max( -fillWidth, 0 ); + float fillHeight = m_position.yMax - m_unscaledPreviewRect.yMax; + m_extraSize.y = Mathf.Max( -fillHeight, 0 ); + } + + if( m_showErrorMessage ) + m_extraSize.y += 24; + } + else if( m_canExpand ) + { + m_extraSize.y = 0; + m_extraSize.x = 0; + } + + m_position.width = m_unpreviewedPosition.width + m_extraSize.x; + m_position.height = m_unpreviewedPosition.height + m_extraSize.y; + } + + + if( m_showErrorMessage ) + { + m_errorBox = m_globalPosition; + m_errorBox.y = ( m_globalPosition.yMax - 28 * drawInfo.InvertedZoom ) + 3 * drawInfo.InvertedZoom; + m_errorBox.height = 25 * drawInfo.InvertedZoom; + } + + m_previousErrorMessage = m_showErrorMessage; + } + + /// + /// This method should only be called to draw elements, runs once per frame and after wires are drawn + /// + /// + public virtual void OnNodeRepaint( DrawInfo drawInfo ) + { + if( !m_isVisible ) + return; + + m_colorBuffer = GUI.color; + // Background + GUI.color = m_infiniteLoopDetected ? Constants.InfiniteLoopColor : Constants.NodeBodyColor; + if( m_useSquareNodeTitle || ContainerGraph.LodLevel >= ParentGraph.NodeLOD.LOD2 ) + GUI.Label( m_globalPosition, string.Empty, UIUtils.NodeWindowOffSquare ); + else + GUI.Label( m_globalPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeWindowOff ) ); + + // Header + //GUI + GUI.color = m_headerColor * m_headerColorModifier; + if( m_useSquareNodeTitle || ContainerGraph.LodLevel >= ParentGraph.NodeLOD.LOD2 ) + GUI.Label( m_headerPosition, string.Empty, UIUtils.NodeHeaderSquare ); + else + GUI.Label( m_headerPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeHeader ) ); + GUI.color = m_colorBuffer; + + // Title + DrawTitle( m_titlePos ); + + // Additional Tile + if( m_hasSubtitle && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + GUI.Label( m_addTitlePos, m_additionalContent, UIUtils.GetCustomStyle( CustomStyle.PropertyValuesTitle ) ); + + // Dropdown + if( m_hasLeftDropdown && !m_dropdownEditing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + GUI.Label( m_dropdownRect, string.Empty, UIUtils.PropertyPopUp ); + + // Expander + if( m_drawPreviewExpander && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + GUI.Label( m_expandRect, string.Empty, ( m_showPreview ? UIUtils.PreviewCollapser : UIUtils.PreviewExpander ) ); + + // Input Ports + int inputCount = m_inputPorts.Count; + + for( int i = 0; i < inputCount; i++ ) + { + if( m_inputPorts[ i ].Visible ) + { + // Input Port Icon + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + { + if( m_inputPorts[ i ].Locked ) + GUI.color = Constants.LockedPortColor; + else if( ContainerGraph.ParentWindow.Options.ColoredPorts ) + GUI.color = UIUtils.GetColorForDataType( m_inputPorts[ i ].DataType, false, true ); + else + GUI.color = m_inputPorts[ i ].HasCustomColor ? m_inputPorts[ i ].CustomColor : UIUtils.GetColorForDataType( m_inputPorts[ i ].DataType, true, true ); + + GUIStyle style = m_inputPorts[ i ].IsConnected ? UIUtils.GetCustomStyle( CustomStyle.PortFullIcon ) : UIUtils.GetCustomStyle( CustomStyle.PortEmptyIcon ); + GUI.Label( m_inputPorts[ i ].Position, string.Empty, style ); + + GUI.color = m_colorBuffer; + } + + // Input Port Label + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + if( m_inputPorts[ i ].Locked ) + { + GUI.color = Constants.PortLockedTextColor; + GUI.Label( m_inputPorts[ i ].LabelPosition, m_inputPorts[ i ].Name, UIUtils.InputPortLabel ); + GUI.color = m_colorBuffer; + } + else + { + if( m_containerGraph.ParentWindow.GlobalShowInternalData && !m_inputPorts[ i ].IsConnected && UIUtils.InternalDataOnPort.fontSize > 1f && ( m_inputPorts[ i ].AutoDrawInternalData || ( m_autoDrawInternalPortData && m_useInternalPortData ) ) && m_inputPorts[ i ].DisplayInternalData.Length > 4 && ( ( m_inputPorts[ i ].DataType >= WirePortDataType.FLOAT && m_inputPorts[ i ].DataType <= WirePortDataType.INT ) || m_inputPorts[ i ].DataType == WirePortDataType.UINT ) ) + { + GUI.color = Constants.NodeBodyColor/* * new Color( 1f, 1f, 1f, 0.75f )*/; + Rect internalBox = m_inputPorts[ i ].LabelPosition; + m_sizeContentAux.text = m_inputPorts[ i ].DisplayInternalData; + Vector2 portText = UIUtils.InternalDataOnPort.CalcSize( m_sizeContentAux ); + internalBox.width = portText.x; + internalBox.height = portText.y; + internalBox.y = m_inputPorts[ i ].LabelPosition.center.y - internalBox.height * 0.5f; + internalBox.x = GlobalPosition.x - internalBox.width - 4 * drawInfo.InvertedZoom - 1; + Rect backBox = new Rect( internalBox ); + backBox.xMin -= 4 * drawInfo.InvertedZoom; + backBox.xMax += 4 * drawInfo.InvertedZoom; + backBox.yMin -= 2 * drawInfo.InvertedZoom; + backBox.yMax += 2 * drawInfo.InvertedZoom; + GUI.Label( backBox, string.Empty, UIUtils.InternalDataBackground ); + GUI.color *= new Color( 1f, 1f, 1f, 0.5f ); + GUI.Label( internalBox, m_sizeContentAux, UIUtils.InternalDataOnPort ); + GUI.color = m_colorBuffer; + } + GUI.Label( m_inputPorts[ i ].LabelPosition, m_inputPorts[ i ].Name, UIUtils.InputPortLabel ); + } + } + } + } + + // Output Ports + int outputCount = m_outputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + if( m_outputPorts[ i ].Visible ) + { + // Output Port Icon + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 ) + { + if( m_outputPorts[ i ].Locked ) + GUI.color = Constants.LockedPortColor; + else if( ContainerGraph.ParentWindow.Options.ColoredPorts ) + GUI.color = UIUtils.GetColorForDataType( m_outputPorts[ i ].DataType, false, false ); + else + GUI.color = m_outputPorts[ i ].HasCustomColor ? m_outputPorts[ i ].CustomColor : UIUtils.GetColorForDataType( m_outputPorts[ i ].DataType, true, false ); + + GUIStyle style = m_outputPorts[ i ].IsConnected ? UIUtils.GetCustomStyle( CustomStyle.PortFullIcon ) : UIUtils.GetCustomStyle( CustomStyle.PortEmptyIcon ); + GUI.Label( m_outputPorts[ i ].Position, string.Empty, style ); + + GUI.color = m_colorBuffer; + } + + // Output Port Label + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + if( m_outputPorts[ i ].Locked ) + { + GUI.color = Constants.PortLockedTextColor; + GUI.Label( m_outputPorts[ i ].LabelPosition, m_outputPorts[ i ].Name, UIUtils.OutputPortLabel ); + GUI.color = m_colorBuffer; + } + else + { + GUI.Label( m_outputPorts[ i ].LabelPosition, m_outputPorts[ i ].Name, UIUtils.OutputPortLabel ); + } + } + } + } + + // Preview + if( ( m_showPreview || m_globalShowPreview ) && m_drawPreview ) + DrawPreview( drawInfo, m_previewRect ); + + // Error and Warning bottom message + if( m_showErrorMessage ) + { + GUI.color = new Color( 0.0f, 0.0f, 0.0f, 0.5f ); + GUI.Label( m_errorBox, string.Empty, UIUtils.Separator ); + GUI.color = m_colorBuffer; + + switch( m_errorMessageTypeIsError ) + { + default: + case NodeMessageType.Error: + { + m_errorMessage.text = ErrorTitle; + m_errorIcon.image = UIUtils.SmallErrorIcon; + m_errorCurrentStyle = UIUtils.BoldErrorStyle; + } + break; + case NodeMessageType.Warning: + { + m_errorMessage.text = WarningTitle; + m_errorIcon.image = UIUtils.SmallWarningIcon; + m_errorCurrentStyle = UIUtils.BoldWarningStyle; + } + break; + case NodeMessageType.Info: + { + m_errorMessage.text = InfoTitle; + m_errorIcon.image = UIUtils.SmallInfoIcon; + m_errorCurrentStyle = UIUtils.BoldInfoStyle; + } + break; + } + + Rect textBox = m_errorBox; + textBox.y += 1 * drawInfo.InvertedZoom; + textBox.height = 24 * drawInfo.InvertedZoom; + + float textWidth = m_errorCurrentStyle.CalcSize( m_errorMessage ).x; + + GUI.Label( textBox, m_errorMessage, m_errorCurrentStyle ); + textBox.x -= textWidth * 0.5f + 12 * drawInfo.InvertedZoom; + GUI.Label( textBox, m_errorIcon, m_errorCurrentStyle ); + textBox.x += textWidth + 24 * drawInfo.InvertedZoom; + GUI.Label( textBox, m_errorIcon, m_errorCurrentStyle ); + } + + // Selection Box + if( m_selected ) + { + GUI.color = Constants.NodeSelectedColor; + if( m_useSquareNodeTitle || ContainerGraph.LodLevel >= ParentGraph.NodeLOD.LOD2 ) + GUI.Label( m_globalPosition, string.Empty, UIUtils.NodeWindowOnSquare ); + else + GUI.Label( m_globalPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ) ); + GUI.color = m_colorBuffer; + } + + // Debug Visualizers + //if( FinishPreviewRender || m_continuousPreviewRefresh ) + //{ + // GUI.color = new Color( 0, 1, 0.5f, 1f ); + // Rect r = m_globalPosition; + // r.width = 8; + // r.height = 8; + // r.x -= 5 * drawInfo.InvertedZoom; + // r.y -= 5 * drawInfo.InvertedZoom; + // GUI.Label( r, string.Empty, UIUtils.GetCustomStyle( CustomStyle.PortFullIcon ) ); + // GUI.color = m_colorBuffer; + // FinishPreviewRender = false; + //} + //GUI.Label( m_remainingBox, string.Empty, UIUtils.Box ); + } + + public bool DropdownEditing { get { return m_dropdownEditing; } set { m_dropdownEditing = value; PreviewIsDirty = true; } } + public void DisablePreview() + { + m_showPreview = false; + m_sizeIsDirty = true; + } + /// + /// Handles gui controls, runs before node layout + /// + /// + public virtual void DrawGUIControls( DrawInfo drawInfo ) + { + if( !m_initialized ) + return; + + if( !m_isVisible ) + return; + + if( drawInfo.CurrentEventType == EventType.MouseDown && drawInfo.LeftMouseButtonPressed ) + { + if( m_expandRect.Contains( drawInfo.MousePosition ) ) + { + m_showPreview = !m_showPreview; + m_sizeIsDirty = true; + ContainerGraph.ParentWindow.MouseInteracted = true; + } + + if( m_hasLeftDropdown && m_dropdownRect.Contains( drawInfo.MousePosition ) ) + { + m_dropdownEditing = true; + } + else if( m_dropdownEditing ) + { + DropdownEditing = false; + } + } + + DrawGuiPorts( drawInfo ); + } + + //public static bool MyRepeatButton( DrawInfo drawInfo, Rect position, string text, GUIStyle style ) + //{ + // if(/* drawInfo.CurrentEventType == EventType.MouseDown &&*/ position.Contains( drawInfo.MousePosition ) ) + // { + // UIUtils.CurrentWindow.MouseInteracted = true; + // return true; + // } + // return false; + //} + + public void DrawGuiPorts( DrawInfo drawInfo ) + { + if( !m_initialized ) + return; + + if( !m_isVisible ) + return; + + if( drawInfo.CurrentEventType == EventType.MouseDown ) + { + int inputCount = m_inputPorts.Count; + int outputCount = m_outputPorts.Count; + + for( int i = 0; i < inputCount; i++ ) + { + if( m_inputPorts[ i ].Visible && !m_inputPorts[ i ].Locked && m_isVisible && m_inputPorts[ i ].ActivePortArea.Contains( drawInfo.MousePosition ) && drawInfo.LeftMouseButtonPressed ) + { + UIUtils.CurrentWindow.MouseInteracted = true; + m_inputPorts[ i ].Click(); + // need to put the mouse button on a hot state so it will detect the Mouse Up event correctly on the Editor Window + int controlID = GUIUtility.GetControlID( FocusType.Passive ); + //int controlID = GUIUtility.GetControlID( "repeatButton".GetHashCode(), FocusType.Passive, m_inputPorts[ i ].ActivePortArea ); + GUIUtility.hotControl = controlID; + + bool saveReference = true; + if( m_inputPorts[ i ].IsConnected ) + { + double doubleTapTime = EditorApplication.timeSinceStartup; + bool doubleTap = ( doubleTapTime - m_doubleClickTimestamp ) < DoubleClickTime; + m_doubleClickTimestamp = doubleTapTime; + + if( doubleTap ) + { + m_containerGraph.DeleteConnection( true, UniqueId, m_inputPorts[ i ].PortId, true, true ); + Event.current.Use(); + } + else + //if ( AppyModifierToPort( _inputPorts[ i ], true ) ) + //{ + //saveReference = false; + //} + if( !ApplyModifierToPort( m_inputPorts[ i ], true ) ) + { + UIUtils.ShowContextOnPick = false; + PickInput( m_inputPorts[ i ] ); + } + saveReference = false; + } + + if( saveReference && !m_containerGraph.ParentWindow.WireReferenceUtils.InputPortReference.IsValid ) + //if ( !modifierApplied && !UIUtils.InputPortReference.IsValid ) + { + m_containerGraph.ParentWindow.WireReferenceUtils.SetInputReference( m_uniqueId, m_inputPorts[ i ].PortId, m_inputPorts[ i ].DataType, m_inputPorts[ i ].TypeLocked ); + } + + IsDirty = true; + inputCount = m_inputPorts.Count; + } + } + + for( int i = 0; i < outputCount; i++ ) + { + if( m_outputPorts[ i ].Visible && m_outputPorts[ i ].ActivePortArea.Contains( drawInfo.MousePosition ) && drawInfo.LeftMouseButtonPressed ) + { + UIUtils.CurrentWindow.MouseInteracted = true; + m_outputPorts[ i ].Click(); + // need to put the mouse button on a hot state so it will detect the Mouse Up event correctly on the Editor Window + int controlID = GUIUtility.GetControlID( FocusType.Passive ); + //int controlID = GUIUtility.GetControlID( "aseRepeatButton".GetHashCode(), FocusType.Passive, m_outputPorts[ i ].ActivePortArea ); + GUIUtility.hotControl = controlID; + + bool saveReference = true; + if( m_outputPorts[ i ].IsConnected ) + { + if( ApplyModifierToPort( m_outputPorts[ i ], false ) ) + { + saveReference = false; + } + } + + if( saveReference && !m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid ) + { + m_containerGraph.ParentWindow.WireReferenceUtils.SetOutputReference( m_uniqueId, m_outputPorts[ i ].PortId, m_outputPorts[ i ].DataType, false ); + } + + IsDirty = true; + outputCount = m_outputPorts.Count; + } + } + } + + //Preview buttons + if( m_drawPreviewMaskButtons && ( drawInfo.CurrentEventType == EventType.MouseDown || drawInfo.CurrentEventType == EventType.MouseUp ) ) + DrawPreviewMaskButtonsLayout( drawInfo, m_previewRect ); + } + + /// + /// Can be used to draw an entire node, runs after wires + /// + /// + public virtual void Draw( DrawInfo drawInfo ) + { + if( !m_initialized ) + return; + + if( drawInfo.CurrentEventType == EventType.Repaint ) + OnNodeRepaint( drawInfo ); + } + + public virtual void SetPreviewInputs() + { + if( !HasPreviewShader || !m_initialized ) + return; + + int count = m_inputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].InputNodeHasPreview( ContainerGraph ) ) + { + m_inputPorts[ i ].SetPreviewInputTexture( ContainerGraph ); + } + else + { + m_inputPorts[ i ].SetPreviewInputValue( ContainerGraph ); + } + } + } + + + public bool SafeDraw( DrawInfo drawInfo ) + { + EditorGUI.BeginChangeCheck(); + Draw( drawInfo ); + if( EditorGUI.EndChangeCheck() ) + { + SaveIsDirty = true; + return true; + } + return false; + } + + public bool ShowTooltip( DrawInfo drawInfo ) + { + if( string.IsNullOrEmpty( m_tooltipText ) ) + return false; + + if( m_globalPosition.Contains( drawInfo.MousePosition ) || m_linkVisibility ) + { + if( m_tooltipTimestamp + 0.6f < Time.realtimeSinceStartup || m_linkVisibility ) + { + bool errorTooltip = false; + if( m_showErrorMessage && m_errorBox.Contains( drawInfo.MousePosition ) && !string.IsNullOrEmpty( m_errorMessageTooltip ) ) + errorTooltip = true; + + Rect globalTooltipPos = m_globalPosition; + GUIContent temp = new GUIContent( errorTooltip ? m_errorMessageTooltip : m_tooltipText ); + UIUtils.TooltipBox.wordWrap = false; + Vector2 optimal = UIUtils.TooltipBox.CalcSize( temp ); + if( optimal.x > 300f ) + { + UIUtils.TooltipBox.wordWrap = true; + optimal.x = 300f; + optimal.y = UIUtils.TooltipBox.CalcHeight( temp, 300f ); + } + + globalTooltipPos.width = Mathf.Max( 120, optimal.x ); + globalTooltipPos.height = optimal.y; + globalTooltipPos.center = m_globalPosition.center; + + if( !errorTooltip && m_hasTooltipLink ) + globalTooltipPos.height += 16; + + if( errorTooltip ) + globalTooltipPos.y = 10 + m_globalPosition.yMax; + else + globalTooltipPos.y = m_globalPosition.yMin - 10 - globalTooltipPos.height; + + if ( globalTooltipPos.x < 10 ) + globalTooltipPos.x = 10; + + if( globalTooltipPos.x + globalTooltipPos.width > Screen.width - 10 ) + globalTooltipPos.x = Screen.width - globalTooltipPos.width - 10; + + //UNCOMMENT this for auto adjust tooltip to the top window box + //if( globalTooltipPos.y < 40 ) + // globalTooltipPos.y = 40; + + if( errorTooltip && globalTooltipPos.y + globalTooltipPos.height > Screen.height - 32 ) + globalTooltipPos.y = Screen.height - 32 - globalTooltipPos.height; + + GUI.Label( globalTooltipPos, temp, UIUtils.TooltipBox ); + + if( !errorTooltip && m_hasTooltipLink ) + { + Rect link = globalTooltipPos; + link.y = globalTooltipPos.yMax - 16; + link.height = 16; + link.width = 86; + link.x = globalTooltipPos.center.x - 43; + Rect hover = globalTooltipPos; + hover.yMax += 15;// m_globalPosition.yMax; + m_linkVisibility = hover.Contains( drawInfo.MousePosition ); + if( link.Contains( drawInfo.MousePosition ) ) + { + if( drawInfo.CurrentEventType == EventType.MouseDown ) + { + if( m_tooltipTimestamp + 1.25f < Time.realtimeSinceStartup ) + { + Application.OpenURL( Attributes.NodeUrl ); + } + } + else + { + UIUtils.MainSkin.customStyles[ 52 ].Draw( link, WikiLinkStr, true, false, false, false ); + } + } + else + { + GUI.Label( link, WikiLinkStr, UIUtils.MainSkin.customStyles[ 52 ] ); + } + } + ContainerGraph.ParentWindow.RequestRepaint(); + return true; + } + } + else + { + if( !m_linkVisibility ) + m_tooltipTimestamp = Time.realtimeSinceStartup; + } + + return false; + } + + public virtual bool SafeDrawProperties() + { + EditorGUI.BeginChangeCheck(); + PreDrawProperties(); + if( m_autoWrapProperties ) + { + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr, DrawProperties ); + } + else + { + DrawProperties(); + } + if( EditorGUI.EndChangeCheck() ) + { + PreviewIsDirty = true; + //UIUtils.RecordObject(this); + //MarkForPreviewUpdate(); + return true; + } + return false; + } + + + public void PreDrawProperties() + { + if( m_useInternalPortData && m_autoDrawInternalPortData ) + { + DrawInternalDataGroup(); + } + } + + virtual public void DrawProperties() { } + + protected void DrawInternalDataGroup() + { + bool drawInternalDataUI = false; + int inputCount = m_inputPorts.Count; + if( inputCount > 0 ) + { + for( int i = 0; i < inputCount; i++ ) + { + if( m_inputPorts[ i ].Available && m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected /*&& ( m_inputPorts[ i ].AutoDrawInternalData || ( m_autoDrawInternalPortData && m_useInternalPortData ) )*/ /*&& m_inputPorts[ i ].AutoDrawInternalData*/ ) + { + drawInternalDataUI = true; + break; + } + } + } + + if( drawInternalDataUI ) + NodeUtils.DrawPropertyGroup( ref m_internalDataFoldout, Constants.InternalDataLabelStr, () => + { + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].Visible /*&& m_inputPorts[ i ].AutoDrawInternalData*/ ) + { + m_inputPorts[ i ].ShowInternalData( this ); + } + } + } ); + } + + protected void PickInput( InputPort port ) + { + WireReference connection = port.GetConnection( 0 ); + OutputPort from = port.GetOutputConnection( 0 ); + + m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.SetReference( from.NodeId, from.PortId, from.DataType, connection.TypeLocked ); + m_containerGraph.DeleteConnection( true, UniqueId, port.PortId, true, true ); + //TODO: check if not necessary + Event.current.Use(); + IsDirty = true; + SetSaveIsDirty(); + } + + protected bool ApplyModifierToPort( WirePort port, bool isInput ) + { + bool modifierApplied = false; + switch( Event.current.modifiers ) + { + case EventModifiers.Alt: + { + m_containerGraph.DeleteConnection( isInput, UniqueId, port.PortId, true, true ); + modifierApplied = true; + m_containerGraph.ParentWindow.InvalidateAlt(); + } + break; + case EventModifiers.Control: + { + //WireReference connection = port.GetConnection( 0 ); + //if ( isInput ) + //{ + // UIUtils.OutputPortReference.SetReference( connection.NodeId, connection.PortId, connection.DataType, connection.TypeLocked ); + //} + //else + //{ + // UIUtils.InputPortReference.SetReference( connection.NodeId, connection.PortId, connection.DataType, connection.TypeLocked ); + //} + + //UIUtils.DeleteConnection( isInput, UniqueId, port.PortId, true ); + //modifierApplied = true; + + if( !isInput ) + { + WireReference connection = port.GetConnection( 0 ); + m_containerGraph.ParentWindow.WireReferenceUtils.InputPortReference.SetReference( connection.NodeId, connection.PortId, connection.DataType, connection.TypeLocked ); + m_containerGraph.DeleteConnection( isInput, UniqueId, port.PortId, true, true ); + modifierApplied = true; + } + } + break; + } + + if( isInput ) + m_containerGraph.ParentWindow.WireReferenceUtils.SwitchPortReference.SetReference( port.NodeId, port.PortId, port.DataType, false ); //always save last connection + else + m_containerGraph.ParentWindow.WireReferenceUtils.SwitchPortReference.SetReference( -1, -1, WirePortDataType.OBJECT, false ); //invalidate connection + + if( modifierApplied ) + { + Event.current.Use(); + IsDirty = true; + SetSaveIsDirty(); + } + return modifierApplied; + } + + public void DeleteAllInputConnections( bool alsoDeletePorts , bool inhibitWireNodeAutoDel = false ) + { + int count = m_inputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + ParentNode connNode = null; + if( inhibitWireNodeAutoDel ) + { + connNode = m_inputPorts[ i ].GetOutputNode(); + connNode.Alive = false; + } + m_containerGraph.DeleteConnection( true, UniqueId, m_inputPorts[ i ].PortId, false, true ); + if( inhibitWireNodeAutoDel ) + { + connNode.Alive = true; + } + } + + } + if( alsoDeletePorts ) + { + m_inputPorts.Clear(); + m_inputPortsDict.Clear(); + } + SetSaveIsDirty(); + } + + public void DeleteAllOutputConnections( bool alsoDeletePorts ) + { + int count = m_outputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_outputPorts[ i ].IsConnected ) + m_containerGraph.DeleteConnection( false, UniqueId, m_outputPorts[ i ].PortId, false, true ); + } + + if( alsoDeletePorts ) + { + m_outputPorts.Clear(); + m_outputPortsDict.Clear(); + } + SetSaveIsDirty(); + } + + public void DeleteInputPortByArrayIdx( int arrayIdx ) + { + if( arrayIdx >= m_inputPorts.Count ) + return; + + m_containerGraph.DeleteConnection( true, UniqueId, m_inputPorts[ arrayIdx ].PortId, false, true ); + m_inputPortsDict.Remove( m_inputPorts[ arrayIdx ].PortId ); + m_inputPorts.RemoveAt( arrayIdx ); + + m_sizeIsDirty = true; + SetSaveIsDirty(); + RecalculateInputPortIdx(); + } + + public void DeleteOutputPortByArrayIdx( int portIdx ) + { + if( portIdx >= m_outputPorts.Count ) + return; + + m_containerGraph.DeleteConnection( false, UniqueId, m_outputPorts[ portIdx ].PortId, false, true ); + m_outputPortsDict.Remove( m_outputPorts[ portIdx ].PortId ); + m_outputPorts.RemoveAt( portIdx ); + m_sizeIsDirty = true; + } + + public InputPort GetInputPortByArrayId( int id ) + { + if( id < m_inputPorts.Count ) + return m_inputPorts[ id ]; + + return null; + } + + public OutputPort GetOutputPortByArrayId( int id ) + { + if( id < m_outputPorts.Count ) + return m_outputPorts[ id ]; + + return null; + } + + public InputPort GetInputPortByUniqueId( int id ) + { + if( m_inputPortsDict.ContainsKey( id ) ) + return m_inputPortsDict[ id ]; + + if( m_inputPortsDict.Count != m_inputPorts.Count ) + m_repopulateDictionaries = true; + + int inputCount = m_inputPorts.Count; + for( int i = 0; i < inputCount; i++ ) + { + if( m_inputPorts[ i ].PortId == id ) + { + return m_inputPorts[ i ]; + } + } + return null; + } + + public OutputPort GetOutputPortByUniqueId( int id ) + { + if( m_outputPortsDict.ContainsKey( id ) ) + return m_outputPortsDict[ id ]; + + if( m_outputPortsDict.Count != m_outputPorts.Count ) + m_repopulateDictionaries = true; + + int outputCount = m_outputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + if( m_outputPorts[ i ].PortId == id ) + return m_outputPorts[ i ]; + } + return null; + } + + public virtual void AfterDuplication(){} + + public override string ToString() + { + string dump = ""; + dump += ( "Type: " + GetType() ); + dump += ( " Unique Id: " + UniqueId + "\n" ); + dump += ( " Inputs: \n" ); + + int inputCount = m_inputPorts.Count; + int outputCount = m_outputPorts.Count; + + for( int inputIdx = 0; inputIdx < inputCount; inputIdx++ ) + { + dump += ( m_inputPorts[ inputIdx ] + "\n" ); + } + dump += ( "Outputs: \n" ); + for( int outputIdx = 0; outputIdx < outputCount; outputIdx++ ) + { + dump += ( m_outputPorts[ outputIdx ] + "\n" ); + } + return dump; + } + + public string GetValueFromOutputStr( int outputId, WirePortDataType inputPortType, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( ignoreLocalvar ) + { + return GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + } + OutputPort outPort = GetOutputPortByUniqueId( outputId ); + if( outPort.IsLocalValue( dataCollector.PortCategory ) ) + { + if( outPort.DataType != WirePortDataType.OBJECT && outPort.DataType != inputPortType ) + { + return UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( m_uniqueId, outputId ), null, outPort.DataType, inputPortType, outPort.LocalValue( dataCollector.PortCategory ) ); + } + else + { + return outPort.LocalValue( dataCollector.PortCategory ); + } + } + + string result = GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + result = CreateOutputLocalVariable( outputId, result, ref dataCollector ); + + if( outPort.DataType != WirePortDataType.OBJECT && outPort.DataType != inputPortType ) + { + result = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( m_uniqueId, outputId ), null, outPort.DataType, inputPortType, result ); + } + return result; + } + + public virtual string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsSRP ) + { + switch( dataCollector.CurrentSRPType ) + { + case TemplateSRPType.HD: if(OnHDAction!=null) OnHDAction( outputId, ref dataCollector ); break; + case TemplateSRPType.Lightweight:if(OnLightweightAction != null) OnLightweightAction( outputId, ref dataCollector ); break; + } + } + return string.Empty; + } + + public string GenerateValueInVertex( ref MasterNodeDataCollector dataCollector, WirePortDataType dataType, string dataValue, string dataName, bool createInterpolator ) + { + + if( !dataCollector.IsFragmentCategory ) + return dataValue; + + //TEMPLATES + if( dataCollector.IsTemplate ) + { + if( createInterpolator && dataCollector.TemplateDataCollectorInstance.HasCustomInterpolatedData( dataName ) ) + return dataName; + + MasterNodePortCategory category = dataCollector.PortCategory; + dataCollector.PortCategory = MasterNodePortCategory.Vertex; + + dataCollector.PortCategory = category; + + if( createInterpolator ) + { + dataCollector.TemplateDataCollectorInstance.RegisterCustomInterpolatedData( dataName, dataType, CurrentPrecisionType, dataValue ); + } + else + { + dataCollector.AddToVertexLocalVariables( -1, CurrentPrecisionType, dataType, dataName, dataValue ); + } + + return dataName; + } + + //SURFACE + { + if( dataCollector.TesselationActive ) + { + UIUtils.ShowMessage( UniqueId, "Unable to use Vertex to Frag when Tessellation is active" ); + return m_outputPorts[ 0 ].ErrorValue; + } + + if( createInterpolator ) + dataCollector.AddToInput( UniqueId, dataName, dataType, CurrentPrecisionType ); + + MasterNodePortCategory portCategory = dataCollector.PortCategory; + dataCollector.PortCategory = MasterNodePortCategory.Vertex; + if( createInterpolator ) + { + dataCollector.AddLocalVariable( UniqueId, Constants.VertexShaderOutputStr + "." + dataName, dataValue + ";" ); + } + else + { + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, dataType, dataName, dataValue ); + } + dataCollector.PortCategory = portCategory; + return createInterpolator ? Constants.InputVarStr + "." + dataName : dataName; + } + } + + public string GenerateInputInVertex( ref MasterNodeDataCollector dataCollector , int inputPortUniqueId , string varName , bool createInterpolator , bool noInterpolationFlag = false , bool sampleFlag = false ) + { + InputPort inputPort = GetInputPortByUniqueId( inputPortUniqueId ); + if( !dataCollector.IsFragmentCategory ) + { + string value = inputPort.GeneratePortInstructions( ref dataCollector ); + dataCollector.AddLocalVariable( -1 , CurrentPrecisionType , inputPort.DataType , varName , value ); + return varName; + } + + //TEMPLATES + if( dataCollector.IsTemplate ) + { + if( createInterpolator && dataCollector.TemplateDataCollectorInstance.HasCustomInterpolatedData( varName ) ) + return varName; + + MasterNodePortCategory category = dataCollector.PortCategory; + dataCollector.PortCategory = MasterNodePortCategory.Vertex; + //bool dirtyVertexVarsBefore = dataCollector.DirtyVertexVariables; + //ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Vertex ); + + string data = inputPort.GeneratePortInstructions( ref dataCollector ); + + dataCollector.PortCategory = category; + //if( !dirtyVertexVarsBefore && dataCollector.DirtyVertexVariables ) + //{ + // dataCollector.AddVertexInstruction( dataCollector.VertexLocalVariablesFromList, UniqueId, false ); + // dataCollector.ClearVertexLocalVariables(); + // ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Vertex ); + //} + + //ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Fragment ); + + if( createInterpolator ) + { + dataCollector.TemplateDataCollectorInstance.RegisterCustomInterpolatedData( varName, inputPort.DataType, CurrentPrecisionType, data,true,MasterNodePortCategory.Fragment,noInterpolationFlag,sampleFlag ); + } + else + { + dataCollector.AddToVertexLocalVariables( -1, CurrentPrecisionType, inputPort.DataType, varName, data ); + } + + return varName; + } + + //SURFACE + { + if( dataCollector.TesselationActive ) + { + UIUtils.ShowMessage( UniqueId, "Unable to use Vertex to Frag when Tessellation is active" ); + return m_outputPorts[ 0 ].ErrorValue; + } + + if( createInterpolator ) + dataCollector.AddToInput( UniqueId, varName, inputPort.DataType, CurrentPrecisionType ); + + MasterNodePortCategory portCategory = dataCollector.PortCategory; + dataCollector.PortCategory = MasterNodePortCategory.Vertex; + + //bool dirtyVertexVarsBefore = dataCollector.DirtyVertexVariables; + + //ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Vertex ); + + string vertexVarValue = inputPort.GeneratePortInstructions( ref dataCollector ); + if( createInterpolator ) + { + dataCollector.AddLocalVariable( UniqueId, Constants.VertexShaderOutputStr + "." + varName, vertexVarValue + ";" ); + } + else + { + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, inputPort.DataType, varName, vertexVarValue ); + } + + dataCollector.PortCategory = portCategory; + + //if( !dirtyVertexVarsBefore && dataCollector.DirtyVertexVariables ) + //{ + // dataCollector.AddVertexInstruction( dataCollector.VertexLocalVariables, UniqueId, false ); + // dataCollector.ClearVertexLocalVariables(); + // ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Vertex ); + //} + + //ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Fragment ); + + return createInterpolator ? Constants.InputVarStr + "." + varName : varName; + } + } + + + protected virtual void OnUniqueIDAssigned() { } + + public string CreateOutputLocalVariable( int outputArrayId, string value, ref MasterNodeDataCollector dataCollector ) + { + OutputPort port = GetOutputPortByUniqueId( outputArrayId ); + + if( port.IsLocalValue( dataCollector.PortCategory ) ) + return port.LocalValue( dataCollector.PortCategory ); + + if( port.ConnectionCount > 1 ) + { + RegisterLocalVariable( outputArrayId, value, ref dataCollector ); + return port.LocalValue( dataCollector.PortCategory ); + } + else + { + // revisit later (break to components case) + port.SetLocalValue( value, dataCollector.PortCategory ); + } + + return value; + } + + public void RegisterLocalVariable( int outputArrayId, string value, ref MasterNodeDataCollector dataCollector, string customName = null ) + { + OutputPort port = GetOutputPortByUniqueId( outputArrayId ); + if( (int)port.DataType >= (int)( 1 << 10 ) || port.DataType == WirePortDataType.OBJECT ) //10 is the flag start of sampler types + { + port.SetLocalValue( value, dataCollector.PortCategory ); + return; + } + + bool vertexMode = dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation; + string localVar = port.ConfigOutputLocalValue( CurrentPrecisionType, value, customName, dataCollector.PortCategory ); + + if( vertexMode ) + { + dataCollector.AddToVertexLocalVariables( m_uniqueId, localVar ); + } + else + { + dataCollector.AddToFragmentLocalVariables( m_uniqueId, localVar ); + } + } + + public void InvalidateConnections() + { + int inputCount = m_inputPorts.Count; + int outputCount = m_outputPorts.Count; + + for( int i = 0; i < inputCount; i++ ) + { + m_inputPorts[ i ].InvalidateAllConnections(); + } + + for( int i = 0; i < outputCount; i++ ) + { + m_outputPorts[ i ].InvalidateAllConnections(); + } + } + + public virtual bool OnClick( Vector2 currentMousePos2D ) + { + bool singleClick = true; + if( ( EditorApplication.timeSinceStartup - m_lastTimeSelected ) < NodeClickTime ) + { + OnNodeDoubleClicked( currentMousePos2D ); + singleClick = false; + } + + m_lastTimeSelected = EditorApplication.timeSinceStartup; + return singleClick; + } + + public virtual void OnNodeDoubleClicked( Vector2 currentMousePos2D ) + { + ContainerGraph.ParentWindow.ParametersWindow.IsMaximized = !ContainerGraph.ParentWindow.ParametersWindow.IsMaximized; + } + + public virtual void OnNodeSelected( bool value ) + { + if( !value ) + { + if( m_inputPorts != null ) + { + int count = m_inputPorts.Count; + for( int i = 0; i < count; i++ ) + { + m_inputPorts[ i ].ResetEditing(); + } + } + + if( m_outputPorts != null ) + { + int count = m_outputPorts.Count; + for( int i = 0; i < count; i++ ) + { + m_outputPorts[ i ].ResetEditing(); + } + } + } + } + + public void ResetOutputLocals() + { + int outputCount = m_outputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + m_outputPorts[ i ].ResetLocalValue(); + } + } + + + public void ResetOutputLocalsIfNot( MasterNodePortCategory category ) + { + int outputCount = m_outputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + //if( !m_outputPorts[ i ].IsLocalOnCategory( category ) ) + // m_outputPorts[ i ].ResetLocalValue(); + m_outputPorts[ i ].ResetLocalValueIfNot( category ); + } + } + + public virtual void Rewire() { } + + //public virtual List NodeReferences { get { return null; } } + + public int UniqueId + { + get { return m_uniqueId; } + + set + { + m_uniqueId = value; + + int inputCount = m_inputPorts.Count; + int outputCount = m_outputPorts.Count; + + for( int inputIdx = 0; inputIdx < inputCount; inputIdx++ ) + { + m_inputPorts[ inputIdx ].NodeId = value; + } + + for( int outputIdx = 0; outputIdx < outputCount; outputIdx++ ) + { + m_outputPorts[ outputIdx ].NodeId = value; + } + OnUniqueIDAssigned(); + } + } + public void SetBaseUniqueId( int uniqueId, bool setOnPorts = false ) + { + m_uniqueId = uniqueId; + if( setOnPorts ) + { + int inputCount = m_inputPorts.Count; + int outputCount = m_outputPorts.Count; + + for( int inputIdx = 0; inputIdx < inputCount; inputIdx++ ) + { + m_inputPorts[ inputIdx ].NodeId = uniqueId; + } + + for( int outputIdx = 0; outputIdx < outputCount; outputIdx++ ) + { + m_outputPorts[ outputIdx ].NodeId = uniqueId; + } + } + } + + public string OutputId + { + get + { + if( ContainerGraph.GraphId > 0 ) + return UniqueId + "_g" + ContainerGraph.GraphId; + else + return UniqueId.ToString(); + } + } + + + public virtual Rect Position { get { return m_position; } } + public Rect TruePosition { get { return m_position; } } + + public Vector2 CenterPosition { get { return new Vector2( m_position.x + m_position.width * 0.5f, m_position.y + m_position.height * 0.5f ); ; } } + + public Rect GlobalPosition { get { return m_globalPosition; } } + + public Vector2 Corner { get { return new Vector2( m_position.x + m_position.width, m_position.y + m_position.height ); } } + public Vector2 Vec2Position + { + get { return new Vector2( m_position.x, m_position.y ); } + + set + { + m_position.x = value.x; + m_position.y = value.y; + } + } + + public Vector3 Vec3Position + { + get { return new Vector3( m_position.x, m_position.y, 0f ); } + + set + { + m_position.x = value.x; + m_position.y = value.y; + } + } + + + public bool Selected + { + get { return m_selected; } + set + { + m_infiniteLoopDetected = false; + m_selected = value; + OnNodeSelected( value ); + } + } + + public List InputPorts { get { return m_inputPorts; } } + + public List OutputPorts + { + get { return m_outputPorts; } + } + + public bool IsConnected { get { return m_connStatus == NodeConnectionStatus.Connected; } } + public NodeConnectionStatus ConnStatus + { + get { return m_connStatus; } + set + { + if( m_selfPowered ) + { + m_connStatus = NodeConnectionStatus.Connected; + } + else + { + m_connStatus = value; + } + + switch( m_connStatus ) + { + case NodeConnectionStatus.Island: + case NodeConnectionStatus.Not_Connected: m_statusColor = Constants.NodeDefaultColor; break; + case NodeConnectionStatus.Connected: m_statusColor = Constants.NodeConnectedColor; break; + case NodeConnectionStatus.Error: m_statusColor = Constants.NodeErrorColor; break; + } + + } + } + + public bool SelfPowered + { + set + { + m_selfPowered = value; + if( value ) + { + ConnStatus = NodeConnectionStatus.Connected; + } + } + } + + // This is also called when recording on Undo + public virtual void OnBeforeSerialize() { } + public virtual void OnAfterDeserialize() + { + m_selected = false; + m_isOnGrid = false; + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + m_inputPorts[ i ].ResetWireReferenceStatus(); + } + m_repopulateDictionaries = true; + m_sizeIsDirty = true; + } + + public virtual int InputIdFromDeprecated( int oldInputId ) { return oldInputId; } + + public virtual int OutputIdFromDeprecated( int oldOutputId ) { return oldOutputId; } + + public virtual void ReadFromDeprecated( ref string[] nodeParams, Type oldType = null ) { } + + //Inherited classes must call this base method in order to setup id and position + public virtual void ReadFromString( ref string[] nodeParams ) + { + ParentReadFromString( ref nodeParams ); + } + + public void ParentReadFromString( ref string[] nodeParams ) + { + m_currentReadParamIdx = IOUtils.NodeTypeId + 1; + + UniqueId = Convert.ToInt32( nodeParams[ m_currentReadParamIdx++ ] ); + + string[] posCoordinates = nodeParams[ m_currentReadParamIdx++ ].Split( IOUtils.VECTOR_SEPARATOR ); + + m_position.x = Convert.ToSingle( posCoordinates[ 0 ] ); + m_position.y = Convert.ToSingle( posCoordinates[ 1 ] ); + + if( UIUtils.CurrentShaderVersion() > 22 ) + { + string val = GetCurrentParam( ref nodeParams ); + if( m_customPrecision ) + { + if( val.Equals("Fixed") ) + m_currentPrecisionType = PrecisionType.Half; + else + m_currentPrecisionType = (PrecisionType)Enum.Parse( typeof( PrecisionType ), val ); + } + else + { + m_currentPrecisionType = PrecisionType.Inherit; + } + } + + if( UIUtils.CurrentShaderVersion() > 5004 ) + m_showPreview = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + + } + + //should be called after ReadFromString + public virtual void ReadInputDataFromString( ref string[] nodeParams ) + { + int count = 0; + if( UIUtils.CurrentShaderVersion() > 7003 ) + { + try + { + count = Convert.ToInt32( nodeParams[ m_currentReadParamIdx++ ] ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + else + { + count = ( m_oldInputCount < 0 ) ? m_inputPorts.Count : m_oldInputCount; + } + + for( int i = 0; i < count && i < nodeParams.Length && m_currentReadParamIdx < nodeParams.Length; i++ ) + { + if( UIUtils.CurrentShaderVersion() < 5003 ) + { + int newId = VersionConvertInputPortId( i ); + if( UIUtils.CurrentShaderVersion() > 23 ) + { + m_inputPorts[ newId ].DataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), nodeParams[ m_currentReadParamIdx++ ] ); + } + + m_inputPorts[ newId ].InternalData = nodeParams[ m_currentReadParamIdx++ ]; + if( m_inputPorts[ newId ].IsEditable && UIUtils.CurrentShaderVersion() >= 3100 && m_currentReadParamIdx < nodeParams.Length ) + { + m_inputPorts[ newId ].Name = nodeParams[ m_currentReadParamIdx++ ]; + } + m_inputPorts[ newId ].UpdatePreviewInternalData(); + } + else + { + string portIdStr = nodeParams[ m_currentReadParamIdx++ ]; + int portId = -1; + try + { + portId = Convert.ToInt32( portIdStr ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + WirePortDataType DataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), nodeParams[ m_currentReadParamIdx++ ] ); + string InternalData = nodeParams[ m_currentReadParamIdx++ ]; + bool isEditable = Convert.ToBoolean( nodeParams[ m_currentReadParamIdx++ ] ); + string Name = string.Empty; + if( isEditable && m_currentReadParamIdx < nodeParams.Length ) + { + Name = nodeParams[ m_currentReadParamIdx++ ]; + } + + InputPort inputPort = GetInputPortByUniqueId( portId ); + if( inputPort != null ) + { + if( UIUtils.IsValidType( DataType ) ) + inputPort.DataType = DataType; + + inputPort.InternalData = InternalData; + if( !string.IsNullOrEmpty( Name ) ) + { + inputPort.Name = Name; + } + inputPort.UpdatePreviewInternalData(); + } + } + } + } + + public virtual void ReadOutputDataFromString( ref string[] nodeParams ) + { + int count = 0; + if( UIUtils.CurrentShaderVersion() > 7003 ) + { + count = Convert.ToInt32( nodeParams[ m_currentReadParamIdx++ ] ); + } + else + { + count = m_outputPorts.Count; + } + + for( int i = 0; i < count && i < nodeParams.Length && m_currentReadParamIdx < nodeParams.Length; i++ ) + { + try + { + WirePortDataType dataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), nodeParams[ m_currentReadParamIdx++ ] ); + int portId = -1; + if( UIUtils.CurrentShaderVersion() > 13903 ) + { + portId = Convert.ToInt32( nodeParams[ m_currentReadParamIdx++ ] ); ; + } + else + { + portId = i; + } + + OutputPort port = GetOutputPortByUniqueId( portId ); + if( port != null && UIUtils.IsValidType( dataType ) ) + { + port.DataType = dataType; + } + + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + } + + public virtual void ReadAdditionalClipboardData( ref string[] nodeParams ) { } + + protected string GetCurrentParam( ref string[] nodeParams ) + { + if( m_currentReadParamIdx < nodeParams.Length ) + { + return nodeParams[ m_currentReadParamIdx++ ]; + } + + UIUtils.ShowMessage( UniqueId, "Invalid params number in node " + m_uniqueId + " of type " + GetType(), MessageSeverity.Error ); + return string.Empty; + } + + protected string GetCurrentParam( int index, ref string[] nodeParams ) + { + if( m_currentReadParamIdx < nodeParams.Length ) + { + return nodeParams[ index ]; + } + + UIUtils.ShowMessage( UniqueId, "Invalid params number in node " + m_uniqueId + " of type " + GetType(), MessageSeverity.Error ); + return string.Empty; + } + + + public virtual void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + IOUtils.AddTypeToString( ref nodeInfo, IOUtils.NodeParam ); + IOUtils.AddFieldValueToString( ref nodeInfo, GetType() ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_uniqueId ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_position.x.ToString() + IOUtils.VECTOR_SEPARATOR + m_position.y.ToString() ) ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentPrecisionType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_showPreview ); + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + m_inputPorts[ i ].WriteToString( ref connectionsInfo ); + } + } + + public virtual void WriteInputDataToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_inputPorts.Count ); + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_inputPorts[ i ].PortId ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_inputPorts[ i ].DataType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_inputPorts[ i ].InternalData ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_inputPorts[ i ].IsEditable ); + if( m_inputPorts[ i ].IsEditable ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_inputPorts[ i ].Name ); + } + } + } + + public void WriteOutputDataToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_outputPorts.Count ); + for( int i = 0; i < m_outputPorts.Count; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_outputPorts[ i ].DataType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_outputPorts[ i ].PortId ); + } + } + + public virtual void WriteAdditionalClipboardData( ref string nodeInfo ) { } + + public virtual string GetIncludes() { return string.Empty; } + public virtual void OnObjectDropped( UnityEngine.Object obj ) { } + public virtual void SetupFromCastObject( UnityEngine.Object obj ) { } + public virtual bool OnNodeInteraction( ParentNode node ) { return false; } + public virtual void OnConnectedOutputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) { } + public virtual void OnConnectedInputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) { } + + public Rect CachedPos { get { return m_cachedPos; } } + + public bool IsOnGrid + { + set { m_isOnGrid = value; } + get { return m_isOnGrid; } + } + + public uint CurrentReadParamIdx + { + get { return m_currentReadParamIdx++; } + set { m_currentReadParamIdx = value; } + } + + public Dictionary InputPortsDict + { + get + { + Dictionary dict = new Dictionary(); + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + dict.Add( m_inputPorts[ i ].Name, m_inputPorts[ i ] ); + } + return dict; + } + } + + public bool IsDirty + { + set { m_isDirty = value && UIUtils.DirtyMask; } + get + { + bool value = m_isDirty; + m_isDirty = false; + return value; + } + } + + public virtual void ResetNodeData() + { + m_category = 0; + m_graphDepth = 0; + } + + public virtual void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + UIUtils.SetCategoryInBitArray( ref m_category, nodeData.Category ); + nodeData.GraphDepth += 1; + if( nodeData.GraphDepth > m_graphDepth ) + { + m_graphDepth = nodeData.GraphDepth; + } + int count = m_inputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + m_inputPorts[ i ].GetOutputNode().PropagateNodeData( nodeData, ref dataCollector ); + } + } + } + + public void SetTitleTextOnCallback( string compareTitle, Action callback ) + { + if( !m_previousTitle.Equals( compareTitle ) ) + { + m_previousTitle = compareTitle; + m_sizeIsDirty = true; + callback( this, compareTitle ); + } + } + + public void SetAdditonalTitleTextOnCallback( string compareTitle, Action callback ) + { + if( !m_previousAdditonalTitle.Equals( compareTitle ) ) + { + m_previousAdditonalTitle = compareTitle; + m_sizeIsDirty = true; + callback( this, compareTitle ); + } + } + + public virtual void SetClippedTitle( string newText, int maxSize = 170, string endString = "..." ) + { + m_content.text = GenerateClippedTitle( newText,maxSize,endString ); + m_sizeIsDirty = true; + } + + public virtual void SetClippedAdditionalTitle( string newText, int maxSize = 170, string endString = "..." ) + { + m_additionalContent.text = GenerateClippedTitle( newText, maxSize, endString ); + m_sizeIsDirty = true; + } + + + public void SetTitleText( string newText ) + { + if( !newText.Equals( m_content.text ) ) + { + m_content.text = newText; + m_sizeIsDirty = true; + } + } + + public void SetAdditonalTitleText( string newText ) + { + if( !newText.Equals( m_additionalContent.text ) ) + { + m_additionalContent.text = newText; + m_sizeIsDirty = true; + } + } + + public string GenerateErrorValue( int outputIdx = 0 ) + { + switch( m_outputPorts[ outputIdx ].DataType ) + { + case WirePortDataType.FLOAT2: + { + return "(0).xx"; + } + case WirePortDataType.FLOAT3: + { + return "(0).xxx"; + } + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + { + return "(0).xxxx"; + } + } + return "0"; + } + + //Methods created to take into account new ports added on nodes newer versions + //This way we can convert connections from previous versions to newer ones and not brake shader graph + public virtual int VersionConvertInputPortId( int portId ) { return portId; } + public virtual int VersionConvertOutputPortId( int portId ) { return portId; } + + public virtual string DataToArray { get { return string.Empty; } } + + public bool SaveIsDirty + { + set { m_saveIsDirty = value && UIUtils.DirtyMask; } + get + { + bool value = m_saveIsDirty; + m_saveIsDirty = false; + return value; + } + } + + public GUIContent TitleContent { get { return m_content; } } + public GUIContent AdditonalTitleContent { get { return m_additionalContent; } } + public bool IsVisible { get { return m_isVisible; } } + public NodeAttributes Attributes { get { return m_nodeAttribs; } } + public bool ReorderLocked { get { return m_reorderLocked; } } + public bool RequireMaterialUpdate { get { return m_requireMaterialUpdate; } } + public bool RMBIgnore { get { return m_rmbIgnore; } } + public float TextLabelWidth { get { return m_textLabelWidth; } } + public bool IsMoving { get { return m_isMoving > 0; } } + public bool MovingInFrame { get { return m_movingInFrame; } set { m_movingInFrame = value; } } + public bool SizeIsDirty { get { return m_sizeIsDirty; } set { m_sizeIsDirty = value; } } + public int Category { get { return m_category; } } + public int CommentaryParent + { + get { return m_commentaryParent; } + set { m_commentaryParent = value; } + } + + public int Depth + { + get { return m_depth; } + set { m_depth = value; } + } + + public int MatrixId + { + get { return m_matrixId; } + set { m_matrixId = value; } + } + + public float PaddingTitleRight + { + get { return m_paddingTitleRight; } + set { m_paddingTitleRight += value; } + } + + public float PaddingTitleLeft + { + get { return m_paddingTitleLeft; } + set { m_paddingTitleLeft += value; } + } + + public int CachedPortsId + { + get + { + return m_cachedPortsId; + } + } + + public virtual bool RecursivePreviewUpdate( Dictionary duplicatesDict = null ) + { + if( duplicatesDict == null ) + { + duplicatesDict = ContainerGraph.ParentWindow.VisitedChanged; + } + + for( int i = 0; i < InputPorts.Count; i++ ) + { + ParentNode outNode = null; + if( InputPorts[ i ].ExternalReferences.Count > 0 ) + { + outNode = ContainerGraph.GetNode( InputPorts[ i ].ExternalReferences[ 0 ].NodeId ); + } + if( outNode != null ) + { + if( !duplicatesDict.ContainsKey( outNode.OutputId ) ) + { + bool result = outNode.RecursivePreviewUpdate(); + if( result ) + PreviewIsDirty = true; + } else if( duplicatesDict[ outNode.OutputId ] ) + { + PreviewIsDirty = true; + } + } + } + + bool needsUpdate = PreviewIsDirty; + RenderNodePreview(); + if( !duplicatesDict.ContainsKey( OutputId ) ) + duplicatesDict.Add( OutputId, needsUpdate ); + return needsUpdate; + } + + public virtual void RenderNodePreview() + { + //Runs at least one time + if( !HasPreviewShader || !m_initialized ) + { + // nodes with no preview don't update at all + PreviewIsDirty = false; + return; + } + + if( !PreviewIsDirty && !m_continuousPreviewRefresh ) + return; + + //Debug.Log( "PREVIEW " + this ); + + SetPreviewInputs(); + + if( m_cachedMainTexId == -1 ) + m_cachedMainTexId = Shader.PropertyToID( "_MainTex" ); + + if( m_cachedMaskTexId == -1 ) + m_cachedMaskTexId = Shader.PropertyToID( "_MaskTex" ); + + if( m_cachedPortsId == -1 ) + m_cachedPortsId = Shader.PropertyToID( "_Ports" ); + + if( m_cachedPortId == -1 ) + m_cachedPortId = Shader.PropertyToID( "_Port" ); + + int count = m_outputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( i == 0 ) + { + RenderTexture temp = RenderTexture.active; + RenderTexture beforeMask = RenderTexture.GetTemporary( Constants.PreviewSize , Constants.PreviewSize , 0, Constants.PreviewFormat , RenderTextureReadWrite.Linear ); + RenderTexture.active = beforeMask; + Graphics.Blit( null, beforeMask, PreviewMaterial, m_previewMaterialPassId ); + + m_portMask.Set( 0, 0, 0, 0 ); + + switch( m_outputPorts[ i ].DataType ) + { + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + m_portMask.Set( 1, 1, 1, 1 ); + break; + case WirePortDataType.FLOAT2: + m_portMask.Set( 1, 1, 0, 0 ); + break; + case WirePortDataType.FLOAT3: + m_portMask.Set( 1, 1, 1, 0 ); + break; + case WirePortDataType.COLOR: + case WirePortDataType.FLOAT4: + m_portMask.Set( 1, 1, 1, 1 ); + break; + default: + m_portMask.Set( 1, 1, 1, 1 ); + break; + } + + if( m_outputPorts[ i ].DataType == WirePortDataType.FLOAT3x3 || m_outputPorts[ i ].DataType == WirePortDataType.FLOAT4x4 ) + { + m_outputPorts[ i ].MaskingMaterial.SetTexture( m_cachedMainTexId, EditorGUIUtility.whiteTexture ); + } + else + { + m_outputPorts[ i ].MaskingMaterial.SetTexture( m_cachedMainTexId, beforeMask ); + } + m_outputPorts[ i ].MaskingMaterial.SetVector( m_cachedPortsId, m_portMask ); + if( !Preferences.GlobalDisablePreviews ) + { + RenderTexture.active = m_outputPorts[ i ].OutputPreviewTexture; + Graphics.Blit( null , m_outputPorts[ i ].OutputPreviewTexture , m_outputPorts[ i ].MaskingMaterial , 0 ); + + RenderTexture.ReleaseTemporary( beforeMask ); + RenderTexture.active = temp; + } + } + else + { + if( !Preferences.GlobalDisablePreviews ) + { + RenderTexture temp = RenderTexture.active; + m_outputPorts[ i ].MaskingMaterial.SetTexture( m_cachedMaskTexId , PreviewTexture ); + m_outputPorts[ i ].MaskingMaterial.SetFloat( m_cachedPortId , i ); + + RenderTexture.active = m_outputPorts[ i ].OutputPreviewTexture; + Graphics.Blit( null , m_outputPorts[ i ].OutputPreviewTexture , m_outputPorts[ i ].MaskingMaterial , 1 ); + RenderTexture.active = temp; + } + } + } + + PreviewIsDirty = m_continuousPreviewRefresh; + + FinishPreviewRender = true; + } + + protected void ShowTab( NodeMessageType type, string tooltip ) + { + m_showErrorMessage = true; + m_errorMessageTypeIsError = type; + m_errorMessageTooltip = tooltip; + } + + protected void ShowTab() + { + m_showErrorMessage = true; + } + + protected void HideTab() + { + m_showErrorMessage = false; + } + + public virtual RenderTexture PreviewTexture + { + get + { + if( m_outputPorts.Count > 0 ) + return m_outputPorts[ 0 ].OutputPreviewTexture; + else + return null; + } + } + + public void FullWriteToString( ref string nodesInfo, ref string connectionsInfo ) + { + WriteToString( ref nodesInfo, ref connectionsInfo ); + WriteInputDataToString( ref nodesInfo ); + WriteOutputDataToString( ref nodesInfo ); + } + + public void ClipboardFullWriteToString( ref string nodesInfo, ref string connectionsInfo ) + { + FullWriteToString( ref nodesInfo, ref connectionsInfo ); + WriteAdditionalClipboardData( ref nodesInfo ); + } + + public void FullReadFromString( ref string[] parameters ) + { + try + { + ReadFromString( ref parameters ); + ReadInputDataFromString( ref parameters ); + ReadOutputDataFromString( ref parameters ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + + public void ClipboardFullReadFromString( ref string[] parameters ) + { + try + { + FullReadFromString( ref parameters ); + ReadAdditionalClipboardData( ref parameters ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + + public string GenerateClippedTitle( string original , int maxSize = 170, string endString = "..." ) + { + if( UIUtils.UnZoomedNodeTitleStyle == null ) + return original; + + GUIContent content = new GUIContent( original ); + + string finalTitle = string.Empty; + bool addEllipsis = false; + for( int i = 1; i <= original.Length; i++ ) + { + content.text = original.Substring( 0, i ); + Vector2 titleSize = UIUtils.UnZoomedNodeTitleStyle.CalcSize( content ); + if( titleSize.x > maxSize ) + { + addEllipsis = true; + break; + } + else + { + finalTitle = content.text; + } + } + if( addEllipsis ) + finalTitle += endString; + + return finalTitle; + } + + public virtual void RefreshOnUndo() { } + public virtual void CalculateCustomGraphDepth() { } + public int GraphDepth { get { return m_graphDepth; } } + + public PrecisionType CurrentPrecisionType { get { return m_currentPrecisionType == PrecisionType.Inherit ? ContainerGraph.CurrentPrecision : m_currentPrecisionType; } } + + + public Material PreviewMaterial + { + get + { + if( m_previewMaterial == null ) + { + m_previewMaterial = new Material( PreviewShader ); + } + return m_previewMaterial; + } + } + + public Shader PreviewShader + { + get + { + if( m_previewShader == null ) + { + m_previewShader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( m_previewShaderGUID ) ); + } + + if( m_previewShader == null ) + { + m_previewShader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "d9ca47581ac157145bff6f72ac5dd73e" ) ); //ranged float guid + } + + if( m_previewShader == null ) + m_previewShader = Shader.Find( "Unlit/Colored Transparent" ); + + return m_previewShader; + } + } + + public bool HasPreviewShader + { + get { return !string.IsNullOrEmpty( m_previewShaderGUID ); } + } + + public void CheckSpherePreview() + { + bool oneIsSphere = false; + + if( m_drawPreviewAsSphere ) + oneIsSphere = true; + int count = m_inputPorts.Count; + for( int i = 0; i < count; i++ ) + { + ParentNode node = null; + if( m_inputPorts[ i ].ExternalReferences.Count > 0) + { + node = ContainerGraph.GetNode( m_inputPorts[ i ].ExternalReferences[ 0 ].NodeId ); + } + if( node != null && node.SpherePreview ) + oneIsSphere = true; + } + + if( m_forceDrawPreviewAsPlane ) + oneIsSphere = false; + + SpherePreview = oneIsSphere; + } + + public bool SpherePreview + { + get { return m_spherePreview; } + set { m_spherePreview = value; } + } + + public bool ShowPreview + { + get { return m_showPreview; } + set { m_showPreview = value; } + } + + public int VisiblePorts + { + get { return m_visiblePorts; } + set { m_visiblePorts = value; } + } + + public bool Docking + { + get { return m_docking; } + set { m_docking = value; } + } + + public bool UseSquareNodeTitle + { + get { return m_useSquareNodeTitle; } + set { m_useSquareNodeTitle = value; } + } + + public bool InsideShaderFunction + { + get { return ContainerGraph != ContainerGraph.ParentWindow.CurrentGraph; } + } + + public virtual void SetContainerGraph( ParentGraph newgraph ) + { + m_containerGraph = newgraph; + } + public virtual void OnMasterNodeReplaced( MasterNode newMasterNode ) { } + public virtual void RefreshExternalReferences() { } + + public Rect DropdownRect { get { return m_dropdownRect; } } + + public virtual bool Contains( Vector2 pos ) { return m_globalPosition.Contains( pos ); } + public virtual bool Contains( Vector3 pos ) { return m_globalPosition.Contains( pos ); } + public bool IsNodeBeingCopied { get { return m_isNodeBeingCopied; } set { m_isNodeBeingCopied = value; } } + + public virtual WirePortDataType GetInputPortVisualDataTypeByArrayIdx( int portArrayIdx ) + { + return m_inputPorts[ portArrayIdx ].DataType; + } + + public virtual WirePortDataType GetOutputPortVisualDataTypeById( int portId ) + { + return GetOutputPortByUniqueId( portId ).DataType; + } + + + public virtual bool CheckFindText( string text ) + { + return TitleContent.text.IndexOf( text, StringComparison.CurrentCultureIgnoreCase ) >= 0; + } + + public virtual ParentNode ExecuteStubCode(){ return this; } + public virtual float HeightEstimate + { + get + { + float heightEstimate = 0; + heightEstimate = 32 + Constants.INPUT_PORT_DELTA_Y; + for( int i = 0; i < InputPorts.Count; i++ ) + { + if( InputPorts[ i ].Visible ) + heightEstimate += 18 + Constants.INPUT_PORT_DELTA_Y; + } + + return heightEstimate; + // Magic number 18 represents m_fontHeight that might not be set yet + //return Constants.NODE_HEADER_EXTRA_HEIGHT + Mathf.Max( 18 + m_inputPorts.Count, m_outputPorts.Count ) * Constants.INPUT_PORT_DELTA_Y; + } + } + public bool WasDeprecated { get { return m_wasDeprecated; } set { m_wasDeprecated = value; } } + public bool Alive { get { return m_alive;} set { m_alive = value; } } + public string TypeName { get { if( m_nodeAttribs != null ) return m_nodeAttribs.Name;return GetType().ToString(); } } + public bool PreviewIsDirty { set { m_previewIsDirty = value; } get { return m_previewIsDirty; } } + protected bool FinishPreviewRender { get { return m_finishPreviewRender; } set { m_finishPreviewRender = value; } } + public virtual bool IsStubNode { get { return false; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs.meta new file mode 100644 index 0000000..c3a66c8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 33e0374f361d5c642a257b9957e4cfa0 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ReordenatorNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ReordenatorNode.cs new file mode 100644 index 0000000..8bd85dc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ReordenatorNode.cs @@ -0,0 +1,170 @@ +using UnityEngine; +using System; +using System.Collections; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class ReordenatorNode : PropertyNode + { + [SerializeField] + private List m_propertyList; + + [SerializeField] + private string m_headerTitle = string.Empty; + + [SerializeField] + private bool m_isInside; + + public ReordenatorNode() : base() + { + + } + + public void Init( string entryName, string entryInspectorName, List list, bool register = true ) + { + m_propertyName = entryName; + m_propertyInspectorName = entryInspectorName; + + m_propertyList = list; + + if( register ) + UIUtils.RegisterPropertyNode( this ); + } + + public override void Destroy() + { + base.Destroy(); + + m_propertyList.Clear(); + m_propertyList = null; + + UIUtils.UnregisterPropertyNode( this ); + } + + //public List PropertyList + //{ + // get { return m_propertyList; } + //} + + public int PropertyListCount + { + get { if ( m_propertyList != null ) return m_propertyList.Count; else return -1; } + } + + public string HeaderTitle { get { return m_headerTitle; } set { m_headerTitle = value; } } + + public bool HasTitle { get { return !string.IsNullOrEmpty( m_headerTitle ); } } + + public bool IsInside { get { return m_isInside; } set { m_isInside = value; } } + + public int RecursiveSetOrderOffset( int offset, bool lockit, int order = -1 ) + { + //Debug.Log( Locked + " " + PropertyName ); + + if ( Locked ) + return offset; + + if( order > -1 ) + OrderIndex = order; + + int currentOffset = offset; + + if( m_propertyList != null ) + m_propertyList.Sort( ( x, y ) => { return ( x as PropertyNode ).OrderIndex.CompareTo( ( y as PropertyNode ).OrderIndex ); } ); + + OrderIndexOffset = currentOffset - RawOrderIndex; + currentOffset++; + + if ( m_propertyList != null ) + for ( int i = 0; i < m_propertyList.Count; i++ ) + { + ReordenatorNode rnode = m_propertyList[ i ] as ReordenatorNode; + if ( rnode != null ) + { + currentOffset = rnode.RecursiveSetOrderOffset( currentOffset, false ); + } + else + { + PropertyNode pnode = m_propertyList[ i ] as PropertyNode; + { + pnode.OrderIndexOffset = currentOffset - pnode.RawOrderIndex;// + ( HasTitle ? 1 : 0 ); + } + currentOffset++; + } + } + + if ( lockit ) + Locked = true; + + return currentOffset; + } + + public int RecursiveCount() + { + int amount = 0; + if ( HasTitle ) + amount += 1; + for ( int i = 0; i < m_propertyList.Count; i++ ) + { + if ( ( m_propertyList[ i ] is ReordenatorNode ) ) + amount += ( m_propertyList[ i ] as ReordenatorNode ).RecursiveCount(); + else + amount +=1; + } + return amount; + } + + public void RecursiveLog() + { + Debug.LogWarning( OrderIndex+" HEADER "+ PropertyName ); + for( int i = 0; i < m_propertyList.Count; i++ ) + { + if( ( m_propertyList[ i ] is ReordenatorNode ) ) + ( m_propertyList[ i ] as ReordenatorNode ).RecursiveLog(); + else + Debug.Log( ( m_propertyList[ i ] as PropertyNode ).OrderIndex+" "+( m_propertyList[ i ] as PropertyNode).PropertyName ); + } + } + + public bool Locked = false; + + public void RecursiveClear() + { + Locked = false; + if( m_propertyList != null) + for ( int i = 0; i < m_propertyList.Count; i++ ) + { + ReordenatorNode renode = ( m_propertyList[ i ] as ReordenatorNode ); + if ( renode != null ) + { + renode.RecursiveClear(); + } + } + } + + public bool RecursiveConnectedProperties() + { + bool connected = false; + if ( m_propertyList != null ) + { + for ( int i = 0; i < m_propertyList.Count; i++ ) + { + ReordenatorNode renode = ( m_propertyList[ i ] as ReordenatorNode ); + if ( renode != null ) + { + bool temp = renode.RecursiveConnectedProperties(); + if( temp ) + connected = true; + } else + { + if ( ( m_propertyList[ i ] as PropertyNode ).IsConnected ) + connected = true; + } + } + } + return connected; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ReordenatorNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ReordenatorNode.cs.meta new file mode 100644 index 0000000..8dc5037 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/ReordenatorNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 91aad2b9cfaf3954c8c450c32d218981 +timeCreated: 1493053838 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP.meta new file mode 100644 index 0000000..11d8b84 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7283c593c3b4be64e957cb2b91abe1af +folderAsset: yes +timeCreated: 1556618802 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/BakedGINode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/BakedGINode.cs new file mode 100644 index 0000000..7a67f48 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/BakedGINode.cs @@ -0,0 +1,107 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +#if UNITY_2018_3_OR_NEWER +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "SRP Baked GI", "Miscellaneous", "Gets Baked GI info." )] + public sealed class BakedGINode : ParentNode + { + private const string HDBakedGIHeader = "ASEBakedGI( {0}, {1}, {2}, {3} )"; + private readonly string[] HDBakedGIBody = + { + "float3 ASEBakedGI( float3 positionWS, float3 normalWS, float2 uvStaticLightmap, float2 uvDynamicLightmap )\n", + "{\n", + "\tfloat3 positionRWS = GetCameraRelativePositionWS( positionWS );\n", + "\treturn SampleBakedGI( positionRWS, normalWS, uvStaticLightmap, uvDynamicLightmap );\n", + "}\n" + }; + + private readonly string LWBakedGIHeader = "ASEBakedGI( {0}, {1}, {2})"; + private readonly string[] LWBakedGIBody = + { + "float3 ASEBakedGI( float3 normalWS, float2 uvStaticLightmap, bool applyScaling )\n", + "{\n", + "#ifdef LIGHTMAP_ON\n", + "\tif( applyScaling )\n", + "\t\tuvStaticLightmap = uvStaticLightmap * unity_LightmapST.xy + unity_LightmapST.zw;\n", + "\treturn SampleLightmap( uvStaticLightmap, normalWS );\n", + "#else\n", + "\treturn SampleSH(normalWS);\n", + "#endif\n", + "}\n" + }; + + private const string ApplyScalingStr = "Apply Scaling"; + + [SerializeField] + private bool m_applyScaling = true; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "World Position" ); + AddInputPort( WirePortDataType.FLOAT3, false, "World Normal" ); + AddInputPort( WirePortDataType.FLOAT2, false, "Static UV" ); + AddInputPort( WirePortDataType.FLOAT2, false, "Dynamic UV" ); + AddOutputPort( WirePortDataType.FLOAT3, Constants.EmptyPortValue ); + m_textLabelWidth = 95; + m_autoWrapProperties = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_applyScaling = EditorGUILayoutToggle( ApplyScalingStr, m_applyScaling ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( !dataCollector.IsSRP ) + { + UIUtils.ShowMessage( "Node only intended to use on HD and Lightweight rendering pipelines" ); + return GenerateErrorValue(); + } + + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string positionWS = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string normalWS = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string uvStaticLightmap = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + string uvDynamicLightmap = m_inputPorts[ 3 ].GeneratePortInstructions( ref dataCollector ); + string localVarName = "bakedGI" + OutputId; + + if( dataCollector.TemplateDataCollectorInstance.IsHDRP ) + { + dataCollector.AddFunction( HDBakedGIBody[ 0 ], HDBakedGIBody, false ); + RegisterLocalVariable( 0, string.Format( HDBakedGIHeader, positionWS, normalWS, uvStaticLightmap, uvDynamicLightmap ), ref dataCollector, localVarName ); + } + else + { + dataCollector.AddFunction( LWBakedGIBody[ 0 ], LWBakedGIBody, false ); + RegisterLocalVariable( 0, string.Format( LWBakedGIHeader, normalWS, uvStaticLightmap, m_applyScaling?"true":"false" ), ref dataCollector, localVarName ); + } + return localVarName; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_applyScaling = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_applyScaling ); + } + + + } +} +#endif diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/BakedGINode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/BakedGINode.cs.meta new file mode 100644 index 0000000..e988a13 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/BakedGINode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6aacdecbe4e41f44988580058f7e0000 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/HD.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/HD.meta new file mode 100644 index 0000000..fc70ae8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/HD.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8469536c6560ff64aaac451c6f38dbba +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/HD/HDEmissionNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/HD/HDEmissionNode.cs new file mode 100644 index 0000000..eeb13d4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/HD/HDEmissionNode.cs @@ -0,0 +1,175 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +//#if UNITY_2019_1_OR_NEWER +//#if UNITY_2018_3_OR_NEWER +using System; +using UnityEditor; +namespace AmplifyShaderEditor +{ + using UnityEngine; + + [Serializable] + [NodeAttributes( "HD Emission", "Miscellaneous", "Get emission HDR Color. Only available on HDRP." )] + public sealed class HDEmissionNode : ParentNode + { + public enum HDEmissionIntensityUnit + { + Luminance, + EV100 + }; + + public readonly string[] EmissionFunctionWithNormalize = + { + "float3 ASEGetEmissionHDRColorNormalize(float3 ldrColor, float luminanceIntensity, float exposureWeight, float inverseCurrentExposureMultiplier)\n", + "{\n", + "\tldrColor = ldrColor * rcp(max(Luminance(ldrColor), 1e-6));\n", + "\tfloat3 hdrColor = ldrColor * luminanceIntensity;\n", + "\thdrColor = lerp( hdrColor* inverseCurrentExposureMultiplier, hdrColor, exposureWeight);\n", + "\treturn hdrColor;\n", + "}\n", + }; + + public readonly string[] EmissionFunction = + { + "float3 ASEGetEmissionHDRColor(float3 ldrColor, float luminanceIntensity, float exposureWeight, float inverseCurrentExposureMultiplier)\n", + "{\n", + "\tfloat3 hdrColor = ldrColor * luminanceIntensity;\n", + "\thdrColor = lerp( hdrColor* inverseCurrentExposureMultiplier, hdrColor, exposureWeight);\n", + "\treturn hdrColor;\n", + "}\n", + }; + + public const string EmissionHeaderLuminance = "ASEGetEmissionHDRColor{0}({1},{2},{3},GetInverseCurrentExposureMultiplier())"; + public const string EmissionHeaderEV100 = "ASEGetEmissionHDRColor{0}({1},ConvertEvToLuminance({2}),{3},GetInverseCurrentExposureMultiplier())"; + + public const string IntensityUnityLabel = "Intensity Unit"; + + public const string NormalizeColorLabel = "Normalize Color"; + public const string ErrorOnCompilationMsg = "Attempting to use HDRP specific node on incorrect SRP or Builtin RP."; + public const string MinorVersionMsg = "This node require at least Unity 2019.1/HDRP v5 to properly work."; + public const string NodeErrorMsg = "Only valid on HDRP"; + public const string MinorNodeErrorMsg = "Invalid Unity/HDRP version"; + + [SerializeField] + private HDEmissionIntensityUnit m_intensityUnit = HDEmissionIntensityUnit.Luminance; + + [SerializeField] + private bool m_normalizeColor = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "Color" ); + AddInputPort( WirePortDataType.FLOAT, false, "Intensity" ); + AddInputPort( WirePortDataType.FLOAT, false, "Exposition Weight" ); + AddOutputPort( WirePortDataType.FLOAT3, Constants.EmptyPortValue ); +#if UNITY_2019_1_OR_NEWER + m_errorMessageTooltip = NodeErrorMsg; +#else + m_errorMessageTooltip = MinorNodeErrorMsg; + m_showErrorMessage = true; +#endif + m_errorMessageTypeIsError = NodeMessageType.Error; + m_autoWrapProperties = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_intensityUnit = (HDEmissionIntensityUnit)EditorGUILayoutEnumPopup( IntensityUnityLabel, m_intensityUnit ); + m_normalizeColor = EditorGUILayoutToggle( NormalizeColorLabel, m_normalizeColor ); + if( m_showErrorMessage ) + { +#if UNITY_2019_1_OR_NEWER + EditorGUILayout.HelpBox( NodeErrorMsg , MessageType.Error ); +#else + EditorGUILayout.HelpBox( MinorNodeErrorMsg , MessageType.Error ); +#endif + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { +#if UNITY_2019_1_OR_NEWER + + if( !dataCollector.IsSRP || !dataCollector.TemplateDataCollectorInstance.IsHDRP ) + { + UIUtils.ShowMessage( ErrorOnCompilationMsg , MessageSeverity.Error ); + return GenerateErrorValue(); + } + + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string colorValue = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string intensityValue = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string expositionWeightValue = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + string functionPrefix = string.Empty; + if( m_normalizeColor ) + { + functionPrefix = "Normalize"; + dataCollector.AddFunction( EmissionFunctionWithNormalize[ 0 ], EmissionFunctionWithNormalize , false); + } + else + { + dataCollector.AddFunction( EmissionFunction[ 0 ], EmissionFunction, false ); + } + + string varName = "hdEmission" + OutputId; + string varValue = string.Empty; + switch( m_intensityUnit ) + { + default: + case HDEmissionIntensityUnit.Luminance: + varValue = string.Format( EmissionHeaderLuminance, functionPrefix, colorValue, intensityValue, expositionWeightValue ); + break; + case HDEmissionIntensityUnit.EV100: + varValue = string.Format( EmissionHeaderEV100, functionPrefix, colorValue, intensityValue, expositionWeightValue ); + break; + } + + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_outputPorts[ 0 ].DataType, varName, varValue ); + m_outputPorts[ 0 ].SetLocalValue( varName, dataCollector.PortCategory ); + return varName; +#else + UIUtils.ShowMessage( MinorVersionMsg , MessageSeverity.Error ); + return GenerateErrorValue(); +#endif + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); +#if UNITY_2019_1_OR_NEWER + m_showErrorMessage = ( ContainerGraph.CurrentCanvasMode == NodeAvailability.SurfaceShader ) || + ( ContainerGraph.CurrentCanvasMode == NodeAvailability.TemplateShader && ContainerGraph.CurrentSRPType != TemplateSRPType.HD ); +#endif + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); +#if UNITY_2019_1_OR_NEWER + Enum.TryParse( GetCurrentParam( ref nodeParams ), out m_intensityUnit ); +#else + try + { + m_intensityUnit = (HDEmissionIntensityUnit)Enum.Parse( typeof( HDEmissionIntensityUnit ) , GetCurrentParam( ref nodeParams ) ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } +#endif + m_normalizeColor = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_intensityUnit ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalizeColor ); + } + } +} +//#endif diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/HD/HDEmissionNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/HD/HDEmissionNode.cs.meta new file mode 100644 index 0000000..7545d0c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/HD/HDEmissionNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d6b42642ffce2754fba2cf8305e1da68 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/MaterialQualityNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/MaterialQualityNode.cs new file mode 100644 index 0000000..b172193 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/MaterialQualityNode.cs @@ -0,0 +1,85 @@ +// Amplify Shader Editor - Visual Shader vEditing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [NodeAttributes( "Material Quality", "Logical Operators", "Choose between separate branches according to currently selected Quality (SRP only) ", Available = true )] + public class MaterialQualityNode : ParentNode + { + private const string SRPError = "Node intended to be used only on SRP templates as it makes use of keywords defined over that environment."; + + private const string MaxKeyword = "MATERIAL_QUALITY_HIGH"; + private const string MedKeyword = "MATERIAL_QUALITY_MEDIUM"; + private const string MinKeyword = "MATERIAL_QUALITY_LOW"; + private const string MaterialPragmas = "#pragma shader_feature " + MaxKeyword + " " + MedKeyword + " " + MinKeyword; + private readonly string[] MaterialCode = + { + "#if defined("+MaxKeyword+")", + "#elif defined("+MedKeyword+")", + "#else", + "#endif" + }; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "High" ); + AddInputPort( WirePortDataType.FLOAT, false, "Medium" ); + AddInputPort( WirePortDataType.FLOAT, false, "Low" ); + AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_errorMessageTypeIsError = NodeMessageType.Error; + m_errorMessageTooltip = SRPError; + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + if( !ContainerGraph.IsSRP ) + { + if( !m_showErrorMessage ) + { + m_showErrorMessage = true; + } + } + else + { + if( m_showErrorMessage ) + { + m_showErrorMessage = false; + } + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + dataCollector.AddToDirectives( MaterialPragmas ); + string maxQualityValue = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string medQualityValue = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string minQualityValue = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + string localVarName = "currQuality" + OutputId; + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_outputPorts[ 0 ].DataType, localVarName, "0" ); + + //High + dataCollector.AddLocalVariable( UniqueId, MaterialCode[ 0 ], true ); + dataCollector.AddLocalVariable( UniqueId, localVarName, maxQualityValue, false, true ); + + //Medium + dataCollector.AddLocalVariable( UniqueId, MaterialCode[ 1 ], true ); + dataCollector.AddLocalVariable( UniqueId, localVarName, medQualityValue, false, true ); + + //Low + dataCollector.AddLocalVariable( UniqueId, MaterialCode[ 2 ], true ); + dataCollector.AddLocalVariable( UniqueId, localVarName, minQualityValue,false,true ); + m_outputPorts[ 0 ].SetLocalValue( localVarName, dataCollector.PortCategory ); + + dataCollector.AddLocalVariable( UniqueId, MaterialCode[ 3 ], true ); + return localVarName; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/MaterialQualityNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/MaterialQualityNode.cs.meta new file mode 100644 index 0000000..a322f3b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/MaterialQualityNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8245233e0833c884b8a176943d80514b +timeCreated: 1570027418 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/URP.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/URP.meta new file mode 100644 index 0000000..e036885 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/URP.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2d54cc941c4e4d249be04d0d3760659a +folderAsset: yes +timeCreated: 1617727953 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/URP/ReflectionProbeNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/URP/ReflectionProbeNode.cs new file mode 100644 index 0000000..7b69c57 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/URP/ReflectionProbeNode.cs @@ -0,0 +1,66 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +#if UNITY_2018_3_OR_NEWER +using System; +using UnityEngine; +using UnityEditor; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Reflection Probe" , "Miscellaneous" , "Provides access to the nearest Reflection Probe to the object. Only available on URP." )] + public class ReflectionProbeNode : ParentNode + { + private const string ReflectionProbeStr = "SHADERGRAPH_REFLECTION_PROBE({0},{1},{2})"; + private const string InfoTransformSpace = "Both View Dir and Normal vectors are set in Object Space"; + public const string NodeErrorMsg = "Only valid on URP"; + public const string ErrorOnCompilationMsg = "Attempting to use URP specific node on incorrect SRP or Builtin RP."; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3 , false , "View Dir" ); + AddInputPort( WirePortDataType.FLOAT3 , false , "Normal" ); + AddInputPort( WirePortDataType.FLOAT , false , "LOD" ); + AddOutputPort( WirePortDataType.FLOAT3 , "Out" ); + m_autoWrapProperties = true; + m_errorMessageTooltip = NodeErrorMsg; + m_errorMessageTypeIsError = NodeMessageType.Error; + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + m_showErrorMessage = ( ContainerGraph.CurrentCanvasMode == NodeAvailability.SurfaceShader ) || + ( ContainerGraph.CurrentCanvasMode == NodeAvailability.TemplateShader && ContainerGraph.CurrentSRPType != TemplateSRPType.Lightweight ); + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUILayout.HelpBox( InfoTransformSpace , MessageType.Info ); + if( m_showErrorMessage ) + { + EditorGUILayout.HelpBox( NodeErrorMsg , MessageType.Error ); + } + } + + public override string GenerateShaderForOutput( int outputId , ref MasterNodeDataCollector dataCollector , bool ignoreLocalvar ) + { + if( !dataCollector.IsSRP || !dataCollector.TemplateDataCollectorInstance.IsLWRP ) + { + UIUtils.ShowMessage( ErrorOnCompilationMsg , MessageSeverity.Error ); + return GenerateErrorValue(); + } + + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string viewDir = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string normal = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string lod = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + + RegisterLocalVariable( outputId , string.Format( ReflectionProbeStr , viewDir , normal , lod ), ref dataCollector ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + } +} +#endif diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/URP/ReflectionProbeNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/URP/ReflectionProbeNode.cs.meta new file mode 100644 index 0000000..4d22122 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SRP/URP/ReflectionProbeNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 391a18455087a034bb4c09be42caa46a +timeCreated: 1617727965 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SignalGeneratorNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SignalGeneratorNode.cs new file mode 100644 index 0000000..1e8c6d4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SignalGeneratorNode.cs @@ -0,0 +1,41 @@ +using System; + +namespace AmplifyShaderEditor +{ + public class SignalGeneratorNode : ParentNode, ISignalGenerator + { + public SignalGeneratorNode() : base() { } + public SignalGeneratorNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + SelfPowered = true; + } + + public void GenerateSignalPropagation() + { + System.Type myType = GetType(); + for ( int i = 0; i < m_inputPorts.Count; i++ ) + { + if ( m_inputPorts[ i ].IsConnected ) + { + m_inputPorts[ i ].GetOutputNode().ActivateNode( UniqueId, i, myType ); + } + } + } + + public void GenerateSignalInibitor() + { + for ( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + ParentNode node = m_inputPorts[ i ].GetOutputNode(); + if( node != null ) + node.DeactivateNode( i, false ); + } + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SignalGeneratorNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SignalGeneratorNode.cs.meta new file mode 100644 index 0000000..9214603 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SignalGeneratorNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2f92560b009046f4a86504e682834405 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes.meta new file mode 100644 index 0000000..4f6f807 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 899b55cb557ca594f926ad64dfa4ad8f +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleAddOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleAddOpNode.cs new file mode 100644 index 0000000..463528f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleAddOpNode.cs @@ -0,0 +1,58 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Add", "Math Operators", "Addition of two or more values ( A + B + .. )", null, KeyCode.A )] + public sealed class SimpleAddOpNode : DynamicTypeNode + { + private int m_cachedPropertyId = -1; + + protected override void CommonInit( int uniqueId ) + { + m_dynamicRestrictions = new WirePortDataType[] + { + WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4, + WirePortDataType.INT + }; + + base.CommonInit( uniqueId ); + m_extensibleInputPorts = true; + m_previewShaderGUID = "9eb150cbc752cbc458a0a37984b9934a"; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if ( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( "_Count" ); + + PreviewMaterial.SetInt( m_cachedPropertyId, m_inputPorts.Count); + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + string result = "( " + m_extensibleInputResults[ 0 ]; + for ( int i = 1; i < m_extensibleInputResults.Count; i++ ) + { + result += " + " + m_extensibleInputResults[ i ]; + } + result += " )"; + return result; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleAddOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleAddOpNode.cs.meta new file mode 100644 index 0000000..c366095 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleAddOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6ca9162ab6c708f40bbc21f0c22909fa +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleDivideOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleDivideOpNode.cs new file mode 100644 index 0000000..0cafeb3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleDivideOpNode.cs @@ -0,0 +1,45 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Divide", "Math Operators", "Division of two values ( A / B )", null, KeyCode.D )] + public sealed class SimpleDivideOpNode : DynamicTypeNode + { + protected override void CommonInit( int uniqueId ) + { + m_dynamicRestrictions = new WirePortDataType[] + { + WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4, + WirePortDataType.INT + }; + + base.CommonInit( uniqueId ); + m_allowMatrixCheck = true; + m_previewShaderGUID = "409f06d00d1094849b0834c52791fa72"; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + SetExtensibleInputData( outputId, ref dataCollector, ignoreLocalvar ); + string result = "( " + m_extensibleInputResults[ 0 ]; + for ( int i = 1; i < m_extensibleInputResults.Count; i++ ) + { + result += " / " + m_extensibleInputResults[ i ]; + } + result += " )"; + return result; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleDivideOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleDivideOpNode.cs.meta new file mode 100644 index 0000000..98e759a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleDivideOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e80e305761a1e6c4898e401a64b17f84 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMaxOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMaxOpNode.cs new file mode 100644 index 0000000..fdb3c8c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMaxOpNode.cs @@ -0,0 +1,24 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Max", "Math Operators", "Maximum of two scalars or each respective component of two vectors" )] + public sealed class SimpleMaxOpNode : DynamicTypeNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_previewShaderGUID = "79d7f2a11092ac84a95ef6823b34adf2"; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + return "max( " + m_inputA + " , " + m_inputB + " )"; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMaxOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMaxOpNode.cs.meta new file mode 100644 index 0000000..fe8023a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMaxOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4ea5a2904ca58164086eeb8ef3084ed2 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMinOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMinOpNode.cs new file mode 100644 index 0000000..4b24eb3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMinOpNode.cs @@ -0,0 +1,24 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Min", "Math Operators", "Minimum of two scalars or each respective component of two vectors" )] + public sealed class SimpleMinOpNode : DynamicTypeNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_previewShaderGUID = "d6033298044f0f14aa9932ca46e58ce6"; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + return "min( " + m_inputA + " , " + m_inputB + " )"; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMinOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMinOpNode.cs.meta new file mode 100644 index 0000000..a92e3e5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMinOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1b19c8479d7a7a9458a6f556bf6545d5 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMultiplyOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMultiplyOpNode.cs new file mode 100644 index 0000000..4a41a77 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMultiplyOpNode.cs @@ -0,0 +1,175 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Multiply", "Math Operators", "Multiplication of two or more values ( A * B * .. )\nIt also handles Matrices multiplication", null, KeyCode.M )] + public sealed class SimpleMultiplyOpNode : DynamicTypeNode + { + protected override void CommonInit( int uniqueId ) + { + m_dynamicRestrictions = new WirePortDataType[] + { + WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4, + WirePortDataType.INT + }; + + base.CommonInit( uniqueId ); + m_extensibleInputPorts = true; + m_vectorMatrixOps = true; + m_previewShaderGUID = "1ba1e43e86415ff4bbdf4d81dfcf035b"; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + int count = 0; + int inputCount = m_inputPorts.Count; + for( int i = 2; i < inputCount; i++ ) + { + count++; + if( !m_inputPorts[ i ].IsConnected ) + PreviewMaterial.SetTexture( ( "_" + Convert.ToChar( i + 65 ) ), UnityEditor.EditorGUIUtility.whiteTexture ); + } + + m_previewMaterialPassId = count; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT3x3 || + m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT4x4 || + m_inputPorts[ 1 ].DataType == WirePortDataType.FLOAT3x3 || + m_inputPorts[ 1 ].DataType == WirePortDataType.FLOAT4x4 ) + { + m_inputA = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + m_inputB = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + + WirePortDataType autoCast = WirePortDataType.OBJECT; + // Check matrix on first input + if( m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT3x3 ) + { + switch( m_inputPorts[ 1 ].DataType ) + { + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + { + m_inputB = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), m_inputB, m_inputPorts[ 1 ].DataType, WirePortDataType.FLOAT3, m_inputB ); + autoCast = WirePortDataType.FLOAT3; + } + break; + case WirePortDataType.FLOAT4x4: + { + m_inputA = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), m_inputA, m_inputPorts[ 0 ].DataType, WirePortDataType.FLOAT4x4, m_inputA ); + } + break; + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT3x3: break; + } + } + + if( m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT4x4 ) + { + switch( m_inputPorts[ 1 ].DataType ) + { + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + { + m_inputB = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), m_inputB, m_inputPorts[ 1 ].DataType, WirePortDataType.FLOAT4, m_inputB ); + autoCast = WirePortDataType.FLOAT4; + } + break; + case WirePortDataType.FLOAT3x3: + { + m_inputB = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), m_inputB, m_inputPorts[ 1 ].DataType, WirePortDataType.FLOAT4x4, m_inputB ); + } + break; + case WirePortDataType.FLOAT4x4: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: break; + } + } + + // Check matrix on second input + if( m_inputPorts[ 1 ].DataType == WirePortDataType.FLOAT3x3 ) + { + switch( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + { + m_inputA = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), m_inputA, m_inputPorts[ 0 ].DataType, WirePortDataType.FLOAT3, m_inputA ); + autoCast = WirePortDataType.FLOAT3; + } + break; + case WirePortDataType.FLOAT4x4: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT3x3: break; + } + } + + if( m_inputPorts[ 1 ].DataType == WirePortDataType.FLOAT4x4 ) + { + switch( m_inputPorts[ 0 ].DataType ) + { + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + { + m_inputA = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), m_inputA, m_inputPorts[ 0 ].DataType, WirePortDataType.FLOAT4, m_inputA ); + autoCast = WirePortDataType.FLOAT4; + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: break; + } + } + string result = "mul( " + m_inputA + ", " + m_inputB + " )"; + if( autoCast != WirePortDataType.OBJECT && autoCast != m_outputPorts[ 0 ].DataType ) + { + result = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( UniqueId, outputId ), result, autoCast, m_outputPorts[ 0 ].DataType, result ); + } + return result; + } + else + { + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + string result = "( " + m_extensibleInputResults[ 0 ]; + for( int i = 1; i < m_extensibleInputResults.Count; i++ ) + { + result += " * " + m_extensibleInputResults[ i ]; + } + result += " )"; + return result; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMultiplyOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMultiplyOpNode.cs.meta new file mode 100644 index 0000000..0283ca7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleMultiplyOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 647081578ac7f014d98090d36b5b1bc8 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleRemainderNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleRemainderNode.cs new file mode 100644 index 0000000..af20ce2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleRemainderNode.cs @@ -0,0 +1,66 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Remainder", "Math Operators", "Remainder between two int variables",tags:"modulo fmod" )] + public sealed class SimpleRemainderNode : DynamicTypeNode + { + private const string VertexFragRemainder = "( {0} % {1} )"; + //private const string SurfaceRemainder = "fmod( {0} , {1} )"; + private const string RemainderCalculationInt = "( {0} - {1} * ({0}/{1}))"; + private const string RemainderCalculationFloat = "( {0} - {1} * floor({0}/{1}))"; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_useInternalPortData = true; + m_textLabelWidth = 35; + ChangeInputType( WirePortDataType.INT, false ); + ChangeOutputType( WirePortDataType.INT, false ); + m_useInternalPortData = true; + m_previewShaderGUID = "8fdfc429d6b191c4985c9531364c1a95"; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); +#if UNITY_2018_1_OR_NEWER + string opMode = VertexFragRemainder; +#else + string opMode = dataCollector.IsTemplate ? + VertexFragRemainder : + ( ( m_outputPorts[ 0 ].DataType == WirePortDataType.INT ) ? RemainderCalculationInt: RemainderCalculationFloat ); +#endif + string result = string.Empty; + switch( m_outputPorts[ 0 ].DataType ) + { + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.INT: + case WirePortDataType.COLOR: + case WirePortDataType.OBJECT: + { + result = string.Format( opMode, m_inputA, m_inputB ); + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + result = UIUtils.InvalidParameter( this ); + } + break; + } + + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleRemainderNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleRemainderNode.cs.meta new file mode 100644 index 0000000..528ea33 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleRemainderNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5785c326a26d2ba4ab642fc2bdd41e9a +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleSubtractOpNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleSubtractOpNode.cs new file mode 100644 index 0000000..eaabab2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleSubtractOpNode.cs @@ -0,0 +1,39 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Subtract", "Math Operators", "Subtraction of two values ( A - B )", null, UnityEngine.KeyCode.S )] + public sealed class SimpleSubtractOpNode : DynamicTypeNode + { + protected override void CommonInit( int uniqueId ) + { + m_dynamicRestrictions = new WirePortDataType[] + { + WirePortDataType.OBJECT, + WirePortDataType.FLOAT, + WirePortDataType.FLOAT2, + WirePortDataType.FLOAT3, + WirePortDataType.FLOAT4, + WirePortDataType.COLOR, + WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4, + WirePortDataType.INT + }; + + base.CommonInit( uniqueId ); + m_allowMatrixCheck = true; + m_previewShaderGUID = "5725e8300be208449973f771ab6682f2"; + } + + public override string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.BuildResults( outputId, ref dataCollector, ignoreLocalvar ); + return "( " + m_inputA + " - " + m_inputB + " )"; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleSubtractOpNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleSubtractOpNode.cs.meta new file mode 100644 index 0000000..a550f19 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SimpleNodes/SimpleSubtractOpNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 204f935dafd0a984297e242583de1da5 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/StickyNoteNode .cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/StickyNoteNode .cs new file mode 100644 index 0000000..f9a91e6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/StickyNoteNode .cs @@ -0,0 +1,502 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Sticky Note", "Miscellaneous", "Allows adding notes into canvas" )] + public sealed class StickyNoteNode : ParentNode, ISerializationCallbackReceiver + { + private const string WarningText = "Characters $ and @ are NOT allowed inside notes since they are internally used as delimiters over the node meta.\nThey will be automatically removed when saving the shader."; + + private const string CommentaryTitle = "Comment"; + private const string NoteTitle = "Note Title"; + private const float BORDER_SIZE_X = 50; + private const float BORDER_SIZE_Y = 50; + private const float MIN_SIZE_X = 100; + private const float MIN_SIZE_Y = 100; + private const float COMMENTARY_BOX_HEIGHT = 30; + private const float NOTE_AREA_ADJUST = 5; + + private readonly Vector2 ResizeButtonPos = new Vector2( 1, 1 ); + + [SerializeField] + private string m_innerTitleText = "New Note"; + + [SerializeField] + private string m_titleText = string.Empty; + + [SerializeField] + private string m_noteText = string.Empty; + + [SerializeField] + private eResizeAxis m_resizeAxis = eResizeAxis.ALL; + + + [SerializeField] + private Rect m_resizeLeftIconCoords; + + [SerializeField] + private Rect m_resizeRightIconCoords; + + [SerializeField] + private Rect m_auxHeaderPos; + + [SerializeField] + private Rect m_innerTitleArea; + + [SerializeField] + private Rect m_noteTextArea; + + + private Texture2D m_resizeIconTex; + + private bool m_isResizingRight = false; + private bool m_isResizingLeft = false; + + private Vector2 m_resizeStartPoint = Vector2.zero; + + private string m_focusTitleName = "StickyNoteTitleText"; + private string m_focusNoteName = "StickyNoteInnerText"; + private bool m_focusOnTitle = false; + + private bool m_checkCommentText = true; + private bool m_checkTitleText = true; + + public Color m_frameColor = Color.white; + + + private bool m_isEditingInnerTitle; + private bool m_stopEditingInnerTitle; + private bool m_startEditingInnerTitle; + + private bool m_isEditingNoteText; + private bool m_stopEditingNoteText; + private bool m_startEditingNoteText; + + private double m_clickTimeTitle; + private double m_doubleClickTimeTitle = 0.3; + + private double m_clickTimeNote; + private double m_doubleClickTimeNote = 0.3; + + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_reorderLocked = true; + m_rmbIgnore = true; + m_defaultInteractionMode = InteractionMode.Both; + m_connStatus = NodeConnectionStatus.Island; + m_textLabelWidth = 90; + m_position.width = 150; + m_position.height = 100; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_focusTitleName = CommentaryTitle + OutputId; + m_focusNoteName = NoteTitle + OutputId; + } + + public override void DrawProperties() + { + base.DrawProperties(); + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr,()=> + { + EditorGUI.BeginChangeCheck(); + m_titleText = EditorGUILayoutTextField( "Frame Title", m_titleText ); + if ( EditorGUI.EndChangeCheck() ) + { + m_checkTitleText = true; + } + EditorGUI.BeginChangeCheck(); + m_innerTitleText = EditorGUILayoutTextField( NoteTitle, m_innerTitleText ); + if ( EditorGUI.EndChangeCheck() ) + { + m_checkCommentText = true; + } + + m_noteText = EditorGUILayoutTextArea( m_noteText , UIUtils.MainSkin.textArea ); + + m_frameColor = EditorGUILayoutColorField( "Frame Color", m_frameColor ); + } ); + EditorGUILayout.HelpBox( WarningText, MessageType.Warning ); + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + //base.OnLayout( drawInfo ); + CalculatePositionAndVisibility( drawInfo ); + + m_headerPosition = m_globalPosition; + m_headerPosition.height = UIUtils.CurrentHeaderHeight; + + m_auxHeaderPos = m_position; + m_auxHeaderPos.height = UIUtils.HeaderMaxHeight; + + m_innerTitleArea = m_globalPosition; + m_innerTitleArea.height = COMMENTARY_BOX_HEIGHT * drawInfo.InvertedZoom; + m_innerTitleArea.xMin += 10 * drawInfo.InvertedZoom; + m_innerTitleArea.xMax -= 10 * drawInfo.InvertedZoom; + + + m_noteTextArea = m_globalPosition; + m_noteTextArea.height -= m_innerTitleArea.height; + m_noteTextArea.yMin += m_innerTitleArea.height + NOTE_AREA_ADJUST * drawInfo.InvertedZoom; + m_noteTextArea.yMax += 4*NOTE_AREA_ADJUST * drawInfo.InvertedZoom; + m_noteTextArea.xMin += 10 * drawInfo.InvertedZoom; + m_noteTextArea.xMax -= 10 * drawInfo.InvertedZoom; + + if ( m_resizeIconTex == null ) + { + m_resizeIconTex = UIUtils.GetCustomStyle( CustomStyle.CommentaryResizeButton ).normal.background; + } + + // LEFT RESIZE BUTTON + m_resizeLeftIconCoords = m_globalPosition; + m_resizeLeftIconCoords.x = m_globalPosition.x + 2; + m_resizeLeftIconCoords.y = m_globalPosition.y + m_globalPosition.height - 2 - ( m_resizeIconTex.height + ResizeButtonPos.y ) * drawInfo.InvertedZoom; + m_resizeLeftIconCoords.width = m_resizeIconTex.width * drawInfo.InvertedZoom; + m_resizeLeftIconCoords.height = m_resizeIconTex.height * drawInfo.InvertedZoom; + + // RIGHT RESIZE BUTTON + m_resizeRightIconCoords = m_globalPosition; + m_resizeRightIconCoords.x = m_globalPosition.x + m_globalPosition.width - 1 - ( m_resizeIconTex.width + ResizeButtonPos.x ) * drawInfo.InvertedZoom; + m_resizeRightIconCoords.y = m_globalPosition.y + m_globalPosition.height - 2 - ( m_resizeIconTex.height + ResizeButtonPos.y ) * drawInfo.InvertedZoom; + m_resizeRightIconCoords.width = m_resizeIconTex.width * drawInfo.InvertedZoom; + m_resizeRightIconCoords.height = m_resizeIconTex.height * drawInfo.InvertedZoom; + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + if ( !m_isVisible ) + return; + + m_colorBuffer = GUI.color; + // Background + GUI.color = Constants.NodeBodyColor * m_frameColor; + GUI.Label( m_globalPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.CommentaryBackground ) ); + + // Header + GUI.color = m_headerColor * m_headerColorModifier * m_frameColor; + GUI.Label( m_headerPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeHeader ) ); + GUI.color = m_colorBuffer; + + // Fixed Title ( only renders when not editing ) + if ( !m_isEditingInnerTitle && !m_startEditingInnerTitle && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + GUI.Label( m_innerTitleArea, m_innerTitleText, UIUtils.CommentaryTitle ); + } + + + // Note Text ( only renders when not editing ) + if( !m_isEditingNoteText && !m_startEditingNoteText && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + GUI.Label( m_noteTextArea, m_noteText, UIUtils.StickyNoteText ); + } + + // Buttons + GUI.Label( m_resizeLeftIconCoords, string.Empty, UIUtils.GetCustomStyle( CustomStyle.CommentaryResizeButtonInv ) ); + GUI.Label( m_resizeRightIconCoords, string.Empty, UIUtils.GetCustomStyle( CustomStyle.CommentaryResizeButton ) ); + + // Selection Box + if ( m_selected ) + { + GUI.color = Constants.NodeSelectedColor; + RectOffset cache = UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ).border; + UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ).border = UIUtils.RectOffsetSix; + GUI.Label( m_globalPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ) ); + UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ).border = cache; + GUI.color = m_colorBuffer; + } + + if ( !string.IsNullOrEmpty( m_titleText ) ) + { + Rect titleRect = m_globalPosition; + titleRect.y -= 24; + titleRect.height = 24; + GUI.Label( titleRect, m_titleText, UIUtils.GetCustomStyle( CustomStyle.CommentarySuperTitle ) ); + } + } + + public override void Move( Vector2 delta, bool snap ) + { + if( m_isResizingRight || m_isResizingLeft ) + return; + + base.Move( delta, snap ); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + // Custom Editable Title + if ( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + if( !m_startEditingNoteText && !m_isEditingNoteText ) + { + if( !m_isEditingInnerTitle && ( ( !ContainerGraph.ParentWindow.MouseInteracted && drawInfo.CurrentEventType == EventType.MouseDown && m_innerTitleArea.Contains( drawInfo.MousePosition ) ) ) ) + { + if( ( EditorApplication.timeSinceStartup - m_clickTimeTitle ) < m_doubleClickTimeTitle ) + m_startEditingInnerTitle = true; + else + GUI.FocusControl( null ); + m_clickTimeTitle = EditorApplication.timeSinceStartup; + } + else if( m_isEditingInnerTitle && ( ( drawInfo.CurrentEventType == EventType.MouseDown && !m_innerTitleArea.Contains( drawInfo.MousePosition ) ) || !EditorGUIUtility.editingTextField ) ) + { + m_stopEditingInnerTitle = true; + } + + if( m_isEditingInnerTitle || m_startEditingInnerTitle ) + { + EditorGUI.BeginChangeCheck(); + GUI.SetNextControlName( m_focusTitleName ); + m_innerTitleText = EditorGUITextField( m_innerTitleArea, string.Empty, m_innerTitleText, UIUtils.CommentaryTitle ); + if( EditorGUI.EndChangeCheck() ) + { + m_checkCommentText = true; + } + + if( m_startEditingInnerTitle ) + EditorGUI.FocusTextInControl( m_focusTitleName ); + } + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + if( m_startEditingInnerTitle ) + { + m_startEditingInnerTitle = false; + m_isEditingInnerTitle = true; + } + + if( m_stopEditingInnerTitle ) + { + m_stopEditingInnerTitle = false; + m_isEditingInnerTitle = false; + GUI.FocusControl( null ); + } + } + } + + //////////////////////// + if( !m_startEditingInnerTitle && !m_isEditingInnerTitle ) + { + if( !m_isEditingNoteText && ( ( !ContainerGraph.ParentWindow.MouseInteracted && drawInfo.CurrentEventType == EventType.MouseDown && m_noteTextArea.Contains( drawInfo.MousePosition ) ) ) ) + { + if( ( EditorApplication.timeSinceStartup - m_clickTimeNote ) < m_doubleClickTimeNote ) + m_startEditingNoteText = true; + else + GUI.FocusControl( null ); + m_clickTimeNote = EditorApplication.timeSinceStartup; + } + else if( m_isEditingNoteText && ( ( drawInfo.CurrentEventType == EventType.MouseDown && !m_noteTextArea.Contains( drawInfo.MousePosition ) ) || !EditorGUIUtility.editingTextField ) ) + { + m_stopEditingInnerTitle = true; + } + + if( m_isEditingNoteText || m_startEditingNoteText ) + { + GUI.SetNextControlName( m_focusNoteName ); + m_noteText = EditorGUITextArea( m_noteTextArea, m_noteText, UIUtils.StickyNoteText ); + if( m_startEditingNoteText ) + EditorGUI.FocusTextInControl( m_focusNoteName ); + } + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + if( m_startEditingNoteText ) + { + m_startEditingNoteText = false; + m_isEditingNoteText = true; + } + + if( m_stopEditingInnerTitle ) + { + m_stopEditingInnerTitle = false; + m_isEditingNoteText = false; + GUI.FocusControl( null ); + } + } + } + //////////////////////// + } + + if ( drawInfo.CurrentEventType == EventType.MouseDown && drawInfo.LeftMouseButtonPressed ) + { + // Left Button + if( m_resizeLeftIconCoords.Contains( drawInfo.MousePosition ) && ContainerGraph.ParentWindow.CurrentEvent.modifiers != EventModifiers.Shift ) + { + if ( !m_isResizingLeft ) + { + m_isResizingLeft = true; + ContainerGraph.ParentWindow.ForceAutoPanDir = true; + m_resizeStartPoint = drawInfo.TransformedMousePos; + } + } + + // Right Button + if ( m_resizeRightIconCoords.Contains( drawInfo.MousePosition ) && ContainerGraph.ParentWindow.CurrentEvent.modifiers != EventModifiers.Shift ) + { + if ( !m_isResizingRight ) + { + m_isResizingRight = true; + ContainerGraph.ParentWindow.ForceAutoPanDir = true; + m_resizeStartPoint = drawInfo.TransformedMousePos; + } + } + } + + if ( drawInfo.CurrentEventType == EventType.Repaint || drawInfo.CurrentEventType == EventType.MouseUp ) + { + // Left Button + EditorGUIUtility.AddCursorRect( m_resizeLeftIconCoords, MouseCursor.ResizeUpRight ); + if ( m_isResizingLeft ) + { + if ( drawInfo.CurrentEventType == EventType.MouseUp ) + { + m_isResizingLeft = false; + ContainerGraph.ParentWindow.ForceAutoPanDir = false; + FireStoppedMovingEvent( false, InteractionMode.Target ); + } + else + { + Vector2 currSize = ( drawInfo.TransformedMousePos - m_resizeStartPoint ) /*/ drawInfo.InvertedZoom*/; + m_resizeStartPoint = drawInfo.TransformedMousePos; + if ( m_resizeAxis != eResizeAxis.Y_AXIS ) + { + m_position.x += currSize.x; + m_position.width -= currSize.x; + if ( m_position.width < MIN_SIZE_X ) + { + m_position.x -= ( MIN_SIZE_X - m_position.width ); + m_position.width = MIN_SIZE_X; + } + } + + if ( m_resizeAxis != eResizeAxis.X_AXIS ) + { + m_position.height += currSize.y; + if ( m_position.height < MIN_SIZE_Y ) + { + m_position.height = MIN_SIZE_Y; + } + } + } + } + + // Right Button + EditorGUIUtility.AddCursorRect( m_resizeRightIconCoords, MouseCursor.ResizeUpLeft ); + if ( m_isResizingRight ) + { + if ( drawInfo.CurrentEventType == EventType.MouseUp ) + { + m_isResizingRight = false; + ContainerGraph.ParentWindow.ForceAutoPanDir = false; + FireStoppedMovingEvent( false, InteractionMode.Target ); + } + else + { + Vector2 currSize = ( drawInfo.TransformedMousePos - m_resizeStartPoint ) /*/ drawInfo.InvertedZoom*/; + m_resizeStartPoint = drawInfo.TransformedMousePos; + if ( m_resizeAxis != eResizeAxis.Y_AXIS ) + { + m_position.width += currSize.x; + if ( m_position.width < MIN_SIZE_X ) + { + m_position.width = MIN_SIZE_X; + } + } + + if ( m_resizeAxis != eResizeAxis.X_AXIS ) + { + m_position.height += currSize.y; + if ( m_position.height < MIN_SIZE_Y ) + { + m_position.height = MIN_SIZE_Y; + } + } + } + } + } + + if ( m_checkCommentText ) + { + m_checkCommentText = false; + m_innerTitleText = m_innerTitleText.Replace( IOUtils.FIELD_SEPARATOR, ' ' ); + } + + if ( m_checkTitleText ) + { + m_checkTitleText = false; + m_titleText = m_titleText.Replace( IOUtils.FIELD_SEPARATOR, ' ' ); + } + + if ( m_focusOnTitle && drawInfo.CurrentEventType == EventType.KeyUp ) + { + m_focusOnTitle = false; + m_startEditingInnerTitle = true; + } + } + + public void Focus() + { + m_focusOnTitle = true; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_position.width = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + m_position.height = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + m_innerTitleText = GetCurrentParam( ref nodeParams ); + m_titleText = GetCurrentParam( ref nodeParams ); + string[] colorChannels = GetCurrentParam( ref nodeParams ).Split( IOUtils.VECTOR_SEPARATOR ); + if ( colorChannels.Length == 4 ) + { + m_frameColor.r = Convert.ToSingle( colorChannels[ 0 ] ); + m_frameColor.g = Convert.ToSingle( colorChannels[ 1 ] ); + m_frameColor.b = Convert.ToSingle( colorChannels[ 2 ] ); + m_frameColor.a = Convert.ToSingle( colorChannels[ 3 ] ); + } + else + { + UIUtils.ShowMessage( UniqueId, "Incorrect number of color values", MessageSeverity.Error ); + } + m_noteText = GetCurrentParam( ref nodeParams ); + m_noteText = m_noteText.Replace( Constants.LineFeedSeparator, '\n' ); + m_noteText = m_noteText.Replace( Constants.SemiColonSeparator, ';' ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_position.width ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_position.height ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_innerTitleText ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_titleText ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_frameColor.r.ToString() + IOUtils.VECTOR_SEPARATOR + m_frameColor.g.ToString() + IOUtils.VECTOR_SEPARATOR + m_frameColor.b.ToString() + IOUtils.VECTOR_SEPARATOR + m_frameColor.a.ToString() ); + + m_noteText = m_noteText.Replace( Constants.LineFeedSeparator.ToString(), string.Empty); + m_noteText = m_noteText.Replace( Constants.SemiColonSeparator.ToString(), string.Empty ); + m_noteText = UIUtils.ForceLFLineEnding( m_noteText ); + + string parsedText = m_noteText.Replace( '\n', Constants.LineFeedSeparator ); + parsedText = parsedText.Replace( ';', Constants.SemiColonSeparator ); + IOUtils.AddFieldValueToString( ref nodeInfo, parsedText ); + } + + public override Rect Position { get { return Event.current.alt ? m_position : m_auxHeaderPos; } } + public override bool Contains( Vector3 pos ) + { + return Event.current.alt ? m_globalPosition.Contains( pos ) : ( m_headerPosition.Contains( pos ) || m_resizeRightIconCoords.Contains( pos ) || m_resizeLeftIconCoords.Contains( pos ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/StickyNoteNode .cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/StickyNoteNode .cs.meta new file mode 100644 index 0000000..085bd13 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/StickyNoteNode .cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6d517b63dc9604043985eb4a82d2d135 +timeCreated: 1607962893 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs.meta new file mode 100644 index 0000000..4487ca3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ddb697d654917eb4aada5b2caeef2db8 +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ColorInputsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ColorInputsNode.cs new file mode 100644 index 0000000..e4223e1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ColorInputsNode.cs @@ -0,0 +1,17 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Color", "Surface Data", "Interpolated per-vertex color", null, UnityEngine.KeyCode.None, true, true, "Vertex Color", typeof( VertexColorNode ) )] + public sealed class ColorInputsNode : SurfaceShaderINParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentInput = SurfaceInputs.COLOR; + InitialSetup(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ColorInputsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ColorInputsNode.cs.meta new file mode 100644 index 0000000..8f36faf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ColorInputsNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ee44f086d7aa7804ea035860c5735cfb +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/GrabScreenPosition.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/GrabScreenPosition.cs new file mode 100644 index 0000000..3e2a511 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/GrabScreenPosition.cs @@ -0,0 +1,118 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Grab Screen Position", "Camera And Screen", "Screen position correctly transformed to be used with Grab Screen Color" )] + public sealed class GrabScreenPosition : ParentNode + { + private readonly string[] m_outputTypeStr = { "Normalized", "Screen" }; + + [SerializeField] + private int m_outputTypeInt = 0; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputVectorPorts( WirePortDataType.FLOAT4, "XYZW" ); + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + m_textLabelWidth = 65; + ConfigureHeader(); + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_outputTypeInt = m_upperLeftWidget.DrawWidget( this, m_outputTypeInt, m_outputTypeStr ); + if( EditorGUI.EndChangeCheck() ) + { + ConfigureHeader(); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + + EditorGUI.BeginChangeCheck(); + m_outputTypeInt = EditorGUILayoutPopup( "Type", m_outputTypeInt, m_outputTypeStr ); + if( EditorGUI.EndChangeCheck() ) + { + ConfigureHeader(); + } + } + + void ConfigureHeader() + { + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_outputTypeStr[ m_outputTypeInt ] ) ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputColorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + string localVarName = string.Empty; + + if( m_outputTypeInt == 0 ) + localVarName = GeneratorUtils.GenerateGrabScreenPositionNormalized( ref dataCollector, UniqueId, CurrentPrecisionType, !dataCollector.UsingCustomScreenPos ); + else + localVarName = GeneratorUtils.GenerateGrabScreenPosition( ref dataCollector, UniqueId, CurrentPrecisionType, !dataCollector.UsingCustomScreenPos ); + + m_outputPorts[ 0 ].SetLocalValue( localVarName, dataCollector.PortCategory ); + return GetOutputColorItem( 0, outputId, localVarName ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 3108 ) + { + if( UIUtils.CurrentShaderVersion() < 6102 ) + { + bool project = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_outputTypeInt = project ? 0 : 1; + } + else + { + m_outputTypeInt = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } + + ConfigureHeader(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_outputTypeInt ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/GrabScreenPosition.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/GrabScreenPosition.cs.meta new file mode 100644 index 0000000..5a57543 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/GrabScreenPosition.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 47af62ad6a29d1b409d526d352b5e677 +timeCreated: 1485198163 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/LocalVertexPosNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/LocalVertexPosNode.cs new file mode 100644 index 0000000..785e39f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/LocalVertexPosNode.cs @@ -0,0 +1,50 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "[Deprecated] Local Position", "Surface Data", "Interpolated Vertex Position in Local Space", null, KeyCode.None, true, true, "Vertex Position", typeof( PosVertexDataNode ) )] + public sealed class LocalVertexPosNode : ParentNode + { + private const string VertexVarName = "localVertexPos"; + private readonly string VertexOnFrag = Constants.InputVarStr + "." + VertexVarName; + private readonly string VertexOnVert = Constants.VertexShaderInputStr + ".vertex"; + + + [SerializeField] + private bool m_addInstruction = false; + + public override void Reset() + { + base.Reset(); + m_addInstruction = true; + } + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputVectorPorts( WirePortDataType.FLOAT3, "XYZ" ); + } + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + return GetOutputVectorItem( 0, outputId, VertexOnVert ); + } + else + { + if ( m_addInstruction ) + { + dataCollector.AddToInput( UniqueId, VertexVarName, WirePortDataType.FLOAT3 ); + dataCollector.AddVertexInstruction( Constants.VertexShaderOutputStr + "." + VertexVarName + " = " + Constants.VertexShaderInputStr + ".vertex.xyz ", UniqueId ); + m_addInstruction = false; + } + + return GetOutputVectorItem( 0, outputId, VertexOnFrag ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/LocalVertexPosNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/LocalVertexPosNode.cs.meta new file mode 100644 index 0000000..91b6b54 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/LocalVertexPosNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2528fbf85b5823a4499871c2a6eecc0a +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenColorNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenColorNode.cs new file mode 100644 index 0000000..9d977e1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenColorNode.cs @@ -0,0 +1,716 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + + [Serializable] + [NodeAttributes( "Grab Screen Color", "Camera And Screen", "Grabed pixel color value from screen" )] + public sealed class ScreenColorNode : PropertyNode + { +#if UNITY_5_6_OR_NEWER + private readonly string[] ASEDeclareMacro = + { + "#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)", + "#define ASE_DECLARE_SCREENSPACE_TEXTURE(tex) UNITY_DECLARE_SCREENSPACE_TEXTURE(tex);", + "#else", + "#define ASE_DECLARE_SCREENSPACE_TEXTURE(tex) UNITY_DECLARE_SCREENSPACE_TEXTURE(tex)", + "#endif" + }; +#endif + private readonly Color ReferenceHeaderColor = new Color( 0.6f, 3.0f, 1.25f, 1.0f ); + + private const string SamplerType = "tex2D"; + private const string GrabTextureDefault = "_GrabTexture"; + private const string ScreenColorStr = "screenColor"; + + [SerializeField] + private TexReferenceType m_referenceType = TexReferenceType.Object; + + [SerializeField] + private int m_referenceArrayId = -1; + + [SerializeField] + private int m_referenceNodeId = -1; + + [SerializeField] + private GUIStyle m_referenceIconStyle = null; + + private ScreenColorNode m_referenceNode = null; + + [SerializeField] + private bool m_normalize = false; + + [SerializeField] + private bool m_useCustomGrab = false; + + [SerializeField] + private float m_referenceWidth = -1; + + [SerializeField] + private bool m_exposure = false; + + //SRP specific code + private const string OpaqueTextureDefine = "REQUIRE_OPAQUE_TEXTURE 1"; + private const string FetchVarName = "fetchOpaqueVal"; + + //private string LWFetchOpaqueTexture = "SAMPLE_TEXTURE2D( _CameraOpaqueTexture, sampler_CameraOpaqueTexture, {0})"; + private string LWFetchOpaqueTexture = "float4( SHADERGRAPH_SAMPLE_SCENE_COLOR( {0} ), 1.0 )"; +#if UNITY_2018_3_OR_NEWER + private const string HDSampleSceneColorHeader5 = "ASEHDSampleSceneColor({0}, {1}, {2})"; + private readonly string[] HDSampleSceneColorFunc5 = + { + "float4 ASEHDSampleSceneColor(float2 uv, float lod, float exposureMultiplier)\n", + "{\n", + "\t#if defined(REQUIRE_OPAQUE_TEXTURE) && defined(_SURFACE_TYPE_TRANSPARENT) && defined(SHADERPASS) && (SHADERPASS != SHADERPASS_LIGHT_TRANSPORT)\n", + "\treturn float4( SampleCameraColor(uv, lod) * exposureMultiplier, 1.0 );\n", + "\t#endif\n", + "\treturn float4(0.0, 0.0, 0.0, 1.0);\n", + "}\n", + }; + + private const string HDSampleSceneColorHeader4 = "ASEHDSampleSceneColor({0})"; + private readonly string[] HDSampleSceneColorFunc4 = + { + "float4 ASEHDSampleSceneColor( float2 uv )\n", + "{\n", + "\t#if defined(REQUIRE_OPAQUE_TEXTURE) && defined(_SURFACE_TYPE_TRANSPARENT) && defined(SHADERPASS) && (SHADERPASS != SHADERPASS_LIGHT_TRANSPORT)\n", + "\treturn float4( SampleCameraColor(uv), 1.0 );\n", + "\t#endif\n", + "\treturn float4(0.0, 0.0, 0.0, 1.0);\n", + "}\n", + }; +#endif + +#if !UNITY_2018_3_OR_NEWER + // Legacy SRP code + private const string DeclareOpaqueTextureObject = "TEXTURE2D( _CameraOpaqueTexture);"; + private const string DeclareOpaqueTextureSampler = "SAMPLER( sampler_CameraOpaqueTexture);"; +#endif + public ScreenColorNode() : base() { } + public ScreenColorNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + + AddInputPort( WirePortDataType.FLOAT2, false, "UV" ); + AddInputPort( WirePortDataType.FLOAT, false, "LOD" ); + m_inputPorts[ 1 ].FloatInternalData = 0; + + AddOutputColorPorts( "RGBA" ); + + m_currentParameterType = PropertyType.Global; + m_underscoredGlobal = true; + m_useVarSubtitle = true; + m_customPrefix = "Grab Screen "; + m_freeType = false; + m_drawAttributes = false; + m_showTitleWhenNotEditing = false; + m_textLabelWidth = 125; + m_showAutoRegisterUI = true; + m_globalDefaultBehavior = false; + m_showVariableMode = true; + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + if( m_referenceType == TexReferenceType.Object ) + UIUtils.RegisterScreenColorNode( this ); + + if( UniqueId > -1 ) + ContainerGraph.ScreenColorNodes.OnReorderEventComplete += OnReorderEventComplete; + + } + + private void OnReorderEventComplete() + { + if( m_referenceType == TexReferenceType.Instance && m_referenceNode != null ) + { + m_referenceArrayId = ContainerGraph.ScreenColorNodes.GetNodeRegisterIdx( m_referenceNode.UniqueId ); + } + } + + void UpdateHeaderColor() + { + m_headerColorModifier = ( m_referenceType == TexReferenceType.Object ) ? Color.white : ReferenceHeaderColor; + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + if( m_referenceNodeId > -1 && m_referenceNode == null ) + { + m_referenceNode = UIUtils.GetScreenColorNode( m_referenceNodeId ) as ScreenColorNode; + if( m_referenceNode == null ) + { + m_referenceNodeId = -1; + m_referenceArrayId = -1; + m_sizeIsDirty = true; + } + } + + if( m_showSubtitle == m_containerGraph.IsSRP ) + { + m_showSubtitle = !m_containerGraph.IsSRP; + m_sizeIsDirty = true; + } + +#if UNITY_2018_3_OR_NEWER + if( ( ContainerGraph.IsHDRP || ContainerGraph.ParentWindow.IsShaderFunctionWindow ) && ASEPackageManagerHelper.CurrentHDVersion >= ASESRPVersions.ASE_SRP_5_13_0 ) + { + m_inputPorts[ 1 ].Visible = true; + } + else + { + m_inputPorts[ 1 ].Visible = false; + } +#else + m_inputPorts[ 1 ].Visible = false; +#endif + } + + protected override void ChangeSizeFinished() + { + if( m_referenceType == TexReferenceType.Instance ) + { + m_position.width += 20; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + CheckReference(); + + if( SoftValidReference ) + { + m_content.text = m_referenceNode.TitleContent.text + Constants.InstancePostfixStr; + SetAdditonalTitleText( m_referenceNode.AdditonalTitleContent.text ); + + if( m_referenceIconStyle == null ) + { + m_referenceIconStyle = UIUtils.GetCustomStyle( CustomStyle.SamplerTextureIcon ); + } + + Rect iconPos = m_globalPosition; + iconPos.width = 19 * drawInfo.InvertedZoom; + iconPos.height = 19 * drawInfo.InvertedZoom; + + iconPos.y += 6 * drawInfo.InvertedZoom; + iconPos.x += m_globalPosition.width - iconPos.width - 7 * drawInfo.InvertedZoom; + + if( GUI.Button( iconPos, string.Empty, m_referenceIconStyle ) ) + { + UIUtils.FocusOnNode( m_referenceNode, 1, true ); + } + } + } + + void CheckReference() + { + if( m_referenceType != TexReferenceType.Instance ) + { + return; + } + + if( m_referenceArrayId > -1 ) + { + ParentNode newNode = UIUtils.GetScreenColorNode( m_referenceArrayId ); + if( newNode == null || newNode.UniqueId != m_referenceNodeId ) + { + m_referenceNode = null; + int count = UIUtils.GetScreenColorNodeAmount(); + for( int i = 0; i < count; i++ ) + { + ParentNode node = UIUtils.GetScreenColorNode( i ); + if( node.UniqueId == m_referenceNodeId ) + { + m_referenceNode = node as ScreenColorNode; + m_referenceArrayId = i; + break; + } + } + } + } + + if( m_referenceNode == null && m_referenceNodeId > -1 ) + { + m_referenceNodeId = -1; + m_referenceArrayId = -1; + } + } + + public override void DrawMainPropertyBlock() + { + EditorGUI.BeginChangeCheck(); + m_referenceType = (TexReferenceType)EditorGUILayoutPopup( Constants.ReferenceTypeStr, (int)m_referenceType, Constants.ReferenceArrayLabels ); + if( EditorGUI.EndChangeCheck() ) + { + m_sizeIsDirty = true; + if( m_referenceType == TexReferenceType.Object ) + { + UIUtils.RegisterScreenColorNode( this ); + m_content.text = m_propertyInspectorName; + } + else + { + UIUtils.UnregisterScreenColorNode( this ); + if( SoftValidReference ) + { + m_content.text = m_referenceNode.TitleContent.text + Constants.InstancePostfixStr; + } + } + UpdateHeaderColor(); + } + + if( m_referenceType == TexReferenceType.Object ) + { + EditorGUI.BeginDisabledGroup( m_containerGraph.IsSRP ); + { + EditorGUI.BeginChangeCheck(); + m_useCustomGrab = EditorGUILayoutToggle( "Custom Grab Pass", m_useCustomGrab ); + EditorGUI.BeginDisabledGroup( !m_useCustomGrab ); + DrawMainPropertyBlockNoPrecision(); + EditorGUI.EndDisabledGroup(); + + m_normalize = EditorGUILayoutToggle( "Normalize", m_normalize ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePort(); + if( m_useCustomGrab ) + { + BeginPropertyFromInspectorCheck(); + } + } + } + EditorGUI.EndDisabledGroup(); + } + else + { + string[] arr = UIUtils.ScreenColorNodeArr(); + bool guiEnabledBuffer = GUI.enabled; + if( arr != null && arr.Length > 0 ) + { + GUI.enabled = true; + } + else + { + m_referenceArrayId = -1; + GUI.enabled = false; + } + + m_referenceArrayId = EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceArrayId, arr ); + GUI.enabled = guiEnabledBuffer; + EditorGUI.BeginDisabledGroup( m_containerGraph.IsSRP ); + { + EditorGUI.BeginChangeCheck(); + m_normalize = EditorGUILayoutToggle( "Normalize", m_normalize ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePort(); + } + } + EditorGUI.EndDisabledGroup(); + } + ShowVariableMode(); + ShowAutoRegister(); +#if UNITY_2018_3_OR_NEWER + if( ( ContainerGraph.IsHDRP || ContainerGraph.ParentWindow.IsShaderFunctionWindow ) && ASEPackageManagerHelper.CurrentHDVersion >= ASESRPVersions.ASE_SRP_5_13_0 ) + { + m_exposure = EditorGUILayoutToggle( "Exposure", m_exposure ); + } +#endif + } + + private void UpdatePort() + { + if( m_normalize ) + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + else + m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT2, false ); + } + + public override void DrawTitle( Rect titlePos ) + { + if( !m_isEditing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + GUI.Label( titlePos, "Grab Screen Color", UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + } + + if( m_useCustomGrab || SoftValidReference ) + { + base.DrawTitle( titlePos ); + m_previousAdditonalTitle = m_additionalContent.text; + } + else + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 ) + { + SetAdditonalTitleTextOnCallback( GrabTextureDefault, ( instance, newSubTitle ) => instance.AdditonalTitleContent.text = string.Format( Constants.SubTitleVarNameFormatStr, newSubTitle ) ); + //GUI.Label( titlePos, PropertyInspectorName, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) ); + } + } + + public void SetMacros( ref MasterNodeDataCollector dataCollector ) + { +#if UNITY_5_6_OR_NEWER + if( !dataCollector.IsTemplate || dataCollector.CurrentSRPType == TemplateSRPType.BuiltIn ) + { + for( int i = 0; i < ASEDeclareMacro.Length; i++ ) + { + dataCollector.AddToDirectives( ASEDeclareMacro[ i ] ); + } + } +#endif + } + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + SetMacros( ref dataCollector ); + +#if !UNITY_2018_3_OR_NEWER + if( dataCollector.IsTemplate && dataCollector.CurrentSRPType == TemplateSRPType.HD ) + { + UIUtils.ShowMessage( UniqueId, "GrabPasses are not supported on Unity HD Scriptable Rendering Pipeline old versions." ); + return GetOutputColorItem( 0, outputId, "(0).xxxx" ); + } +#endif + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputColorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + string valueName = string.Empty; + if( dataCollector.IsSRP ) + { +#if !UNITY_2018_3_OR_NEWER + dataCollector.AddToUniforms( UniqueId, DeclareOpaqueTextureObject ); + dataCollector.AddToUniforms( UniqueId, DeclareOpaqueTextureSampler ); +#endif + valueName = FetchVarName + OutputId; + dataCollector.AddToDirectives( OpaqueTextureDefine, -1 , AdditionalLineType.Define); + string uvCoords = GetUVCoords( ref dataCollector, ignoreLocalVar, false ); + if( dataCollector.TemplateDataCollectorInstance.IsLWRP ) + { + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT4, valueName, string.Format( LWFetchOpaqueTexture, uvCoords ) ); + } + else + { +#if UNITY_2018_3_OR_NEWER + if( ASEPackageManagerHelper.CurrentHDVersion >= ASESRPVersions.ASE_SRP_5_13_0 ) + { + string lod = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + dataCollector.AddFunction( HDSampleSceneColorFunc5[ 0 ], HDSampleSceneColorFunc5, false ); + string exposureValue = m_exposure ? "1.0" : "GetInverseCurrentExposureMultiplier()"; + dataCollector.AddLocalVariable( UniqueId, m_currentPrecisionType, WirePortDataType.FLOAT4, valueName, string.Format( HDSampleSceneColorHeader5, uvCoords, lod, exposureValue ) ); + } + else + { + dataCollector.AddFunction( HDSampleSceneColorFunc4[ 0 ], HDSampleSceneColorFunc4, false ); + dataCollector.AddLocalVariable( UniqueId, m_currentPrecisionType, WirePortDataType.FLOAT4, valueName, string.Format( HDSampleSceneColorHeader4, uvCoords ) ); + } +#endif + } + } + else + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + string propertyName = CurrentPropertyReference; + OnPropertyNameChanged(); + //bool emptyName = string.IsNullOrEmpty( m_propertyInspectorName ) || propertyName == GrabTextureDefault; + bool emptyName = string.IsNullOrEmpty( m_propertyInspectorName ) || !m_useCustomGrab; + dataCollector.AddGrabPass( emptyName ? string.Empty : propertyName ); + valueName = SetFetchedData( ref dataCollector, ignoreLocalVar ); + } + + m_outputPorts[ 0 ].SetLocalValue( valueName, dataCollector.PortCategory ); + return GetOutputColorItem( 0, outputId, valueName ); + } + + + public override void OnPropertyNameChanged() + { + base.OnPropertyNameChanged(); + UIUtils.UpdateScreenColorDataNode( UniqueId, DataToArray ); + } + + public string SetFetchedData( ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + string propertyName = CurrentPropertyReference; + + bool isProjecting = m_normalize; + + if( !m_inputPorts[ 0 ].IsConnected ) // to generate proper screen pos by itself + isProjecting = true; + + if( ignoreLocalVar ) + { + string samplerValue = SamplerType + ( isProjecting ? "proj" : "" ) + "( " + propertyName + ", " + GetUVCoords( ref dataCollector, ignoreLocalVar, isProjecting ) + " )"; + return samplerValue; + } + + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string uvValue = GetUVCoords( ref dataCollector, ignoreLocalVar, isProjecting ); +#if UNITY_5_6_OR_NEWER + if( isProjecting ) + { + uvValue = string.Format( "{0}.xy/{0}.w", uvValue ); + } + string samplerOp = string.Format( "UNITY_SAMPLE_SCREENSPACE_TEXTURE({0},{1})", propertyName, uvValue ); +#else + string samplerOp = SamplerType + ( isProjecting ? "proj" : "" ) + "( " + propertyName + ", " + uvValue + " )"; +#endif + dataCollector.AddLocalVariable( UniqueId, UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_outputPorts[ 0 ].DataType ) + " " + ScreenColorStr + OutputId + " = " + samplerOp + ";" ); + return ScreenColorStr + OutputId; + } + + private string GetUVCoords( ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar, bool isProjecting ) + { + string result = string.Empty; + + if( m_inputPorts[ 0 ].IsConnected ) + { + result = m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, ( isProjecting ? WirePortDataType.FLOAT4 : WirePortDataType.FLOAT2 ), ignoreLocalVar, true ); + } + else + { + string customScreenPos = null; + + if( dataCollector.IsTemplate ) + customScreenPos = dataCollector.TemplateDataCollectorInstance.GetScreenPos( CurrentPrecisionType ); + + if( isProjecting ) + result = GeneratorUtils.GenerateGrabScreenPosition( ref dataCollector, UniqueId, CurrentPrecisionType, !dataCollector.UsingCustomScreenPos, customScreenPos ); + else + result = GeneratorUtils.GenerateGrabScreenPositionNormalized( ref dataCollector, UniqueId, CurrentPrecisionType, !dataCollector.UsingCustomScreenPos, customScreenPos ); + } + + if( isProjecting && !dataCollector.IsSRP ) +#if UNITY_5_6_OR_NEWER + return result; +#else + return "UNITY_PROJ_COORD( " + result + " )"; +#endif + else + return result; + } + + public override void Destroy() + { + base.Destroy(); + if( m_referenceType == TexReferenceType.Object ) + { + UIUtils.UnregisterScreenColorNode( this ); + } + if( UniqueId > -1 ) + ContainerGraph.ScreenColorNodes.OnReorderEventComplete -= OnReorderEventComplete; + } + + public bool SoftValidReference + { + get + { + if( m_referenceType == TexReferenceType.Instance && m_referenceArrayId > -1 ) + { + m_referenceNode = UIUtils.GetScreenColorNode( m_referenceArrayId ); + if( m_referenceNode == null ) + { + m_referenceArrayId = -1; + m_referenceWidth = -1; + } + else if( m_referenceWidth != m_referenceNode.Position.width ) + { + m_referenceWidth = m_referenceNode.Position.width; + m_sizeIsDirty = true; + } + return m_referenceNode != null; + } + return false; + } + } + + public string CurrentPropertyReference + { + get + { + string propertyName = string.Empty; + if( m_referenceType == TexReferenceType.Instance && m_referenceArrayId > -1 ) + { + ScreenColorNode node = UIUtils.GetScreenColorNode( m_referenceArrayId ); + propertyName = ( node != null ) ? node.PropertyName : m_propertyName; + } + else if( !m_useCustomGrab ) + { + propertyName = GrabTextureDefault; + } + else + { + propertyName = m_propertyName; + } + return propertyName; + } + } + + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 12 ) + { + m_referenceType = (TexReferenceType)Enum.Parse( typeof( TexReferenceType ), GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 22 ) + { + m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + else + { + m_referenceArrayId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + if( m_referenceType == TexReferenceType.Instance ) + { + UIUtils.UnregisterScreenColorNode( this ); + } + + UpdateHeaderColor(); + } + + if( UIUtils.CurrentShaderVersion() > 12101 ) + { + m_useCustomGrab = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + else + { + m_useCustomGrab = true; + } + + if( UIUtils.CurrentShaderVersion() > 14102 ) + { + m_normalize = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 18801 ) + { + m_exposure = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + if( !m_isNodeBeingCopied && m_referenceType == TexReferenceType.Object ) + { + ContainerGraph.ScreenColorNodes.UpdateDataOnNode( UniqueId, DataToArray ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_referenceType ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( ( m_referenceNode != null ) ? m_referenceNode.UniqueId : -1 ) ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_useCustomGrab ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalize ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_exposure ); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( m_referenceType == TexReferenceType.Instance ) + { + if( UIUtils.CurrentShaderVersion() > 22 ) + { + m_referenceNode = UIUtils.GetNode( m_referenceNodeId ) as ScreenColorNode; + m_referenceArrayId = UIUtils.GetScreenColorNodeRegisterId( m_referenceNodeId ); + } + else + { + m_referenceNode = UIUtils.GetScreenColorNode( m_referenceArrayId ); + if( m_referenceNode != null ) + { + m_referenceNodeId = m_referenceNode.UniqueId; + } + } + } + + if( UIUtils.CurrentShaderVersion() <= 14102 ) + { + if( m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT4 ) + m_normalize = true; + else + m_normalize = false; + } + } + + public override string PropertyName + { + get + { + if( m_useCustomGrab ) + return base.PropertyName; + else + return GrabTextureDefault; + } + } + + public override string GetPropertyValStr() + { + return PropertyName; + } + + public override string DataToArray { get { return m_propertyName; } } + + public override string GetUniformValue() + { + if( SoftValidReference ) + { + if( m_referenceNode.IsConnected ) + return string.Empty; + + return m_referenceNode.GetUniformValue(); + } +#if UNITY_5_6_OR_NEWER + return "ASE_DECLARE_SCREENSPACE_TEXTURE( " + PropertyName + " )"; +#else + return "uniform sampler2D " + PropertyName + ";"; +#endif + } + + public override bool GetUniformData( out string dataType, out string dataName, ref bool fullValue ) + { + if( SoftValidReference ) + { + //if ( m_referenceNode.IsConnected ) + //{ + // dataType = string.Empty; + // dataName = string.Empty; + //} + + return m_referenceNode.GetUniformData( out dataType, out dataName, ref fullValue ); + } +#if UNITY_5_6_OR_NEWER + dataName = "ASE_DECLARE_SCREENSPACE_TEXTURE( " + PropertyName + " )"; + dataType = string.Empty; + fullValue = true; +#else + dataType = "sampler2D"; + dataName = PropertyName; +#endif + return true; + } + + public override void CheckIfAutoRegister( ref MasterNodeDataCollector dataCollector ) + { + if( m_autoRegister && (m_connStatus != NodeConnectionStatus.Connected || InsideShaderFunction )) + { + SetMacros( ref dataCollector ); + RegisterProperty( ref dataCollector ); + string propertyName = CurrentPropertyReference; + bool emptyName = string.IsNullOrEmpty( m_propertyInspectorName ) || propertyName == GrabTextureDefault; + dataCollector.AddGrabPass( emptyName ? string.Empty : propertyName ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenColorNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenColorNode.cs.meta new file mode 100644 index 0000000..2012d50 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenColorNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b266c7cca236bcb469d6d4f13df55df5 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenDepthNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenDepthNode.cs new file mode 100644 index 0000000..d08d1c8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenDepthNode.cs @@ -0,0 +1,173 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Screen Depth", "Camera And Screen", "Given a screen position returns the depth of the scene to the object as seen by the camera" )] + public sealed class ScreenDepthNode : ParentNode + { + [SerializeField] + private bool m_convertToLinear = true; + + [SerializeField] + private int m_viewSpaceInt = 0; + + private const string ConvertToLinearStr = "Convert To Linear"; + + private readonly string[] m_viewSpaceStr = { "Eye Space", "0-1 Space" }; + + private readonly string[] m_vertexNameStr = { "eyeDepth", "clampDepth" }; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT4, false, "Pos" ); + AddOutputPort( WirePortDataType.FLOAT, "Depth" ); + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + SetAdditonalTitleText( string.Format( Constants.SubTitleSpaceFormatStr, m_viewSpaceStr[ m_viewSpaceInt ] ) ); + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_viewSpaceInt = m_upperLeftWidget.DrawWidget( this, m_viewSpaceInt, m_viewSpaceStr ); + if( EditorGUI.EndChangeCheck() ) + { + SetAdditonalTitleText( string.Format( Constants.SubTitleSpaceFormatStr, m_viewSpaceStr[ m_viewSpaceInt ] ) ); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_viewSpaceInt = EditorGUILayoutPopup( "View Space", m_viewSpaceInt, m_viewSpaceStr ); + if( EditorGUI.EndChangeCheck() ) + { + SetAdditonalTitleText( string.Format( Constants.SubTitleSpaceFormatStr, m_viewSpaceStr[ m_viewSpaceInt ] ) ); + } + + m_convertToLinear = EditorGUILayoutToggle( ConvertToLinearStr, m_convertToLinear ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + UIUtils.ShowNoVertexModeNodeMessage( this ); + return "0"; + } + + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputColorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + if( !( dataCollector.IsTemplate && dataCollector.IsSRP ) ) + dataCollector.AddToIncludes( UniqueId, Constants.UnityCgLibFuncs ); + + if( !dataCollector.IsTemplate || dataCollector.TemplateDataCollectorInstance.CurrentSRPType != TemplateSRPType.HD ) + { + if( dataCollector.IsTemplate && dataCollector.CurrentSRPType == TemplateSRPType.Lightweight ) + { + //dataCollector.AddToUniforms( UniqueId, Constants.CameraDepthTextureSRPVar ); + //dataCollector.AddToUniforms( UniqueId, Constants.CameraDepthTextureSRPSampler ); + dataCollector.AddToDirectives( Constants.CameraDepthTextureLWEnabler, -1, AdditionalLineType.Define ); + } + else + { + dataCollector.AddToUniforms( UniqueId, Constants.CameraDepthTextureValue ); + } + dataCollector.AddToUniforms( UniqueId, Constants.CameraDepthTextureTexelSize ); + } + + + string screenPosNorm = string.Empty; + if( m_inputPorts[ 0 ].IsConnected ) + screenPosNorm = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + else + { + if( dataCollector.IsTemplate ) + { + if( !dataCollector.TemplateDataCollectorInstance.GetCustomInterpolatedData( TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED, WirePortDataType.FLOAT4, PrecisionType.Float, ref screenPosNorm, true,MasterNodePortCategory.Fragment ) ) + { + screenPosNorm = GeneratorUtils.GenerateScreenPositionNormalized( ref dataCollector, UniqueId, CurrentPrecisionType, !dataCollector.UsingCustomScreenPos ); + } + } + else + { + screenPosNorm = GeneratorUtils.GenerateScreenPositionNormalized( ref dataCollector, UniqueId, CurrentPrecisionType, !dataCollector.UsingCustomScreenPos ); + } + } + + string screenDepthInstruction = TemplateHelperFunctions.CreateDepthFetch( dataCollector, screenPosNorm ); + + if( m_convertToLinear ) + { + string viewSpace = m_viewSpaceInt == 0 ? "LinearEyeDepth" : "Linear01Depth"; + string formatStr = string.Empty; + if( ( dataCollector.IsTemplate && dataCollector.IsSRP ) ) + formatStr = "(" + screenDepthInstruction + ",_ZBufferParams)"; + else + formatStr = "(" + screenDepthInstruction + ")"; + screenDepthInstruction = viewSpace + formatStr; + } + else + { + if( m_viewSpaceInt == 0 ) + { + screenDepthInstruction = string.Format( "({0}*( _ProjectionParams.z - _ProjectionParams.y ))", screenDepthInstruction ); + } + } + + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT, m_vertexNameStr[ m_viewSpaceInt ] + OutputId, screenDepthInstruction ); + + m_outputPorts[ 0 ].SetLocalValue( m_vertexNameStr[ m_viewSpaceInt ] + OutputId, dataCollector.PortCategory ); + return GetOutputColorItem( 0, outputId, m_vertexNameStr[ m_viewSpaceInt ] + OutputId ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_viewSpaceInt = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() >= 13901 ) + { + m_convertToLinear = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + SetAdditonalTitleText( string.Format( Constants.SubTitleSpaceFormatStr, m_viewSpaceStr[ m_viewSpaceInt ] ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_viewSpaceInt ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_convertToLinear ); + } + } + +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenDepthNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenDepthNode.cs.meta new file mode 100644 index 0000000..95f7777 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenDepthNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 52266d8a6f7f4fe428dcee2ddb0514ac +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenPosInputsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenPosInputsNode.cs new file mode 100644 index 0000000..6acaa57 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenPosInputsNode.cs @@ -0,0 +1,155 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Screen Position", "Camera And Screen", "Screen space position, you can either get the Screen position as is or Normalize it to have it at the [0,1] range" )] + public sealed class ScreenPosInputsNode : SurfaceShaderINParentNode + { + private const string ProjectStr = "Project"; + private const string UVInvertHack = "Scale and Offset"; + private readonly string[] m_outputTypeStr = { "Normalized", "Screen" }; + + [SerializeField] + private int m_outputTypeInt = 0; + + [SerializeField] + private bool m_scaleAndOffset = false; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentInput = SurfaceInputs.SCREEN_POS; + InitialSetup(); + m_textLabelWidth = 65; + m_autoWrapProperties = true; + + m_hasLeftDropdown = true; + m_previewShaderGUID = "a5e7295278a404175b732f1516fb68a6"; + + if( UIUtils.CurrentWindow != null && UIUtils.CurrentWindow.CurrentGraph != null && UIUtils.CurrentShaderVersion() <= 2400 ) + { + m_outputTypeInt = 1; + m_previewMaterialPassId = m_outputTypeInt; + } + + ConfigureHeader(); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_outputTypeInt = m_upperLeftWidget.DrawWidget( this, m_outputTypeInt, m_outputTypeStr ); + if( EditorGUI.EndChangeCheck() ) + { + ConfigureHeader(); + } + } + + public override void DrawProperties() + { + //base.DrawProperties(); + + EditorGUI.BeginChangeCheck(); + m_outputTypeInt = EditorGUILayoutPopup( "Type", m_outputTypeInt, m_outputTypeStr ); + if( EditorGUI.EndChangeCheck() ) + { + ConfigureHeader(); + } + } + + void ConfigureHeader() + { + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_outputTypeStr[ m_outputTypeInt ] ) ); + m_previewMaterialPassId = m_outputTypeInt; + } + + public override void Reset() + { + base.Reset(); + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + { + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + m_currentPrecisionType = PrecisionType.Float; + + string screenPos = string.Empty; + if( m_outputTypeInt == 0 ) + { + if( dataCollector.IsTemplate ) + { + screenPos = dataCollector.TemplateDataCollectorInstance.GetScreenPosNormalized( CurrentPrecisionType ); + } + else + { + screenPos = GeneratorUtils.GenerateScreenPositionNormalized( ref dataCollector, UniqueId, CurrentPrecisionType); + } + } + else + { + if( dataCollector.IsTemplate ) + { + screenPos = dataCollector.TemplateDataCollectorInstance.GetScreenPos( CurrentPrecisionType ); + } + else + { + screenPos = GeneratorUtils.GenerateScreenPosition( ref dataCollector, UniqueId, CurrentPrecisionType ); + } + } + + m_outputPorts[ 0 ].SetLocalValue( screenPos, dataCollector.PortCategory ); + return GetOutputVectorItem( 0, outputId, screenPos ); + + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 2400 ) + { + if( UIUtils.CurrentShaderVersion() < 6102 ) + { + bool project = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_outputTypeInt = project ? 0 : 1; + } + else + { + m_outputTypeInt = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } + + if( UIUtils.CurrentShaderVersion() > 3107 ) + { + m_scaleAndOffset = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_scaleAndOffset = false; + } + + ConfigureHeader(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_outputTypeInt ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_scaleAndOffset ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenPosInputsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenPosInputsNode.cs.meta new file mode 100644 index 0000000..60d2abb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ScreenPosInputsNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 32cea8ff65efa3844a0047477ec789da +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/SurfaceShaderINParentNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/SurfaceShaderINParentNode.cs new file mode 100644 index 0000000..e0f094b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/SurfaceShaderINParentNode.cs @@ -0,0 +1,122 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class SurfaceShaderINParentNode : ParentNode + { + [SerializeField] + protected SurfaceInputs m_currentInput; + + [SerializeField] + protected string m_currentInputValueStr; + + [SerializeField] + protected string m_currentInputDecStr; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentInput = SurfaceInputs.UV_COORDS; + m_textLabelWidth = 65; + m_customPrecision = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + DrawPrecisionProperty(); + } + //This needs to be called on the end of the CommonInit on all children + protected void InitialSetup() + { + m_currentInputValueStr = Constants.InputVarStr + "." + UIUtils.GetInputValueFromType( m_currentInput ); + + string outputName = "Out"; + switch ( m_currentInput ) + { + case SurfaceInputs.DEPTH: + { + AddOutputPort( WirePortDataType.FLOAT, outputName ); + } + break; + case SurfaceInputs.UV_COORDS: + { + outputName = "UV"; + AddOutputVectorPorts( WirePortDataType.FLOAT2, outputName ); + } + break; + case SurfaceInputs.UV2_COORDS: + { + outputName = "UV"; + AddOutputVectorPorts( WirePortDataType.FLOAT2, outputName ); + } + break; + case SurfaceInputs.VIEW_DIR: + { + outputName = "XYZ"; + AddOutputVectorPorts( WirePortDataType.FLOAT3, outputName ); + } + break; + case SurfaceInputs.COLOR: + { + outputName = "RGBA"; + AddOutputVectorPorts( WirePortDataType.FLOAT4, outputName ); + } + break; + case SurfaceInputs.SCREEN_POS: + { + outputName = "XYZW"; + AddOutputVectorPorts( WirePortDataType.FLOAT4, outputName ); + } + break; + case SurfaceInputs.WORLD_POS: + { + outputName = "XYZ"; + AddOutputVectorPorts( WirePortDataType.FLOAT3, outputName ); + } + break; + case SurfaceInputs.WORLD_REFL: + { + outputName = "XYZ"; + AddOutputVectorPorts( WirePortDataType.FLOAT3, outputName ); + } + break; + case SurfaceInputs.WORLD_NORMAL: + { + outputName = "XYZ"; + AddOutputVectorPorts( WirePortDataType.FLOAT3, outputName ); + } + break; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + dataCollector.AddToInput( UniqueId, m_currentInput, CurrentPrecisionType ); + switch ( m_currentInput ) + { + case SurfaceInputs.VIEW_DIR: + case SurfaceInputs.WORLD_REFL: + case SurfaceInputs.WORLD_NORMAL: + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + } + break; + case SurfaceInputs.WORLD_POS: + case SurfaceInputs.DEPTH: + case SurfaceInputs.UV_COORDS: + case SurfaceInputs.UV2_COORDS: + case SurfaceInputs.COLOR: + case SurfaceInputs.SCREEN_POS: break; + }; + + return GetOutputVectorItem( 0, outputId, m_currentInputValueStr ); + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/SurfaceShaderINParentNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/SurfaceShaderINParentNode.cs.meta new file mode 100644 index 0000000..92a1e5b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/SurfaceShaderINParentNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 71628885b2fde0944bf7dd8e4eb2770f +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/TexelSizeNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/TexelSizeNode.cs new file mode 100644 index 0000000..1de1003 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/TexelSizeNode.cs @@ -0,0 +1,325 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Texel Size", "Textures", "Texel Size for a given texture object" )] + public sealed class TexelSizeNode : ParentNode + { + private readonly string[] Dummy = { string.Empty }; + [SerializeField] + private int m_referenceSamplerId = -1; + + [SerializeField] + private int m_referenceNodeId = -1; + + [SerializeField] + private TexturePropertyNode m_inputReferenceNode = null; + + private TexturePropertyNode m_referenceNode = null; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + [SerializeField] + private string m_previousTexture = string.Empty; + + private int m_cachedSamplerId = -1; + private int m_cachedSamplerIdArray = -1; + private int m_cachedSamplerIdCube = -1; + private int m_cachedSamplerId3D = -1; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.SAMPLER2D, false, "Tex" ); + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.SAMPLER2DARRAY, WirePortDataType.OBJECT ); + AddOutputVectorPorts( WirePortDataType.FLOAT4, Constants.EmptyPortValue ); + ChangeOutputName( 1, "1/Width" ); + ChangeOutputName( 2, "1/Height" ); + ChangeOutputName( 3, "Width" ); + ChangeOutputName( 4, "Height" ); + m_textLabelWidth = 80; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + m_previewShaderGUID = "6b20226576a059443b58aa2d0b942276"; + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_inputReferenceNode = m_inputPorts[ 0 ].GetOutputNodeWhichIsNotRelay() as TexturePropertyNode; + UpdateTitle(); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + m_inputReferenceNode = null; + UpdateTitle(); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ 0 ].MatchPortToConnection(); + UpdateTitle(); + } + + void UpdateTitle() + { + if( m_inputReferenceNode != null ) + { + m_additionalContent.text = string.Format( Constants.PropertyValueLabel, m_inputReferenceNode.PropertyInspectorName ); + } + else if( m_referenceSamplerId > -1 && m_referenceNode != null ) + { + m_additionalContent.text = string.Format( Constants.PropertyValueLabel, m_referenceNode.PropertyInspectorName ); + } + else + { + m_additionalContent.text = string.Empty; + } + m_sizeIsDirty = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + bool guiEnabledBuffer = GUI.enabled; + EditorGUI.BeginChangeCheck(); + List arr = new List( UIUtils.TexturePropertyNodeArr() ); + + if( arr != null && arr.Count > 0 ) + { + arr.Insert( 0, "None" ); + GUI.enabled = true && ( !m_inputPorts[ 0 ].IsConnected ); + m_referenceSamplerId = EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceSamplerId + 1, arr.ToArray() ) - 1; + } + else + { + m_referenceSamplerId = -1; + GUI.enabled = false; + EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceSamplerId, Dummy ); + } + + GUI.enabled = guiEnabledBuffer; + if( EditorGUI.EndChangeCheck() ) + { + m_referenceNode = UIUtils.GetTexturePropertyNode( m_referenceSamplerId ); + if( m_referenceNode != null ) + { + m_referenceNodeId = m_referenceNode.UniqueId; + } + else + { + m_referenceNodeId = -1; + m_referenceSamplerId = -1; + } + UpdateTitle(); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + string texelName = string.Empty; + + if( m_inputPorts[ 0 ].IsConnected ) + { + texelName = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) + "_TexelSize"; + } + else if( m_referenceNode != null ) + { + m_referenceNode.BaseGenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + texelName = m_referenceNode.PropertyName + "_TexelSize"; + } + else + { + texelName = "_TexelSize"; + UIUtils.ShowMessage( UniqueId, "Please specify a texture sample on the Texel Size node", MessageSeverity.Warning ); + } + + dataCollector.AddToUniforms( UniqueId, "float4 " + texelName + ";", dataCollector.IsSRP ); + + switch( outputId ) + { + case 0: return texelName; + case 1: return ( texelName + ".x" ); + case 2: return ( texelName + ".y" ); + case 3: return ( texelName + ".z" ); + case 4: return ( texelName + ".w" ); + } + + return string.Empty; + } + + void SetPreviewTexture( Texture newValue ) + { + if( newValue is Cubemap ) + { + m_previewMaterialPassId = 3; + if( m_cachedSamplerIdCube == -1 ) + m_cachedSamplerIdCube = Shader.PropertyToID( "_Cube" ); + + PreviewMaterial.SetTexture( m_cachedSamplerIdCube, newValue as Cubemap ); + } + else if( newValue is Texture2DArray ) + { + + m_previewMaterialPassId = 2; + if( m_cachedSamplerIdArray == -1 ) + m_cachedSamplerIdArray = Shader.PropertyToID( "_Array" ); + + PreviewMaterial.SetTexture( m_cachedSamplerIdArray, newValue as Texture2DArray ); + } + else if( newValue is Texture3D ) + { + m_previewMaterialPassId = 1; + if( m_cachedSamplerId3D == -1 ) + m_cachedSamplerId3D = Shader.PropertyToID( "_Sampler3D" ); + + PreviewMaterial.SetTexture( m_cachedSamplerId3D, newValue as Texture3D ); + } + else + { + m_previewMaterialPassId = 0; + if( m_cachedSamplerId == -1 ) + m_cachedSamplerId = Shader.PropertyToID( "_Sampler" ); + + PreviewMaterial.SetTexture( m_cachedSamplerId, newValue ); + } + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + if( m_inputPorts[ 0 ].IsConnected ) + { + SetPreviewTexture( m_inputPorts[ 0 ].InputPreviewTexture( ContainerGraph ) ); + } + else if( m_referenceNode != null ) + { + if( m_referenceNode.Value != null ) + { + SetPreviewTexture( m_referenceNode.Value ); + } + else + { + SetPreviewTexture( m_referenceNode.PreviewTexture ); + } + } + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + + if( m_referenceNode != null && m_previousTexture != m_referenceNode.AdditonalTitleContent.text ) + { + m_previousTexture = m_referenceNode.AdditonalTitleContent.text; + PreviewIsDirty = true; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + EditorGUI.BeginChangeCheck(); + { + List arr = new List( UIUtils.TexturePropertyNodeArr() ); + bool guiEnabledBuffer = GUI.enabled; + + if( arr != null && arr.Count > 0 ) + { + arr.Insert( 0, "None" ); + GUI.enabled = true && ( !m_inputPorts[ 0 ].IsConnected ); + m_referenceSamplerId = m_upperLeftWidget.DrawWidget( this, m_referenceSamplerId + 1, arr.ToArray() ) - 1; + } + else + { + m_referenceSamplerId = -1; + GUI.enabled = false; + m_upperLeftWidget.DrawWidget( this, m_referenceSamplerId, Dummy ); + } + GUI.enabled = guiEnabledBuffer; + } + if( EditorGUI.EndChangeCheck() ) + { + m_referenceNode = UIUtils.GetTexturePropertyNode( m_referenceSamplerId ); + if( m_referenceNode != null ) + { + m_referenceNodeId = m_referenceNode.UniqueId; + } + else + { + m_referenceNodeId = -1; + m_referenceSamplerId = -1; + } + UpdateTitle(); + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( UIUtils.CurrentShaderVersion() > 2404 ) + { + m_referenceNode = UIUtils.GetNode( m_referenceNodeId ) as TexturePropertyNode; + m_referenceSamplerId = UIUtils.GetTexturePropertyNodeRegisterId( m_referenceNodeId ); + } + else + { + m_referenceNode = UIUtils.GetTexturePropertyNode( m_referenceSamplerId ); + if( m_referenceNode != null ) + { + m_referenceNodeId = m_referenceNode.UniqueId; + } + } + UpdateTitle(); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 2404 ) + { + m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + else + { + m_referenceSamplerId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_referenceNodeId ); + } + + public override void Destroy() + { + base.Destroy(); + m_referenceNode = null; + m_inputReferenceNode = null; + m_upperLeftWidget = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/TexelSizeNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/TexelSizeNode.cs.meta new file mode 100644 index 0000000..1e6fa01 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/TexelSizeNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1a23decd88779d24f9af6ae30c3d5a5f +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/UVCoordsParentNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/UVCoordsParentNode.cs new file mode 100644 index 0000000..b259d89 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/UVCoordsParentNode.cs @@ -0,0 +1,112 @@ +//// Amplify Shader Editor - Visual Shader Editing Tool +//// Copyright (c) Amplify Creations, Lda + +//using UnityEngine; +//using UnityEditor; +//using System; + +//namespace AmplifyShaderEditor +//{ +// [Serializable] +// [NodeAttributes( "[Old]Texture Coordinates", "Surface Data", "Texture UV coordinates set", null, KeyCode.U, false )] +// public sealed class UVCoordsParentNode : ParentNode +// { +// private const string TilingStr = "Tiling"; + +// [SerializeField] +// private int m_textureCoordChannel = 0; + +// [SerializeField] +// private int m_textureCoordSet = 0; + +// [SerializeField] +// private Vector2 m_tiling = new Vector2( 1, 1 ); + +// protected override void CommonInit( int uniqueId ) +// { +// base.CommonInit( uniqueId ); +// AddOutputVectorPorts( WirePortDataType.FLOAT2, Constants.EmptyPortValue ); +// m_textLabelWidth = 75; +// } + +// public override void DrawProperties() +// { +// base.DrawProperties(); +// int newChannel = EditorGUILayoutIntPopup( Constants.AvailableUVChannelLabel, m_textureCoordChannel, Constants.AvailableUVChannelsStr, Constants.AvailableUVChannels ); +// if ( newChannel != m_textureCoordChannel ) +// { +// if ( UIUtils.IsChannelAvailable( newChannel ) ) +// { +// UIUtils.ShowMessage( "Attempting to use an unoccupied used texture channel" ); +// } +// else +// { +// m_textureCoordChannel = newChannel; +// } +// } +// else if ( m_textureCoordChannel > -1 && UIUtils.IsChannelAvailable( m_textureCoordChannel ) ) +// { +// UIUtils.ShowMessage( "Texture Channel " + m_textureCoordChannel + " is unavailable for TextureCoordinate node" ); +// m_textureCoordChannel = -1; +// } + +// m_textureCoordSet = EditorGUILayoutIntPopup( Constants.AvailableUVSetsLabel, m_textureCoordSet, Constants.AvailableUVSetsStr, Constants.AvailableUVSets ); + +// m_tiling = EditorGUILayoutVector2Field( TilingStr, m_tiling ); +// } + +// public override void Draw( DrawInfo drawInfo ) +// { +// base.Draw( drawInfo ); +// if ( m_isVisible ) +// { +// m_propertyDrawPos.x = m_globalPosition.x + Constants.FLOAT_WIDTH_SPACING; +// m_propertyDrawPos.y = m_outputPorts[ 1 ].Position.y; +// m_propertyDrawPos.width = 2.7f * drawInfo.InvertedZoom * Constants.FLOAT_DRAW_WIDTH_FIELD_SIZE; +// m_propertyDrawPos.height = drawInfo.InvertedZoom * Constants.FLOAT_DRAW_HEIGHT_FIELD_SIZE; + +// m_propertyDrawPos.y = m_outputPorts[ 1 ].Position.y; +// UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref m_tiling.x ); + +// m_propertyDrawPos.y = m_outputPorts[ 2 ].Position.y; +// UIUtils.DrawFloat( this, ref m_propertyDrawPos, ref m_tiling.y ); +// } +// } + +// public override void ReadFromString( ref string[] nodeParams ) +// { +// base.ReadFromString( ref nodeParams ); +// m_textureCoordChannel = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); +// m_tiling.x = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); +// m_tiling.y = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); +// } + +// public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) +// { +// base.WriteToString( ref nodeInfo, ref connectionsInfo ); +// IOUtils.AddFieldValueToString( ref nodeInfo, m_textureCoordChannel ); +// IOUtils.AddFieldValueToString( ref nodeInfo, m_tiling.x ); +// IOUtils.AddFieldValueToString( ref nodeInfo, m_tiling.y ); +// } + +// public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) +// { +// string uvChannelDeclaration = IOUtils.GetUVChannelDeclaration( UIUtils.GetChannelName( m_textureCoordChannel ), m_textureCoordChannel, m_textureCoordSet ); +// dataCollector.AddToInput( UniqueId, uvChannelDeclaration, true ); + +// if ( dataCollector.GetChannelUsage( m_textureCoordChannel ) != TextureChannelUsage.Used ) +// dataCollector.SetChannelUsage( m_textureCoordChannel, TextureChannelUsage.Required ); + +// string uvTileStr = string.Empty; +// switch ( outputId ) +// { +// case 0: { uvTileStr = "float2( " + m_tiling.x + " , " + m_tiling.y + " )"; } break; +// case 1: { uvTileStr = m_tiling.x.ToString(); } break; +// case 2: { uvTileStr = m_tiling.y.ToString(); } break; +// } +// string uvChannelName = IOUtils.GetUVChannelName( UIUtils.GetChannelName( m_textureCoordChannel ), m_textureCoordSet ); +// return ( uvTileStr + "*" + GetOutputVectorItem( 0, outputId, Constants.InputVarStr + "." + uvChannelName ) ); +// } + +// } +//} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/UVCoordsParentNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/UVCoordsParentNode.cs.meta new file mode 100644 index 0000000..eae8ca5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/UVCoordsParentNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 73fb18e7d547d514695cb0b83a29f80e +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ViewDirInputsCoordNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ViewDirInputsCoordNode.cs new file mode 100644 index 0000000..e60a359 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ViewDirInputsCoordNode.cs @@ -0,0 +1,167 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public enum ViewSpace + { + Tangent, + World + } + + [Serializable] + [NodeAttributes( "View Dir", "Camera And Screen", "View direction vector, you can select between World space or Tangent space" )] + public sealed class ViewDirInputsCoordNode : SurfaceShaderINParentNode + { + private const string SpaceStr = "Space"; + private const string WorldDirVarStr = "worldViewDir"; + private const string NormalizeOptionStr = "Safe Normalize"; + + [SerializeField] + private bool m_safeNormalize = false; + + [SerializeField] + private ViewSpace m_viewDirSpace = ViewSpace.World; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentInput = SurfaceInputs.VIEW_DIR; + InitialSetup(); + m_textLabelWidth = 120; + m_autoWrapProperties = true; + m_drawPreviewAsSphere = true; + m_hasLeftDropdown = true; + UpdateTitle(); + m_previewShaderGUID = "07b57d9823df4bd4d8fe6dcb29fca36a"; + } + + private void UpdateTitle() + { + m_additionalContent.text = string.Format( Constants.SubTitleSpaceFormatStr, m_viewDirSpace.ToString() ); + m_sizeIsDirty = true; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + m_upperLeftWidget.DrawWidget( ref m_viewDirSpace, this, OnWidgetUpdate ); + } + + private readonly Action OnWidgetUpdate = ( x ) => + { + ( x as ViewDirInputsCoordNode ).UpdateTitle(); + }; + + public override void DrawProperties() + { + //base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_viewDirSpace = (ViewSpace)EditorGUILayoutEnumPopup( SpaceStr, m_viewDirSpace ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateTitle(); + } + m_safeNormalize = EditorGUILayoutToggle( NormalizeOptionStr, m_safeNormalize ); + EditorGUILayout.HelpBox( "Having safe normalize ON makes sure your view vector is not zero even if you are using your shader with no cameras.", MessageType.None ); + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_viewDirSpace == ViewSpace.World ) + m_previewMaterialPassId = 0; + else if( m_viewDirSpace == ViewSpace.Tangent ) + m_previewMaterialPassId = 1; + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + if( m_viewDirSpace == ViewSpace.Tangent ) + dataCollector.DirtyNormal = true; + + if( m_safeNormalize ) + dataCollector.SafeNormalizeViewDir = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( dataCollector.IsTemplate ) + { + string varName = ( m_viewDirSpace == ViewSpace.World ) ? dataCollector.TemplateDataCollectorInstance.GetViewDir(true,MasterNodePortCategory.Fragment, m_safeNormalize?NormalizeType.Safe:NormalizeType.Regular) : + dataCollector.TemplateDataCollectorInstance.GetTangentViewDir( CurrentPrecisionType, true,MasterNodePortCategory.Fragment, m_safeNormalize ? NormalizeType.Safe : NormalizeType.Regular ); + return GetOutputVectorItem( 0, outputId, varName ); + } + + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + string result = GeneratorUtils.GenerateViewDirection( ref dataCollector, UniqueId, m_viewDirSpace ); + return GetOutputVectorItem( 0, outputId, result ); + } + else + { + if( m_viewDirSpace == ViewSpace.World ) + { + if( dataCollector.DirtyNormal || m_safeNormalize ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_POS ); + string result = GeneratorUtils.GenerateViewDirection( ref dataCollector, UniqueId ); + return GetOutputVectorItem( 0, outputId, result ); + } + else + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.VIEW_DIR, PrecisionType.Float ); + return GetOutputVectorItem( 0, outputId, m_currentInputValueStr ); + //return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + } + } + else + { + if( m_safeNormalize ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + dataCollector.ForceNormal = true; + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_POS ); + string result = GeneratorUtils.GenerateViewDirection( ref dataCollector, UniqueId, ViewSpace.Tangent ); + return GetOutputVectorItem( 0, outputId, result ); + } + else + { + dataCollector.ForceNormal = true; + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + } + } + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 2402 ) + m_viewDirSpace = (ViewSpace)Enum.Parse( typeof( ViewSpace ), GetCurrentParam( ref nodeParams ) ); + + if( UIUtils.CurrentShaderVersion() > 15201 ) + { + m_safeNormalize = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + UpdateTitle(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_viewDirSpace ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_safeNormalize ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ViewDirInputsCoordNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ViewDirInputsCoordNode.cs.meta new file mode 100644 index 0000000..3298572 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/ViewDirInputsCoordNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4755b85e957e31d4b96d341070b156b5 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalInputsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalInputsNode.cs new file mode 100644 index 0000000..d179cdd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalInputsNode.cs @@ -0,0 +1,119 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "[Deprecated] World Normal", "Surface Data", "Vertex Normal World", null, KeyCode.None, true, true, "World Normal", typeof( WorldNormalVector ) )] + public sealed class WorldNormalInputsNode : SurfaceShaderINParentNode + { + private const string PerPixelLabelStr = "Per Pixel"; + + [SerializeField] + private bool m_perPixel = true; + + [SerializeField] + private string m_precisionString; + + [SerializeField] + private bool m_addInstruction = false; + + public override void Reset() + { + base.Reset(); + m_addInstruction = true; + } + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentInput = SurfaceInputs.WORLD_NORMAL; + InitialSetup(); + //UIUtils.AddNormalDependentCount(); + } + + //public override void Destroy() + //{ + // ContainerGraph.RemoveNormalDependentCount(); + // base.Destroy(); + //} + + public override void DrawProperties() + { + base.DrawProperties(); + m_perPixel = EditorGUILayoutToggleLeft( PerPixelLabelStr, m_perPixel ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + if ( m_addInstruction ) + { + string precision = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, WirePortDataType.FLOAT3 ); + dataCollector.AddVertexInstruction( precision + " worldNormal = UnityObjectToWorldNormal(" + Constants.VertexShaderInputStr + ".normal)", UniqueId ); + m_addInstruction = false; + } + + return GetOutputVectorItem( 0, outputId, "worldNormal" ); + } + else + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + if ( dataCollector.PortCategory != MasterNodePortCategory.Debug && m_perPixel && dataCollector.DirtyNormal ) + { + //string result = "WorldNormalVector( " + Constants.InputVarStr + " , float3( 0,0,1 ))"; + m_precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, WirePortDataType.FLOAT3 ); + string result = string.Format( Constants.WorldNormalLocalDecStr, m_precisionString ); + int count = 0; + for ( int i = 0; i < m_outputPorts.Count; i++ ) + { + if ( m_outputPorts[ i ].IsConnected ) + { + if ( m_outputPorts[ i ].ConnectionCount > 2 ) + { + count = 2; + break; + } + count += 1; + if ( count > 1 ) + break; + } + } + if ( count > 1 ) + { + string localVarName = "WorldNormal" + OutputId; + dataCollector.AddToLocalVariables( UniqueId, CurrentPrecisionType, m_outputPorts[ 0 ].DataType, localVarName, result ); + return GetOutputVectorItem( 0, outputId, localVarName ); + } + else + { + return GetOutputVectorItem( 0, outputId, result ); + } + } + else + { + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + } + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if ( UIUtils.CurrentShaderVersion() > 2504 ) + m_perPixel = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_perPixel ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalInputsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalInputsNode.cs.meta new file mode 100644 index 0000000..da99f65 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalInputsNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 891e3ffa10c12c54e83a1e40df03df2f +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalVector.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalVector.cs new file mode 100644 index 0000000..4ce54a5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalVector.cs @@ -0,0 +1,178 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "World Normal", "Surface Data", "Per pixel world normal vector, accepts a Normal vector in tangent space (ie: normalmap)" )] + public sealed class WorldNormalVector : ParentNode + { + private const string NormalVecValStr = "newWorldNormal"; + private const string NormalVecDecStr = "float3 {0} = {1};"; + + private const string NormalizeOptionStr = "Normalize"; + private const string NormalizeFunc = "normalize( {0} )"; + + [SerializeField] + private bool m_normalize = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "Normal" ); + AddOutputVectorPorts( WirePortDataType.FLOAT3, "XYZ" ); + m_inputPorts[ 0 ].Vector3InternalData = Vector3.forward; + m_previewShaderGUID = "5f55f4841abb61e45967957788593a9d"; + m_drawPreviewAsSphere = true; + m_autoWrapProperties = true; + m_textLabelWidth = 80; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_inputPorts[ 0 ].IsConnected ) + m_previewMaterialPassId = 1; + else + m_previewMaterialPassId = 0; + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + if( m_inputPorts[ 0 ].IsConnected ) + dataCollector.DirtyNormal = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_normalize = EditorGUILayoutToggle( NormalizeOptionStr, m_normalize ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate ) + { + if( m_inputPorts[ 0 ].IsConnected ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + + string value = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( UniqueId, CurrentPrecisionType, m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ), OutputId ); + if( m_normalize ) + { + value = string.Format( NormalizeFunc, value ); + } + RegisterLocalVariable( 0, value, ref dataCollector, "worldNormal" + OutputId ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + else + { + string value = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( CurrentPrecisionType ); + string name; + if( m_normalize ) + { + name = "normalizedWorldNormal"; + value = string.Format( NormalizeFunc, value ); + RegisterLocalVariable( 0, value, ref dataCollector, name ); + } + else + { + name = value; + } + return GetOutputVectorItem( 0, outputId, name ); + } + } + + if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + + string result = string.Empty; + if( m_inputPorts[ 0 ].IsConnected ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + dataCollector.ForceNormal = true; + + result = "(WorldNormalVector( " + Constants.InputVarStr + " , " + m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) + " ))"; + if( m_normalize ) + { + result = string.Format( NormalizeFunc, result ); + } + + int connCount = 0; + for( int i = 0; i < m_outputPorts.Count; i++ ) + { + connCount += m_outputPorts[ i ].ConnectionCount; + } + + if( connCount > 1 ) + { + dataCollector.AddToFragmentLocalVariables( UniqueId, string.Format( NormalVecDecStr, NormalVecValStr + OutputId, result ) ); + return GetOutputVectorItem( 0, outputId, NormalVecValStr + OutputId ); + } + } + else + { + if( !dataCollector.DirtyNormal ) + { + result = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId, m_normalize ); + } + else + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + result = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId, m_normalize ); + dataCollector.ForceNormal = true; + } + } + + return GetOutputVectorItem( 0, outputId, result ); + } + else + { + if( m_inputPorts[ 0 ].IsConnected ) + { + string inputTangent = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + string normal = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId ); + string tangent = GeneratorUtils.GenerateWorldTangent( ref dataCollector, UniqueId ); + dataCollector.AddToVertexLocalVariables( UniqueId, "float3x3 tangentToWorld = CreateTangentToWorldPerVertex( " + normal + ", " + tangent + ", " + Constants.VertexShaderInputStr + ".tangent.w );" ); + dataCollector.AddToVertexLocalVariables( UniqueId, "float3 tangentNormal" + OutputId + " = " + inputTangent + ";" ); + string result = "(tangentToWorld[0] * tangentNormal" + OutputId + ".x + tangentToWorld[1] * tangentNormal" + OutputId + ".y + tangentToWorld[2] * tangentNormal" + OutputId + ".z)"; + if( m_normalize ) + { + result = string.Format( NormalizeFunc, result ); + } + dataCollector.AddToVertexLocalVariables( UniqueId, "float3 modWorldNormal" + OutputId + " = " + result + ";" ); + return GetOutputVectorItem( 0, outputId, "modWorldNormal" + OutputId ); + } + else + { + string result = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId, m_normalize ); + return GetOutputVectorItem( 0, outputId, result ); + } + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 14202 ) + { + m_normalize = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalize ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalVector.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalVector.cs.meta new file mode 100644 index 0000000..7646e49 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldNormalVector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d61a084db19701c4fb3030ee953ac509 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldPosInputsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldPosInputsNode.cs new file mode 100644 index 0000000..15c0b29 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldPosInputsNode.cs @@ -0,0 +1,37 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "World Position", "Surface Data", "World space position" )] + public sealed class WorldPosInputsNode : SurfaceShaderINParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentInput = SurfaceInputs.WORLD_POS; + m_drawPreviewAsSphere = true; + m_previewShaderGUID = "70d5405009b31a349a4d8285f30cf5d9"; + InitialSetup(); + } + + public override void DrawProperties() { } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if ( dataCollector.IsTemplate ) + { + string varName = dataCollector.TemplateDataCollectorInstance.GetWorldPos(); + return GetOutputVectorItem( 0, outputId, varName ); + } + + string worldPosition = GeneratorUtils.GenerateWorldPosition( ref dataCollector, UniqueId ); + + return GetOutputVectorItem( 0, outputId, worldPosition ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldPosInputsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldPosInputsNode.cs.meta new file mode 100644 index 0000000..91f10c8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldPosInputsNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 850bb0065928b7f499b869b8adc1ce5c +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflInputsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflInputsNode.cs new file mode 100644 index 0000000..99b4978 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflInputsNode.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "[Deprecated] World Reflection", "Surface Data", "World reflection vector", null, KeyCode.None, true, true, "World Reflection", typeof( WorldReflectionVector ) )] + public sealed class WorldReflInputsNode : SurfaceShaderINParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentInput = SurfaceInputs.WORLD_REFL; + InitialSetup(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflInputsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflInputsNode.cs.meta new file mode 100644 index 0000000..8e4e079 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflInputsNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e4f39f3a52f10644392decce9d1e6790 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflectionVector.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflectionVector.cs new file mode 100644 index 0000000..d9fd77b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflectionVector.cs @@ -0,0 +1,215 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "World Reflection", "Surface Data", "Per pixel world reflection vector, accepts a Normal vector in tangent space (ie: normalmap)" )] + public sealed class WorldReflectionVector : ParentNode + { + private const string ReflectionVecValStr = "newWorldReflection"; + private const string ReflectionVecDecStr = "{0} {1} = {2};"; + + private const string NormalizeOptionStr = "Normalize"; + private const string NormalizeFunc = "normalize( {0} )"; + + [SerializeField] + private bool m_normalize = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "Normal" ); + AddOutputVectorPorts( WirePortDataType.FLOAT3, "XYZ" ); + m_drawPreviewAsSphere = true; + m_previewShaderGUID = "8e267e9aa545eeb418585a730f50273e"; + m_autoWrapProperties = true; + m_textLabelWidth = 80; + //UIUtils.AddNormalDependentCount(); + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( m_inputPorts[ 0 ].IsConnected ) + m_previewMaterialPassId = 1; + else + m_previewMaterialPassId = 0; + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_normalize = EditorGUILayoutToggle( NormalizeOptionStr, m_normalize ); + } + + //public override void Destroy() + //{ + // ContainerGraph.RemoveNormalDependentCount(); + // base.Destroy(); + //} + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + if( m_inputPorts[ 0 ].IsConnected ) + dataCollector.DirtyNormal = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( dataCollector.IsTemplate ) + { + if( m_inputPorts[ 0 ].IsConnected ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + + string value = dataCollector.TemplateDataCollectorInstance.GetWorldReflection( CurrentPrecisionType, m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) ); + if( m_normalize ) + { + value = string.Format( NormalizeFunc, value ); + } + RegisterLocalVariable( 0, value, ref dataCollector, "worldRefl" + OutputId ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + else + { + string name; + string value = dataCollector.TemplateDataCollectorInstance.GetWorldReflection( CurrentPrecisionType ); + if( m_normalize ) + { + name = "normalizedWorldRefl"; + value = string.Format( NormalizeFunc, value ); + RegisterLocalVariable( 0, value, ref dataCollector, name ); + } + else + { + name = value; + } + return GetOutputVectorItem( 0, outputId, name ); + } + } + + bool isVertex = ( dataCollector.PortCategory == MasterNodePortCategory.Tessellation || dataCollector.PortCategory == MasterNodePortCategory.Vertex ); + if( isVertex ) + { + if( m_inputPorts[ 0 ].IsConnected ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + string normal = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId ); + string tangent = GeneratorUtils.GenerateWorldTangent( ref dataCollector, UniqueId ); + dataCollector.AddToVertexLocalVariables( UniqueId, "float3x3 tangentToWorld = CreateTangentToWorldPerVertex( " + normal + ", "+ tangent + ", "+ Constants.VertexShaderInputStr + ".tangent.w );" ); + string inputTangent = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + dataCollector.AddToVertexLocalVariables( UniqueId, "float3 tangentNormal" + OutputId + " = " + inputTangent + ";" ); + + string viewDir = GeneratorUtils.GenerateViewDirection( ref dataCollector, UniqueId ); + dataCollector.AddToVertexLocalVariables( UniqueId, "float3 modWorldNormal" + OutputId + " = ( tangentToWorld[0] * tangentNormal" + OutputId + ".x + tangentToWorld[1] * tangentNormal" + OutputId + ".y + tangentToWorld[2] * tangentNormal" + OutputId + ".z);" ); + + string value = "reflect( -" + viewDir + ", modWorldNormal" + OutputId + " )"; + if( m_normalize ) + { + value = string.Format( NormalizeFunc, value ); + } + + RegisterLocalVariable( 0, value, ref dataCollector, "modReflection" + OutputId ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + else + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + string worldNormal = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId ); + string viewDir = GeneratorUtils.GenerateViewDirection( ref dataCollector, UniqueId ); + + string value = "reflect( -" + viewDir + ", " + worldNormal + " )"; + if( m_normalize ) + { + value = string.Format( NormalizeFunc, value ); + } + RegisterLocalVariable( 0, value, ref dataCollector, ReflectionVecValStr + OutputId ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + } + else + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_REFL, CurrentPrecisionType ); + + string result = string.Empty; + if( m_inputPorts[ 0 ].IsConnected ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + dataCollector.ForceNormal = true; + + result = "WorldReflectionVector( " + Constants.InputVarStr + " , " + m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) + " )"; + if( m_normalize ) + { + result = String.Format( NormalizeFunc, result ); + } + int connCount = 0; + for( int i = 0; i < m_outputPorts.Count; i++ ) + { + connCount += m_outputPorts[ i ].ConnectionCount; + } + + if( connCount > 1 ) + { + string precisionType = UIUtils.PrecisionWirePortToCgType( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision, WirePortDataType.FLOAT3 ); + + dataCollector.AddToFragmentLocalVariables( UniqueId, string.Format( ReflectionVecDecStr, precisionType, ReflectionVecValStr + OutputId, result ) ); + RegisterLocalVariable( 0, result, ref dataCollector, ReflectionVecValStr + OutputId ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + } + else + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + result = GeneratorUtils.GenerateWorldReflection( ref dataCollector, UniqueId , m_normalize ); + if( dataCollector.DirtyNormal ) + dataCollector.ForceNormal = true; + } + + return GetOutputVectorItem( 0, outputId, result ); + //RegisterLocalVariable( 0, result, ref dataCollector, "worldrefVec" + OutputId ); + //return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue ); + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 14202 ) + { + m_normalize = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_normalize ); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( UIUtils.CurrentShaderVersion() <= 14202 ) + { + if( !m_inputPorts[ 0 ].IsConnected ) + { + m_normalize = true; + } + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflectionVector.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflectionVector.cs.meta new file mode 100644 index 0000000..eb2bf47 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/SurfaceShaderInputs/WorldReflectionVector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bd82e1d90bd90fc4d924e97e5fdcc7de +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures.meta new file mode 100644 index 0000000..263b4f7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3ab7ef71451065148bf8221d353c5020 +folderAsset: yes +timeCreated: 1481126945 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/BlendNormalsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/BlendNormalsNode.cs new file mode 100644 index 0000000..1c5db39 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/BlendNormalsNode.cs @@ -0,0 +1,104 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Blend Normals", "Textures", "Blend Normals" )] + public class BlendNormalsNode : ParentNode + { + public readonly static string[] ModeListStr = { "Tangent Normals", "Reoriented Tangent Normals", "Reoriented World Normals" }; + public readonly static int[] ModeListInt = { 0, 1, 2 }; + + [SerializeField] + public int m_selectedMode = 0; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT3, false, "Normal A" ); + AddInputPort( WirePortDataType.FLOAT3, false, "Normal B" ); + AddInputPort( WirePortDataType.FLOAT3, false, "Vertex Normal" ); + m_inputPorts[ 2 ].Visible = false; + AddOutputPort( WirePortDataType.FLOAT3, "XYZ" ); + m_useInternalPortData = true; + m_previewShaderGUID = "bcdf750ff5f70444f98b8a3efa50dc6f"; + } + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + m_previewMaterialPassId = m_selectedMode; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( !( dataCollector.IsTemplate && dataCollector.IsSRP ) ) + dataCollector.AddToIncludes( UniqueId, Constants.UnityStandardUtilsLibFuncs ); + + string _inputA = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string _inputB = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string result = "BlendNormals( " + _inputA + " , " + _inputB + " )"; + + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + switch( m_selectedMode ) + { + default: + case 0: + result = "BlendNormal( " + _inputA + " , " + _inputB + " )"; + break; + case 1: + result = "BlendNormalRNM( " + _inputA + " , " + _inputB + " )"; + break; + case 2: + string inputC = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + result = "BlendNormalWorldspaceRNM( " + _inputA + " , " + _inputB + ", " + inputC + " )"; + break; + } + } + return CreateOutputLocalVariable( 0, result, ref dataCollector ); + } + + public override void DrawProperties() + { + base.DrawProperties(); + if( ContainerGraph.IsSRP ) + { + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr, () => + { + EditorGUI.BeginChangeCheck(); + m_selectedMode = EditorGUILayoutIntPopup( "Mode", m_selectedMode, ModeListStr, ModeListInt ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_selectedMode == 2 ) + { + m_inputPorts[ 2 ].Visible = true; + } + else + { + m_inputPorts[ 2 ].Visible = false; + } + m_sizeIsDirty = true; + } + } ); + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 14503 ) + m_selectedMode = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedMode ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/BlendNormalsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/BlendNormalsNode.cs.meta new file mode 100644 index 0000000..b92fa34 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/BlendNormalsNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: eceb6029efe39524d83b45c10a979943 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/HeightMapBlendNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/HeightMapBlendNode.cs new file mode 100644 index 0000000..abb68d6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/HeightMapBlendNode.cs @@ -0,0 +1,81 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node HeightMap Texture Masking +// Donated by Rea + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "HeightMap Texture Blend", "Textures", "Advanced Texture Blending by using heightMap and splatMask, usefull for texture layering ", null, KeyCode.None, true, false, null, null, "Rea" )] + public sealed class HeightMapBlendNode : ParentNode + { + + private const string PreventNaNLabel = "Prevent NaN"; + private const string PreventNaNInfo = "Prevent NaN results by applying by clamping negative base numbers over the internal pow instruction to 0."; + [SerializeField] + private bool m_preventNaN = false; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "HeightMap" ); + AddInputPort( WirePortDataType.FLOAT, false, "SplatMask" ); + AddInputPort( WirePortDataType.FLOAT, false, "BlendStrength" ); + AddOutputVectorPorts( WirePortDataType.FLOAT, Constants.EmptyPortValue ); + m_textLabelWidth = 120; + m_useInternalPortData = true; + m_inputPorts[ 2 ].FloatInternalData = 1; + m_autoWrapProperties = true; + m_previewShaderGUID = "b2ac23d6d5dcb334982b6f31c2e7a734"; + } + + public override void DrawProperties() + { + base.DrawProperties(); + m_preventNaN = EditorGUILayoutToggle( PreventNaNLabel , m_preventNaN ); + EditorGUILayout.HelpBox( PreventNaNInfo , MessageType.Info ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string HeightMap = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string SplatMask = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector); + string Blend = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + string baseOp = "((" + HeightMap + "*" + SplatMask + ")*4)+(" + SplatMask + "*2)"; + if( m_preventNaN ) + baseOp = "max( (" + baseOp + "), 0 )"; + string HeightMask = "saturate(pow("+baseOp+"," + Blend + "))"; + string varName = "HeightMask" + OutputId; + + RegisterLocalVariable( 0, HeightMask, ref dataCollector , varName ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + /* + A = (heightMap * SplatMask)*4 + B = SplatMask*2 + C = pow(A+B,Blend) + saturate(C) + saturate(pow(((heightMap * SplatMask)*4)+(SplatMask*2),Blend)); + */ + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 18910 ) + m_preventNaN = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo , ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo , ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_preventNaN ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/HeightMapBlendNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/HeightMapBlendNode.cs.meta new file mode 100644 index 0000000..62736ab --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/HeightMapBlendNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b80a218ca12b89948b83d0dee41fc056 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/PannerNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/PannerNode.cs new file mode 100644 index 0000000..e20c8c0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/PannerNode.cs @@ -0,0 +1,110 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Panner", "UV Coordinates", "Pans UV texture coordinates according to its inputs" )] + public sealed class PannerNode : ParentNode + { + private const string _speedXStr = "Speed X"; + private const string _speedYStr = "Speed Y"; + + private int m_cachedUsingEditorId = -1; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT2, false, "UV" ,-1,MasterNodePortCategory.Fragment,0); + AddInputPort( WirePortDataType.FLOAT2, false, "Speed", -1, MasterNodePortCategory.Fragment, 2 ); + AddInputPort( WirePortDataType.FLOAT, false, "Time", -1, MasterNodePortCategory.Fragment, 1 ); + AddOutputPort( WirePortDataType.FLOAT2, "Out" ); + m_textLabelWidth = 70; + m_useInternalPortData = true; + m_previewShaderGUID = "6f89a5d96bdad114b9bbd0c236cac622"; + m_inputPorts[ 2 ].FloatInternalData = 1; + m_continuousPreviewRefresh = true; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if ( m_cachedUsingEditorId == -1 ) + m_cachedUsingEditorId = Shader.PropertyToID( "_UsingEditor" ); + + PreviewMaterial.SetFloat( m_cachedUsingEditorId, ( m_inputPorts[ 2 ].IsConnected ? 0 : 1 ) ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + if( portId == 1 ) + { + m_continuousPreviewRefresh = false; + } + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + if( portId == 1 ) + { + m_continuousPreviewRefresh = true; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string timePort = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + + if( !m_inputPorts[ 2 ].IsConnected ) + { + if( !( dataCollector.IsTemplate && dataCollector.IsSRP ) ) + dataCollector.AddToIncludes( UniqueId, Constants.UnityShaderVariables ); + timePort += " * _Time.y"; + } + + string speed = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string result = "( " + timePort + " * " + speed + " + " + m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) + ")"; + + RegisterLocalVariable( 0, result, ref dataCollector, "panner" + OutputId ); + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() < 13107 ) + { + // The internal data for the new port can be set in here since it didn't existed + // on older shader versions + float speedX = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + float speedY = Convert.ToSingle( GetCurrentParam( ref nodeParams ) ); + m_inputPorts[ 1 ].Vector2InternalData = new Vector2( speedX, speedY ); + } + } + + public override void ReadInputDataFromString( ref string[] nodeParams ) + { + base.ReadInputDataFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() < 13107 ) + { + //Time Port must be rewritten after internal data is read + // already existed in previous shaders + m_inputPorts[ 2 ].FloatInternalData = 1; + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/PannerNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/PannerNode.cs.meta new file mode 100644 index 0000000..e05e46e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/PannerNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 08ddf1dd61719944b9e50d4bc87c0413 +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/RotatorNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/RotatorNode.cs new file mode 100644 index 0000000..18aa778 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/RotatorNode.cs @@ -0,0 +1,96 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Rotator", "UV Coordinates", "Rotates UVs or any Vector2 value from an Anchor point for a specified Time value")] + public sealed class RotatorNode : ParentNode + { + private int m_cachedUsingEditorId = -1; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT2, false, "UV" ); + AddInputPort( WirePortDataType.FLOAT2, false, "Anchor" ); + AddInputPort( WirePortDataType.FLOAT, false, "Time" ); + AddOutputPort( WirePortDataType.FLOAT2, "Out" ); + m_useInternalPortData = true; + m_inputPorts[ 2 ].FloatInternalData = 1; + m_textLabelWidth = 50; + m_previewShaderGUID = "e21408a1c7f12f14bbc2652f69bce1fc"; + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if ( m_cachedUsingEditorId == -1 ) + m_cachedUsingEditorId = Shader.PropertyToID( "_UsingEditor" ); + + PreviewMaterial.SetFloat( m_cachedUsingEditorId, (m_inputPorts[ 2 ].IsConnected ? 0 : 1 ) ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + if( portId == 2 ) + { + m_continuousPreviewRefresh = false; + } + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + if( portId == 2 ) + { + m_continuousPreviewRefresh = true; + } + } + + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + string result = string.Empty; + string uv = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string anchor = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + string time = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + if ( !m_inputPorts[ 2 ].IsConnected ) + { + if( !( dataCollector.IsTemplate && dataCollector.IsSRP ) ) + dataCollector.AddToIncludes( UniqueId, Constants.UnityShaderVariables ); + time += " * _Time.y"; + } + + result += uv; + + string cosVar = "cos" + OutputId; + string sinVar = "sin" + OutputId; + dataCollector.AddLocalVariable( UniqueId, "float " + cosVar + " = cos( "+time+" );"); + dataCollector.AddLocalVariable( UniqueId, "float " + sinVar + " = sin( "+time+" );"); + + string value = "mul( " + result + " - " + anchor + " , float2x2( "+cosVar+" , -"+sinVar+" , "+sinVar+" , "+cosVar+" )) + "+anchor; + RegisterLocalVariable( 0, value, ref dataCollector, "rotator" + OutputId ); + + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( UIUtils.CurrentShaderVersion() < 13107 ) + { + m_inputPorts[ 2 ].FloatInternalData = 1; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/RotatorNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/RotatorNode.cs.meta new file mode 100644 index 0000000..b031237 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/RotatorNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e228d03a789934a4f90f9587396692e3 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerNode.cs new file mode 100644 index 0000000..c80a2ce --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerNode.cs @@ -0,0 +1,2325 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + // Disabling Substance Deprecated warning + + public enum TexReferenceType + { + Object = 0, + Instance + } + + public enum MipType + { + Auto, + MipLevel, + MipBias, + Derivative + } + + public enum ReferenceState + { + Self, + Connected, + Instance + } + + [Serializable] +#if UNITY_2018_1_OR_NEWER + [NodeAttributes( "Texture Sample", "Textures", "Samples a chosen texture and returns its color values, Texture and UVs can be overriden and you can select different mip modes and levels. It can also unpack and scale textures marked as normalmaps.", KeyCode.T, true, 0, int.MaxValue, typeof( Texture ), typeof( Texture2D ), typeof( Texture3D ), typeof( Cubemap ), typeof( CustomRenderTexture ), Tags = "Array" )] +#else + + // Disabling Substance Deprecated warning +#pragma warning disable 0618 + [NodeAttributes("Texture Sample", "Textures", "Samples a chosen texture and returns its color values, Texture and UVs can be overriden and you can select different mip modes and levels. It can also unpack and scale textures marked as normalmaps.", KeyCode.T, true, 0, int.MaxValue, typeof(Texture), typeof(Texture2D), typeof(Texture3D), typeof(Cubemap), typeof(ProceduralTexture), typeof(RenderTexture) +#if UNITY_2017_1_OR_NEWER + ,typeof( CustomRenderTexture ) +#endif + )] +#pragma warning restore 0618 +#endif + public sealed class SamplerNode : TexturePropertyNode + { + private const string MipModeStr = "Mip Mode"; + + private const string DefaultTextureUseSematicsStr = "Use Semantics"; + private const string DefaultTextureIsNormalMapsStr = "Is Normal Map"; + + private const string NormalScaleStr = "Scale"; + + private float InstanceIconWidth = 19; + private float InstanceIconHeight = 19; + + private readonly Color ReferenceHeaderColor = new Color( 2.66f, 1.02f, 0.6f, 1.0f ); + + public readonly static int[] AvailableAutoCast = { 0, 1, 2, 3, 4 }; + public readonly static string[] AvailableAutoCastStr = { "Auto", "Locked To Texture 1D", "Locked To Texture 2D", "Locked To Texture 3D", "Locked To Cube" }; + + [SerializeField] + private int m_textureCoordSet = 0; + + [SerializeField] + private bool m_autoUnpackNormals = false; + + [SerializeField] + private bool m_useSemantics; + + [SerializeField] + private string m_samplerType; + + [SerializeField] + private MipType m_mipMode = MipType.Auto; + + [SerializeField] + private TexReferenceType m_referenceType = TexReferenceType.Object; + + [SerializeField] + private int m_referenceArrayId = -1; + + [SerializeField] + private int m_referenceNodeId = -1; + + private SamplerNode m_referenceSampler = null; + + [SerializeField] + private GUIStyle m_referenceStyle = null; + + [SerializeField] + private GUIStyle m_referenceIconStyle = null; + + [SerializeField] + private GUIContent m_referenceContent = null; + + [SerializeField] + private float m_referenceWidth = -1; + + [SerializeField] + private SamplerStateAutoGenerator m_samplerStateAutoGenerator = new SamplerStateAutoGenerator(); + + private Vector4Node m_texCoordsHelper; + + private string m_previousAdditionalText = string.Empty; + + private int m_cachedUvsId = -1; + private int m_cachedUnpackId = -1; + private int m_cachedLodId = -1; + + private InputPort m_texPort; + private InputPort m_uvPort; + private InputPort m_lodPort; + private InputPort m_ddxPort; + private InputPort m_ddyPort; + private InputPort m_normalPort; + private InputPort m_samplerPort; + private InputPort m_indexPort; + private OutputPort m_colorPort; + + private TexturePropertyNode m_previewTextProp = null; + private ReferenceState m_state = ReferenceState.Self; + + private Rect m_iconPos; + + public SamplerNode() : base() { } + public SamplerNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + if( m_useSamplerArrayIdx < 0 ) + { + m_useSamplerArrayIdx = 0; + } + + m_defaultTextureValue = TexturePropertyValues.white; + AddInputPort( WirePortDataType.SAMPLER2D, false, "Tex" ); + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.SAMPLER2DARRAY, WirePortDataType.OBJECT ); + AddInputPort( WirePortDataType.FLOAT2, false, "UV" ); + AddInputPort( WirePortDataType.FLOAT, false, "Level" ); + AddInputPort( WirePortDataType.FLOAT2, false, "DDX" ); + AddInputPort( WirePortDataType.FLOAT2, false, "DDY" ); + AddInputPort( WirePortDataType.FLOAT, false, NormalScaleStr ); + AddInputPort( WirePortDataType.FLOAT, false, "Index" ); + AddInputPort( WirePortDataType.SAMPLERSTATE, false, "SS" ); + m_inputPorts[ 7 ].CreatePortRestrictions( WirePortDataType.SAMPLERSTATE ); + + m_texPort = m_inputPorts[ 0 ]; + m_uvPort = m_inputPorts[ 1 ]; + m_lodPort = m_inputPorts[ 2 ]; + m_ddxPort = m_inputPorts[ 3 ]; + m_ddyPort = m_inputPorts[ 4 ]; + m_normalPort = m_inputPorts[ 5 ]; + m_indexPort = m_inputPorts[ 6 ]; + m_samplerPort = m_inputPorts[ 7 ]; + m_lodPort.AutoDrawInternalData = true; + m_indexPort.AutoDrawInternalData = true; + m_normalPort.AutoDrawInternalData = true; + m_lodPort.Visible = false; + m_ddxPort.Visible = false; + m_ddyPort.Visible = false; + m_indexPort.Visible = false; + m_normalPort.Visible = m_autoUnpackNormals; + m_normalPort.FloatInternalData = 1.0f; + + //Remove output port (sampler) + m_outputPortsDict.Remove( m_outputPorts[ 1 ].PortId ); + m_outputPorts.RemoveAt( 1 ); + + m_outputPortsDict.Remove( m_outputPorts[ 0 ].PortId ); + m_outputPorts.RemoveAt( 0 ); + + AddOutputColorPorts( "RGBA" ); + m_colorPort = m_outputPorts[ 0 ]; + m_currentParameterType = PropertyType.Property; + // m_useCustomPrefix = true; + m_customPrefix = "Texture Sample "; + m_referenceContent = new GUIContent( string.Empty ); + m_freeType = false; + m_useSemantics = true; + m_drawPicker = false; + ConfigTextureData( TextureType.Texture2D ); + m_selectedLocation = PreviewLocation.TopCenter; + m_previewShaderGUID = "7b4e86a89b70ae64993bf422eb406422"; + + m_errorMessageTooltip = "A texture object marked as normal map is connected to this sampler. Please consider turning on the Unpack Normal Map option"; + m_errorMessageTypeIsError = NodeMessageType.Warning; + m_textLabelWidth = 135; + m_customPrecision = false; + } + + public override void SetPreviewInputs() + { + //TODO: rewrite this to be faster + base.SetPreviewInputs(); + + if( m_cachedUvsId == -1 ) + m_cachedUvsId = Shader.PropertyToID( "_CustomUVs" ); + + PreviewMaterial.SetInt( m_cachedUvsId, ( m_uvPort.IsConnected ? 1 : 0 ) ); + + if( m_cachedUnpackId == -1 ) + m_cachedUnpackId = Shader.PropertyToID( "_Unpack" ); + + PreviewMaterial.SetInt( m_cachedUnpackId, m_autoUnpackNormals ? 1 : 0 ); + + if( m_cachedLodId == -1 ) + m_cachedLodId = Shader.PropertyToID( "_LodType" ); + + PreviewMaterial.SetInt( m_cachedLodId, ( m_mipMode == MipType.MipLevel ? 1 : ( m_mipMode == MipType.MipBias ? 2 : 0 ) ) ); + + if( m_typeId == -1 ) + m_typeId = Shader.PropertyToID( "_Type" ); + + bool usingTexture = false; + if( m_texPort.IsConnected ) + { + usingTexture = true; + SetPreviewTexture( m_texPort.InputPreviewTexture( ContainerGraph ) ); + } + else if( SoftValidReference && m_referenceSampler.TextureProperty != null ) + { + if( m_referenceSampler.TextureProperty.Value != null ) + { + usingTexture = true; + SetPreviewTexture( m_referenceSampler.TextureProperty.Value ); + } + else + { + usingTexture = true; + SetPreviewTexture( m_referenceSampler.PreviewTexture ); + } + } + else if( TextureProperty != null ) + { + if( TextureProperty.Value != null ) + { + usingTexture = true; + SetPreviewTexture( TextureProperty.Value ); + } + } + + if( m_defaultId == -1 ) + m_defaultId = Shader.PropertyToID( "_Default" ); + + if( usingTexture ) + { + PreviewMaterial.SetInt( m_defaultId, 0 ); + m_previewMaterialPassId = 1; + } + else + { + PreviewMaterial.SetInt( m_defaultId, ( (int)m_defaultTextureValue ) + 1 ); + m_previewMaterialPassId = 0; + } + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + if( m_referenceType == TexReferenceType.Object ) + { + UIUtils.RegisterSamplerNode( this ); + UIUtils.RegisterPropertyNode( this ); + } + m_textureProperty = this; + + if( UniqueId > -1 ) + ContainerGraph.SamplerNodes.OnReorderEventComplete += OnReorderEventComplete; + } + + private void OnReorderEventComplete() + { + if( m_referenceType == TexReferenceType.Instance && m_referenceSampler != null ) + { + m_referenceArrayId = ContainerGraph.SamplerNodes.GetNodeRegisterIdx( m_referenceSampler.UniqueId ); + } + } + + public void ConfigSampler() + { + switch( m_currentType ) + { + case TextureType.Texture1D: + m_samplerType = "tex1D"; + break; + case TextureType.ProceduralTexture: + case TextureType.Texture2D: + m_samplerType = "tex2D"; + break; + case TextureType.Texture2DArray: + m_samplerType = "tex2DArray"; + break; + case TextureType.Texture3D: + m_samplerType = "tex3D"; + break; + case TextureType.Cube: + m_samplerType = "texCUBE"; + break; + } + } + + public override void DrawSubProperties() + { + ShowDefaults(); + + DrawSamplerOptions(); + + EditorGUI.BeginChangeCheck(); + Type currType = ( m_autocastMode == AutoCastType.Auto ) ? typeof( Texture ) : m_textureType; + m_defaultValue = EditorGUILayoutObjectField( Constants.DefaultValueLabel, m_defaultValue, currType, false ) as Texture; + if( EditorGUI.EndChangeCheck() ) + { + CheckTextureImporter( true ); + SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) ); + ConfigureInputPorts(); + ConfigureOutputPorts(); + //ResizeNodeToPreview(); + } + } + + public override void DrawMaterialProperties() + { + ShowDefaults(); + + DrawSamplerOptions(); + + EditorGUI.BeginChangeCheck(); + Type currType = ( m_autocastMode == AutoCastType.Auto ) ? typeof( Texture ) : m_textureType; + m_materialValue = EditorGUILayoutObjectField( Constants.MaterialValueLabel, m_materialValue, currType, false ) as Texture; + if( EditorGUI.EndChangeCheck() ) + { + CheckTextureImporter( true ); + SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) ); + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + } + + new void ShowDefaults() + { + m_defaultTextureValue = (TexturePropertyValues)EditorGUILayoutEnumPopup( DefaultTextureStr, m_defaultTextureValue ); + //AutoCastType newAutoCast = (AutoCastType)EditorGUILayoutIntPopup( AutoCastModeStr, (int)m_autocastMode, AvailableAutoCastStr, AvailableAutoCast ); + AutoCastType newAutoCast = (AutoCastType)EditorGUILayoutEnumPopup( AutoCastModeStr, m_autocastMode ); + if( newAutoCast != m_autocastMode ) + { + m_autocastMode = newAutoCast; + if( m_autocastMode != AutoCastType.Auto ) + { + ConfigTextureData( m_currentType ); + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + } + } + + public override void AdditionalCheck() + { + m_autoUnpackNormals = m_isNormalMap; + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + + + public override void OnConnectedOutputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( portId, otherNodeId, otherPortId, name, type ); + if( portId == m_texPort.PortId ) + { + m_texPort.MatchPortToConnection(); + m_textureProperty = m_texPort.GetOutputNodeWhichIsNotRelay( 0 ) as TexturePropertyNode; + if( m_textureProperty != null ) + { + m_currentType = m_textureProperty.CurrentType; + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + else + { + m_currentType = Constants.WireToTexture[ type ]; + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + } + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + + if( portId == m_texPort.PortId ) + { + m_texPort.MatchPortToConnection(); + m_textureProperty = m_texPort.GetOutputNodeWhichIsNotRelay( 0 ) as TexturePropertyNode; + if( m_textureProperty == null ) + { + if( Constants.WireToTexture.TryGetValue( m_texPort.ConnectionType() , out m_currentType ) ) + { + //m_currentType = Constants.WireToTexture[ m_texPort.ConnectionType() ]; + m_textureProperty = this; + // This cast fails only from within shader functions if connected to a Sampler Input + // and in this case property is set by what is connected to that input + UIUtils.UnregisterPropertyNode( this ); + UIUtils.UnregisterTexturePropertyNode( this ); + } + } + else + { + m_currentType = m_textureProperty.CurrentType; + + UIUtils.UnregisterPropertyNode( this ); + UIUtils.UnregisterTexturePropertyNode( this ); + } + + ConfigureInputPorts(); + ConfigureOutputPorts(); + //ResizeNodeToPreview(); + } + + UpdateTitle(); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + + if( portId == m_texPort.PortId ) + { + m_textureProperty = this; + + if( m_referenceType == TexReferenceType.Object ) + { + UIUtils.RegisterPropertyNode( this ); + UIUtils.RegisterTexturePropertyNode( this ); + } + + ConfigureOutputPorts(); + //ResizeNodeToPreview(); + } + + UpdateTitle(); + } + + private void ForceInputPortsChange() + { + m_texPort.ChangeType( Constants.TextureToWire[ m_currentType ], false ); + m_normalPort.ChangeType( WirePortDataType.FLOAT, false ); + switch( m_currentType ) + { + case TextureType.Texture1D: + m_uvPort.ChangeType( WirePortDataType.FLOAT, false ); + m_ddxPort.ChangeType( WirePortDataType.FLOAT, false ); + m_ddyPort.ChangeType( WirePortDataType.FLOAT, false ); + break; + case TextureType.ProceduralTexture: + case TextureType.Texture2D: + case TextureType.Texture2DArray: + m_uvPort.ChangeType( WirePortDataType.FLOAT2, false ); + m_ddxPort.ChangeType( WirePortDataType.FLOAT2, false ); + m_ddyPort.ChangeType( WirePortDataType.FLOAT2, false ); + break; + case TextureType.Texture3D: + case TextureType.Cube: + m_uvPort.ChangeType( WirePortDataType.FLOAT3, false ); + m_ddxPort.ChangeType( WirePortDataType.FLOAT3, false ); + m_ddyPort.ChangeType( WirePortDataType.FLOAT3, false ); + break; + } + } + + public override void ConfigureInputPorts() + { + m_normalPort.Visible = AutoUnpackNormals; + + switch( m_mipMode ) + { + case MipType.Auto: + m_lodPort.Visible = false; + m_ddxPort.Visible = false; + m_ddyPort.Visible = false; + break; + case MipType.MipLevel: + m_lodPort.Name = "Level"; + m_lodPort.Visible = true; + m_ddxPort.Visible = false; + m_ddyPort.Visible = false; + break; + case MipType.MipBias: + m_lodPort.Name = "Bias"; + m_lodPort.Visible = true; + m_ddxPort.Visible = false; + m_ddyPort.Visible = false; + break; + case MipType.Derivative: + m_lodPort.Visible = false; + m_ddxPort.Visible = true; + m_ddyPort.Visible = true; + break; + } + + switch( m_currentType ) + { + case TextureType.Texture1D: + m_uvPort.ChangeType( WirePortDataType.FLOAT, false ); + m_ddxPort.ChangeType( WirePortDataType.FLOAT, false ); + m_ddyPort.ChangeType( WirePortDataType.FLOAT, false ); + break; + case TextureType.ProceduralTexture: + case TextureType.Texture2D: + case TextureType.Texture2DArray: + m_uvPort.ChangeType( WirePortDataType.FLOAT2, false ); + m_ddxPort.ChangeType( WirePortDataType.FLOAT2, false ); + m_ddyPort.ChangeType( WirePortDataType.FLOAT2, false ); + break; + case TextureType.Texture3D: + case TextureType.Cube: + m_uvPort.ChangeType( WirePortDataType.FLOAT3, false ); + m_ddxPort.ChangeType( WirePortDataType.FLOAT3, false ); + m_ddyPort.ChangeType( WirePortDataType.FLOAT3, false ); + break; + } + + if( m_currentType == TextureType.Texture2DArray ) + m_indexPort.Visible = true; + else + m_indexPort.Visible = false; + + m_sizeIsDirty = true; + } + + public override void ConfigureOutputPorts() + { + m_outputPorts[ m_colorPort.PortId + 4 ].Visible = !AutoUnpackNormals; + + if( !AutoUnpackNormals ) + { + m_colorPort.ChangeProperties( "RGBA", WirePortDataType.COLOR, false ); + m_outputPorts[ m_colorPort.PortId + 1 ].ChangeProperties( "R", WirePortDataType.FLOAT, false ); + m_outputPorts[ m_colorPort.PortId + 2 ].ChangeProperties( "G", WirePortDataType.FLOAT, false ); + m_outputPorts[ m_colorPort.PortId + 3 ].ChangeProperties( "B", WirePortDataType.FLOAT, false ); + m_outputPorts[ m_colorPort.PortId + 4 ].ChangeProperties( "A", WirePortDataType.FLOAT, false ); + + } + else + { + m_colorPort.ChangeProperties( "XYZ", WirePortDataType.FLOAT3, false ); + m_outputPorts[ m_colorPort.PortId + 1 ].ChangeProperties( "X", WirePortDataType.FLOAT, false ); + m_outputPorts[ m_colorPort.PortId + 2 ].ChangeProperties( "Y", WirePortDataType.FLOAT, false ); + m_outputPorts[ m_colorPort.PortId + 3 ].ChangeProperties( "Z", WirePortDataType.FLOAT, false ); + } + + m_sizeIsDirty = true; + } + + void UpdateTitle() + { + if( m_referenceType == TexReferenceType.Object ) + { + SetTitleText( m_propertyInspectorName ); + SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) ); + } + + m_sizeIsDirty = true; + } + + public override void OnObjectDropped( UnityEngine.Object obj ) + { + base.OnObjectDropped( obj ); + ConfigFromObject( obj ); + } + + public override void SetupFromCastObject( UnityEngine.Object obj ) + { + base.SetupFromCastObject( obj ); + ConfigFromObject( obj ); + } + + void UpdateHeaderColor() + { + m_headerColorModifier = ( m_referenceType == TexReferenceType.Object ) ? Color.white : ReferenceHeaderColor; + } + + void ShowSamplerUI() + { + EditorGUI.BeginDisabledGroup( m_samplerPort.IsConnected ); + string[] contents = UIUtils.TexturePropertyNodeArr(); + string[] arr = new string[ contents.Length + 1 ]; + arr[ 0 ] = ""; + for( int i = 1; i < contents.Length + 1; i++ ) + { + arr[ i ] = contents[ i - 1 ]; + } + m_useSamplerArrayIdx = EditorGUILayoutPopup( "Reference Sampler", m_useSamplerArrayIdx, arr ); + EditorGUI.EndDisabledGroup(); + } + + public void DrawSamplerOptions() + { + if( !m_indexPort.IsConnected ) + { + m_indexPort.FloatInternalData = EditorGUILayoutFloatField( "Index", m_indexPort.FloatInternalData ); + } + + m_textureCoordSet = EditorGUILayoutIntPopup( Constants.AvailableUVSetsLabel, m_textureCoordSet, Constants.AvailableUVSetsStr, Constants.AvailableUVSets ); + + MipType newMipMode = (MipType)EditorGUILayoutEnumPopup( MipModeStr, m_mipMode ); + if( newMipMode != m_mipMode ) + { + m_mipMode = newMipMode; + ConfigureInputPorts(); + ConfigureOutputPorts(); + //ResizeNodeToPreview(); + } + + if( !m_lodPort.IsConnected && m_lodPort.Visible ) + { + m_lodPort.FloatInternalData = EditorGUILayoutFloatField( newMipMode == MipType.MipBias ? "Mip Bias" : "Mip Level", m_lodPort.FloatInternalData ); + } + + if( m_currentType == TextureType.Texture2DArray && ( newMipMode == MipType.Derivative || newMipMode == MipType.MipBias ) && !UIUtils.CurrentWindow.OutsideGraph.IsSRP ) + { + EditorGUILayout.HelpBox( "Derivative and Bias mip modes for Texture Arrays only works on some platforms (D3D11 XBOXONE GLES3 GLCORE)", MessageType.Warning ); + } + + EditorGUI.BeginChangeCheck(); + m_autoUnpackNormals = EditorGUILayoutToggle( "Unpack Normal Map", m_autoUnpackNormals ); + if( m_autoUnpackNormals && !m_normalPort.IsConnected ) + { + m_normalPort.FloatInternalData = EditorGUILayoutFloatField( NormalScaleStr, m_normalPort.FloatInternalData ); + } + + if( EditorGUI.EndChangeCheck() ) + { + ConfigureInputPorts(); + ConfigureOutputPorts(); + //ResizeNodeToPreview(); + } + ShowSamplerUI(); + if( m_showErrorMessage ) + { + EditorGUILayout.HelpBox( m_errorMessageTooltip, MessageType.Warning ); + } + } + + public override void DrawMainPropertyBlock() + { + EditorGUI.BeginChangeCheck(); + m_referenceType = (TexReferenceType)EditorGUILayoutPopup( Constants.ReferenceTypeStr, (int)m_referenceType, Constants.ReferenceArrayLabels ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_referenceType == TexReferenceType.Object ) + { + UIUtils.RegisterSamplerNode( this ); + UIUtils.RegisterPropertyNode( this ); + if( !m_texPort.IsConnected ) + UIUtils.RegisterTexturePropertyNode( this ); + + SetTitleText( m_propertyInspectorName ); + SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) ); + m_referenceArrayId = -1; + m_referenceNodeId = -1; + m_referenceSampler = null; + m_textureProperty = m_texPort.IsConnected ? m_texPort.GetOutputNodeWhichIsNotRelay( 0 ) as TexturePropertyNode : this; + + } + else + { + UIUtils.UnregisterSamplerNode( this ); + UIUtils.UnregisterPropertyNode( this ); + if( !m_texPort.IsConnected ) + UIUtils.UnregisterTexturePropertyNode( this ); + } + UpdateHeaderColor(); + } + + if( m_referenceType == TexReferenceType.Object ) + { + EditorGUI.BeginChangeCheck(); + if( m_texPort.IsConnected ) + { + m_drawAttributes = false; + DrawSamplerOptions(); + } + else + { + m_drawAttributes = true; + base.DrawMainPropertyBlock(); + } + if( EditorGUI.EndChangeCheck() ) + { + OnPropertyNameChanged(); + } + } + else + { + m_drawAttributes = true; + string[] arr = UIUtils.SamplerNodeArr(); + bool guiEnabledBuffer = GUI.enabled; + if( arr != null && arr.Length > 0 ) + { + GUI.enabled = true; + } + else + { + m_referenceArrayId = -1; + GUI.enabled = false; + } + + EditorGUI.BeginChangeCheck(); + m_referenceArrayId = EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceArrayId, arr ); + if( EditorGUI.EndChangeCheck() ) + { + m_referenceSampler = ContainerGraph.SamplerNodes.GetNode( m_referenceArrayId ); + if( m_referenceSampler != null ) + { + m_referenceNodeId = m_referenceSampler.UniqueId; + } + else + { + m_referenceArrayId = -1; + m_referenceNodeId = -1; + } + } + GUI.enabled = guiEnabledBuffer; + + DrawSamplerOptions(); + } + } + + public override void OnPropertyNameChanged() + { + base.OnPropertyNameChanged(); + UIUtils.UpdateSamplerDataNode( UniqueId, PropertyName ); + UIUtils.UpdateTexturePropertyDataNode( UniqueId, PropertyName ); + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if( m_state != ReferenceState.Self && drawInfo.CurrentEventType == EventType.MouseDown && m_previewRect.Contains( drawInfo.MousePosition ) && drawInfo.LeftMouseButtonPressed ) + { + UIUtils.FocusOnNode( m_previewTextProp, 1, true ); + Event.current.Use(); + } + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + CheckReference(); + + if( SoftValidReference ) + { + m_state = ReferenceState.Instance; + m_previewTextProp = m_referenceSampler.TextureProperty; + } + else if( m_texPort.IsConnected ) + { + m_state = ReferenceState.Connected; + m_previewTextProp = TextureProperty; + } + else + { + m_state = ReferenceState.Self; + } + + if( m_previewTextProp == null ) + m_previewTextProp = this; + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + if( m_drawPreview ) + { + m_iconPos = m_globalPosition; + m_iconPos.width = InstanceIconWidth * drawInfo.InvertedZoom; + m_iconPos.height = InstanceIconHeight * drawInfo.InvertedZoom; + + m_iconPos.y += 10 * drawInfo.InvertedZoom; + m_iconPos.x += m_globalPosition.width - m_iconPos.width - 5 * drawInfo.InvertedZoom; + } + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + + if( !m_isVisible ) + return; + + if( drawInfo.CurrentEventType != EventType.Repaint ) + return; + + switch( m_state ) + { + default: + case ReferenceState.Self: + { + m_drawPreview = false; + //SetTitleText( PropertyInspectorName /*m_propertyInspectorName*/ ); + //small optimization, string format or concat on every frame generates garbage + //string tempVal = GetPropertyValStr(); + //if ( !m_previousAdditionalText.Equals( tempVal ) ) + //{ + // m_previousAdditionalText = tempVal; + // m_additionalContent.text = string.Concat( "Value( ", tempVal, " )" ); + //} + + m_drawPicker = true; + } + break; + case ReferenceState.Connected: + { + m_drawPreview = true; + m_drawPicker = false; + + SetTitleText( m_previewTextProp.PropertyInspectorName + " (Input)" ); + m_previousAdditionalText = m_previewTextProp.AdditonalTitleContent.text; + SetAdditonalTitleText( m_previousAdditionalText ); + // Draw chain lock + GUI.Label( m_iconPos, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerTextureIcon ) ); + + // Draw frame around preview + GUI.Label( m_previewRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + } + break; + case ReferenceState.Instance: + { + m_drawPreview = true; + m_drawPicker = false; + + //SetTitleText( m_previewTextProp.PropertyInspectorName + Constants.InstancePostfixStr ); + //m_previousAdditionalText = m_previewTextProp.AdditonalTitleContent.text; + //SetAdditonalTitleText( m_previousAdditionalText ); + + SetTitleTextOnCallback( m_previewTextProp.PropertyInspectorName, ( instance, newTitle ) => instance.TitleContent.text = newTitle + Constants.InstancePostfixStr ); + if( m_previewTextProp.AdditonalTitleContent.text != m_additionalContent.text ) + { + PreviewIsDirty = true; + } + SetAdditonalTitleText( m_previewTextProp.AdditonalTitleContent.text ); + + // Draw chain lock + GUI.Label( m_iconPos, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerTextureIcon ) ); + + // Draw frame around preview + GUI.Label( m_previewRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + } + break; + } + } + + void CheckReference() + { + if( m_referenceType != TexReferenceType.Instance ) + { + return; + } + + if( m_referenceArrayId > -1 ) + { + ParentNode newNode = ContainerGraph.SamplerNodes.GetNode( m_referenceArrayId ); + if( newNode == null || newNode.UniqueId != m_referenceNodeId ) + { + m_referenceSampler = null; + int count = ContainerGraph.SamplerNodes.NodesList.Count; + for( int i = 0; i < count; i++ ) + { + ParentNode node = ContainerGraph.SamplerNodes.GetNode( i ); + if( node.UniqueId == m_referenceNodeId ) + { + m_referenceSampler = node as SamplerNode; + m_referenceArrayId = i; + break; + } + } + } + else + { + m_texPort.DataType = m_referenceSampler.TexPort.DataType; + // Set current type + TextureType newTextureType = m_referenceSampler.CurrentType; + + // Set References Options + AutoCastType newAutoCast = m_referenceSampler.AutocastMode; + if( newAutoCast != m_autocastMode || newTextureType != m_currentType ) + { + m_currentType = newTextureType; + m_autocastMode = newAutoCast; + //if( m_autocastMode != AutoCastType.Auto ) + { + ConfigTextureData( m_currentType ); + ConfigureInputPorts(); + ConfigureOutputPorts(); + //ResizeNodeToPreview(); + } + } + } + } + + if( m_referenceSampler == null && m_referenceNodeId > -1 ) + { + m_referenceNodeId = -1; + m_referenceArrayId = -1; + } + } + + public void SetTitleTextDelay( string newText ) + { + if( !newText.Equals( m_content.text ) ) + { + m_content.text = newText; + BeginDelayedDirtyProperty(); + } + } + + public void SetAdditonalTitleTextDelay( string newText ) + { + if( !newText.Equals( m_additionalContent.text ) ) + { + m_additionalContent.text = newText; + BeginDelayedDirtyProperty(); + } + } + + private void DrawTexturePropertyPreview( DrawInfo drawInfo, bool instance ) + { + if( drawInfo.CurrentEventType != EventType.Repaint ) + return; + + Rect newPos = m_previewRect; + + TexturePropertyNode texProp = null; + if( instance ) + texProp = m_referenceSampler.TextureProperty; + else + texProp = TextureProperty; + + if( texProp == null ) + texProp = this; + + float previewSizeX = PreviewSizeX; + float previewSizeY = PreviewSizeY; + newPos.width = previewSizeX * drawInfo.InvertedZoom; + newPos.height = previewSizeY * drawInfo.InvertedZoom; + + SetTitleText( texProp.PropertyInspectorName + ( instance ? Constants.InstancePostfixStr : " (Input)" ) ); + SetAdditonalTitleText( texProp.AdditonalTitleContent.text ); + + if( m_referenceStyle == null ) + { + m_referenceStyle = UIUtils.GetCustomStyle( CustomStyle.SamplerTextureRef ); + } + + if( m_referenceIconStyle == null || m_referenceIconStyle.normal == null ) + { + m_referenceIconStyle = UIUtils.GetCustomStyle( CustomStyle.SamplerTextureIcon ); + if( m_referenceIconStyle != null && m_referenceIconStyle.normal != null && m_referenceIconStyle.normal.background != null ) + { + InstanceIconWidth = m_referenceIconStyle.normal.background.width; + InstanceIconHeight = m_referenceIconStyle.normal.background.height; + } + } + + Rect iconPos = m_globalPosition; + iconPos.width = InstanceIconWidth * drawInfo.InvertedZoom; + iconPos.height = InstanceIconHeight * drawInfo.InvertedZoom; + + iconPos.y += 10 * drawInfo.InvertedZoom; + iconPos.x += m_globalPosition.width - iconPos.width - 5 * drawInfo.InvertedZoom; + + //if ( GUI.Button( newPos, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerTextureRef )/* m_referenceStyle */) || + // GUI.Button( iconPos, string.Empty, m_referenceIconStyle ) + // ) + //{ + // UIUtils.FocusOnNode( texProp, 1, true ); + //} + + if( texProp.Value != null ) + { + DrawPreview( drawInfo, m_previewRect ); + GUI.Label( newPos, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + //UIUtils.GetCustomStyle( CustomStyle.SamplerButton ).fontSize = ( int )Mathf.Round( 9 * drawInfo.InvertedZoom ); + } + } + + public override string GenerateSamplerPropertyName( int outputId, ref MasterNodeDataCollector dataCollector ) + { + string generatedSamplerState = PropertyName; + if( m_forceSamplingMacrosGen ) + { + generatedSamplerState = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, PropertyName, m_variableMode ); + } + + if( outputId > 0 ) + return generatedSamplerState; + else + return PropertyName; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + UIUtils.ShowMessage( UniqueId, m_nodeAttribs.Name + " cannot be used on Master Node Tessellation port" ); + return "(-1)"; + } + + OnPropertyNameChanged(); + + ConfigSampler(); + + string portProperty = string.Empty; + if( m_texPort.IsConnected ) + portProperty = m_texPort.GenerateShaderForOutput( ref dataCollector, true ); + + if( SoftValidReference ) + { + OrderIndex = m_referenceSampler.RawOrderIndex; + if( m_referenceSampler.TexPort.IsConnected ) + { + portProperty = m_referenceSampler.TexPort.GeneratePortInstructions( ref dataCollector ); + } + else + { + m_referenceSampler.RegisterProperty( ref dataCollector ); + } + } + + if( IsObject && ( !m_texPort.IsConnected || portProperty == "0.0" ) ) + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + + string valueName = SetFetchedData( ref dataCollector, ignoreLocalVar, outputId, portProperty ); + if( TextureProperty is VirtualTextureObject ) + { + return valueName; + } + else + { + + return GetOutputColorItem( 0, outputId, valueName ); + } + } + + public string SampleVirtualTexture( VirtualTextureObject node, string coord ) + { + string sampler = string.Empty; + switch( node.Channel ) + { + default: + case VirtualChannel.Albedo: + case VirtualChannel.Base: + sampler = "VTSampleAlbedo( " + coord + " )"; + break; + case VirtualChannel.Normal: + case VirtualChannel.Height: + case VirtualChannel.Occlusion: + case VirtualChannel.Displacement: + sampler = "VTSampleNormal( " + coord + " )"; + break; + case VirtualChannel.Specular: + case VirtualChannel.SpecMet: + case VirtualChannel.Material: + sampler = "VTSampleSpecular( " + coord + " )"; + break; + } + return sampler; + } + + public string SampleTexture( ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar, string portProperty, MipType currMipMode, string propertyName , VariableMode varMode ) + { + string samplerValue = string.Empty; + string uvCoords = GetUVCoords( ref dataCollector, ignoreLocalVar, portProperty ); + + bool isVertex = ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ); + + bool useMacros = false; + + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; +#if UNITY_2018_1_OR_NEWER + if( outsideGraph.SamplingMacros || m_currentType == TextureType.Texture2DArray ) +#else + if( ( outsideGraph.SamplingMacros && !outsideGraph.IsStandardSurface ) || m_currentType == TextureType.Texture2DArray ) +#endif + { + useMacros = Constants.TexSampleSRPMacros.ContainsKey( m_currentType ); + } + + if( useMacros || m_currentType == TextureType.Texture2DArray ) + { + string suffix = string.Empty; + switch( currMipMode ) + { + default: + case MipType.Auto: break; + case MipType.MipLevel: suffix = "_LOD"; break; + case MipType.MipBias: suffix = "_BIAS"; break; + case MipType.Derivative: suffix = "_GRAD"; break; + } + + if( isVertex ) + suffix = "_LOD"; + + string samplerToUse = string.Empty; + + if( !m_samplerPort.IsConnected && m_useSamplerArrayIdx > 0 ) + { + TexturePropertyNode samplerNode = UIUtils.GetTexturePropertyNode( m_useSamplerArrayIdx - 1 ); + if( samplerNode != null ) + { + if( samplerNode.IsConnected ) + { + string property = samplerNode.CurrentPropertyReference; + samplerToUse = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, property, varMode ); + } + else + { + UIUtils.ShowMessage( UniqueId, string.Format( "{0} attempting to use sampler from unconnected {1} node. Reference Sampler nodes must be in use for their samplers to be created.", m_propertyName, samplerNode.PropertyName ), MessageSeverity.Warning ); + dataCollector.AddToUniforms( UniqueId, string.Format( Constants.SamplerDeclarationSRPMacros[ m_currentType ], propertyName ) ); + samplerToUse = propertyName; + } + } + else + { + UIUtils.ShowMessage( UniqueId, m_propertyName + " attempting to use sampler from invalid node.", MessageSeverity.Warning ); + dataCollector.AddToUniforms( UniqueId, string.Format( Constants.SamplerDeclarationSRPMacros[ m_currentType ], propertyName ) ); + samplerToUse = propertyName; + } + } + else + { + string samplerState = m_samplerPort.GeneratePortInstructions( ref dataCollector ); + if( m_samplerPort.IsConnected && !string.IsNullOrEmpty( samplerState ) && !samplerState.Equals( "0" ) ) + { + samplerToUse = samplerState; + } + else + { + samplerToUse = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, propertyName , varMode ); + } + } + + if( outsideGraph.IsSRP ) + { + if( m_currentType == TextureType.Texture3D && ( currMipMode == MipType.MipBias || currMipMode == MipType.Derivative ) ) + GeneratorUtils.AddCustom3DSRPMacros( ref dataCollector ); + samplerValue = string.Format( Constants.TexSampleSRPMacros[ m_currentType ], suffix, propertyName, samplerToUse, uvCoords ); + } + else + { +#if !UNITY_2018_1_OR_NEWER + if( outsideGraph.IsStandardSurface ) + { + if( m_currentType == TextureType.Texture2DArray ) + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector, m_currentType, currMipMode ); + samplerValue = string.Format( Constants.TexSampleStandardMacros[ m_currentType ], suffix, propertyName, samplerToUse, uvCoords ); + } + else +#endif + { + GeneratorUtils.AddCustomStandardSamplingMacros( ref dataCollector, m_currentType, currMipMode ); + samplerValue = string.Format( Constants.TexSampleSamplerStandardMacros[ m_currentType ], suffix, propertyName, samplerToUse, uvCoords ); + } + } + } + else + { + string mipType = ""; + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + mipType = "lod"; + } + + switch( currMipMode ) + { + case MipType.Auto: + break; + case MipType.MipLevel: + mipType = "lod"; + break; + case MipType.MipBias: + mipType = "bias"; + break; + case MipType.Derivative: + break; + } + samplerValue = m_samplerType + mipType + "( " + propertyName + ", " + uvCoords + " )"; + } + + return samplerValue; + } + + public string SetFetchedData( ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar, int outputId, string portProperty = null ) + { + m_precisionString = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType, m_colorPort.DataType ); + string propertyName = CurrentPropertyReference; + VariableMode varMode = VarModeReference; + if( !string.IsNullOrEmpty( portProperty ) && portProperty != "0.0" ) + { + propertyName = portProperty; + } + + MipType currMipMode = m_mipMode; + + if( ignoreLocalVar ) + { + if( TextureProperty is VirtualTextureObject ) + Debug.Log( "TODO" ); + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + currMipMode = MipType.MipLevel; + } + + string samplerValue = SampleTexture( ref dataCollector, ignoreLocalVar, portProperty, currMipMode, propertyName , varMode ); + + AddNormalMapTag( ref dataCollector, ref samplerValue ); + return samplerValue; + } + + VirtualTextureObject vtex = ( TextureProperty as VirtualTextureObject ); + + if( vtex != null ) + { + string atPathname = AssetDatabase.GUIDToAssetPath( Constants.ATSharedLibGUID ); + if( string.IsNullOrEmpty( atPathname ) ) + { + UIUtils.ShowMessage( UniqueId, "Could not find Amplify Texture on your project folder. Please install it and re-compile the shader.", MessageSeverity.Error ); + } + else + { + //Need to see if the asset really exists because AssetDatabase.GUIDToAssetPath() can return a valid path if + // the asset was previously imported and deleted after that + UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath( atPathname ); + if( obj == null ) + { + UIUtils.ShowMessage( UniqueId, "Could not find Amplify Texture on your project folder. Please install it and re-compile the shader.", MessageSeverity.Error ); + } + else + { + if( m_colorPort.IsLocalValue( dataCollector.PortCategory ) ) + return m_colorPort.LocalValue( dataCollector.PortCategory ); + + //string remapPortR = ".r"; + //string remapPortG = ".g"; + //string remapPortB = ".b"; + //string remapPortA = ".a"; + + //if ( vtex.Channel == VirtualChannel.Occlusion ) + //{ + // remapPortR = ".r"; remapPortG = ".r"; remapPortB = ".r"; remapPortA = ".r"; + //} + //else if ( vtex.Channel == VirtualChannel.SpecMet && ( ContainerGraph.CurrentStandardSurface != null && ContainerGraph.CurrentStandardSurface.CurrentLightingModel == StandardShaderLightModel.Standard ) ) + //{ + // remapPortR = ".r"; remapPortG = ".r"; remapPortB = ".r"; + //} + //else if ( vtex.Channel == VirtualChannel.Height || vtex.Channel == VirtualChannel.Displacement ) + //{ + // remapPortR = ".b"; remapPortG = ".b"; remapPortB = ".b"; remapPortA = ".b"; + //} + + dataCollector.AddToPragmas( UniqueId, IOUtils.VirtualTexturePragmaHeader ); + dataCollector.AddToIncludes( UniqueId, atPathname ); + + string lodBias = string.Empty; + if( dataCollector.IsFragmentCategory ) + { + lodBias = m_mipMode == MipType.MipLevel ? "Lod" : m_mipMode == MipType.MipBias ? "Bias" : ""; + } + else + { + lodBias = "Lod"; + } + + int virtualCoordId = dataCollector.GetVirtualCoordinatesId( UniqueId, GetVirtualUVCoords( ref dataCollector, ignoreLocalVar, portProperty ), lodBias ); + string virtualSampler = SampleVirtualTexture( vtex, Constants.VirtualCoordNameStr + virtualCoordId ); + string virtualVariable = dataCollector.AddVirtualLocalVariable( UniqueId, "virtualNode" + OutputId, virtualSampler ); + + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT4, virtualVariable, virtualSampler ); + + AddNormalMapTag( ref dataCollector, ref virtualVariable ); + + switch( vtex.Channel ) + { + default: + case VirtualChannel.Albedo: + case VirtualChannel.Base: + case VirtualChannel.Normal: + case VirtualChannel.Specular: + case VirtualChannel.SpecMet: + case VirtualChannel.Material: + virtualVariable = GetOutputColorItem( 0, outputId, virtualVariable ); + break; + case VirtualChannel.Displacement: + case VirtualChannel.Height: + { + if( outputId > 0 ) + virtualVariable += ".b"; + else + { + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT4, "virtual_cast_" + OutputId, virtualVariable + ".b" ); + virtualVariable = "virtual_cast_" + OutputId; + } + //virtualVariable = UIUtils.CastPortType( dataCollector.PortCategory, m_currentPrecisionType, new NodeCastInfo( UniqueId, outputId ), virtualVariable, WirePortDataType.FLOAT, WirePortDataType.FLOAT4, virtualVariable ); + } + break; + case VirtualChannel.Occlusion: + { + if( outputId > 0 ) + virtualVariable += ".r"; + else + { + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT4, "virtual_cast_" + OutputId, virtualVariable + ".r" ); + virtualVariable = "virtual_cast_" + OutputId; + } + } + break; + } + + //for ( int i = 0; i < m_outputPorts.Count; i++ ) + //{ + // if ( m_outputPorts[ i ].IsConnected ) + // { + + // //TODO: make the sampler not generate local variables at all times + // m_textureFetchedValue = "virtualNode" + OutputId; + // m_isTextureFetched = true; + + // //dataCollector.AddToLocalVariables( m_uniqueId, m_precisionString + " " + m_textureFetchedValue + " = " + virtualSampler + ";" ); + // if ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + // dataCollector.AddToVertexLocalVariables( UniqueId, m_precisionString + " " + m_textureFetchedValue + " = " + virtualSampler + ";" ); + // else + // dataCollector.AddToLocalVariables( UniqueId, m_precisionString + " " + m_textureFetchedValue + " = " + virtualSampler + ";" ); + + // m_colorPort.SetLocalValue( m_textureFetchedValue ); + // m_outputPorts[ m_colorPort.PortId + 1 ].SetLocalValue( m_textureFetchedValue + remapPortR ); + // m_outputPorts[ m_colorPort.PortId + 2 ].SetLocalValue( m_textureFetchedValue + remapPortG ); + // m_outputPorts[ m_colorPort.PortId + 3 ].SetLocalValue( m_textureFetchedValue + remapPortB ); + // m_outputPorts[ m_colorPort.PortId + 4 ].SetLocalValue( m_textureFetchedValue + remapPortA ); + // return m_textureFetchedValue; + // } + //} + + return virtualVariable; + } + } + } + + if( m_colorPort.IsLocalValue( dataCollector.PortCategory ) ) + return m_colorPort.LocalValue( dataCollector.PortCategory ); + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + currMipMode = MipType.MipLevel; + //mipType = "lod"; + } + + string samplerOp = SampleTexture( ref dataCollector, ignoreLocalVar, portProperty, currMipMode, propertyName , varMode ); + + AddNormalMapTag( ref dataCollector, ref samplerOp ); + + int connectedPorts = 0; + for( int i = 0; i < m_outputPorts.Count; i++ ) + { + if( m_outputPorts[ i ].IsConnected ) + { + connectedPorts += 1; + if( connectedPorts > 1 || m_outputPorts[ i ].ConnectionCount > 1 ) + { + // Create common local var and mark as fetched + string textureFetchedValue = m_samplerType + "Node" + OutputId; + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + dataCollector.AddToVertexLocalVariables( UniqueId, m_precisionString + " " + textureFetchedValue + " = " + samplerOp + ";" ); + else + dataCollector.AddToFragmentLocalVariables( UniqueId, m_precisionString + " " + textureFetchedValue + " = " + samplerOp + ";" ); + + + m_colorPort.SetLocalValue( textureFetchedValue, dataCollector.PortCategory ); + m_outputPorts[ m_colorPort.PortId + 1 ].SetLocalValue( textureFetchedValue + ".r", dataCollector.PortCategory ); + m_outputPorts[ m_colorPort.PortId + 2 ].SetLocalValue( textureFetchedValue + ".g", dataCollector.PortCategory ); + m_outputPorts[ m_colorPort.PortId + 3 ].SetLocalValue( textureFetchedValue + ".b", dataCollector.PortCategory ); + m_outputPorts[ m_colorPort.PortId + 4 ].SetLocalValue( textureFetchedValue + ".a", dataCollector.PortCategory ); + return textureFetchedValue; + } + } + } + return samplerOp; + } + + public string GetUVCoords( ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar, string portProperty ) + { + bool isVertex = ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ); + + // make sure the final result is always a float4 with empty 0's in the middle + string uvAppendix = ", "; + int coordSize = 3; + if( m_uvPort.DataType == WirePortDataType.FLOAT2 ) + { + uvAppendix = ", 0, "; + coordSize = 2; + } + else if( m_uvPort.DataType == WirePortDataType.FLOAT ) + { + uvAppendix = ", 0, 0, "; + coordSize = 1; + } + + string uvs = m_uvPort.GeneratePortInstructions( ref dataCollector ); + + // generate automatic UVs if not connected + if( !m_uvPort.IsConnected ) + { + string propertyName = CurrentPropertyReference; + + // check for references + if( !string.IsNullOrEmpty( portProperty ) && portProperty != "0.0" ) + propertyName = portProperty; + + int coordSet = ( ( m_textureCoordSet < 0 ) ? 0 : m_textureCoordSet ); + string uvName = IOUtils.GetUVChannelName( propertyName, coordSet ); + string dummyPropUV = "_tex" + ( coordSize != 2 ? "" + coordSize : "" ) + "coord" + ( coordSet > 0 ? ( coordSet + 1 ).ToString() : "" ); + string dummyUV = "uv" + ( coordSet > 0 ? ( coordSet + 1 ).ToString() : "" ) + dummyPropUV; + + string attr = GetPropertyValue(); + bool scaleOffset = true; + if( attr.IndexOf( "[NoScaleOffset]" ) > -1 ) + scaleOffset = false; + + string texCoordsST = string.Empty; + if( scaleOffset ) + { + if( m_texCoordsHelper == null ) + { + m_texCoordsHelper = CreateInstance(); + m_texCoordsHelper.ContainerGraph = ContainerGraph; + m_texCoordsHelper.SetBaseUniqueId( UniqueId, true ); + m_texCoordsHelper.RegisterPropertyOnInstancing = false; + m_texCoordsHelper.AddGlobalToSRPBatcher = true; + } + + if( UIUtils.CurrentWindow.OutsideGraph.IsInstancedShader ) + { + m_texCoordsHelper.CurrentParameterType = PropertyType.InstancedProperty; + } + else + { + m_texCoordsHelper.CurrentParameterType = PropertyType.Global; + } + m_texCoordsHelper.ResetOutputLocals(); + m_texCoordsHelper.SetRawPropertyName( propertyName + "_ST" ); + texCoordsST = m_texCoordsHelper.GenerateShaderForOutput( 0, ref dataCollector, false ); + } + + string coordInput = string.Empty; + if( !dataCollector.IsTemplate && coordSet > 3 ) + { + coordInput = GeneratorUtils.GenerateAutoUVs( ref dataCollector, UniqueId, coordSet, null, WirePortDataType.FLOAT2 ); + } + else + { + dataCollector.AddToProperties( UniqueId, "[HideInInspector] " + dummyPropUV + "( \"\", 2D ) = \"white\" {}", 9999 ); + if( isVertex ) + { + coordInput = Constants.VertexShaderInputStr + ".texcoord"; + if( coordSet > 0 ) + coordInput += coordSet.ToString(); + } + else + { + coordInput = Constants.InputVarStr + "." + dummyUV; + dataCollector.AddToInput( UniqueId, dummyUV, m_uvPort.DataType ); + } + } + + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + string result = string.Empty; + if( dataCollector.TemplateDataCollectorInstance.GetCustomInterpolatedData( TemplateHelperFunctions.IntToUVChannelInfo[ m_textureCoordSet ], m_uvPort.DataType, PrecisionType.Float, ref result, false, dataCollector.PortCategory ) ) + { + coordInput = result; + } + else + if( dataCollector.TemplateDataCollectorInstance.HasUV( m_textureCoordSet ) ) + coordInput = dataCollector.TemplateDataCollectorInstance.GetUVName( m_textureCoordSet, m_uvPort.DataType ); + else + coordInput = dataCollector.TemplateDataCollectorInstance.RegisterUV( m_textureCoordSet, m_uvPort.DataType ); + } + + if( !scaleOffset ) + uvName += OutputId; + + if( coordSize > 2 ) + { + uvName += coordSize; + dataCollector.UsingHigherSizeTexcoords = true; + dataCollector.AddLocalVariable( UniqueId, "float" + coordSize + " " + uvName + " = " + coordInput + ";" ); + if( scaleOffset ) + dataCollector.AddLocalVariable( UniqueId, uvName + ".xy = " + coordInput + ".xy * " + texCoordsST + ".xy + " + texCoordsST + ".zw;" ); + } + else + { + if( coordSize == 1 ) + uvName += coordSize; + + if( scaleOffset ) + dataCollector.AddLocalVariable( UniqueId, PrecisionType.Float, m_uvPort.DataType, uvName, coordInput + " * " + texCoordsST + ".xy + " + texCoordsST + ".zw" ); + else + dataCollector.AddLocalVariable( UniqueId, PrecisionType.Float, m_uvPort.DataType, uvName, coordInput ); + } + + uvs = uvName; + } + + + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; + if( m_currentType == TextureType.Texture2DArray ) + { + string index = m_indexPort.GeneratePortInstructions( ref dataCollector ); + uvs = string.Format( "{0},{1}", uvs, index ); + + if( !( ( outsideGraph.SamplingMacros || m_currentType == TextureType.Texture2DArray ) && outsideGraph.IsSRP ) ) + { + uvs = "float3(" + uvs + ")"; + } + } + + if( isVertex ) + { + string lodLevel = m_lodPort.GeneratePortInstructions( ref dataCollector ); +#if UNITY_2018_1_OR_NEWER + if( ( outsideGraph.SamplingMacros || m_currentType == TextureType.Texture2DArray ) && m_currentType != TextureType.Texture1D ) +#else + if( ( ( outsideGraph.SamplingMacros && !outsideGraph.IsStandardSurface ) || m_currentType == TextureType.Texture2DArray ) && m_currentType != TextureType.Texture1D ) +#endif + return uvs + ", " + lodLevel; + else + return UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT4 ) + "( " + uvs + uvAppendix + lodLevel + ")"; + } + else + { + if( ( m_mipMode == MipType.MipLevel || m_mipMode == MipType.MipBias ) /*&& m_lodPort.IsConnected*/ ) + { + string lodLevel = m_lodPort.GeneratePortInstructions( ref dataCollector ); +#if UNITY_2018_1_OR_NEWER + if( ( outsideGraph.SamplingMacros || m_currentType == TextureType.Texture2DArray ) && m_currentType != TextureType.Texture1D ) +#else + if( ( ( outsideGraph.SamplingMacros && !outsideGraph.IsStandardSurface ) || m_currentType == TextureType.Texture2DArray ) && m_currentType != TextureType.Texture1D ) +#endif + return uvs + ", " + lodLevel; + else + return UIUtils.PrecisionWirePortToCgType( PrecisionType.Float, WirePortDataType.FLOAT4 ) + "( " + uvs + uvAppendix + lodLevel + ")"; + } + else if( m_mipMode == MipType.Derivative ) + { + string ddx = m_ddxPort.GeneratePortInstructions( ref dataCollector ); + string ddy = m_ddyPort.GeneratePortInstructions( ref dataCollector ); + + return uvs + ", " + ddx + ", " + ddy; + } + else + { + return uvs; + } + } + } + + public string GetVirtualUVCoords( ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar, string portProperty ) + { + string bias = ""; + if( !dataCollector.IsFragmentCategory || m_mipMode == MipType.MipBias || m_mipMode == MipType.MipLevel ) + { + string lodLevel = m_lodPort.GeneratePortInstructions( ref dataCollector ); + bias += ", " + lodLevel; + } + + if( m_uvPort.IsConnected ) + { + string uvs = m_uvPort.GeneratePortInstructions( ref dataCollector ); + return uvs + bias; + } + else + { + string propertyName = CurrentPropertyReference; + if( !string.IsNullOrEmpty( portProperty ) ) + { + propertyName = portProperty; + } + string uvChannelName = IOUtils.GetUVChannelName( propertyName, m_textureCoordSet ); + + + string uvCoord = string.Empty; + if( dataCollector.IsTemplate ) + { + string uvName = string.Empty; + if( dataCollector.TemplateDataCollectorInstance.HasUV( m_textureCoordSet ) ) + { + uvName = dataCollector.TemplateDataCollectorInstance.GetUVName( m_textureCoordSet, m_uvPort.DataType ); + } + else + { + uvName = dataCollector.TemplateDataCollectorInstance.RegisterUV( m_textureCoordSet, m_uvPort.DataType ); + } + + string attr = GetPropertyValue(); + + if( attr.IndexOf( "[NoScaleOffset]" ) > -1 ) + { + dataCollector.AddLocalVariable( UniqueId, PrecisionType.Float, WirePortDataType.FLOAT2, uvChannelName, uvName ); + } + else + { + dataCollector.AddToUniforms( UniqueId, "uniform float4 " + propertyName + "_ST;" ); + dataCollector.AddLocalVariable( UniqueId, PrecisionType.Float, WirePortDataType.FLOAT2, uvChannelName, uvName + " * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw" ); + } + uvCoord = uvChannelName; + } + else + { + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + uvCoord = Constants.VertexShaderInputStr + ".texcoord"; + if( m_textureCoordSet > 0 ) + { + uvCoord += m_textureCoordSet.ToString(); + } + } + else + { + propertyName = CurrentPropertyReference; + if( !string.IsNullOrEmpty( portProperty ) && portProperty != "0.0" ) + { + propertyName = portProperty; + } + uvChannelName = IOUtils.GetUVChannelName( propertyName, m_textureCoordSet ); + + string dummyPropUV = "_texcoord" + ( m_textureCoordSet > 0 ? ( m_textureCoordSet + 1 ).ToString() : "" ); + string dummyUV = "uv" + ( m_textureCoordSet > 0 ? ( m_textureCoordSet + 1 ).ToString() : "" ) + dummyPropUV; + + dataCollector.AddToProperties( UniqueId, "[HideInInspector] " + dummyPropUV + "( \"\", 2D ) = \"white\" {}", 100 ); + dataCollector.AddToInput( UniqueId, dummyUV, WirePortDataType.FLOAT2 ); + + string attr = GetPropertyValue(); + + if( attr.IndexOf( "[NoScaleOffset]" ) > -1 ) + { + dataCollector.AddToLocalVariables( UniqueId, PrecisionType.Float, WirePortDataType.FLOAT2, uvChannelName, Constants.InputVarStr + "." + dummyUV ); + } + else + { + dataCollector.AddToUniforms( UniqueId, "uniform float4 " + propertyName + "_ST;" ); + dataCollector.AddToLocalVariables( UniqueId, PrecisionType.Float, WirePortDataType.FLOAT2, uvChannelName, Constants.InputVarStr + "." + dummyUV + " * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw" ); + } + uvCoord = uvChannelName; + } + } + return uvCoord + bias; + } + } + + private void AddNormalMapTag( ref MasterNodeDataCollector dataCollector, ref string value ) + { + if( m_autoUnpackNormals ) + { + bool isScaledNormal = false; + if( m_normalPort.IsConnected ) + { + isScaledNormal = true; + } + else + { + if( m_normalPort.FloatInternalData != 1 ) + { + isScaledNormal = true; + } + } + + string scaleValue = isScaledNormal ? m_normalPort.GeneratePortInstructions( ref dataCollector ) : "1.0f"; + value = GeneratorUtils.GenerateUnpackNormalStr( ref dataCollector, CurrentPrecisionType, UniqueId, OutputId, value, isScaledNormal, scaleValue ); + + if( isScaledNormal ) + { + if( !( dataCollector.IsTemplate && dataCollector.IsSRP ) ) + { + dataCollector.AddToIncludes( UniqueId, Constants.UnityStandardUtilsLibFuncs ); + } + } + } + } + + public override void ReadOutputDataFromString( ref string[] nodeParams ) + { + base.ReadOutputDataFromString( ref nodeParams ); + ConfigureOutputPorts(); + } + + public override int InputIdFromDeprecated( int oldInputId ) + { + // this is not a good solution, it doesn't check for the deprecated type and thus assumes it always comes from texture array + switch( oldInputId ) + { + default: + return oldInputId; + case 0: + return 1; + case 1: + return 6; + case 2: + return 2; + case 3: + return 5; + case 4: + return 3; + case 5: + return 4; + case 6: + return 0; + } + } + + public override void ReadFromDeprecated( ref string[] nodeParams, Type oldType = null ) + { + base.ReadFromDeprecated( ref nodeParams, oldType ); + if( oldType == typeof( TextureArrayNode ) ) + { + base.ReadFromStringArray( ref nodeParams ); + string textureName = GetCurrentParam( ref nodeParams ); + m_defaultValue = AssetDatabase.LoadAssetAtPath( textureName ); + if( m_defaultValue ) + { + m_materialValue = m_defaultValue; + } + + m_textureCoordSet = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_referenceType = (TexReferenceType)Enum.Parse( typeof( TexReferenceType ), GetCurrentParam( ref nodeParams ) ); + m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( m_referenceType == TexReferenceType.Instance ) + { + UIUtils.UnregisterSamplerNode( this ); + UIUtils.UnregisterPropertyNode( this ); + } + UpdateHeaderColor(); + + if( UIUtils.CurrentShaderVersion() > 3202 ) + m_mipMode = (MipType)Enum.Parse( typeof( MipType ), GetCurrentParam( ref nodeParams ) ); + + if( UIUtils.CurrentShaderVersion() > 5105 ) + m_autoUnpackNormals = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + + m_currentType = TextureType.Texture2DArray; + //m_autocastMode = AutoCastType.LockedToTexture2DArray; + + if( m_defaultValue == null ) + { + ConfigureInputPorts(); + ConfigureOutputPorts(); + //ResizeNodeToPreview(); + } + else + { + if( m_materialValue == null ) + { + ConfigFromObject( m_defaultValue, false, false ); + } + else + { + CheckTextureImporter( false, false ); + } + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + + if( !m_isNodeBeingCopied && m_referenceType == TexReferenceType.Object ) + { + ContainerGraph.SamplerNodes.UpdateDataOnNode( UniqueId, DataToArray ); + } + + // reading input data due to internal data being lost + int count = 0; + if( UIUtils.CurrentShaderVersion() > 7003 ) + { + try + { + count = Convert.ToInt32( nodeParams[ m_currentReadParamIdx++ ] ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + else + { + count = ( m_oldInputCount < 0 ) ? m_inputPorts.Count : m_oldInputCount; + } + + for( int i = 0; i < count && i < nodeParams.Length && m_currentReadParamIdx < nodeParams.Length; i++ ) + { + if( UIUtils.CurrentShaderVersion() < 5003 ) + { + int newId = VersionConvertInputPortId( i ); + string InternalData = string.Empty; + + if( UIUtils.CurrentShaderVersion() > 23 ) + { + Enum.Parse( typeof( WirePortDataType ), nodeParams[ m_currentReadParamIdx++ ] ); + } + + InternalData = nodeParams[ m_currentReadParamIdx++ ]; + if( UIUtils.CurrentShaderVersion() >= 3100 && m_currentReadParamIdx < nodeParams.Length ) + { + nodeParams[ m_currentReadParamIdx++ ].ToString(); + } + + if( newId == 2 ) + { + m_indexPort.InternalData = InternalData; + m_indexPort.UpdatePreviewInternalData(); + } + + if( newId == 3 ) + { + m_lodPort.InternalData = InternalData; + m_lodPort.UpdatePreviewInternalData(); + } + } + else + { + string portIdStr = nodeParams[ m_currentReadParamIdx++ ]; + int portId = -1; + try + { + portId = Convert.ToInt32( portIdStr ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + Enum.Parse( typeof( WirePortDataType ), nodeParams[ m_currentReadParamIdx++ ] ); + string InternalData = nodeParams[ m_currentReadParamIdx++ ]; + bool isEditable = Convert.ToBoolean( nodeParams[ m_currentReadParamIdx++ ] ); + if( isEditable && m_currentReadParamIdx < nodeParams.Length ) + { + nodeParams[ m_currentReadParamIdx++ ].ToString(); + } + + if( portId == 1 ) + { + m_indexPort.InternalData = InternalData; + m_indexPort.UpdatePreviewInternalData(); + } + + if( portId == 2 ) + { + m_lodPort.InternalData = InternalData; + m_lodPort.UpdatePreviewInternalData(); + } + } + } + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + string defaultTextureGUID = GetCurrentParam( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 14101 ) + { + m_defaultValue = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( defaultTextureGUID ) ); + string materialTextureGUID = GetCurrentParam( ref nodeParams ); + m_materialValue = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( materialTextureGUID ) ); + } + else + { + m_defaultValue = AssetDatabase.LoadAssetAtPath( defaultTextureGUID ); + } + m_useSemantics = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_textureCoordSet = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_isNormalMap = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_defaultTextureValue = (TexturePropertyValues)Enum.Parse( typeof( TexturePropertyValues ), GetCurrentParam( ref nodeParams ) ); + m_autocastMode = (AutoCastType)Enum.Parse( typeof( AutoCastType ), GetCurrentParam( ref nodeParams ) ); + m_autoUnpackNormals = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + + if( UIUtils.CurrentShaderVersion() > 12 ) + { + m_referenceType = (TexReferenceType)Enum.Parse( typeof( TexReferenceType ), GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 22 ) + { + m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + else + { + m_referenceArrayId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + if( m_referenceType == TexReferenceType.Instance ) + { + UIUtils.UnregisterSamplerNode( this ); + UIUtils.UnregisterPropertyNode( this ); + } + UpdateHeaderColor(); + } + if( UIUtils.CurrentShaderVersion() > 2406 ) + m_mipMode = (MipType)Enum.Parse( typeof( MipType ), GetCurrentParam( ref nodeParams ) ); + + + if( UIUtils.CurrentShaderVersion() > 3201 ) + m_currentType = (TextureType)Enum.Parse( typeof( TextureType ), GetCurrentParam( ref nodeParams ) ); + + if( m_defaultValue == null ) + { + ConfigureInputPorts(); + ConfigureOutputPorts(); + //ResizeNodeToPreview(); + } + else + { + if( m_materialValue == null ) + { + ConfigFromObject( m_defaultValue, false, false ); + } + else + { + CheckTextureImporter( false, false ); + } + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + + if( !m_isNodeBeingCopied && m_referenceType == TexReferenceType.Object ) + { + ContainerGraph.SamplerNodes.UpdateDataOnNode( UniqueId, DataToArray ); + } + + if( UIUtils.CurrentShaderVersion() >= 6001 && UIUtils.CurrentShaderVersion() < 7003 ) + { + m_oldInputCount = 6; + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + ForceInputPortsChange(); + + if( m_useSamplerArrayIdx > -1 ) + { + m_useSamplerArrayIdx = UIUtils.GetTexturePropertyNodeRegisterId( m_useSamplerArrayIdx ) + 1; + } + else + { + m_useSamplerArrayIdx = 0; + } + + EditorGUI.BeginChangeCheck(); + if( m_referenceType == TexReferenceType.Instance ) + { + if( UIUtils.CurrentShaderVersion() > 22 ) + { + + + m_referenceSampler = ContainerGraph.GetNode( m_referenceNodeId ) as SamplerNode; + m_referenceArrayId = ContainerGraph.SamplerNodes.GetNodeRegisterIdx( m_referenceNodeId ); + } + else + { + m_referenceSampler = ContainerGraph.SamplerNodes.GetNode( m_referenceArrayId ); + if( m_referenceSampler != null ) + { + m_referenceNodeId = m_referenceSampler.UniqueId; + } + } + } + + if( EditorGUI.EndChangeCheck() ) + { + OnPropertyNameChanged(); + } + } + + public override void ReadAdditionalData( ref string[] nodeParams ) { } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_defaultValue != null ) ? AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_defaultValue ) ) : Constants.NoStringValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_materialValue != null ) ? AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_materialValue ) ) : Constants.NoStringValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_useSemantics.ToString() ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_textureCoordSet.ToString() ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_isNormalMap.ToString() ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultTextureValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_autocastMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_autoUnpackNormals ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_referenceType ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( ( m_referenceSampler != null ) ? m_referenceSampler.UniqueId : -1 ) ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_mipMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentType ); + } + + public override void WriteAdditionalToString( ref string nodeInfo, ref string connectionsInfo ) { } + + public override int VersionConvertInputPortId( int portId ) + { + int newPort = portId; + //change normal scale port to last + if( UIUtils.CurrentShaderVersion() < 2407 ) + { + if( portId == 1 ) + newPort = 4; + } + + if( UIUtils.CurrentShaderVersion() < 2408 ) + { + newPort = newPort + 1; + } + + return newPort; + } + + public override void Destroy() + { + base.Destroy(); + + //Not calling m_texCoordsHelper.Destroy() on purpose so UIUtils does not incorrectly unregister stuff + if( m_texCoordsHelper != null ) + { + DestroyImmediate( m_texCoordsHelper ); + m_texCoordsHelper = null; + } + + m_samplerStateAutoGenerator.Destroy(); + m_samplerStateAutoGenerator = null; + m_defaultValue = null; + m_materialValue = null; + m_referenceSampler = null; + m_referenceStyle = null; + m_referenceContent = null; + m_texPort = null; + m_uvPort = null; + m_lodPort = null; + m_ddxPort = null; + m_ddyPort = null; + m_normalPort = null; + m_colorPort = null; + m_samplerPort = null; + m_indexPort = null; + + if( m_referenceType == TexReferenceType.Object ) + { + UIUtils.UnregisterSamplerNode( this ); + UIUtils.UnregisterPropertyNode( this ); + } + if( UniqueId > -1 ) + ContainerGraph.SamplerNodes.OnReorderEventComplete -= OnReorderEventComplete; + } + + public override string GetPropertyValStr() + { + return m_materialMode ? ( m_materialValue != null ? m_materialValue.name : IOUtils.NO_TEXTURES ) : ( m_defaultValue != null ? m_defaultValue.name : IOUtils.NO_TEXTURES ); + } + + public TexturePropertyNode TextureProperty + { + get + { + if( m_referenceSampler != null ) + { + m_textureProperty = m_referenceSampler as TexturePropertyNode; + } + else if( m_texPort.IsConnected ) + { + m_textureProperty = m_texPort.GetOutputNodeWhichIsNotRelay( 0 ) as TexturePropertyNode; + } + + if( m_textureProperty == null ) + return this; + + return m_textureProperty; + } + } + + public override string GetPropertyValue() + { + if( SoftValidReference ) + { + if( m_referenceSampler.TexPort.IsConnected ) + { + return string.Empty; + } + else + { + return m_referenceSampler.TextureProperty.GetPropertyValue(); + } + } + else + if( m_texPort.IsConnected && ( m_texPort.GetOutputNodeWhichIsNotRelay( 0 ) as TexturePropertyNode ) != null ) + { + return TextureProperty.GetPropertyValue(); + } + + switch( m_currentType ) + { + case TextureType.Texture1D: + { + return PropertyAttributes + GetTexture1DPropertyValue(); + } + case TextureType.ProceduralTexture: + case TextureType.Texture2D: + { + return PropertyAttributes + GetTexture2DPropertyValue(); + } + case TextureType.Texture3D: + { + return PropertyAttributes + GetTexture3DPropertyValue(); + } + case TextureType.Cube: + { + return PropertyAttributes + GetCubePropertyValue(); + } + case TextureType.Texture2DArray: + { + return PropertyAttributes + GetTexture2DArrayPropertyValue(); + } + } + return string.Empty; + } + + public override string GetUniformValue() + { + + if( SoftValidReference ) + { + if( m_referenceSampler.TexPort.IsConnected ) + return string.Empty; + else + return m_referenceSampler.TextureProperty.GetUniformValue(); + } + else if( m_texPort.IsConnected && ( m_texPort.GetOutputNodeWhichIsNotRelay( 0 ) as TexturePropertyNode ) != null ) + { + return TextureProperty.GetUniformValue(); + } + + return base.GetUniformValue(); + } + + public override bool GetUniformData( out string dataType, out string dataName, ref bool fullValue ) + { + if( SoftValidReference ) + { + if( m_referenceSampler.TexPort.IsConnected ) + { + base.GetUniformData( out dataType, out dataName, ref fullValue ); + return false; + } + else + return m_referenceSampler.TextureProperty.GetUniformData( out dataType, out dataName, ref fullValue ); + } + else if( m_texPort.IsConnected && ( m_texPort.GetOutputNodeWhichIsNotRelay( 0 ) as TexturePropertyNode ) != null ) + { + return TextureProperty.GetUniformData( out dataType, out dataName, ref fullValue ); + + } + + return base.GetUniformData( out dataType, out dataName, ref fullValue ); + } + + public string UVCoordsName { get { return Constants.InputVarStr + "." + IOUtils.GetUVChannelName( CurrentPropertyReference, m_textureCoordSet ); } } + public bool HasPropertyReference + { + get + { + if( m_referenceType == TexReferenceType.Instance && m_referenceArrayId > -1 ) + { + SamplerNode node = ContainerGraph.SamplerNodes.GetNode( m_referenceArrayId ); + if( node != null ) + return true; + } + + if( m_texPort.IsConnected ) + { + return true; + } + + return false; + } + } + + public override string CurrentPropertyReference + { + get + { + string propertyName = string.Empty; + if( m_referenceType == TexReferenceType.Instance && m_referenceArrayId > -1 ) + { + SamplerNode node = ContainerGraph.SamplerNodes.GetNode( m_referenceArrayId ); + propertyName = ( node != null ) ? node.TextureProperty.PropertyName : PropertyName; + } + else if( m_texPort.IsConnected && ( m_texPort.GetOutputNodeWhichIsNotRelay( 0 ) as TexturePropertyNode ) != null ) + { + propertyName = TextureProperty.PropertyName; + } + else + { + propertyName = PropertyName; + } + return propertyName; + } + } + + public VariableMode VarModeReference + { + get + { + VariableMode mode; + if( m_referenceType == TexReferenceType.Instance && m_referenceArrayId > -1 ) + { + SamplerNode node = ContainerGraph.SamplerNodes.GetNode( m_referenceArrayId ); + mode = ( node != null ) ? node.CurrentVariableMode : m_variableMode; + } + else if( m_texPort.IsConnected && ( m_texPort.GetOutputNodeWhichIsNotRelay( 0 ) as TexturePropertyNode ) != null ) + { + mode = TextureProperty.CurrentVariableMode; + } + else + { + mode = m_variableMode; + } + return mode; + } + } + + public bool SoftValidReference + { + get + { + if( m_referenceType == TexReferenceType.Instance && m_referenceArrayId > -1 ) + { + m_referenceSampler = ContainerGraph.SamplerNodes.GetNode( m_referenceArrayId ); + + m_texPort.Locked = true; + + if( m_referenceContent == null ) + m_referenceContent = new GUIContent(); + + + if( m_referenceSampler != null ) + { + m_referenceContent.image = m_referenceSampler.Value; + if( m_referenceWidth != m_referenceSampler.Position.width ) + { + m_referenceWidth = m_referenceSampler.Position.width; + m_sizeIsDirty = true; + } + } + else + { + m_referenceArrayId = -1; + m_referenceWidth = -1; + } + + return m_referenceSampler != null; + } + m_texPort.Locked = false; + return false; + } + } + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( PropertyName ) ) + { + m_materialValue = material.GetTexture( PropertyName ); + CheckTextureImporter( true ); + PreviewIsDirty = true; + } + + } + public override void SetContainerGraph( ParentGraph newgraph ) + { + base.SetContainerGraph( newgraph ); + m_textureProperty = m_texPort.GetOutputNodeWhichIsNotRelay( 0 ) as TexturePropertyNode; + if( m_textureProperty == null ) + { + m_textureProperty = this; + } + } + + public bool AutoUnpackNormals + { + get { return m_autoUnpackNormals; } + set + { + if( value != m_autoUnpackNormals ) + { + m_autoUnpackNormals = value; + if( !UIUtils.IsLoading ) + { + m_defaultTextureValue = value ? TexturePropertyValues.bump : TexturePropertyValues.white; + } + } + } + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + if( dataCollector.IsTemplate ) + { + if( !m_texPort.IsConnected ) + dataCollector.TemplateDataCollectorInstance.SetUVUsage( m_textureCoordSet, m_uvPort.DataType ); + } + else if( m_textureCoordSet > 3 ) + { + dataCollector.AddCustomAppData( string.Format( TemplateHelperFunctions.TexUVFullSemantic, m_textureCoordSet ) ); + } + } + + private InputPort TexPort { get { return m_texPort; } } + public bool IsObject { get { return ( m_referenceType == TexReferenceType.Object ) || ( m_referenceSampler == null ); } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerNode.cs.meta new file mode 100644 index 0000000..87957e4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 057d23b232d9c044cbf3f1d0b1a06909 +timeCreated: 1481126953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerStateNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerStateNode.cs new file mode 100644 index 0000000..8adbe94 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerStateNode.cs @@ -0,0 +1,378 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Sampler State", "Textures", "Creates a custom sampler state or returns the default one of a selected texture object" )] + public class SamplerStateNode : ParentNode + { + private readonly string[] Dummy = { string.Empty }; + private const string WrapModeStr = "Wrap Mode"; + private const string UAxisStr = "U axis"; + private const string VAxisStr = "V axis"; + private const string FilterModeStr = "Filter Mode"; + private const string MessageMacrosOFF = "Sampling Macros option is turned OFF, this node will not generate any sampler state"; + private const string MessageTextureObject = "Only Texture Objects that are actually being sampled within the shader generate valid sampler states.\n\nPlease make sure the referenced Texture Object is being sampled otherwise the shader will fail to compile."; + private const string MessageUnitSuppport = "Unity support for sampler states in versions below Unity 2018.1 is limited.\n\nNotably, only vertex/frag shaders support it and not surfaces shaders and sampler states can only be reused and not created if the version is below 2017.1"; + + [SerializeField] + protected int m_wrapMode = 0; + + [SerializeField] + protected TextureWrapMode m_wrapModeU = TextureWrapMode.Repeat; + + [SerializeField] + protected TextureWrapMode m_wrapModeV = TextureWrapMode.Repeat; + + [SerializeField] + protected FilterMode m_filterMode = FilterMode.Bilinear; + + [SerializeField] + private int m_referenceSamplerId = -1; + + [SerializeField] + private int m_referenceNodeId = -1; + + [SerializeField] + private TexturePropertyNode m_inputReferenceNode = null; + + private TexturePropertyNode m_referenceNode = null; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + private InputPort m_texPort; + + private readonly string[] m_wrapModeStr = { + "Repeat", + "Clamp", +#if UNITY_2018_3_OR_NEWER + "Mirror", + "Mirror Once", + "Per-axis" +#endif + }; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.SAMPLER2D, false, "Tex" ); + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.SAMPLER2DARRAY ); + AddOutputPort( WirePortDataType.SAMPLERSTATE, "Out" ); + m_texPort = m_inputPorts[ 0 ]; + m_hasLeftDropdown = true; + m_autoWrapProperties = true; + m_errorMessageTypeIsError = NodeMessageType.Warning; + m_errorMessageTooltip = MessageMacrosOFF; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_inputReferenceNode = m_inputPorts[ 0 ].GetOutputNodeWhichIsNotRelay() as TexturePropertyNode; + UpdateTitle(); + + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + m_inputReferenceNode = null; + UpdateTitle(); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ 0 ].MatchPortToConnection(); + UpdateTitle(); + } + + void UpdateTitle() + { + if( m_inputReferenceNode != null ) + { + m_additionalContent.text = string.Format( Constants.PropertyValueLabel, m_inputReferenceNode.PropertyInspectorName ); + } + else if( m_referenceSamplerId > -1 && m_referenceNode != null ) + { + m_additionalContent.text = string.Format( Constants.PropertyValueLabel, m_referenceNode.PropertyInspectorName ); + } + else + { + m_additionalContent.text = string.Empty; + } + m_sizeIsDirty = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + bool guiEnabledBuffer = GUI.enabled; + EditorGUI.BeginChangeCheck(); + List arr = new List( UIUtils.TexturePropertyNodeArr() ); + + if( arr != null && arr.Count > 0 ) + { + arr.Insert( 0, "None" ); + GUI.enabled = true && ( !m_inputPorts[ 0 ].IsConnected ); + m_referenceSamplerId = EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceSamplerId + 1, arr.ToArray() ) - 1; + } + else + { + m_referenceSamplerId = -1; + GUI.enabled = false; + EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceSamplerId, Dummy ); + } + + GUI.enabled = guiEnabledBuffer; + if( EditorGUI.EndChangeCheck() ) + { + m_referenceNode = UIUtils.GetTexturePropertyNode( m_referenceSamplerId ); + if( m_referenceNode != null ) + { + m_referenceNodeId = m_referenceNode.UniqueId; + } + else + { + m_referenceNodeId = -1; + m_referenceSamplerId = -1; + } + UpdateTitle(); + } + + EditorGUI.BeginDisabledGroup( m_texPort.IsConnected || m_referenceNodeId >= 0 ); + EditorGUI.BeginChangeCheck(); + m_wrapMode = EditorGUILayoutPopup( WrapModeStr, m_wrapMode, m_wrapModeStr ); + if( EditorGUI.EndChangeCheck() ) + { + switch( m_wrapMode ) + { + case 0: + m_wrapModeU = TextureWrapMode.Repeat; + m_wrapModeV = TextureWrapMode.Repeat; + break; + case 1: + m_wrapModeU = TextureWrapMode.Clamp; + m_wrapModeV = TextureWrapMode.Clamp; + break; +#if UNITY_2018_3_OR_NEWER + case 2: + m_wrapModeU = TextureWrapMode.Mirror; + m_wrapModeV = TextureWrapMode.Mirror; + break; + case 3: + m_wrapModeU = TextureWrapMode.MirrorOnce; + m_wrapModeV = TextureWrapMode.MirrorOnce; + break; +#endif + } + } + + if( m_wrapMode == 4 ) + { + EditorGUI.indentLevel++; + m_wrapModeU = (TextureWrapMode)EditorGUILayoutEnumPopup( UAxisStr, m_wrapModeU ); + m_wrapModeV = (TextureWrapMode)EditorGUILayoutEnumPopup( VAxisStr, m_wrapModeV ); + EditorGUI.indentLevel--; + } + + m_filterMode = (FilterMode)EditorGUILayoutEnumPopup( FilterModeStr, m_filterMode ); + EditorGUI.EndDisabledGroup(); + + if( !UIUtils.CurrentWindow.OutsideGraph.SamplingMacros ) + EditorGUILayout.HelpBox( MessageMacrosOFF, MessageType.Warning ); + + if( m_texPort.IsConnected || m_referenceNodeId >= 0 ) + EditorGUILayout.HelpBox( MessageTextureObject, MessageType.Info ); + +#if !UNITY_2018_1_OR_NEWER + EditorGUILayout.HelpBox( MessageUnitSuppport, MessageType.Warning ); +#endif + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( !UIUtils.CurrentWindow.OutsideGraph.SamplingMacros && ContainerGraph.CurrentShaderFunction == null ) + m_showErrorMessage = true; + else + m_showErrorMessage = false; + + EditorGUI.BeginChangeCheck(); + { + List arr = new List( UIUtils.TexturePropertyNodeArr() ); + bool guiEnabledBuffer = GUI.enabled; + + if( arr != null && arr.Count > 0 ) + { + arr.Insert( 0, "None" ); + GUI.enabled = true && ( !m_inputPorts[ 0 ].IsConnected ); + m_referenceSamplerId = m_upperLeftWidget.DrawWidget( this, m_referenceSamplerId + 1, arr.ToArray() ) - 1; + } + else + { + m_referenceSamplerId = -1; + GUI.enabled = false; + m_upperLeftWidget.DrawWidget( this, m_referenceSamplerId, Dummy ); + } + GUI.enabled = guiEnabledBuffer; + } + if( EditorGUI.EndChangeCheck() ) + { + m_referenceNode = UIUtils.GetTexturePropertyNode( m_referenceSamplerId ); + if( m_referenceNode != null ) + { + m_referenceNodeId = m_referenceNode.UniqueId; + } + else + { + m_referenceNodeId = -1; + m_referenceSamplerId = -1; + } + UpdateTitle(); + } + } + + public string GenerateSamplerAttributes() + { + string result = string.Empty; + switch( m_filterMode ) + { + case FilterMode.Point: + result += "_point"; + break; + default: + case FilterMode.Bilinear: + result += "_linear"; + break; + case FilterMode.Trilinear: + result += "_trilinear"; + break; + } + + int finalWrap = m_wrapModeU == m_wrapModeV ? (int)m_wrapModeU : m_wrapMode; + switch( finalWrap ) + { + case 0: + default: + result += "_repeat"; + break; + case 1: + result += "_clamp"; + break; +#if UNITY_2018_3_OR_NEWER + case 2: + result += "_mirror"; + break; + case 3: + result += "_mirrorOnce"; + break; +#endif + case 4: + { + switch( m_wrapModeU ) + { + default: + case TextureWrapMode.Repeat: + result += "_repeatU"; + break; + case TextureWrapMode.Clamp: + result += "_clampU"; + break; +#if UNITY_2018_3_OR_NEWER + case TextureWrapMode.Mirror: + result += "_mirrorU"; + break; + case TextureWrapMode.MirrorOnce: + result += "_mirrorOnceU"; + break; +#endif + } + switch( m_wrapModeV ) + { + default: + case TextureWrapMode.Repeat: + result += "_repeatV"; + break; + case TextureWrapMode.Clamp: + result += "_clampV"; + break; +#if UNITY_2018_3_OR_NEWER + case TextureWrapMode.Mirror: + result += "_mirrorV"; + break; + case TextureWrapMode.MirrorOnce: + result += "_mirrorOnceV"; + break; +#endif + } + } + break; + } + return result; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( !m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + { + string propertyOrOptions = string.Empty; + if( m_texPort.IsConnected ) + { + propertyOrOptions = m_texPort.GeneratePortInstructions( ref dataCollector ); + } + else if( m_referenceNode != null ) + { + m_referenceNode.BaseGenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + propertyOrOptions = m_referenceNode.PropertyName; + } + else + { + propertyOrOptions = GenerateSamplerAttributes(); + } + + string sampler = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, propertyOrOptions , VariableMode.Create ); + + m_outputPorts[ 0 ].SetLocalValue( sampler, dataCollector.PortCategory ); + } + + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + m_referenceNode = UIUtils.GetNode( m_referenceNodeId ) as TexturePropertyNode; + m_referenceSamplerId = UIUtils.GetTexturePropertyNodeRegisterId( m_referenceNodeId ); + UpdateTitle(); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_wrapMode = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_wrapModeU = (TextureWrapMode)Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_wrapModeV = (TextureWrapMode)Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_filterMode = (FilterMode)Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_wrapMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, (int)m_wrapModeU ); + IOUtils.AddFieldValueToString( ref nodeInfo, (int)m_wrapModeV ); + IOUtils.AddFieldValueToString( ref nodeInfo, (int)m_filterMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_referenceNodeId ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerStateNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerStateNode.cs.meta new file mode 100644 index 0000000..397a1c8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SamplerStateNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 43b6f20fe0e24ff40bf9f25b001b40d8 +timeCreated: 1593535352 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SubstanceSamplerNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SubstanceSamplerNode.cs new file mode 100644 index 0000000..b75ef85 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SubstanceSamplerNode.cs @@ -0,0 +1,1360 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; +#if !UNITY_2018_1_OR_NEWER +namespace AmplifyShaderEditor +{ + // Disabling Substance Deprecated warning +#pragma warning disable 0618 + [Serializable] + [NodeAttributes( "Substance Sample", "Textures", "Samples a procedural material", KeyCode.None, true, 0, int.MaxValue, typeof( SubstanceArchive ), typeof( ProceduralMaterial ) )] + public sealed class SubstanceSamplerNode : PropertyNode + { + private const string GlobalVarDecStr = "uniform sampler2D {0};"; + private const string PropertyDecStr = "{0}(\"{0}\", 2D) = \"white\""; + + private const string AutoNormalStr = "Auto-Normal"; + private const string SubstanceStr = "Substance"; + + private float TexturePreviewSizeX = 128; + private float TexturePreviewSizeY = 128; + + private float PickerPreviewWidthAdjust = 18; + + private bool m_editing; + + private CacheNodeConnections m_cacheNodeConnections; + + [SerializeField] + private int m_firstOutputConnected = 0; + + [SerializeField] + private ProceduralMaterial m_proceduralMaterial; + + [SerializeField] + private int m_textureCoordSet = 0; + + [SerializeField] + private ProceduralOutputType[] m_textureTypes; + + [SerializeField] + private bool m_autoNormal = true; + + private System.Type m_type; + + private Texture[] m_textures = new Texture[] { }; + + private List m_outputConns = new List(); + + private Rect m_previewArea; + + private Rect m_pickerArea; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT2, false, "UV" ); + AddOutputPort( WirePortDataType.COLOR, Constants.EmptyPortValue ); + m_insideSize.Set( TexturePreviewSizeX + PickerPreviewWidthAdjust, TexturePreviewSizeY + 10 ); + m_type = typeof( ProceduralMaterial ); + m_currentParameterType = PropertyType.Property; + m_freeType = false; + m_freeName = false; + m_autoWrapProperties = true; + m_customPrefix = "Substance Sample "; + m_drawPrecisionUI = false; + m_showPreview = true; + m_drawPreviewExpander = false; + m_selectedLocation = PreviewLocation.TopCenter; + m_cacheNodeConnections = new CacheNodeConnections(); + m_previewShaderGUID = "6f322c1da33f1e744941aafcb0ad1a2d"; + m_showAutoRegisterUI = false; + } + + public override void RenderNodePreview() + { + //Runs at least one time + if( !m_initialized ) + { + // nodes with no preview don't update at all + PreviewIsDirty = false; + return; + } + + if( !PreviewIsDirty ) + return; + + SetPreviewInputs(); + + PreviewMaterial.SetInt( "_CustomUVs", m_inputPorts[ 0 ].IsConnected ? 1 : 0 ); + + if( m_proceduralMaterial == null ) + return; + + if( !Preferences.GlobalDisablePreviews ) + { + Texture[] texs = m_proceduralMaterial.GetGeneratedTextures(); + int count = m_outputPorts.Count; + for( int i = 0 ; i < count ; i++ ) + { + RenderTexture temp = RenderTexture.active; + RenderTexture.active = m_outputPorts[ i ].OutputPreviewTexture; + + PreviewMaterial.SetTexture( "_GenTex" , texs[ i ] ); + + if( m_autoNormal && m_textureTypes[ i ] == ProceduralOutputType.Normal ) + Graphics.Blit( null , m_outputPorts[ i ].OutputPreviewTexture , PreviewMaterial , 1 ); + else + Graphics.Blit( null , m_outputPorts[ i ].OutputPreviewTexture , PreviewMaterial , 0 ); + RenderTexture.active = temp; + } + } + + PreviewIsDirty = m_continuousPreviewRefresh; + } + + public override void OnOutputPortConnected( int portId, int otherNodeId, int otherPortId ) + { + base.OnOutputPortConnected( portId, otherNodeId, otherPortId ); + m_firstOutputConnected = -1; + } + + public override void OnOutputPortDisconnected( int portId ) + { + base.OnOutputPortDisconnected( portId ); + m_firstOutputConnected = -1; + } + + void CalculateFirstOutputConnected() + { + m_outputConns.Clear(); + int count = m_outputPorts.Count; + bool connectionsAvailable = false; + for( int i = 0; i < count; i++ ) + { + if( m_outputPorts[ i ].IsConnected ) + { + connectionsAvailable = true; + } + } + + for( int i = 0; i < count; i++ ) + { + if( connectionsAvailable ) + { + if( m_outputPorts[ i ].IsConnected ) + { + if( m_firstOutputConnected < 0 ) + m_firstOutputConnected = i; + + m_outputConns.Add( i ); + } + } + else + { + m_outputConns.Add( i ); + } + } + + if( m_firstOutputConnected < 0 ) + m_firstOutputConnected = 0; + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_previewArea = m_remainingBox; + m_previewArea.width = TexturePreviewSizeX * drawInfo.InvertedZoom; + m_previewArea.height = TexturePreviewSizeY * drawInfo.InvertedZoom; + m_previewArea.x += 0.5f * m_remainingBox.width - 0.5f * m_previewArea.width; + m_pickerArea = m_previewArea; + m_pickerArea.width = 40 * drawInfo.InvertedZoom; + m_pickerArea.x = m_previewArea.xMax - m_pickerArea.width - 2; + m_pickerArea.height = 14 * drawInfo.InvertedZoom; + m_pickerArea.y = m_previewArea.yMax - m_pickerArea.height - 2; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if( !( drawInfo.CurrentEventType == EventType.MouseDown || drawInfo.CurrentEventType == EventType.MouseUp || drawInfo.CurrentEventType == EventType.ExecuteCommand || drawInfo.CurrentEventType == EventType.DragPerform ) ) + return; + + bool insideBox = m_previewArea.Contains( drawInfo.MousePosition ); + + if( insideBox ) + { + m_editing = true; + } + else if( m_editing && !insideBox && drawInfo.CurrentEventType != EventType.ExecuteCommand ) + { + GUI.FocusControl( null ); + m_editing = false; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( m_editing ) + { + m_textures = m_proceduralMaterial != null ? m_proceduralMaterial.GetGeneratedTextures() : null; + if( GUI.Button( m_pickerArea, string.Empty, GUIStyle.none ) ) + { + int controlID = EditorGUIUtility.GetControlID( FocusType.Passive ); + EditorGUIUtility.ShowObjectPicker( m_proceduralMaterial, false, "", controlID ); + } + + string commandName = Event.current.commandName; + UnityEngine.Object newValue = null; + if( commandName == "ObjectSelectorUpdated" ) + { + newValue = EditorGUIUtility.GetObjectPickerObject(); + if( newValue != (UnityEngine.Object)m_proceduralMaterial ) + { + PreviewIsDirty = true; + UndoRecordObject( "Changing value EditorGUIObjectField on node Substance Sample" ); + + m_proceduralMaterial = newValue != null ? (ProceduralMaterial)newValue : null; + m_textures = m_proceduralMaterial != null ? m_proceduralMaterial.GetGeneratedTextures() : null; + OnNewSubstanceSelected( m_textures ); + } + } + else if( commandName == "ObjectSelectorClosed" ) + { + newValue = EditorGUIUtility.GetObjectPickerObject(); + if( newValue != (UnityEngine.Object)m_proceduralMaterial ) + { + PreviewIsDirty = true; + UndoRecordObject( "Changing value EditorGUIObjectField on node Substance Sample" ); + + m_proceduralMaterial = newValue != null ? (ProceduralMaterial)newValue : null; + m_textures = m_proceduralMaterial != null ? m_proceduralMaterial.GetGeneratedTextures() : null; + OnNewSubstanceSelected( m_textures ); + } + m_editing = false; + } + + if( GUI.Button( m_previewArea, string.Empty, GUIStyle.none ) ) + { + if( m_proceduralMaterial != null ) + { + Selection.activeObject = m_proceduralMaterial; + EditorGUIUtility.PingObject( Selection.activeObject ); + } + m_editing = false; + } + } + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + if( !m_editing ) + m_textures = m_proceduralMaterial != null ? m_proceduralMaterial.GetGeneratedTextures() : null; + + if( m_textures != null ) + { + if( m_firstOutputConnected < 0 ) + { + CalculateFirstOutputConnected(); + } + else if( m_textures.Length != m_textureTypes.Length ) + { + OnNewSubstanceSelected( m_textures ); + } + + int texCount = m_outputConns.Count; + Rect individuals = m_previewArea; + individuals.height /= texCount; + + for( int i = 0; i < texCount; i++ ) + { + EditorGUI.DrawPreviewTexture( individuals, m_textures[ m_outputConns[ i ] ], null, ScaleMode.ScaleAndCrop ); + individuals.y += individuals.height; + } + } + else + { + GUI.Label( m_previewArea, string.Empty, UIUtils.ObjectFieldThumb ); + } + + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + { + Rect smallButton = m_previewArea; + smallButton.height = 14 * drawInfo.InvertedZoom; + smallButton.y = m_previewArea.yMax - smallButton.height - 2; + smallButton.width = 40 * drawInfo.InvertedZoom; + smallButton.x = m_previewArea.xMax - smallButton.width - 2; + if( m_textures == null ) + { + GUI.Label( m_previewArea, "None (Procedural Material)", UIUtils.ObjectFieldThumbOverlay ); + } + GUI.Label( m_pickerArea, "Select", UIUtils.GetCustomStyle( CustomStyle.SamplerButton ) ); + } + + GUI.Label( m_previewArea, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + } + } + + void OnNewSubstanceSelected( Texture[] textures ) + { + CacheCurrentSettings(); + ConfigPortsFromMaterial( true, textures ); + ConnectFromCache(); + m_requireMaterialUpdate = true; + CalculateFirstOutputConnected(); + ContainerGraph.ParentWindow.RequestRepaint(); + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_proceduralMaterial = EditorGUILayoutObjectField( SubstanceStr, m_proceduralMaterial, m_type, false ) as ProceduralMaterial; + if( EditorGUI.EndChangeCheck() ) + { + Texture[] textures = m_proceduralMaterial != null ? m_proceduralMaterial.GetGeneratedTextures() : null; + if( textures != null ) + { + OnNewSubstanceSelected( textures ); + } + } + + m_textureCoordSet = EditorGUILayoutIntPopup( Constants.AvailableUVSetsLabel, m_textureCoordSet, Constants.AvailableUVSetsStr, Constants.AvailableUVSets ); + EditorGUI.BeginChangeCheck(); + m_autoNormal = EditorGUILayoutToggle( AutoNormalStr, m_autoNormal ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < m_textureTypes.Length; i++ ) + { + WirePortDataType portType = ( m_autoNormal && m_textureTypes[ i ] == ProceduralOutputType.Normal ) ? WirePortDataType.FLOAT3 : WirePortDataType.COLOR; + if( m_outputPorts[ i ].DataType != portType ) + { + m_outputPorts[ i ].ChangeType( portType, false ); + } + } + } + } + + private void CacheCurrentSettings() + { + m_cacheNodeConnections.Clear(); + for( int portId = 0; portId < m_outputPorts.Count; portId++ ) + { + if( m_outputPorts[ portId ].IsConnected ) + { + int connCount = m_outputPorts[ portId ].ConnectionCount; + for( int connIdx = 0; connIdx < connCount; connIdx++ ) + { + WireReference connection = m_outputPorts[ portId ].GetConnection( connIdx ); + m_cacheNodeConnections.Add( m_outputPorts[ portId ].Name, new NodeCache( connection.NodeId, connection.PortId ) ); + } + } + } + } + + private void ConnectFromCache() + { + for( int i = 0; i < m_outputPorts.Count; i++ ) + { + List connections = m_cacheNodeConnections.GetList( m_outputPorts[ i ].Name ); + if( connections != null ) + { + int count = connections.Count; + for( int connIdx = 0; connIdx < count; connIdx++ ) + { + UIUtils.SetConnection( connections[ connIdx ].TargetNodeId, connections[ connIdx ].TargetPortId, UniqueId, i ); + } + } + } + } + + + private void ConfigPortsFromMaterial( bool invalidateConnections = false, Texture[] newTextures = null ) + { + SetAdditonalTitleText( ( m_proceduralMaterial != null ) ? string.Format( Constants.PropertyValueLabel, m_proceduralMaterial.name ) : "Value( )" ); + + Texture[] textures = newTextures != null ? newTextures : ( ( m_proceduralMaterial != null ) ? m_proceduralMaterial.GetGeneratedTextures() : null ); + if( textures != null ) + { + m_firstOutputConnected = -1; + string nameToRemove = m_proceduralMaterial.name + "_"; + m_textureTypes = new ProceduralOutputType[ textures.Length ]; + for( int i = 0; i < textures.Length; i++ ) + { + ProceduralTexture procTex = textures[ i ] as ProceduralTexture; + m_textureTypes[ i ] = procTex.GetProceduralOutputType(); + + WirePortDataType portType = ( m_autoNormal && m_textureTypes[ i ] == ProceduralOutputType.Normal ) ? WirePortDataType.FLOAT3 : WirePortDataType.COLOR; + string newName = textures[ i ].name.Replace( nameToRemove, string.Empty ); + char firstLetter = Char.ToUpper( newName[ 0 ] ); + newName = firstLetter.ToString() + newName.Substring( 1 ); + if( i < m_outputPorts.Count ) + { + m_outputPorts[ i ].ChangeProperties( newName, portType, false ); + if( invalidateConnections ) + { + m_outputPorts[ i ].FullDeleteConnections(); + } + } + else + { + AddOutputPort( portType, newName ); + } + } + + if( textures.Length < m_outputPorts.Count ) + { + int itemsToRemove = m_outputPorts.Count - textures.Length; + for( int i = 0; i < itemsToRemove; i++ ) + { + int idx = m_outputPorts.Count - 1; + if( m_outputPorts[ idx ].IsConnected ) + { + m_outputPorts[ idx ].ForceClearConnection(); + } + RemoveOutputPort( idx ); + } + } + } + else + { + int itemsToRemove = m_outputPorts.Count - 1; + m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, WirePortDataType.COLOR, false ); + m_outputPorts[ 0 ].ForceClearConnection(); + + for( int i = 0; i < itemsToRemove; i++ ) + { + int idx = m_outputPorts.Count - 1; + if( m_outputPorts[ idx ].IsConnected ) + { + m_outputPorts[ idx ].ForceClearConnection(); + } + RemoveOutputPort( idx ); + } + } + + m_sizeIsDirty = true; + m_isDirty = true; + } + + private void ConfigFromObject( UnityEngine.Object obj ) + { + ProceduralMaterial newMat = AssetDatabase.LoadAssetAtPath( AssetDatabase.GetAssetPath( obj ) ); + if( newMat != null ) + { + m_proceduralMaterial = newMat; + ConfigPortsFromMaterial(); + } + } + + public override void OnObjectDropped( UnityEngine.Object obj ) + { + ConfigFromObject( obj ); + } + + public override void SetupFromCastObject( UnityEngine.Object obj ) + { + ConfigFromObject( obj ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_proceduralMaterial == null ) + { + return "(0).xxxx"; + } + + if( m_outputPorts[ outputId ].IsLocalValue( dataCollector.PortCategory ) ) + { + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + Texture[] textures = m_proceduralMaterial.GetGeneratedTextures(); + + string uvPropertyName = string.Empty; + for( int i = 0; i < m_outputPorts.Count; i++ ) + { + if( m_outputPorts[ i ].HasConnectedNode ) + { + uvPropertyName = textures[ i ].name; + break; + } + } + + string name = textures[ outputId ].name + OutputId; + dataCollector.AddToUniforms( UniqueId, string.Format( GlobalVarDecStr, textures[ outputId ].name ) ); + dataCollector.AddToProperties( UniqueId, string.Format( PropertyDecStr, textures[ outputId ].name ) + "{}", -1 ); + bool isVertex = ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ); + string value = string.Format( "tex2D{0}({1}, {2})", ( isVertex ? "lod" : string.Empty ), textures[ outputId ].name, GetUVCoords( ref dataCollector, ignoreLocalvar, uvPropertyName ) ); + if( m_autoNormal && m_textureTypes[ outputId ] == ProceduralOutputType.Normal ) + { + value = GeneratorUtils.GenerateUnpackNormalStr( ref dataCollector, CurrentPrecisionType, UniqueId, OutputId, value, false, "1.0" ); + } + + dataCollector.AddPropertyNode( this ); + RegisterLocalVariable( outputId, value, ref dataCollector, name ); + + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + public string GetUVCoords( ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar, string propertyName ) + { + bool isVertex = ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ); + if( m_inputPorts[ 0 ].IsConnected ) + { + return m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, isVertex ? WirePortDataType.FLOAT4 : WirePortDataType.FLOAT2, ignoreLocalVar, true ); + } + else + { + string uvChannelName = IOUtils.GetUVChannelName( propertyName, m_textureCoordSet ); + + if( dataCollector.IsTemplate ) + { + string propertyHelperVar = propertyName + "_ST"; + dataCollector.AddToUniforms( UniqueId, "float4", propertyHelperVar, dataCollector.IsSRP ); + string uvName = string.Empty; + if( dataCollector.TemplateDataCollectorInstance.HasUV( m_textureCoordSet ) ) + { + uvName = dataCollector.TemplateDataCollectorInstance.GetUVName( m_textureCoordSet ); + } + else + { + uvName = dataCollector.TemplateDataCollectorInstance.RegisterUV( m_textureCoordSet ); + } + + uvChannelName = "uv" + propertyName; + if( isVertex ) + { + string value = string.Format( Constants.TilingOffsetFormat, uvName, propertyHelperVar + ".xy", propertyHelperVar + ".zw" ); + string lodLevel = "0"; + + value = "float4( " + value + ", 0 , " + lodLevel + " )"; + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT4, uvChannelName, value ); + } + else + { + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT2, uvChannelName, string.Format( Constants.TilingOffsetFormat, uvName, propertyHelperVar + ".xy", propertyHelperVar + ".zw" ) ); + } + } + else + { + string vertexCoords = Constants.VertexShaderInputStr + ".texcoord"; + if( m_textureCoordSet > 0 ) + { + vertexCoords += m_textureCoordSet.ToString(); + } + + + string dummyPropUV = "_texcoord" + ( m_textureCoordSet > 0 ? ( m_textureCoordSet + 1 ).ToString() : "" ); + string dummyUV = "uv" + ( m_textureCoordSet > 0 ? ( m_textureCoordSet + 1 ).ToString() : "" ) + dummyPropUV; + + dataCollector.AddToUniforms( UniqueId, "uniform float4 " + propertyName + "_ST;" ); + dataCollector.AddToProperties( UniqueId, "[HideInInspector] " + dummyPropUV + "( \"\", 2D ) = \"white\" {}", 100 ); + dataCollector.AddToInput( UniqueId, dummyUV, WirePortDataType.FLOAT2 ); + + if( isVertex ) + { + dataCollector.AddToVertexLocalVariables( UniqueId, "float4 " + uvChannelName + " = float4(" + vertexCoords + " * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw, 0 ,0);" ); + return uvChannelName; + } + else + dataCollector.AddToLocalVariables( UniqueId, PrecisionType.Float, WirePortDataType.FLOAT2, uvChannelName, Constants.InputVarStr + "." + dummyUV + " * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw" ); + + } + + return uvChannelName; + } + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if( m_proceduralMaterial != null ) + { + Texture[] textures = m_proceduralMaterial.GetGeneratedTextures(); + for( int i = 0; i < textures.Length; i++ ) + { + if( mat.HasProperty( textures[ i ].name ) && !InsideShaderFunction ) + { + mat.SetTexture( textures[ i ].name, textures[ i ] ); + } + } + } + } + + public override bool UpdateShaderDefaults( ref Shader shader, ref TextureDefaultsDataColector defaultCol ) + { + if( m_proceduralMaterial != null ) + { + Texture[] textures = m_proceduralMaterial.GetGeneratedTextures(); + for( int i = 0; i < textures.Length; i++ ) + { + defaultCol.AddValue( textures[ i ].name, textures[ i ] ); + } + } + return true; + } + + public override void Destroy() + { + base.Destroy(); + m_textures = null; + m_proceduralMaterial = null; + m_cacheNodeConnections.Clear(); + m_cacheNodeConnections = null; + m_outputConns.Clear(); + m_outputConns = null; + } + + public override string GetPropertyValStr() + { + return m_proceduralMaterial ? m_proceduralMaterial.name : string.Empty; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + string guid = GetCurrentParam( ref nodeParams ); + m_textureCoordSet = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_autoNormal = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + if( guid.Length > 1 ) + { + m_proceduralMaterial = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( guid ) ); + if( m_proceduralMaterial != null ) + { + ConfigPortsFromMaterial(); + } + else + { + UIUtils.ShowMessage( UniqueId, "Substance not found ", MessageSeverity.Error ); + } + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + string guid = ( m_proceduralMaterial != null ) ? AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_proceduralMaterial ) ) : "0"; + IOUtils.AddFieldValueToString( ref nodeInfo, guid ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_textureCoordSet ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_autoNormal ); + } + + } +#pragma warning restore 0618 +} +#elif SUBSTANCE_PLUGIN_ENABLED + +using Substance.Game; + +namespace AmplifyShaderEditor +{ + public enum ASEProceduralOutputType + { + Color, + Normal, + } + // Disabling Substance Deprecated warning +#pragma warning disable 0618 + [Serializable] + [NodeAttributes( "Substance Sample", "Textures", "Samples a procedural material", KeyCode.None, true, 0, int.MaxValue, typeof( SubstanceGraph ), typeof( Substance.Game.Substance ) )] + public sealed class SubstanceSamplerNode : PropertyNode + { + private const string NormalMapCheck = "normal"; + private const string GlobalVarDecStr = "uniform sampler2D {0};"; + private const string PropertyDecStr = "{0}(\"{1}\", 2D) = \"white\""; + + private const string AutoNormalStr = "Auto-Normal"; + private const string SubstanceStr = "Substance"; + + private float TexturePreviewSizeX = 128; + private float TexturePreviewSizeY = 128; + + private float PickerPreviewWidthAdjust = 18; + + private bool m_editing; + + private CacheNodeConnections m_cacheNodeConnections; + + [SerializeField] + private int m_firstOutputConnected = 0; + + [SerializeField] + private Substance.Game.SubstanceGraph m_substanceGraph; + [SerializeField] + private string m_substanceGUID = string.Empty; + + [SerializeField] + private int m_textureCoordSet = 0; + + [SerializeField] + private ASEProceduralOutputType[] m_textureTypes; + + [SerializeField] + private bool m_autoNormal = true; + + private System.Type m_type; + + private List m_textures = new List(); + + private List m_outputConns = new List(); + + private Rect m_previewArea; + + private Rect m_pickerArea; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT2, false, "UV" ); + AddOutputPort( WirePortDataType.COLOR, Constants.EmptyPortValue ); + m_insideSize.Set( TexturePreviewSizeX + PickerPreviewWidthAdjust, TexturePreviewSizeY + 10 ); + m_type = typeof( Substance.Game.Substance ); + m_currentParameterType = PropertyType.Property; + m_freeType = false; + m_freeName = false; + m_autoWrapProperties = true; + m_customPrefix = "Substance Sample "; + m_drawPrecisionUI = false; + m_showPreview = true; + m_drawPreviewExpander = false; + m_selectedLocation = PreviewLocation.TopCenter; + m_cacheNodeConnections = new CacheNodeConnections(); + m_previewShaderGUID = "6f322c1da33f1e744941aafcb0ad1a2d"; + m_showAutoRegisterUI = false; + } + + public override void RenderNodePreview() + { + if( !m_initialized ) + return; + + SetPreviewInputs(); + PreviewMaterial.SetInt( "_CustomUVs", m_inputPorts[ 0 ].IsConnected ? 1 : 0 ); + + if( m_substanceGraph == null ) + return; + + List texs = m_substanceGraph.generatedTextures; + int count = m_outputPorts.Count; + for( int i = 0; i < count; i++ ) + { + RenderTexture temp = RenderTexture.active; + RenderTexture.active = m_outputPorts[ i ].OutputPreviewTexture; + + PreviewMaterial.SetTexture( "_GenTex", texs[ i ] ); + + if( m_autoNormal && m_textureTypes[ i ] == ASEProceduralOutputType.Normal ) + Graphics.Blit( null, m_outputPorts[ i ].OutputPreviewTexture, PreviewMaterial, 1 ); + else + Graphics.Blit( null, m_outputPorts[ i ].OutputPreviewTexture, PreviewMaterial, 0 ); + RenderTexture.active = temp; + } + } + + public override void OnOutputPortConnected( int portId, int otherNodeId, int otherPortId ) + { + base.OnOutputPortConnected( portId, otherNodeId, otherPortId ); + m_firstOutputConnected = -1; + } + + public override void OnOutputPortDisconnected( int portId ) + { + base.OnOutputPortDisconnected( portId ); + m_firstOutputConnected = -1; + } + + void CalculateFirstOutputConnected() + { + m_outputConns.Clear(); + int count = m_outputPorts.Count; + bool connectionsAvailable = false; + for( int i = 0; i < count; i++ ) + { + if( m_outputPorts[ i ].IsConnected ) + { + connectionsAvailable = true; + } + } + + for( int i = 0; i < count; i++ ) + { + if( connectionsAvailable ) + { + if( m_outputPorts[ i ].IsConnected ) + { + if( m_firstOutputConnected < 0 ) + m_firstOutputConnected = i; + + m_outputConns.Add( i ); + } + } + else + { + m_outputConns.Add( i ); + } + } + + if( m_firstOutputConnected < 0 ) + m_firstOutputConnected = 0; + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + + m_previewArea = m_remainingBox; + m_previewArea.width = TexturePreviewSizeX * drawInfo.InvertedZoom; + m_previewArea.height = TexturePreviewSizeY * drawInfo.InvertedZoom; + m_previewArea.x += 0.5f * m_remainingBox.width - 0.5f * m_previewArea.width; + m_pickerArea = m_previewArea; + m_pickerArea.width = 40 * drawInfo.InvertedZoom; + m_pickerArea.x = m_previewArea.xMax - m_pickerArea.width - 2; + m_pickerArea.height = 14 * drawInfo.InvertedZoom; + m_pickerArea.y = m_previewArea.yMax - m_pickerArea.height - 2; + } + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if( !( drawInfo.CurrentEventType == EventType.MouseDown || drawInfo.CurrentEventType == EventType.MouseUp || drawInfo.CurrentEventType == EventType.ExecuteCommand || drawInfo.CurrentEventType == EventType.DragPerform ) ) + return; + + bool insideBox = m_previewArea.Contains( drawInfo.MousePosition ); + + if( insideBox ) + { + m_editing = true; + } + else if( m_editing && !insideBox && drawInfo.CurrentEventType != EventType.ExecuteCommand ) + { + GUI.FocusControl( null ); + m_editing = false; + } + } + + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( m_editing ) + { + m_textures = m_substanceGraph != null ? m_substanceGraph.generatedTextures : null; + if( GUI.Button( m_pickerArea, string.Empty, GUIStyle.none ) ) + { + int controlID = EditorGUIUtility.GetControlID( FocusType.Passive ); + EditorGUIUtility.ShowObjectPicker( m_substanceGraph, false, "", controlID ); + } + + string commandName = Event.current.commandName; + UnityEngine.Object newValue = null; + if( commandName == "ObjectSelectorUpdated" ) + { + newValue = EditorGUIUtility.GetObjectPickerObject(); + if( newValue != (UnityEngine.Object)m_substanceGraph ) + { + UndoRecordObject( "Changing value EditorGUIObjectField on node Substance Sample" ); + + SubstanceGraph = newValue != null ? (SubstanceGraph)newValue : null; + m_textures = m_substanceGraph != null ? m_substanceGraph.generatedTextures : null; + OnNewSubstanceSelected( m_textures ); + } + } + else if( commandName == "ObjectSelectorClosed" ) + { + newValue = EditorGUIUtility.GetObjectPickerObject(); + if( newValue != (UnityEngine.Object)m_substanceGraph ) + { + UndoRecordObject( "Changing value EditorGUIObjectField on node Substance Sample" ); + + SubstanceGraph = newValue != null ? (SubstanceGraph)newValue : null; + m_textures = m_substanceGraph != null ? m_substanceGraph.generatedTextures : null; + OnNewSubstanceSelected( m_textures ); + } + m_editing = false; + } + + if( GUI.Button( m_previewArea, string.Empty, GUIStyle.none ) ) + { + if( m_substanceGraph != null ) + { + Selection.activeObject = m_substanceGraph; + EditorGUIUtility.PingObject( Selection.activeObject ); + } + m_editing = false; + } + } + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + if( !m_editing ) + m_textures = m_substanceGraph != null ? m_substanceGraph.generatedTextures : null; + + if( m_textures != null ) + { + if( m_firstOutputConnected < 0 ) + { + CalculateFirstOutputConnected(); + } + else if( m_textures.Count != m_textureTypes.Length ) + { + OnNewSubstanceSelected( m_textures ); + } + + int texCount = m_outputConns.Count; + Rect individuals = m_previewArea; + individuals.height /= texCount; + + for( int i = 0; i < texCount; i++ ) + { + + //EditorGUI.DrawPreviewTexture( individuals, m_textures[ m_outputConns[ i ] ], null, ScaleMode.ScaleAndCrop ); + EditorGUI.DrawPreviewTexture( individuals, m_outputPorts[ m_outputConns[ i ] ].OutputPreviewTexture, null, ScaleMode.ScaleAndCrop ); + individuals.y += individuals.height; + } + } + else + { + GUI.Label( m_previewArea, string.Empty, UIUtils.ObjectFieldThumb ); + } + + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + { + Rect smallButton = m_previewArea; + smallButton.height = 14 * drawInfo.InvertedZoom; + smallButton.y = m_previewArea.yMax - smallButton.height - 2; + smallButton.width = 40 * drawInfo.InvertedZoom; + smallButton.x = m_previewArea.xMax - smallButton.width - 2; + if( m_textures == null ) + { + GUI.Label( m_previewArea, "None (Procedural Material)", UIUtils.ObjectFieldThumbOverlay ); + } + GUI.Label( m_pickerArea, "Select", UIUtils.GetCustomStyle( CustomStyle.SamplerButton ) ); + } + + GUI.Label( m_previewArea, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + } + } + + void OnNewSubstanceSelected( List textures ) + { + CacheCurrentSettings(); + ConfigPortsFromMaterial( true, textures ); + ConnectFromCache(); + m_requireMaterialUpdate = true; + CalculateFirstOutputConnected(); + ContainerGraph.ParentWindow.RequestRepaint(); + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + SubstanceGraph = EditorGUILayoutObjectField( SubstanceStr, m_substanceGraph, m_type, false ) as SubstanceGraph; + if( EditorGUI.EndChangeCheck() ) + { + List textures = m_substanceGraph != null ? m_substanceGraph.generatedTextures : null; + if( textures != null ) + { + OnNewSubstanceSelected( textures ); + } + } + + m_textureCoordSet = EditorGUILayoutIntPopup( Constants.AvailableUVSetsLabel, m_textureCoordSet, Constants.AvailableUVSetsStr, Constants.AvailableUVSets ); + EditorGUI.BeginChangeCheck(); + m_autoNormal = EditorGUILayoutToggle( AutoNormalStr, m_autoNormal ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < m_textureTypes.Length; i++ ) + { + WirePortDataType portType = ( m_autoNormal && m_textureTypes[ i ] == ASEProceduralOutputType.Normal ) ? WirePortDataType.FLOAT3 : WirePortDataType.COLOR; + if( m_outputPorts[ i ].DataType != portType ) + { + m_outputPorts[ i ].ChangeType( portType, false ); + } + } + } + } + + private void CacheCurrentSettings() + { + m_cacheNodeConnections.Clear(); + for( int portId = 0; portId < m_outputPorts.Count; portId++ ) + { + if( m_outputPorts[ portId ].IsConnected ) + { + int connCount = m_outputPorts[ portId ].ConnectionCount; + for( int connIdx = 0; connIdx < connCount; connIdx++ ) + { + WireReference connection = m_outputPorts[ portId ].GetConnection( connIdx ); + m_cacheNodeConnections.Add( m_outputPorts[ portId ].Name, new NodeCache( connection.NodeId, connection.PortId ) ); + } + } + } + } + + private void ConnectFromCache() + { + for( int i = 0; i < m_outputPorts.Count; i++ ) + { + List connections = m_cacheNodeConnections.GetList( m_outputPorts[ i ].Name ); + if( connections != null ) + { + int count = connections.Count; + for( int connIdx = 0; connIdx < count; connIdx++ ) + { + UIUtils.SetConnection( connections[ connIdx ].TargetNodeId, connections[ connIdx ].TargetPortId, UniqueId, i ); + } + } + } + } + + + private void ConfigPortsFromMaterial( bool invalidateConnections = false, List newTextures = null ) + { + SetAdditonalTitleText( ( m_substanceGraph != null ) ? string.Format( Constants.PropertyValueLabel, m_substanceGraph.name ) : "Value( )" ); + + List textures = newTextures != null ? newTextures : ( ( m_substanceGraph != null ) ? m_substanceGraph.generatedTextures : null ); + if( textures != null ) + { + m_firstOutputConnected = -1; + string nameToRemove = m_substanceGraph.graphLabel + "_"; + m_textureTypes = new ASEProceduralOutputType[ textures.Count ]; + for( int i = 0; i < textures.Count; i++ ) + { + //TODO: Replace for a more efficient test as soon as Laurent gives more infos + bool isNormal = textures[ i ].format == TextureFormat.BC5 || textures[ i ].name.EndsWith( NormalMapCheck ); + m_textureTypes[ i ] = isNormal?ASEProceduralOutputType.Normal:ASEProceduralOutputType.Color; + + WirePortDataType portType = ( m_autoNormal && m_textureTypes[ i ] == ASEProceduralOutputType.Normal ) ? WirePortDataType.FLOAT3 : WirePortDataType.COLOR; + string newName = textures[ i ].name.Replace( nameToRemove, string.Empty ); + char firstLetter = Char.ToUpper( newName[ 0 ] ); + newName = firstLetter.ToString() + newName.Substring( 1 ); + if( i < m_outputPorts.Count ) + { + m_outputPorts[ i ].ChangeProperties( newName, portType, false ); + if( invalidateConnections ) + { + m_outputPorts[ i ].FullDeleteConnections(); + } + } + else + { + AddOutputPort( portType, newName ); + } + } + + if( textures.Count < m_outputPorts.Count ) + { + int itemsToRemove = m_outputPorts.Count - textures.Count; + for( int i = 0; i < itemsToRemove; i++ ) + { + int idx = m_outputPorts.Count - 1; + if( m_outputPorts[ idx ].IsConnected ) + { + m_outputPorts[ idx ].ForceClearConnection(); + } + RemoveOutputPort( idx ); + } + } + } + else + { + int itemsToRemove = m_outputPorts.Count - 1; + m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, WirePortDataType.COLOR, false ); + m_outputPorts[ 0 ].ForceClearConnection(); + + for( int i = 0; i < itemsToRemove; i++ ) + { + int idx = m_outputPorts.Count - 1; + if( m_outputPorts[ idx ].IsConnected ) + { + m_outputPorts[ idx ].ForceClearConnection(); + } + RemoveOutputPort( idx ); + } + } + + m_sizeIsDirty = true; + m_isDirty = true; + } + + private void ConfigFromObject( UnityEngine.Object obj ) + { + SubstanceGraph newGraph = obj as SubstanceGraph;// AssetDatabase.LoadAssetAtPath( AssetDatabase.GetAssetPath( obj ) ); + if( newGraph != null ) + { + SubstanceGraph = newGraph; + ConfigPortsFromMaterial(); + } + + Substance.Game.Substance newSubstance = obj as Substance.Game.Substance;// AssetDatabase.LoadAssetAtPath( AssetDatabase.GetAssetPath( obj ) ); + if( newSubstance != null && newSubstance.graphs.Count > 0 ) + { + SubstanceGraph = newSubstance.graphs[0]; + ConfigPortsFromMaterial(); + } + + } + + public override void OnObjectDropped( UnityEngine.Object obj ) + { + ConfigFromObject( obj ); + } + + public override void SetupFromCastObject( UnityEngine.Object obj ) + { + ConfigFromObject( obj ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_substanceGraph == null ) + { + return "(0).xxxx"; + } + + if( m_outputPorts[ outputId ].IsLocalValue( dataCollector.PortCategory ) ) + { + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + List textures = m_substanceGraph.generatedTextures; + + string uvPropertyName = string.Empty; + for( int i = 0; i < m_outputPorts.Count; i++ ) + { + if( m_outputPorts[ i ].HasConnectedNode ) + { + uvPropertyName = UIUtils.GeneratePropertyName( textures[ i ].name , PropertyType.Property ); + break; + } + } + + string propertyName = UIUtils.GeneratePropertyName( textures[ outputId ].name, PropertyType.Property ); + string name = propertyName + OutputId; + dataCollector.AddToUniforms( UniqueId, string.Format( GlobalVarDecStr, propertyName ) ); + dataCollector.AddToProperties( UniqueId, string.Format( PropertyDecStr, propertyName, textures[ outputId ].name ) + "{}", -1 ); + bool isVertex = ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ); + string value = string.Format( "tex2D{0}({1}, {2})", ( isVertex ? "lod" : string.Empty ), propertyName, GetUVCoords( ref dataCollector, ignoreLocalvar, uvPropertyName ) ); + if( m_autoNormal && m_textureTypes[ outputId ] == ASEProceduralOutputType.Normal ) + { + value = GeneratorUtils.GenerateUnpackNormalStr( ref dataCollector, CurrentPrecisionType, UniqueId, OutputId, value, false, "1.0" ); + } + + dataCollector.AddPropertyNode( this ); + RegisterLocalVariable( outputId, value, ref dataCollector, name ); + + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + public string GetUVCoords( ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar, string propertyName ) + { + bool isVertex = ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ); + if( m_inputPorts[ 0 ].IsConnected ) + { + return m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, isVertex ? WirePortDataType.FLOAT4 : WirePortDataType.FLOAT2, ignoreLocalVar, true ); + } + else + { + string uvChannelName = IOUtils.GetUVChannelName( propertyName, m_textureCoordSet ); + + if( dataCollector.IsTemplate ) + { + string propertyHelperVar = propertyName + "_ST"; + dataCollector.AddToUniforms( UniqueId, "float4", propertyHelperVar, dataCollector.IsSRP ); + string uvName = string.Empty; + string result = string.Empty; + if( dataCollector.TemplateDataCollectorInstance.GetCustomInterpolatedData( TemplateHelperFunctions.IntToUVChannelInfo[ m_textureCoordSet ], WirePortDataType.FLOAT4, PrecisionType.Float, ref result, false, dataCollector.PortCategory ) ) + { + if( m_inputPorts[ 0 ].DataType != WirePortDataType.FLOAT4 ) + result += UIUtils.GetAutoSwizzle( m_inputPorts[ 0 ].DataType ); + uvName = result; + } + else + if( dataCollector.TemplateDataCollectorInstance.HasUV( m_textureCoordSet ) ) + { + uvName = dataCollector.TemplateDataCollectorInstance.GetUVName( m_textureCoordSet ); + } + else + { + uvName = dataCollector.TemplateDataCollectorInstance.RegisterUV( m_textureCoordSet ); + } + + uvChannelName = "uv" + propertyName; + if( isVertex ) + { + string value = string.Format( Constants.TilingOffsetFormat, uvName, propertyHelperVar + ".xy", propertyHelperVar + ".zw" ); + string lodLevel = "0"; + + value = "float4( " + value + ", 0 , " + lodLevel + " )"; + dataCollector.AddLocalVariable( UniqueId, m_currentPrecisionType, WirePortDataType.FLOAT4, uvChannelName, value ); + } + else + { + dataCollector.AddLocalVariable( UniqueId, m_currentPrecisionType, WirePortDataType.FLOAT2, uvChannelName, string.Format( Constants.TilingOffsetFormat, uvName, propertyHelperVar + ".xy", propertyHelperVar + ".zw" ) ); + } + } + else + { + string vertexCoords = Constants.VertexShaderInputStr + ".texcoord"; + if( m_textureCoordSet > 0 ) + { + vertexCoords += m_textureCoordSet.ToString(); + } + + + string dummyPropUV = "_texcoord" + ( m_textureCoordSet > 0 ? ( m_textureCoordSet + 1 ).ToString() : "" ); + string dummyUV = "uv" + ( m_textureCoordSet > 0 ? ( m_textureCoordSet + 1 ).ToString() : "" ) + dummyPropUV; + + dataCollector.AddToUniforms( UniqueId, "uniform float4 " + propertyName + "_ST;" ); + dataCollector.AddToProperties( UniqueId, "[HideInInspector] " + dummyPropUV + "( \"\", 2D ) = \"white\" {}", 100 ); + dataCollector.AddToInput( UniqueId, dummyUV, WirePortDataType.FLOAT2 ); + + if( isVertex ) + { + dataCollector.AddToVertexLocalVariables( UniqueId, "float4 " + uvChannelName + " = float4(" + vertexCoords + " * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw, 0 ,0);" ); + return uvChannelName; + } + else + dataCollector.AddToLocalVariables( UniqueId, PrecisionType.Float, WirePortDataType.FLOAT2, uvChannelName, Constants.InputVarStr + "." + dummyUV + " * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw" ); + + } + + return uvChannelName; + } + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if( m_substanceGraph != null ) + { + List textures = m_substanceGraph.generatedTextures; + for( int i = 0; i < textures.Count; i++ ) + { + string textureName = UIUtils.GeneratePropertyName( textures[ i ].name, PropertyType.Property ); + if( mat.HasProperty( textureName ) && !InsideShaderFunction ) + { + mat.SetTexture( textureName, textures[ i ] ); + } + } + } + } + + public override bool UpdateShaderDefaults( ref Shader shader, ref TextureDefaultsDataColector defaultCol ) + { + if( m_substanceGraph != null ) + { + List textures = m_substanceGraph.generatedTextures; + for( int i = 0; i < textures.Count; i++ ) + { + defaultCol.AddValue( UIUtils.GeneratePropertyName( textures[ i ].name, PropertyType.Property ), textures[ i ] ); + } + } + return true; + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + if( m_substanceGraph == null && !string.IsNullOrEmpty( m_substanceGUID ) ) + { + SubstanceGraph = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( m_substanceGUID ) ); + if( m_substanceGraph == null ) + { + m_substanceGUID = string.Empty; + } + } + } + + public override void Destroy() + { + base.Destroy(); + m_textures = null; + m_substanceGraph = null; + m_substanceGUID = string.Empty; + m_cacheNodeConnections.Clear(); + m_cacheNodeConnections = null; + m_outputConns.Clear(); + m_outputConns = null; + } + + public override string GetPropertyValStr() + { + return m_substanceGraph ? m_substanceGraph.name : string.Empty; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + string guid = GetCurrentParam( ref nodeParams ); + m_textureCoordSet = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_autoNormal = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + if( guid.Length > 1 ) + { + SubstanceGraph = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( guid ) ); + if( m_substanceGraph != null ) + { + ConfigPortsFromMaterial(); + } + else + { + UIUtils.ShowMessage( "Substance not found ", MessageSeverity.Error ); + } + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + string guid = ( m_substanceGraph != null ) ? AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_substanceGraph ) ) : "0"; + IOUtils.AddFieldValueToString( ref nodeInfo, guid ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_textureCoordSet ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_autoNormal ); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( m_substanceGraph != null ) + { + int count = m_outputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_autoNormal && m_textureTypes[ i ] == ASEProceduralOutputType.Normal ) + m_outputPorts[ i ].ChangeType( WirePortDataType.FLOAT3, false ); + else + m_outputPorts[ i ].ChangeType( WirePortDataType.FLOAT4, false ); + } + } + } + + public SubstanceGraph SubstanceGraph + { + set + { + m_substanceGraph = value; + if( value != null ) + { + m_substanceGUID = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( value ) ); + } + else + { + m_substanceGUID = string.Empty; + } + } + get { return m_substanceGraph; } + } + } +#pragma warning restore 0618 +} +#endif diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SubstanceSamplerNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SubstanceSamplerNode.cs.meta new file mode 100644 index 0000000..02886b0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/SubstanceSamplerNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7323b6020278e034b9e4c670cbc61361 +timeCreated: 1486640033 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCFlipBookUVAnimation.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCFlipBookUVAnimation.cs new file mode 100644 index 0000000..3735c3a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCFlipBookUVAnimation.cs @@ -0,0 +1,238 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Flipbook UV Animation +// Donated by The Four Headed Cat - @fourheadedcat + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + + [Serializable] + [NodeAttributes( "Flipbook UV Animation", "UV Coordinates", "Animate a Flipbook Texture Modifying UV Coordinates.", null, KeyCode.None, true, false, null, null, "The Four Headed Cat - @fourheadedcat" )] + public sealed class TFHCFlipBookUVAnimation : ParentNode + + { + + private const string TextureVerticalDirectionStr = "Texture Direction"; + private const string NegativeSpeedBehaviorStr = "If Negative Speed"; + + [SerializeField] + private int m_selectedTextureVerticalDirection = 0; + + [SerializeField] + private int m_negativeSpeedBehavior = 0; + + [SerializeField] + private readonly string[] m_textureVerticalDirectionValues = { "Top To Bottom", "Bottom To Top" }; + + [SerializeField] + private readonly string[] m_negativeSpeedBehaviorValues = { "Switch to Positive", "Reverse Animation" }; + + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT2, false, "UV" ); + AddInputPort( WirePortDataType.FLOAT, false, "Columns" ); + AddInputPort( WirePortDataType.FLOAT, false, "Rows" ); + AddInputPort( WirePortDataType.FLOAT, false, "Speed" ); + AddInputPort( WirePortDataType.FLOAT, false, "Start Frame" ); + AddInputPort( WirePortDataType.FLOAT, false, "Time" ); + + AddOutputVectorPorts( WirePortDataType.FLOAT2, "UV" ); + m_outputPorts[ 1 ].Name = "U"; + m_outputPorts[ 2 ].Name = "V"; + m_textLabelWidth = 125; + m_useInternalPortData = true; + m_autoWrapProperties = true; + m_previewShaderGUID = "04fe24be792bfd5428b92132d7cf0f7d"; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + if( portId == 5 ) + { + m_previewMaterialPassId = 1; + } + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + if( portId == 5 ) + { + m_previewMaterialPassId = 0; + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUILayout.BeginVertical(); + m_selectedTextureVerticalDirection = EditorGUILayoutPopup( TextureVerticalDirectionStr, m_selectedTextureVerticalDirection, m_textureVerticalDirectionValues ); + m_negativeSpeedBehavior = EditorGUILayoutPopup( NegativeSpeedBehaviorStr, m_negativeSpeedBehavior, m_negativeSpeedBehaviorValues ); + EditorGUILayout.EndVertical(); + EditorGUILayout.HelpBox( "Flipbook UV Animation:\n\n - UV: Texture Coordinates to Flipbook.\n - Columns: number of Columns (X) of the Flipbook Texture.\n - Rows: number of Rows (Y) of the Flipbook Textures.\n - Speed: speed of the animation.\n - Texture Direction: set the vertical order of the texture tiles.\n - If Negative Speed: set the behavior when speed is negative.\n\n - Out: UV Coordinates.", MessageType.None ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_selectedTextureVerticalDirection = ( int ) int.Parse( GetCurrentParam( ref nodeParams ) ); + m_negativeSpeedBehavior = ( int ) int.Parse( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedTextureVerticalDirection ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_negativeSpeedBehavior ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + // OPTIMIZATION NOTES + // + // round( fmod( x, y ) ) can be replaced with a faster + // floor( frac( x / y ) * y + 0.5 ) => div can be muls with 1/y, almost always static/constant + // + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + string uv = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string columns = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + + if ( !m_inputPorts[ 1 ].IsConnected ) + columns = ( float.Parse( columns ) == 0f ? "1" : columns ); + + string rows = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + if ( !m_inputPorts[ 2 ].IsConnected ) + rows = ( float.Parse( rows ) == 0f ? "1" : rows ); + + string speed = m_inputPorts[ 3 ].GeneratePortInstructions( ref dataCollector ); + string startframe = m_inputPorts[ 4 ].GeneratePortInstructions( ref dataCollector ); + string timer = m_inputPorts[ 5 ].IsConnected ? m_inputPorts[ 5 ].GeneratePortInstructions( ref dataCollector ) : "_Time[ 1 ]"; + + string vcomment1 = "// *** BEGIN Flipbook UV Animation vars ***"; + string vcomment2 = "// Total tiles of Flipbook Texture"; + string vtotaltiles = "float fbtotaltiles" + OutputId + " = " + columns + " * " + rows + ";"; + string vcomment3 = "// Offsets for cols and rows of Flipbook Texture"; + string vcolsoffset = "float fbcolsoffset" + OutputId + " = 1.0f / " + columns + ";"; + string vrowssoffset = "float fbrowsoffset" + OutputId + " = 1.0f / " + rows + ";"; + string vcomment4 = "// Speed of animation"; + + string vspeed = string.Format( "float fbspeed{0} = {1} * {2};", OutputId,timer,speed); + string vcomment5 = "// UV Tiling (col and row offset)"; + string vtiling = "float2 fbtiling" + OutputId + " = float2(fbcolsoffset" + OutputId + ", fbrowsoffset" + OutputId + ");"; + string vcomment6 = "// UV Offset - calculate current tile linear index, and convert it to (X * coloffset, Y * rowoffset)"; + string vcomment7 = "// Calculate current tile linear index"; + //float fbcurrenttileindex1 = round( fmod( fbspeed1 + _Float0, fbtotaltiles1 ) ); + string vcurrenttileindex = "float fbcurrenttileindex" + OutputId + " = round( fmod( fbspeed" + OutputId + " + " + startframe + ", fbtotaltiles" + OutputId + ") );"; + string vcurrenttileindex1 = "fbcurrenttileindex" + OutputId + " += ( fbcurrenttileindex" + OutputId + " < 0) ? fbtotaltiles" + OutputId + " : 0;"; + //fbcurrenttileindex1 += ( fbcurrenttileindex1 < 0 ) ? fbtotaltiles1 : 0; + //string vcurrenttileindex = "int fbcurrenttileindex" + m_uniqueId + " = (int)fmod( fbspeed" + m_uniqueId + ", fbtotaltiles" + m_uniqueId + ") + " + startframe + ";"; + string vcomment8 = "// Obtain Offset X coordinate from current tile linear index"; + + //float fblinearindextox1 = round( fmod( fbcurrenttileindex1, 5.0 ) ); + //string voffsetx1 = "int fblinearindextox" + m_uniqueId + " = fbcurrenttileindex" + m_uniqueId + " % (int)" + columns + ";"; + string voffsetx1 = "float fblinearindextox" + OutputId + " = round ( fmod ( fbcurrenttileindex" + OutputId + ", " + columns + " ) );"; + string vcomment9 = String.Empty; + string voffsetx2 = String.Empty; + if ( m_negativeSpeedBehavior != 0 ) + { + vcomment9 = "// Reverse X animation if speed is negative"; + voffsetx2 = "fblinearindextox" + OutputId + " = (" + speed + " > 0 ? fblinearindextox" + OutputId + " : (int)" + columns + " - fblinearindextox" + OutputId + ");"; + } + string vcomment10 = "// Multiply Offset X by coloffset"; + string voffsetx3 = "float fboffsetx" + OutputId + " = fblinearindextox" + OutputId + " * fbcolsoffset" + OutputId + ";"; + string vcomment11 = "// Obtain Offset Y coordinate from current tile linear index"; + //float fblinearindextoy1 = round( fmod( ( fbcurrenttileindex1 - fblinearindextox1 ) / 5.0, 5.0 ) ); + string voffsety1 = "float fblinearindextoy" + OutputId + " = round( fmod( ( fbcurrenttileindex" + OutputId + " - fblinearindextox" + OutputId + " ) / " + columns + ", " + rows + " ) );"; + //string voffsety1 = "int fblinearindextoy" + m_uniqueId + " = (int)( ( fbcurrenttileindex" + m_uniqueId + " - fblinearindextox" + m_uniqueId + " ) / " + columns + " ) % (int)" + rows + ";"; + //string vcomment10 = "// Reverse Y to get from Top to Bottom"; + //string voffsety2 = "fblinearindextoy" + m_uniqueId + " = (int)" + rows + " - fblinearindextoy" + m_uniqueId + ";"; + string vcomment12 = String.Empty; + string voffsety2 = String.Empty; + if ( m_negativeSpeedBehavior == 0 ) + { + if ( m_selectedTextureVerticalDirection == 0 ) + { + vcomment12 = "// Reverse Y to get tiles from Top to Bottom"; + voffsety2 = "fblinearindextoy" + OutputId + " = (int)(" + rows + "-1) - fblinearindextoy" + OutputId + ";"; + } + } + else + { + string reverseanimationoperator = String.Empty; + if ( m_selectedTextureVerticalDirection == 0 ) + { + vcomment12 = "// Reverse Y to get tiles from Top to Bottom and Reverse Y animation if speed is negative"; + reverseanimationoperator = " < "; + } + else + { + vcomment12 = "// Reverse Y animation if speed is negative"; + reverseanimationoperator = " > "; + } + voffsety2 = "fblinearindextoy" + OutputId + " = (" + speed + reverseanimationoperator + " 0 ? fblinearindextoy" + OutputId + " : (int)" + rows + " - fblinearindextoy" + OutputId + ");"; + } + string vcomment13 = "// Multiply Offset Y by rowoffset"; + string voffsety3 = "float fboffsety" + OutputId + " = fblinearindextoy" + OutputId + " * fbrowsoffset" + OutputId + ";"; + string vcomment14 = "// UV Offset"; + string voffset = "float2 fboffset" + OutputId + " = float2(fboffsetx" + OutputId + ", fboffsety" + OutputId + ");"; + //string voffset = "float2 fboffset" + m_uniqueId + " = float2( ( ( (int)fmod( fbspeed" + m_uniqueId + " , fbtotaltiles" + m_uniqueId + ") % (int)" + columns + " ) * fbcolsoffset" + m_OutputId + " ) , ( ( (int)" + rows + " - ( (int)( ( (int)fmod( fbspeed" + m_uniqueId + " , fbtotaltiles" + m_uniqueId + " ) - ( (int)fmod( fbspeed" + m_uniqueId + " , fbtotaltiles" + m_uniqueId + " ) % (int)" + columns + " ) ) / " + columns + " ) % (int)" + rows + " ) ) * fbrowsoffset" + m_uniqueId + " ) );"; + string vcomment15 = "// Flipbook UV"; + string vfbuv = "half2 fbuv" + OutputId + " = " + uv + " * fbtiling" + OutputId + " + fboffset" + OutputId + ";"; + string vcomment16 = "// *** END Flipbook UV Animation vars ***"; + string result = "fbuv" + OutputId; + + dataCollector.AddLocalVariable( UniqueId, vcomment1 ); + dataCollector.AddLocalVariable( UniqueId, vcomment2 ); + dataCollector.AddLocalVariable( UniqueId, vtotaltiles ); + dataCollector.AddLocalVariable( UniqueId, vcomment3 ); + dataCollector.AddLocalVariable( UniqueId, vcolsoffset ); + dataCollector.AddLocalVariable( UniqueId, vrowssoffset ); + dataCollector.AddLocalVariable( UniqueId, vcomment4 ); + dataCollector.AddLocalVariable( UniqueId, vspeed ); + dataCollector.AddLocalVariable( UniqueId, vcomment5 ); + dataCollector.AddLocalVariable( UniqueId, vtiling ); + dataCollector.AddLocalVariable( UniqueId, vcomment6 ); + dataCollector.AddLocalVariable( UniqueId, vcomment7 ); + dataCollector.AddLocalVariable( UniqueId, vcurrenttileindex ); + dataCollector.AddLocalVariable( UniqueId, vcurrenttileindex1 ); + dataCollector.AddLocalVariable( UniqueId, vcomment8 ); + dataCollector.AddLocalVariable( UniqueId, voffsetx1 ); + if ( m_negativeSpeedBehavior != 0 ) + { + dataCollector.AddLocalVariable( UniqueId, vcomment9 ); + dataCollector.AddLocalVariable( UniqueId, voffsetx2 ); + } + dataCollector.AddLocalVariable( UniqueId, vcomment10 ); + dataCollector.AddLocalVariable( UniqueId, voffsetx3 ); + dataCollector.AddLocalVariable( UniqueId, vcomment11 ); + dataCollector.AddLocalVariable( UniqueId, voffsety1 ); + if ( m_selectedTextureVerticalDirection == 0 || m_negativeSpeedBehavior != 0 ) + { + dataCollector.AddLocalVariable( UniqueId, vcomment12 ); + dataCollector.AddLocalVariable( UniqueId, voffsety2 ); + } + dataCollector.AddLocalVariable( UniqueId, vcomment13 ); + dataCollector.AddLocalVariable( UniqueId, voffsety3 ); + dataCollector.AddLocalVariable( UniqueId, vcomment14 ); + dataCollector.AddLocalVariable( UniqueId, voffset ); + dataCollector.AddLocalVariable( UniqueId, vcomment15 ); + dataCollector.AddLocalVariable( UniqueId, vfbuv ); + dataCollector.AddLocalVariable( UniqueId, vcomment16 ); + + m_outputPorts[ 0 ].SetLocalValue( result, dataCollector.PortCategory ); + + return GetOutputVectorItem( 0, outputId, result ); + + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCFlipBookUVAnimation.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCFlipBookUVAnimation.cs.meta new file mode 100644 index 0000000..cf165fe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCFlipBookUVAnimation.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 38b8c76e7f2dc294581195a669942706 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCPixelate.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCPixelate.cs new file mode 100644 index 0000000..3d778d9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCPixelate.cs @@ -0,0 +1,54 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Pixelate UV +// Donated by The Four Headed Cat - @fourheadedcat + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Pixelate UV", "UV Coordinates", "Pixelate Texture Modifying UV.", null, KeyCode.None, true, false, null, null, "The Four Headed Cat - @fourheadedcat" )] + public sealed class TFHCPixelate : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT2, true, "UV" ); + AddInputPort( WirePortDataType.FLOAT, false, "Pixels X" ); + AddInputPort( WirePortDataType.FLOAT, false, "Pixels Y" ); + AddOutputPort( WirePortDataType.FLOAT2, "Out" ); + m_useInternalPortData = true; + m_previewShaderGUID = "e2f7e3c513ed18340868b8cbd0d85cfb"; + } + + public override void DrawProperties() + { + base.DrawProperties (); + EditorGUILayout.HelpBox ("Pixelate UV.\n\n - UV is the Texture Coordinates to pixelate.\n - Pixels X is the number of horizontal pixels\n - Pixels Y is the number of vertical pixels.", MessageType.None); + + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + string uv = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + string PixelCount_X = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ); + string PixelCount_Y = m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ); + + string pixelWidth = "float pixelWidth" + OutputId + " = 1.0f / " + PixelCount_X + ";"; + string pixelHeight = "float pixelHeight" + OutputId + " = 1.0f / " + PixelCount_Y + ";"; + string pixelatedUV = "half2 pixelateduv" + OutputId + " = half2((int)(" + uv + ".x / pixelWidth" + OutputId + ") * pixelWidth" + OutputId + ", (int)(" + uv + ".y / pixelHeight" + OutputId + ") * pixelHeight" + OutputId + ");"; + string result = "pixelateduv" + OutputId; + + dataCollector.AddLocalVariable( UniqueId, pixelWidth ); + dataCollector.AddLocalVariable( UniqueId, pixelHeight ); + dataCollector.AddLocalVariable( UniqueId, pixelatedUV ); + + return GetOutputVectorItem( 0, outputId, result); + + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCPixelate.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCPixelate.cs.meta new file mode 100644 index 0000000..fc01dd0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TFHCPixelate.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 72a1a810ace8ea440ba20d4a4f9086ce +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureCoordinatesNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureCoordinatesNode.cs new file mode 100644 index 0000000..f2820df --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureCoordinatesNode.cs @@ -0,0 +1,628 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Texture Coordinates", "UV Coordinates", "Texture UV coordinates set, if Tex is connected to a texture object it will use that texture scale factors, otherwise uses Tilling and Offset port values", null, KeyCode.U, tags: "uv" )] + public sealed class TextureCoordinatesNode : ParentNode + { + + private const string DummyPropertyDec = "[HideInInspector] _DummyTex{0}( \"\", 2D ) = \"white\""; + private const string DummyUniformDec = "uniform sampler2D _DummyTex{0};"; + private const string DummyTexCoordDef = "uv{0}_DummyTex{0}"; + private const string DummyTexCoordSurfDef = "float2 texCoordDummy{0} = {1}.uv{2}_DummyTex{2}*{3} + {4};"; + private const string DummyTexCoordSurfVar = "texCoordDummy{0}"; + + private readonly string[] Dummy = { string.Empty }; + + private const string TilingStr = "Tiling"; + private const string OffsetStr = "Offset"; + private const string TexCoordStr = "texcoord_"; + + [SerializeField] + private int m_referenceArrayId = -1; + + [SerializeField] + private int m_referenceNodeId = -1; + + [SerializeField] + private int m_textureCoordChannel = 0; + + //[SerializeField] + //private int m_texcoordId = -1; + + [SerializeField] + private int m_texcoordSize = 2; + + [SerializeField] + private string m_surfaceTexcoordName = string.Empty; + + [SerializeField] + private TexturePropertyNode m_inputReferenceNode = null; + + private Vector4Node m_texCoordsHelper; + + private TexturePropertyNode m_referenceNode = null; + + private InputPort m_texPort = null; + private InputPort m_tilingPort = null; + private InputPort m_offsetPort = null; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.SAMPLER2D, false, "Tex", -1, MasterNodePortCategory.Fragment, 2 ); + m_texPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + m_texPort.CreatePortRestrictions( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.SAMPLER2DARRAY, WirePortDataType.OBJECT ); + + AddInputPort( WirePortDataType.FLOAT2, false, "Tiling", -1, MasterNodePortCategory.Fragment, 0 ); + m_tilingPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + m_tilingPort.Vector2InternalData = new Vector2( 1, 1 ); + AddInputPort( WirePortDataType.FLOAT2, false, "Offset", -1, MasterNodePortCategory.Fragment, 1 ); + m_offsetPort = m_inputPorts[ m_inputPorts.Count - 1 ]; + + + AddOutputVectorPorts( WirePortDataType.FLOAT2, "UV" ); + m_outputPorts[ 1 ].Name = "U"; + m_outputPorts[ 2 ].Name = "V"; + AddOutputPort( WirePortDataType.FLOAT, "W" ); + AddOutputPort( WirePortDataType.FLOAT, "T" ); + m_textLabelWidth = 90; + m_useInternalPortData = true; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + m_tilingPort.Category = MasterNodePortCategory.Vertex; + m_offsetPort.Category = MasterNodePortCategory.Vertex; + UpdateOutput(); + m_previewShaderGUID = "085e462b2de441a42949be0e666cf5d2"; + } + + public override void Reset() + { + m_surfaceTexcoordName = string.Empty; + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + if( portId == 2 ) + { + m_texPort.MatchPortToConnection(); + m_inputReferenceNode = m_texPort.GetOutputNodeWhichIsNotRelay() as TexturePropertyNode; + UpdatePorts(); + } + UpdateTitle(); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + if( portId == 2 ) + { + m_inputReferenceNode = null; + UpdatePorts(); + } + UpdateTitle(); + } + + public override void OnConnectedOutputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( portId, otherNodeId, otherPortId, name, type ); + if( portId == 2 ) + { + m_texPort.MatchPortToConnection(); + UpdateTitle(); + } + } + + void UpdateTitle() + { + if( m_inputReferenceNode != null ) + { + m_additionalContent.text = string.Format( "Value( {0} )", m_inputReferenceNode.PropertyInspectorName ); + } + else if( m_referenceArrayId > -1 && m_referenceNode != null ) + { + m_additionalContent.text = string.Format( "Value( {0} )", m_referenceNode.PropertyInspectorName ); + } + else + { + m_additionalContent.text = string.Empty; + } + m_sizeIsDirty = true; + } + + void UpdatePorts() + { + if( m_inputReferenceNode != null || m_texPort.IsConnected ) + { + m_tilingPort.Locked = true; + m_offsetPort.Locked = true; + } + else if( m_referenceArrayId > -1 ) + { + m_tilingPort.Locked = true; + m_offsetPort.Locked = true; + } + else + { + m_tilingPort.Locked = false; + m_offsetPort.Locked = false; + } + } + + public override void DrawProperties() + { + bool guiEnabledBuffer = GUI.enabled; + + EditorGUI.BeginChangeCheck(); + List arr = new List( UIUtils.TexturePropertyNodeArr() ); + if( arr != null && arr.Count > 0 ) + { + arr.Insert( 0, "None" ); + GUI.enabled = true && ( !m_texPort.IsConnected ); + m_referenceArrayId = EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceArrayId + 1, arr.ToArray() ) - 1; + } + else + { + m_referenceArrayId = -1; + GUI.enabled = false; + EditorGUILayoutPopup( Constants.AvailableReferenceStr, 0, Dummy ); + } + + GUI.enabled = guiEnabledBuffer; + if( EditorGUI.EndChangeCheck() ) + { + m_referenceNode = UIUtils.GetTexturePropertyNode( m_referenceArrayId ); + if( m_referenceNode != null ) + { + m_referenceNodeId = m_referenceNode.UniqueId; + } + else + { + m_referenceNodeId = -1; + m_referenceArrayId = -1; + } + + UpdateTitle(); + UpdatePorts(); + } + + EditorGUI.BeginChangeCheck(); + m_texcoordSize = EditorGUILayoutIntPopup( Constants.AvailableUVSizesLabel, m_texcoordSize, Constants.AvailableUVSizesStr, Constants.AvailableUVSizes ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateOutput(); + } + + m_textureCoordChannel = EditorGUILayoutIntPopup( Constants.AvailableUVSetsLabel, m_textureCoordChannel, Constants.AvailableUVSetsStr, Constants.AvailableUVSets ); + + + if( m_referenceArrayId > -1 ) + GUI.enabled = false; + + base.DrawProperties(); + + GUI.enabled = guiEnabledBuffer; + } + + private void UpdateOutput() + { + if( m_texcoordSize == 3 ) + { + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_outputPorts[ 0 ].Name = "UVW"; + m_outputPorts[ 3 ].Visible = true; + m_outputPorts[ 4 ].Visible = false; + } + else if( m_texcoordSize == 4 ) + { + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_outputPorts[ 0 ].Name = "UVWT"; + m_outputPorts[ 3 ].Visible = true; + m_outputPorts[ 4 ].Visible = true; + } + else + { + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT2, false ); + m_outputPorts[ 0 ].Name = "UV"; + m_outputPorts[ 3 ].Visible = false; + m_outputPorts[ 4 ].Visible = false; + } + m_sizeIsDirty = true; + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); + CheckReference(); + } + + //public override void Draw( DrawInfo drawInfo ) + //{ + // base.Draw( drawInfo ); + // //CheckReference(); + //} + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( m_dropdownEditing ) + { + EditorGUI.BeginChangeCheck(); + m_texcoordSize = EditorGUIIntPopup( m_dropdownRect, m_texcoordSize, Constants.AvailableUVSizesStr, Constants.AvailableUVSizes, UIUtils.PropertyPopUp ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateOutput(); + DropdownEditing = false; + } + } + } + + void CheckReference() + { + if( m_referenceArrayId > -1 ) + { + ParentNode newNode = UIUtils.GetTexturePropertyNode( m_referenceArrayId ); + if( newNode == null || newNode.UniqueId != m_referenceNodeId ) + { + m_referenceNode = null; + int count = UIUtils.GetTexturePropertyNodeAmount(); + for( int i = 0; i < count; i++ ) + { + ParentNode node = UIUtils.GetTexturePropertyNode( i ); + if( node.UniqueId == m_referenceNodeId ) + { + m_referenceNode = node as TexturePropertyNode; + m_referenceArrayId = i; + break; + } + } + } + } + + if( m_referenceNode == null && m_referenceNodeId > -1 ) + { + m_referenceNodeId = -1; + m_referenceArrayId = -1; + UpdateTitle(); + UpdatePorts(); + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_textureCoordChannel = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 2402 ) + { + if( UIUtils.CurrentShaderVersion() > 2404 ) + { + m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + else + { + m_referenceArrayId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } + + if( UIUtils.CurrentShaderVersion() > 5001 ) + { + m_texcoordSize = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + UpdateOutput(); + } + } + + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( UIUtils.CurrentShaderVersion() > 2402 ) + { + if( UIUtils.CurrentShaderVersion() > 2404 ) + { + m_referenceNode = UIUtils.GetNode( m_referenceNodeId ) as TexturePropertyNode; + if( m_referenceNodeId > -1 ) + m_referenceArrayId = UIUtils.GetTexturePropertyNodeRegisterId( m_referenceNodeId ); + } + else + { + m_referenceNode = UIUtils.GetTexturePropertyNode( m_referenceArrayId ); + if( m_referenceNode != null ) + { + m_referenceNodeId = m_referenceNode.UniqueId; + } + } + UpdateTitle(); + UpdatePorts(); + } + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + if( dataCollector != null && dataCollector.TesselationActive ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + return; + } + + if( dataCollector.IsTemplate ) + { + dataCollector.TemplateDataCollectorInstance.SetUVUsage( m_textureCoordChannel, m_texcoordSize ); + } + else if( m_textureCoordChannel > 3 ) + { + dataCollector.AddCustomAppData( string.Format( TemplateHelperFunctions.TexUVFullSemantic, m_textureCoordChannel ) ); + } + UIUtils.SetCategoryInBitArray( ref m_category, nodeData.Category ); + + MasterNodePortCategory propagateCategory = ( nodeData.Category != MasterNodePortCategory.Vertex && nodeData.Category != MasterNodePortCategory.Tessellation ) ? MasterNodePortCategory.Vertex : nodeData.Category; + nodeData.Category = propagateCategory; + nodeData.GraphDepth += 1; + if( nodeData.GraphDepth > m_graphDepth ) + { + m_graphDepth = nodeData.GraphDepth; + } + + int count = m_inputPorts.Count; + for( int i = 0; i < count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + //m_inputPorts[ i ].GetOutputNode().PropagateNodeCategory( category ); + m_inputPorts[ i ].GetOutputNode().PropagateNodeData( nodeData, ref dataCollector ); + } + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_textureCoordChannel ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( ( m_referenceNode != null ) ? m_referenceNode.UniqueId : -1 ) ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_texcoordSize ); + } + + string GetValidPropertyName() + { + string propertyName = string.Empty; + if( m_inputReferenceNode != null ) + { + propertyName = m_inputReferenceNode.PropertyName; + } + else if( m_referenceArrayId > -1 ) + { + m_referenceNode = UIUtils.GetTexturePropertyNode( m_referenceArrayId ); + if( m_referenceNode != null ) + { + propertyName = m_referenceNode.PropertyName; + } + } + + return propertyName; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + UIUtils.ShowMessage( UniqueId, m_nodeAttribs.Name + " cannot be used on Master Node Tessellation port" ); + return "-1"; + } + + //bool isVertex = ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ); + + string tiling = string.Empty; + string offset = string.Empty; + + string portProperty = string.Empty; + if( m_texPort.IsConnected ) + { + portProperty = m_texPort.GeneratePortInstructions( ref dataCollector ); + } + else if( m_referenceArrayId > -1 ) + { + TexturePropertyNode temp = UIUtils.GetTexturePropertyNode( m_referenceArrayId ); + if( temp != null ) + { + portProperty = temp.BaseGenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + } + } + + //TEMPLATES + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + string uvName = string.Empty; + string result = string.Empty; + string indexStr = m_textureCoordChannel > 0 ? ( m_textureCoordChannel + 1 ).ToString() : ""; + string sizeDif = string.Empty; + if( m_texcoordSize == 3 ) + sizeDif = "3"; + else if( m_texcoordSize == 4 ) + sizeDif = "4"; + + if( dataCollector.TemplateDataCollectorInstance.GetCustomInterpolatedData( TemplateHelperFunctions.IntToUVChannelInfo[ m_textureCoordChannel ], m_outputPorts[ 0 ].DataType, PrecisionType.Float, ref result, false, dataCollector.PortCategory ) ) + { + uvName = result; + } + else if( dataCollector.TemplateDataCollectorInstance.HasUV( m_textureCoordChannel ) ) + { + uvName = dataCollector.TemplateDataCollectorInstance.GetUVName( m_textureCoordChannel, m_outputPorts[ 0 ].DataType ); + } + else + { + uvName = dataCollector.TemplateDataCollectorInstance.RegisterUV( m_textureCoordChannel, m_outputPorts[ 0 ].DataType ); + } + string currPropertyName = GetValidPropertyName(); + if( !string.IsNullOrEmpty( portProperty ) && portProperty != "0.0" ) + { + currPropertyName = portProperty; + } + if( !string.IsNullOrEmpty( currPropertyName ) ) + { + string finalTexCoordName = "uv" + indexStr + ( m_texcoordSize > 2 ? "s" + sizeDif : "" ) + currPropertyName; + string dummyPropertyTexcoords = currPropertyName + "_ST"; + + if( m_texCoordsHelper == null ) + { + m_texCoordsHelper = CreateInstance(); + m_texCoordsHelper.ContainerGraph = ContainerGraph; + m_texCoordsHelper.SetBaseUniqueId( UniqueId, true ); + m_texCoordsHelper.RegisterPropertyOnInstancing = false; + m_texCoordsHelper.AddGlobalToSRPBatcher = true; + } + + if( UIUtils.CurrentWindow.OutsideGraph.IsInstancedShader ) + { + m_texCoordsHelper.CurrentParameterType = PropertyType.InstancedProperty; + } + else + { + m_texCoordsHelper.CurrentParameterType = PropertyType.Global; + } + m_texCoordsHelper.ResetOutputLocals(); + m_texCoordsHelper.SetRawPropertyName( dummyPropertyTexcoords ); + dummyPropertyTexcoords = m_texCoordsHelper.GenerateShaderForOutput( 0, ref dataCollector, false ); + + if( m_texcoordSize > 2 ) + { + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_outputPorts[ 0 ].DataType, finalTexCoordName, uvName ); + dataCollector.AddLocalVariable( UniqueId, finalTexCoordName + ".xy", string.Format( Constants.TilingOffsetFormat, uvName + ".xy", dummyPropertyTexcoords + ".xy", dummyPropertyTexcoords + ".zw" ) + ";" ); + m_outputPorts[ 0 ].SetLocalValue( finalTexCoordName, dataCollector.PortCategory ); + } + else + { + RegisterLocalVariable( 0, string.Format( Constants.TilingOffsetFormat, uvName, dummyPropertyTexcoords + ".xy", dummyPropertyTexcoords + ".zw" ), ref dataCollector, finalTexCoordName ); + } + //RegisterLocalVariable( 0, string.Format( Constants.TilingOffsetFormat, uvName, dummyPropertyTexcoords+".xy", dummyPropertyTexcoords+".zw" ), ref dataCollector, finalTexCoordName ); + } + else + { + string finalTexCoordName = "texCoord" + OutputId; + tiling = m_tilingPort.GeneratePortInstructions( ref dataCollector ); + offset = m_offsetPort.GeneratePortInstructions( ref dataCollector ); + + if( m_texcoordSize > 2 ) + { + dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_outputPorts[ 0 ].DataType, finalTexCoordName, uvName ); + dataCollector.AddLocalVariable( UniqueId, finalTexCoordName + ".xy", string.Format( Constants.TilingOffsetFormat, uvName + ".xy", tiling, offset ) + ";" ); + m_outputPorts[ 0 ].SetLocalValue( finalTexCoordName, dataCollector.PortCategory ); + } + else + { + RegisterLocalVariable( 0, string.Format( Constants.TilingOffsetFormat, uvName, tiling, offset ), ref dataCollector, finalTexCoordName ); + } + //RegisterLocalVariable( 0, string.Format( Constants.TilingOffsetFormat, uvName, tiling, offset ), ref dataCollector, finalTexCoordName ); + } + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + + //SURFACE + string propertyName = GetValidPropertyName(); + if( !string.IsNullOrEmpty( portProperty ) && portProperty != "0.0" ) + { + propertyName = portProperty; + } + + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + + if( !m_tilingPort.IsConnected && m_tilingPort.Vector2InternalData == Vector2.one ) + tiling = null; + else + tiling = m_tilingPort.GeneratePortInstructions( ref dataCollector ); + + if( !m_offsetPort.IsConnected && m_offsetPort.Vector2InternalData == Vector2.zero ) + offset = null; + else + offset = m_offsetPort.GeneratePortInstructions( ref dataCollector ); + + if( !string.IsNullOrEmpty( propertyName ) /*m_referenceArrayId > -1*/ ) + { + m_surfaceTexcoordName = GeneratorUtils.GenerateAutoUVs( ref dataCollector, UniqueId, m_textureCoordChannel, propertyName, m_outputPorts[ 0 ].DataType, tiling, offset, OutputId ); + } + else + { + m_surfaceTexcoordName = GeneratorUtils.GenerateAutoUVs( ref dataCollector, UniqueId, m_textureCoordChannel, null, m_outputPorts[ 0 ].DataType, tiling, offset, OutputId ); + } + + m_outputPorts[ 0 ].SetLocalValue( m_surfaceTexcoordName, dataCollector.PortCategory ); + return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) ); + } + + public override void ReadInputDataFromString( ref string[] nodeParams ) + { + if( UIUtils.CurrentShaderVersion() > 7003 ) + { + base.ReadInputDataFromString( ref nodeParams ); + } + else + { + for( int i = 0; i < 2 && i < nodeParams.Length && m_currentReadParamIdx < nodeParams.Length; i++ ) + { + if( UIUtils.CurrentShaderVersion() < 5003 ) + { + int newId = VersionConvertInputPortId( i ) + 1; + if( UIUtils.CurrentShaderVersion() > 23 ) + { + m_inputPorts[ newId ].DataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), nodeParams[ m_currentReadParamIdx++ ] ); + } + + m_inputPorts[ newId ].InternalData = nodeParams[ m_currentReadParamIdx++ ]; + if( m_inputPorts[ newId ].IsEditable && UIUtils.CurrentShaderVersion() >= 3100 && m_currentReadParamIdx < nodeParams.Length ) + { + m_inputPorts[ newId ].Name = nodeParams[ m_currentReadParamIdx++ ]; + } + } + else + { + int portId = Convert.ToInt32( nodeParams[ m_currentReadParamIdx++ ] ); + WirePortDataType DataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), nodeParams[ m_currentReadParamIdx++ ] ); + string InternalData = nodeParams[ m_currentReadParamIdx++ ]; + bool isEditable = Convert.ToBoolean( nodeParams[ m_currentReadParamIdx++ ] ); + string Name = string.Empty; + if( isEditable && m_currentReadParamIdx < nodeParams.Length ) + { + Name = nodeParams[ m_currentReadParamIdx++ ]; + } + + InputPort inputPort = GetInputPortByUniqueId( portId ); + if( inputPort != null ) + { + inputPort.DataType = DataType; + inputPort.InternalData = InternalData; + if( !string.IsNullOrEmpty( Name ) ) + { + inputPort.Name = Name; + } + } + } + } + } + } + + public override void Destroy() + { + base.Destroy(); + m_referenceNode = null; + + if( m_texCoordsHelper != null ) + { + //Not calling m_texCoordsHelper.Destroy() on purpose so UIUtils does not incorrectly unregister stuff + DestroyImmediate( m_texCoordsHelper ); + m_texCoordsHelper = null; + } + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureCoordinatesNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureCoordinatesNode.cs.meta new file mode 100644 index 0000000..be9e118 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureCoordinatesNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 872b1da17041cd64482c826cbfd9c8c6 +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TexturePropertyNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TexturePropertyNode.cs new file mode 100644 index 0000000..c4257cb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TexturePropertyNode.cs @@ -0,0 +1,1138 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + public enum TexturePropertyValues + { + white, + black, + gray, + bump + } + + public enum TextureType + { + Texture1D, + Texture2D, + Texture3D, + Cube, + Texture2DArray, + ProceduralTexture + } + + public enum AutoCastType + { + Auto = 0, + LockedToTexture1D, + LockedToTexture2D, + LockedToTexture3D, + LockedToCube, + LockedToTexture2DArray + } + + + [Serializable] + [NodeAttributes( "Texture Object", "Textures", "Represents a Texture Asset. Can be used in samplers Tex inputs or shader function inputs to reuse the same texture multiple times.", SortOrderPriority = 1 )] + public class TexturePropertyNode : PropertyNode + { + private const string ObjectSelectorCmdStr = "ObjectSelectorClosed"; + + protected readonly string[] AvailablePropertyTypeLabels = { PropertyType.Property.ToString(), PropertyType.Global.ToString() }; + protected readonly int[] AvailablePropertyTypeValues = { (int)PropertyType.Property, (int)PropertyType.Global }; + + protected const int OriginalFontSizeUpper = 9; + protected const int OriginalFontSizeLower = 9; + + protected const string DefaultTextureStr = "Default Texture"; + protected const string AutoCastModeStr = "Auto-Cast Mode"; + + protected const string AutoUnpackNormalsStr = "Normal"; + + [SerializeField] + protected Texture m_defaultValue; + + [SerializeField] + protected Texture m_materialValue; + + [SerializeField] + protected TexturePropertyValues m_defaultTextureValue; + + [SerializeField] + protected bool m_isNormalMap; + + [SerializeField] + protected System.Type m_textureType = typeof( Texture2D ); + + [SerializeField] + protected int m_useSamplerArrayIdx = -1; + + //[SerializeField] + //protected bool m_isTextureFetched; + + //[SerializeField] + //protected string m_textureFetchedValue; + + [SerializeField] + protected TextureType m_currentType = TextureType.Texture2D; + + [SerializeField] + protected AutoCastType m_autocastMode = AutoCastType.Auto; + + protected int PreviewSizeX = 128; + protected int PreviewSizeY = 128; + + protected bool m_linearTexture; + + protected TexturePropertyNode m_textureProperty = null; + + protected bool m_drawPicker; + + protected bool m_drawAutocast = true; + + protected int m_cachedSamplerId = -1; + protected int m_cachedSamplerIdArray = -1; + protected int m_cachedSamplerIdCube = -1; + protected int m_cachedSamplerId3D = -1; + protected int m_defaultId = -1; + protected int m_typeId = -1; + + private TextureType m_previousType = TextureType.Texture2D; + private string m_labelText = "None (Texture2D)"; + + protected bool m_isEditingPicker; + + protected bool m_forceSamplingMacrosGen = false; + + public TexturePropertyNode() : base() { } + public TexturePropertyNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { } + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + GlobalTypeWarningText = string.Format( GlobalTypeWarningText, "Texture" ); + m_defaultTextureValue = TexturePropertyValues.white; + m_insideSize.Set( PreviewSizeX, PreviewSizeY + 5 ); + AddOutputPort( WirePortDataType.SAMPLER2D, "Tex" ); + AddOutputPort( WirePortDataType.SAMPLERSTATE, "SS" ); + m_outputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.SAMPLER2DARRAY, WirePortDataType.OBJECT ); + m_currentParameterType = PropertyType.Property; + m_customPrefix = "Texture "; + m_drawPrecisionUI = false; + m_showVariableMode = true; + m_freeType = false; + m_drawPicker = true; + m_hasLeftDropdown = true; + m_textLabelWidth = 115; + m_longNameSize = 225; + m_availableAttribs.Add( new PropertyAttributes( "No Scale Offset", "[NoScaleOffset]" ) ); + m_availableAttribs.Add( new PropertyAttributes( "Normal", "[Normal]" ) ); + m_availableAttribs.Add( new PropertyAttributes( "Single Line Texture", "[SingleLineTexture]" ) ); + m_showPreview = true; + m_drawPreviewExpander = false; + m_drawPreview = false; + m_drawPreviewMaskButtons = false; + m_previewShaderGUID = "e53988745ec6e034694ee2640cd3d372"; + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + m_hasLeftDropdown = true; + } + + protected void SetPreviewTexture( Texture newValue ) + { + if( newValue is Cubemap ) + { + PreviewMaterial.SetInt( m_typeId, 3 ); + + if( m_cachedSamplerIdCube == -1 ) + m_cachedSamplerIdCube = Shader.PropertyToID( "_Cube" ); + + PreviewMaterial.SetTexture( m_cachedSamplerIdCube, newValue as Cubemap ); + } + else if( newValue is Texture2DArray ) + { + PreviewMaterial.SetInt( m_typeId, 4 ); + + if( m_cachedSamplerIdArray == -1 ) + m_cachedSamplerIdArray = Shader.PropertyToID( "_Array" ); + + PreviewMaterial.SetTexture( m_cachedSamplerIdArray, newValue as Texture2DArray ); + } + else if( newValue is Texture3D ) + { + PreviewMaterial.SetInt( m_typeId, 2 ); + + if( m_cachedSamplerId3D == -1 ) + m_cachedSamplerId3D = Shader.PropertyToID( "_Sampler3D" ); + + PreviewMaterial.SetTexture( m_cachedSamplerId3D, newValue as Texture3D ); + } + else + { + PreviewMaterial.SetInt( m_typeId, 1 ); + + if( m_cachedSamplerId == -1 ) + m_cachedSamplerId = Shader.PropertyToID( "_Sampler" ); + + PreviewMaterial.SetTexture( m_cachedSamplerId, newValue ); + } + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + + if( Value == null ) + { + if( m_defaultId == -1 ) + m_defaultId = Shader.PropertyToID( "_Default" ); + + PreviewMaterial.SetInt( m_defaultId, ( (int)m_defaultTextureValue ) + 1 ); + m_previewMaterialPassId = 0; + } + else + { + if( m_defaultId == -1 ) + m_defaultId = Shader.PropertyToID( "_Default" ); + + PreviewMaterial.SetInt( m_defaultId, 0 ); + + if( m_typeId == -1 ) + m_typeId = Shader.PropertyToID( "_Type" ); + + m_previewMaterialPassId = 1; + SetPreviewTexture( Value ); + //if( Value is Cubemap ) + //{ + // PreviewMaterial.SetInt( m_typeId, 3 ); + + // if( m_cachedSamplerIdCube == -1 ) + // m_cachedSamplerIdCube = Shader.PropertyToID( "_Cube" ); + + // PreviewMaterial.SetTexture( m_cachedSamplerIdCube, Value as Cubemap ); + //} + //else if( Value is Texture2DArray ) + //{ + // PreviewMaterial.SetInt( m_typeId, 4 ); + + // if( m_cachedSamplerIdArray == -1 ) + // m_cachedSamplerIdArray = Shader.PropertyToID( "_Array" ); + + // PreviewMaterial.SetTexture( m_cachedSamplerIdArray, Value as Texture2DArray ); + //} + //else if( Value is Texture3D ) + //{ + // PreviewMaterial.SetInt( m_typeId, 2 ); + + // if( m_cachedSamplerId3D == -1 ) + // m_cachedSamplerId3D = Shader.PropertyToID( "_Sampler3D" ); + + // PreviewMaterial.SetTexture( m_cachedSamplerId3D, Value as Texture3D ); + //} + //else + //{ + // PreviewMaterial.SetInt( m_typeId, 1 ); + + // if( m_cachedSamplerId == -1 ) + // m_cachedSamplerId = Shader.PropertyToID( "_Sampler" ); + + // PreviewMaterial.SetTexture( m_cachedSamplerId, Value ); + //} + } + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + m_textureProperty = this; + UIUtils.RegisterPropertyNode( this ); + UIUtils.RegisterTexturePropertyNode( this ); + } + + protected void ConfigTextureData( TextureType type ) + { + switch( m_autocastMode ) + { + case AutoCastType.Auto: + { + m_currentType = type; + } + break; + case AutoCastType.LockedToTexture1D: + { + m_currentType = TextureType.Texture1D; + } + break; + case AutoCastType.LockedToTexture2DArray: + { + m_currentType = TextureType.Texture2DArray; + } + break; + case AutoCastType.LockedToTexture2D: + { + m_currentType = TextureType.Texture2D; + } + break; + case AutoCastType.LockedToTexture3D: + { + m_currentType = TextureType.Texture3D; + } + break; + case AutoCastType.LockedToCube: + { + m_currentType = TextureType.Cube; + } + break; + } + + ConfigTextureType(); + } + + protected void ConfigTextureType() + { + switch( m_currentType ) + { + case TextureType.Texture1D: + { + m_textureType = typeof( Texture ); + } + break; + case TextureType.Texture2DArray: + { + m_textureType = typeof( Texture2DArray ); + } + break; + case TextureType.Texture2D: + { + m_textureType = typeof( Texture2D ); + } + break; + case TextureType.Texture3D: + { + m_textureType = typeof( Texture3D ); + } + break; + case TextureType.Cube: + { + m_textureType = typeof( Cubemap ); + } + break; +#if !UNITY_2018_1_OR_NEWER + // Disabling Substance Deprecated warning +#pragma warning disable 0618 + case TextureType.ProceduralTexture: + { + m_textureType = typeof( ProceduralTexture ); + } + break; +#pragma warning restore 0618 +#endif + + } + } + + protected void DrawTexturePropertyType() + { + PropertyType parameterType = (PropertyType)EditorGUILayoutIntPopup( ParameterTypeStr, (int)m_currentParameterType, AvailablePropertyTypeLabels, AvailablePropertyTypeValues ); + if( parameterType != m_currentParameterType ) + { + ChangeParameterType( parameterType ); + } + } + + // Texture1D + public string GetTexture1DPropertyValue() + { + return PropertyName + "(\"" + m_propertyInspectorName + "\", 2D) = \"" + m_defaultTextureValue + "\" {}"; + } + + public string GetTexture1DUniformValue() + { + return "uniform sampler1D " + PropertyName + ";"; + } + + // Texture2D + public string GetTexture2DPropertyValue() + { + return PropertyName + "(\"" + m_propertyInspectorName + "\", 2D) = \"" + m_defaultTextureValue + "\" {}"; + } + + public string GetTexture2DUniformValue() + { + if( PropertyName == "_CameraDepthTexture" ) + return Constants.CameraDepthTextureValue; + else + return GeneratorUtils.GetPropertyDeclaraction( PropertyName, TextureType.Texture2D, ";" ); + } + + //Texture3D + public string GetTexture3DPropertyValue() + { + return PropertyName + "(\"" + m_propertyInspectorName + "\", 3D) = \"" + m_defaultTextureValue + "\" {}"; + } + + public string GetTexture3DUniformValue() + { + return GeneratorUtils.GetPropertyDeclaraction( PropertyName, TextureType.Texture3D, ";" ); + } + + // Cube + public string GetCubePropertyValue() + { + return PropertyName + "(\"" + m_propertyInspectorName + "\", CUBE) = \"" + m_defaultTextureValue + "\" {}"; + } + + public string GetCubeUniformValue() + { + return GeneratorUtils.GetPropertyDeclaraction( PropertyName, TextureType.Cube, ";" ); + } + + // Texture2DArray + public string GetTexture2DArrayPropertyValue() + { + return PropertyName + "(\"" + m_propertyInspectorName + "\", 2DArray) = \"" + m_defaultTextureValue + "\" {}"; + } + + public string GetTexture2DArrayUniformValue() + { + return GeneratorUtils.GetPropertyDeclaraction( PropertyName, TextureType.Texture2DArray, ";" ); + } + + public override void DrawMainPropertyBlock() + { + DrawTexturePropertyType(); + base.DrawMainPropertyBlock(); + } + + public override void DrawSubProperties() + { + ShowDefaults(); + + + EditorGUI.BeginChangeCheck(); + Type currType = ( m_autocastMode == AutoCastType.Auto ) ? typeof( Texture ) : m_textureType; + m_defaultValue = EditorGUILayoutObjectField( Constants.DefaultValueLabel, m_defaultValue, currType, false ) as Texture; + if( EditorGUI.EndChangeCheck() ) + { + CheckTextureImporter( true ); + SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) ); + } + } + + public override void DrawMaterialProperties() + { + ShowDefaults(); + + EditorGUI.BeginChangeCheck(); + Type currType = ( m_autocastMode == AutoCastType.Auto ) ? typeof( Texture ) : m_textureType; + m_materialValue = EditorGUILayoutObjectField( Constants.MaterialValueLabel, m_materialValue, currType, false ) as Texture; + if( EditorGUI.EndChangeCheck() ) + { + CheckTextureImporter( true ); + SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) ); + } + } + + new void ShowDefaults() + { + m_defaultTextureValue = (TexturePropertyValues)EditorGUILayoutEnumPopup( DefaultTextureStr, m_defaultTextureValue ); + + if( !m_drawAutocast ) + return; + + AutoCastType newAutoCast = (AutoCastType)EditorGUILayoutEnumPopup( AutoCastModeStr, m_autocastMode ); + if( newAutoCast != m_autocastMode ) + { + m_autocastMode = newAutoCast; + if( m_autocastMode != AutoCastType.Auto ) + { + ConfigTextureData( m_currentType ); + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + } + } + + private void ConfigurePortsFromReference() + { + m_sizeIsDirty = true; + } + + public virtual void ConfigureOutputPorts() + { + switch( m_currentType ) + { + case TextureType.Texture1D: + m_outputPorts[ 0 ].ChangeType( WirePortDataType.SAMPLER1D, false ); + break; + case TextureType.ProceduralTexture: + case TextureType.Texture2D: + m_outputPorts[ 0 ].ChangeType( WirePortDataType.SAMPLER2D, false ); + break; + case TextureType.Texture3D: + m_outputPorts[ 0 ].ChangeType( WirePortDataType.SAMPLER3D, false ); + break; + case TextureType.Cube: + m_outputPorts[ 0 ].ChangeType( WirePortDataType.SAMPLERCUBE, false ); + break; + case TextureType.Texture2DArray: + m_outputPorts[ 0 ].ChangeType( WirePortDataType.SAMPLER2DARRAY, false ); + break; + } + + m_sizeIsDirty = true; + } + + public virtual void ConfigureInputPorts() + { + } + + public virtual void AdditionalCheck() + { + } + + public virtual void CheckTextureImporter( bool additionalCheck, bool writeDefault = true ) + { + m_requireMaterialUpdate = true; + Texture texture = m_materialMode ? m_materialValue : m_defaultValue; + TextureImporter importer = AssetImporter.GetAtPath( AssetDatabase.GetAssetPath( texture ) ) as TextureImporter; + if( importer != null ) + { + +#if UNITY_5_5_OR_NEWER + m_isNormalMap = importer.textureType == TextureImporterType.NormalMap; +#else + m_isNormalMap = importer.normalmap; +#endif + if( writeDefault && !UIUtils.IsLoading ) + { + if( m_defaultTextureValue == TexturePropertyValues.bump && !m_isNormalMap ) + m_defaultTextureValue = TexturePropertyValues.white; + else if( m_isNormalMap ) + m_defaultTextureValue = TexturePropertyValues.bump; + } + + if( additionalCheck ) + AdditionalCheck(); + m_linearTexture = !importer.sRGBTexture; + } + + if( ( texture as Texture2DArray ) != null ) + { + ConfigTextureData( TextureType.Texture2DArray ); + } + else if( ( texture as Texture2D ) != null ) + { + ConfigTextureData( TextureType.Texture2D ); + } + else if( ( texture as Texture3D ) != null ) + { + ConfigTextureData( TextureType.Texture3D ); + } + else if( ( texture as Cubemap ) != null ) + { + ConfigTextureData( TextureType.Cube ); + } +#if !UNITY_2018_1_OR_NEWER + // Disabling Substance Deprecated warning +#pragma warning disable 0618 + else if( ( texture as ProceduralTexture ) != null ) + { + ConfigTextureData( TextureType.ProceduralTexture ); + } +#pragma warning restore 0618 +#endif + + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + + public override void OnObjectDropped( UnityEngine.Object obj ) + { + base.OnObjectDropped( obj ); + ConfigFromObject( obj ); + } + + public override void SetupFromCastObject( UnityEngine.Object obj ) + { + base.SetupFromCastObject( obj ); + ConfigFromObject( obj ); + } + + protected void ConfigFromObject( UnityEngine.Object obj, bool writeDefault = true, bool additionalCheck = true ) + { + Texture texture = obj as Texture; + if( texture ) + { + m_materialValue = texture; + m_defaultValue = texture; + CheckTextureImporter( additionalCheck, writeDefault ); + } + } + + + + public override void DrawGUIControls( DrawInfo drawInfo ) + { + base.DrawGUIControls( drawInfo ); + + if( !( drawInfo.CurrentEventType == EventType.MouseDown || drawInfo.CurrentEventType == EventType.MouseUp || drawInfo.CurrentEventType == EventType.ExecuteCommand || drawInfo.CurrentEventType == EventType.DragPerform ) ) + return; + + bool insideBox = m_previewRect.Contains( drawInfo.MousePosition ); + + bool closePicker = false; + if( insideBox ) + { + m_isEditingPicker = true; + } + else if( m_isEditingPicker && !insideBox && drawInfo.CurrentEventType != EventType.ExecuteCommand ) + { + closePicker = true; + } + + if( m_isEditingPicker && drawInfo.CurrentEventType == EventType.ExecuteCommand && + Event.current.commandName.Equals( ObjectSelectorCmdStr ) ) + { + closePicker = true; + } + + if( closePicker ) + { + GUI.FocusControl( null ); + m_isEditingPicker = false; + } + + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + base.OnNodeLayout( drawInfo ); + ConfigTextureType(); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( m_dropdownEditing ) + { + PropertyType parameterType = (PropertyType)EditorGUIIntPopup( m_dropdownRect, (int)m_currentParameterType, AvailablePropertyTypeLabels, AvailablePropertyTypeValues, UIUtils.PropertyPopUp ); + if( parameterType != m_currentParameterType ) + { + ChangeParameterType( parameterType ); + DropdownEditing = false; + } + } + + if( m_isEditingPicker && m_drawPicker && m_currentParameterType != PropertyType.Global ) + { + Rect hitRect = m_previewRect; + hitRect.height = 14 * drawInfo.InvertedZoom; + hitRect.y = m_previewRect.yMax - hitRect.height; + hitRect.width = 4 * 14 * drawInfo.InvertedZoom; + + bool restoreMouse = false; + if( Event.current.type == EventType.MouseDown && hitRect.Contains( drawInfo.MousePosition ) ) + { + restoreMouse = true; + Event.current.type = EventType.Ignore; + } + + EditorGUI.BeginChangeCheck(); + m_colorBuffer = GUI.color; + GUI.color = Color.clear; + Type currType = ( m_autocastMode == AutoCastType.Auto ) ? typeof( Texture ) : m_textureType; + if( m_materialMode ) + { + m_materialValue = EditorGUIObjectField( m_previewRect, m_materialValue, currType, false ) as Texture; + } + else + { + m_defaultValue = EditorGUIObjectField( m_previewRect, m_defaultValue, currType, false ) as Texture; + } + GUI.color = m_colorBuffer; + + if( EditorGUI.EndChangeCheck() ) + { + CheckTextureImporter( true ); + SetTitleText( m_propertyInspectorName ); + SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) ); + ConfigureInputPorts(); + ConfigureOutputPorts(); + BeginDelayedDirtyProperty(); + PreviewIsDirty = true; + } + //else if( drawInfo.CurrentEventType == EventType.ExecuteCommand ) + //{ + // GUI.FocusControl( null ); + // m_isEditingPicker = false; + //} + + if( restoreMouse ) + { + Event.current.type = EventType.MouseDown; + } + + if( ( drawInfo.CurrentEventType == EventType.MouseDown || drawInfo.CurrentEventType == EventType.MouseUp ) ) + DrawPreviewMaskButtonsLayout( drawInfo, m_previewRect ); + } + + if( !m_drawPicker ) + return; + + if( drawInfo.CurrentEventType == EventType.Repaint ) + { + DrawTexturePicker( drawInfo ); + } + } + + + + protected void DrawTexturePicker( DrawInfo drawInfo ) + { + Rect newRect = m_previewRect; + Texture currentValue = m_materialMode ? m_materialValue : m_defaultValue; + + //??? + //m_showPreview = true; + bool showButtons = m_currentParameterType != PropertyType.Global; + + if( currentValue == null ) + GUI.Label( newRect, string.Empty, UIUtils.ObjectFieldThumb ); + else + DrawPreview( drawInfo, m_previewRect ); + + if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 ) + { + Rect butRect = m_previewRect; + butRect.y -= 1; + butRect.x += 1; + + Rect smallButton = newRect; + smallButton.height = 14 * drawInfo.InvertedZoom; + smallButton.y = newRect.yMax - smallButton.height - 2; + smallButton.width = 40 * drawInfo.InvertedZoom; + smallButton.x = newRect.xMax - smallButton.width - 2; + if( currentValue == null ) + { + if( m_previousType != m_currentType ) + { + m_previousType = m_currentType; + m_labelText = "None (" + m_currentType.ToString() + ")"; + } + + GUI.Label( newRect, m_labelText, UIUtils.ObjectFieldThumbOverlay ); + } + else if( showButtons ) + { + DrawPreviewMaskButtonsRepaint( drawInfo, butRect ); + } + + if( showButtons ) + GUI.Label( smallButton, "Select", UIUtils.GetCustomStyle( CustomStyle.SamplerButton ) ); + } + + GUI.Label( newRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) ); + } + + public override void CheckIfAutoRegister( ref MasterNodeDataCollector dataCollector ) + { + // Also testing inside shader function because node can be used indirectly over a custom expression and directly over a Function Output node + // That isn't being used externaly making it to not be registered ( since m_connStatus it set to Connected by being connected to an output node + if( CurrentParameterType != PropertyType.Constant && m_autoRegister && ( m_connStatus != NodeConnectionStatus.Connected || InsideShaderFunction ) ) + { + RegisterProperty( ref dataCollector ); + if( m_autoRegister && m_containerGraph.ParentWindow.OutsideGraph.SamplingMacros ) + { + GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, PropertyName , m_variableMode ); + } + } + } + + public string GenerateSamplerState( ref MasterNodeDataCollector dataCollector ) + { + return GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, PropertyName , m_variableMode ); + } + + public virtual string GenerateSamplerPropertyName( int outputId, ref MasterNodeDataCollector dataCollector ) + { + string generatedSamplerState = string.Empty; + + if( outputId > 0 || m_forceSamplingMacrosGen ) + { + generatedSamplerState = GeneratorUtils.GenerateSamplerState( ref dataCollector, UniqueId, PropertyName , m_variableMode ); + } + + if( outputId > 0 ) + return generatedSamplerState; + else + return PropertyName; + } + + public string BaseGenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + return GenerateSamplerPropertyName( outputId , ref dataCollector ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + return BaseGenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + } + + public override void UpdateMaterial( Material mat ) + { + base.UpdateMaterial( mat ); + if( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction ) + { + OnPropertyNameChanged(); + if( mat.HasProperty( PropertyName ) ) + { + mat.SetTexture( PropertyName, m_materialValue ); + } + } + } + + public override void SetMaterialMode( Material mat, bool fetchMaterialValues ) + { + base.SetMaterialMode( mat, fetchMaterialValues ); + if( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) ) + { + if( mat.HasProperty( PropertyName ) ) + { + m_materialValue = mat.GetTexture( PropertyName ); + CheckTextureImporter( false, false ); + } + } + } + + public override void ForceUpdateFromMaterial( Material material ) + { + if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( PropertyName ) ) + { + m_materialValue = material.GetTexture( PropertyName ); + CheckTextureImporter( false, false ); + PreviewIsDirty = true; + } + } + + public override bool UpdateShaderDefaults( ref Shader shader, ref TextureDefaultsDataColector defaultCol/* ref string metaStr */) + { + if( m_defaultValue != null ) + { + defaultCol.AddValue( PropertyName, m_defaultValue ); + } + + return true; + } + + public void ReadFromStringArray( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + ReadAdditionalData( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 17101 ) + { + m_useSamplerArrayIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } + + public virtual void ReadAdditionalData( ref string[] nodeParams ) + { + string defaultTextureGUID = GetCurrentParam( ref nodeParams ); + //m_defaultValue = AssetDatabase.LoadAssetAtPath( textureName ); + if( UIUtils.CurrentShaderVersion() > 14101 ) + { + m_defaultValue = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( defaultTextureGUID ) ); + string materialTextureGUID = GetCurrentParam( ref nodeParams ); + m_materialValue = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( materialTextureGUID ) ); + } + else + { + m_defaultValue = AssetDatabase.LoadAssetAtPath( defaultTextureGUID ); + } + + m_isNormalMap = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_defaultTextureValue = (TexturePropertyValues)Enum.Parse( typeof( TexturePropertyValues ), GetCurrentParam( ref nodeParams ) ); + m_autocastMode = (AutoCastType)Enum.Parse( typeof( AutoCastType ), GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 15306 ) + { + m_currentType = (TextureType)Enum.Parse( typeof( TextureType ), GetCurrentParam( ref nodeParams ) ); + } + else + { + m_currentType = TextureType.Texture2D; + } + + ConfigTextureData( m_currentType ); + + //ConfigFromObject( m_defaultValue ); + if( m_materialValue == null ) + { + ConfigFromObject( m_defaultValue ); + } + else + { + CheckTextureImporter( true, true ); + } + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + + public override void ReadAdditionalClipboardData( ref string[] nodeParams ) + { + base.ReadAdditionalClipboardData( ref nodeParams ); + string textureName = GetCurrentParam( ref nodeParams ); + m_materialValue = AssetDatabase.LoadAssetAtPath( textureName ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + WriteAdditionalToString( ref nodeInfo, ref connectionsInfo ); + if( m_useSamplerArrayIdx > 0 ) + { + TexturePropertyNode samplerNode = UIUtils.GetTexturePropertyNode( m_useSamplerArrayIdx - 1 ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( samplerNode != null ? samplerNode.UniqueId : -1 ) ); + } + else + { + IOUtils.AddFieldValueToString( ref nodeInfo, -1 ); + } + } + + public virtual void WriteAdditionalToString( ref string nodeInfo, ref string connectionsInfo ) + { + //IOUtils.AddFieldValueToString( ref nodeInfo, ( m_defaultValue != null ) ? AssetDatabase.GetAssetPath( m_defaultValue ) : Constants.NoStringValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_defaultValue != null ) ? AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_defaultValue ) ) : Constants.NoStringValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_materialValue != null ) ? AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_materialValue ) ) : Constants.NoStringValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_isNormalMap.ToString() ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultTextureValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_autocastMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentType ); + } + + public override void WriteAdditionalClipboardData( ref string nodeInfo ) + { + base.WriteAdditionalClipboardData( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_materialValue != null ) ? AssetDatabase.GetAssetPath( m_materialValue ) : Constants.NoStringValue ); + } + + public override void Destroy() + { + base.Destroy(); + m_defaultValue = null; + m_materialValue = null; + m_textureProperty = null; + UIUtils.UnregisterPropertyNode( this ); + UIUtils.UnregisterTexturePropertyNode( this ); + } + + public override string GetPropertyValStr() + { + return m_materialMode ? ( m_materialValue != null ? m_materialValue.name : IOUtils.NO_TEXTURES ) : ( m_defaultValue != null ? m_defaultValue.name : IOUtils.NO_TEXTURES ); + } + + public override string GetPropertyValue() + { + switch( m_currentType ) + { + case TextureType.Texture1D: + { + return PropertyAttributes + GetTexture1DPropertyValue(); + } + case TextureType.ProceduralTexture: + case TextureType.Texture2D: + { + return PropertyAttributes + GetTexture2DPropertyValue(); + } + case TextureType.Texture3D: + { + return PropertyAttributes + GetTexture3DPropertyValue(); + } + case TextureType.Cube: + { + return PropertyAttributes + GetCubePropertyValue(); + } + case TextureType.Texture2DArray: + { + return PropertyAttributes + GetTexture2DArrayPropertyValue(); + } + } + return string.Empty; + } + + public override string GetUniformValue() + { + switch( m_currentType ) + { + case TextureType.Texture1D: + { + return GetTexture1DUniformValue(); + } + case TextureType.ProceduralTexture: + case TextureType.Texture2D: + { + return GetTexture2DUniformValue(); + } + case TextureType.Texture3D: + { + return GetTexture3DUniformValue(); + } + case TextureType.Cube: + { + return GetCubeUniformValue(); + } + case TextureType.Texture2DArray: + { + return GetTexture2DArrayUniformValue(); + } + } + + return string.Empty; + } + + public override bool GetUniformData( out string dataType, out string dataName, ref bool fullValue ) + { + m_excludeUniform = false; + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; +#if UNITY_2018_1_OR_NEWER + if( outsideGraph.SamplingMacros || m_currentType == TextureType.Texture2DArray ) +#else + if( ( outsideGraph.SamplingMacros && !outsideGraph.IsStandardSurface ) || m_currentType == TextureType.Texture2DArray ) +#endif + { + if( outsideGraph.IsSRP ) + { + if( Constants.TexDeclarationSRPMacros.ContainsKey( m_currentType ) ) + { + dataName = GeneratorUtils.GetPropertyDeclaraction( PropertyName, m_currentType, ";" ); + dataType = string.Empty; + fullValue = true; + return true; + } + } + else if( Constants.TexDeclarationStandardMacros.ContainsKey( m_currentType ) ) + { +#if !UNITY_2018_1_OR_NEWER + if( m_currentType == TextureType.Texture2DArray && outsideGraph.IsStandardSurface ) + dataName = string.Format( Constants.TexDeclarationStandardMacros[ m_currentType ], PropertyName ); + else +#endif + dataName = GeneratorUtils.GetPropertyDeclaraction( PropertyName, m_currentType, ";" ); + dataType = string.Empty; + fullValue = true; + return true; + } + } + + //TODO: this is a hack and needs to be properly fixed + if( PropertyName == "_CameraDepthTexture" ) + { + m_excludeUniform = true; + dataType = "UNITY_DECLARE_DEPTH_TEXTURE("; + dataName = m_propertyName + " )"; + return true; + } + + dataType = UIUtils.TextureTypeToCgType( m_currentType ); + dataName = m_propertyName; + return true; + } + + public virtual string CurrentPropertyReference + { + get + { + string propertyName = string.Empty; + propertyName = PropertyName; + return propertyName; + } + } + + public Texture Value + { + get { return m_materialMode ? m_materialValue : m_defaultValue; } + set + { + if( m_materialMode ) + m_materialValue = value; + else + m_defaultValue = value; + } + } + + public Texture MaterialValue + { + get { return m_materialValue; } + set { m_materialValue = value; } + } + + public Texture DefaultValue + { + get { return m_defaultValue; } + set { m_defaultValue = value; } + } + + public void SetInspectorName( string newName ) + { + m_propertyInspectorName = newName; + } + + public void SetPropertyName( string newName ) + { + m_propertyName = newName; + } + + public bool IsValid { get { return m_materialMode ? ( m_materialValue != null ) : ( m_defaultValue != null ); } } + + public virtual bool IsNormalMap { get { return m_isNormalMap; } } + public bool IsLinearTexture { get { return m_linearTexture; } } + + public override void OnPropertyNameChanged() + { + base.OnPropertyNameChanged(); + UIUtils.UpdateTexturePropertyDataNode( UniqueId, PropertyName ); + } + + public override void SetGlobalValue() { Shader.SetGlobalTexture( m_propertyName, m_defaultValue ); } + public override void FetchGlobalValue() { m_materialValue = Shader.GetGlobalTexture( m_propertyName ); } + public override string DataToArray { get { return PropertyName; } } + public TextureType CurrentType { get { return m_currentType; } } + + public bool DrawAutocast + { + get { return m_drawAutocast; } + set { m_drawAutocast = value; } + } + + public TexturePropertyValues DefaultTextureValue + { + get { return m_defaultTextureValue; } + set { m_defaultTextureValue = value; } + } + + public AutoCastType AutocastMode + { + get { return m_autocastMode; } + } + public bool ForceSamplingMacrosGen { set { m_forceSamplingMacrosGen = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TexturePropertyNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TexturePropertyNode.cs.meta new file mode 100644 index 0000000..721cc6d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TexturePropertyNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c1210b3dd22dafe418c5a998df2c3443 +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureTransformNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureTransformNode.cs new file mode 100644 index 0000000..1650453 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureTransformNode.cs @@ -0,0 +1,364 @@ +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Texture Transform", "Textures", "Gives access to texture tiling and offset as set on the material inspector" )] + public sealed class TextureTransformNode : ParentNode + { + private readonly string[] Dummy = { string.Empty }; + private const string InstancedLabelStr = "Instanced"; + + [SerializeField] + private bool m_instanced = false; + + [SerializeField] + private int m_referenceSamplerId = -1; + + [SerializeField] + private int m_referenceNodeId = -1; + + [SerializeField] + private TexturePropertyNode m_inputReferenceNode = null; + + private TexturePropertyNode m_referenceNode = null; + + private Vector4Node m_texCoordsHelper; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + private int m_cachedSamplerId = -1; + private int m_cachedSamplerIdArray = -1; + private int m_cachedSamplerIdCube = -1; + private int m_cachedSamplerId3D = -1; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.SAMPLER2D, false, "Tex" ); + m_inputPorts[ 0 ].CreatePortRestrictions( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.SAMPLER2DARRAY, WirePortDataType.OBJECT ); + AddOutputPort( WirePortDataType.FLOAT2, "Tiling" ); + AddOutputPort( WirePortDataType.FLOAT2, "Offset" ); + m_textLabelWidth = 80; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + m_previewShaderGUID = "25ba2903568b00343ae06788994cab54"; + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void RenderNodePreview() + { + //Runs at least one time + if( !m_initialized ) + { + // nodes with no preview don't update at all + PreviewIsDirty = false; + return; + } + + if( !PreviewIsDirty ) + return; + + SetPreviewInputs(); + + if( !Preferences.GlobalDisablePreviews ) + { + RenderTexture temp = RenderTexture.active; + + RenderTexture.active = m_outputPorts[ 0 ].OutputPreviewTexture; + PreviewMaterial.SetInt( "_PreviewID" , 0 ); + Graphics.Blit( null , m_outputPorts[ 0 ].OutputPreviewTexture , PreviewMaterial , m_previewMaterialPassId ); + + RenderTexture.active = m_outputPorts[ 1 ].OutputPreviewTexture; + PreviewMaterial.SetInt( "_PreviewID" , 1 ); + Graphics.Blit( null , m_outputPorts[ 1 ].OutputPreviewTexture , PreviewMaterial , m_previewMaterialPassId ); + RenderTexture.active = temp; + + } + + PreviewIsDirty = m_continuousPreviewRefresh; + FinishPreviewRender = true; + } + + void SetPreviewTexture( Texture newValue ) + { + if( newValue is Cubemap ) + { + m_previewMaterialPassId = 3; + if( m_cachedSamplerIdCube == -1 ) + m_cachedSamplerIdCube = Shader.PropertyToID( "_Cube" ); + + PreviewMaterial.SetTexture( m_cachedSamplerIdCube, newValue as Cubemap ); + } + else if( newValue is Texture2DArray ) + { + + m_previewMaterialPassId = 2; + if( m_cachedSamplerIdArray == -1 ) + m_cachedSamplerIdArray = Shader.PropertyToID( "_Array" ); + + PreviewMaterial.SetTexture( m_cachedSamplerIdArray, newValue as Texture2DArray ); + } + else if( newValue is Texture3D ) + { + m_previewMaterialPassId = 1; + if( m_cachedSamplerId3D == -1 ) + m_cachedSamplerId3D = Shader.PropertyToID( "_Sampler3D" ); + + PreviewMaterial.SetTexture( m_cachedSamplerId3D, newValue as Texture3D ); + } + else + { + m_previewMaterialPassId = 0; + if( m_cachedSamplerId == -1 ) + m_cachedSamplerId = Shader.PropertyToID( "_Sampler" ); + + PreviewMaterial.SetTexture( m_cachedSamplerId, newValue ); + } + } + + public override void SetPreviewInputs() + { + base.SetPreviewInputs(); + if( m_inputPorts[ 0 ].IsConnected ) + { + SetPreviewTexture( m_inputPorts[ 0 ].InputPreviewTexture( ContainerGraph ) ); + } + else if( m_referenceNode != null ) + { + if( m_referenceNode.Value != null ) + { + SetPreviewTexture( m_referenceNode.Value ); + } + else + { + SetPreviewTexture( m_referenceNode.PreviewTexture ); + } + } + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + m_inputPorts[ 0 ].MatchPortToConnection(); + m_inputReferenceNode = m_inputPorts[ 0 ].GetOutputNodeWhichIsNotRelay() as TexturePropertyNode; + UpdateTitle(); + + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + m_inputReferenceNode = null; + UpdateTitle(); + } + + public override void OnConnectedOutputNodeChanges( int outputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( outputPortId, otherNodeId, otherPortId, name, type ); + m_inputPorts[ 0 ].MatchPortToConnection(); + UpdateTitle(); + } + + void UpdateTitle() + { + if( m_inputReferenceNode != null ) + { + m_additionalContent.text = string.Format( Constants.PropertyValueLabel, m_inputReferenceNode.PropertyInspectorName ); + } + else if( m_referenceSamplerId > -1 && m_referenceNode != null ) + { + m_additionalContent.text = string.Format( Constants.PropertyValueLabel, m_referenceNode.PropertyInspectorName ); + } + else + { + m_additionalContent.text = string.Empty; + } + m_sizeIsDirty = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + bool guiEnabledBuffer = GUI.enabled; + EditorGUI.BeginChangeCheck(); + List arr = new List( UIUtils.TexturePropertyNodeArr() ); + + if( arr != null && arr.Count > 0 ) + { + arr.Insert( 0, "None" ); + GUI.enabled = true && ( !m_inputPorts[ 0 ].IsConnected ); + m_referenceSamplerId = EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceSamplerId + 1, arr.ToArray() ) - 1; + } + else + { + m_referenceSamplerId = -1; + GUI.enabled = false; + EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceSamplerId, Dummy ); + } + + GUI.enabled = guiEnabledBuffer; + if( EditorGUI.EndChangeCheck() ) + { + m_referenceNode = UIUtils.GetTexturePropertyNode( m_referenceSamplerId ); + if( m_referenceNode != null ) + { + m_referenceNodeId = m_referenceNode.UniqueId; + } + else + { + m_referenceNodeId = -1; + m_referenceSamplerId = -1; + } + UpdateTitle(); + } + + m_instanced = EditorGUILayoutToggle( InstancedLabelStr, m_instanced ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( !m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + string texTransform = string.Empty; + + if( m_inputPorts[ 0 ].IsConnected ) + { + texTransform = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) + "_ST"; + } + else if( m_referenceNode != null ) + { + m_referenceNode.BaseGenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + texTransform = m_referenceNode.PropertyName + "_ST"; + } + else + { + texTransform = "_ST"; + UIUtils.ShowMessage( UniqueId, "Please specify a texture sample on the Texture Transform Size node", MessageSeverity.Warning ); + } + + //bool excludeUniformKeyword = UIUtils.CurrentWindow.OutsideGraph.IsInstancedShader || UIUtils.CurrentWindow.OutsideGraph.IsSRP; + //string uniformRegister = UIUtils.GenerateUniformName( excludeUniformKeyword, WirePortDataType.FLOAT4, texTransform ); + //dataCollector.AddToUniforms( UniqueId, uniformRegister, true ); + if( m_texCoordsHelper == null ) + { + m_texCoordsHelper = CreateInstance(); + m_texCoordsHelper.ContainerGraph = ContainerGraph; + m_texCoordsHelper.SetBaseUniqueId( UniqueId, true ); + m_texCoordsHelper.RegisterPropertyOnInstancing = false; + m_texCoordsHelper.AddGlobalToSRPBatcher = true; + } + + if( m_instanced ) + { + m_texCoordsHelper.CurrentParameterType = PropertyType.InstancedProperty; + } + else + { + m_texCoordsHelper.CurrentParameterType = PropertyType.Global; + } + m_texCoordsHelper.ResetOutputLocals(); + m_texCoordsHelper.SetRawPropertyName( texTransform ); + texTransform = m_texCoordsHelper.GenerateShaderForOutput( 0, ref dataCollector, false ); + + m_outputPorts[ 0 ].SetLocalValue( texTransform + ".xy", dataCollector.PortCategory ); + m_outputPorts[ 1 ].SetLocalValue( texTransform + ".zw", dataCollector.PortCategory ); + } + + return m_outputPorts[ outputId ].LocalValue( dataCollector.PortCategory ); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + EditorGUI.BeginChangeCheck(); + { + List arr = new List( UIUtils.TexturePropertyNodeArr() ); + bool guiEnabledBuffer = GUI.enabled; + + if( arr != null && arr.Count > 0 ) + { + arr.Insert( 0, "None" ); + GUI.enabled = true && ( !m_inputPorts[ 0 ].IsConnected ); + m_referenceSamplerId = m_upperLeftWidget.DrawWidget( this, m_referenceSamplerId + 1, arr.ToArray() ) - 1; + } + else + { + m_referenceSamplerId = -1; + GUI.enabled = false; + m_upperLeftWidget.DrawWidget( this, m_referenceSamplerId, Dummy ); + } + GUI.enabled = guiEnabledBuffer; + } + if( EditorGUI.EndChangeCheck() ) + { + m_referenceNode = UIUtils.GetTexturePropertyNode( m_referenceSamplerId ); + if( m_referenceNode != null ) + { + m_referenceNodeId = m_referenceNode.UniqueId; + } + else + { + m_referenceNodeId = -1; + m_referenceSamplerId = -1; + } + UpdateTitle(); + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + m_referenceNode = UIUtils.GetNode( m_referenceNodeId ) as TexturePropertyNode; + m_referenceSamplerId = UIUtils.GetTexturePropertyNodeRegisterId( m_referenceNodeId ); + UpdateTitle(); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 17200 ) + { + m_instanced = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_referenceNodeId ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_instanced ); + } + + public override void Destroy() + { + base.Destroy(); + m_referenceNode = null; + m_inputReferenceNode = null; + m_upperLeftWidget = null; + if( m_texCoordsHelper != null ) + { + //Not calling m_texCoordsHelper.Destroy() on purpose so UIUtils does not incorrectly unregister stuff + DestroyImmediate( m_texCoordsHelper ); + m_texCoordsHelper = null; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureTransformNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureTransformNode.cs.meta new file mode 100644 index 0000000..be1ce29 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/TextureTransformNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4f9ca941b3f5014448e530c761a418d9 +timeCreated: 1512045037 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/UnpackScaleNormalNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/UnpackScaleNormalNode.cs new file mode 100644 index 0000000..e374cc5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/UnpackScaleNormalNode.cs @@ -0,0 +1,68 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +namespace AmplifyShaderEditor +{ + [NodeAttributes( "Unpack Scale Normal", "Textures", "Applies UnpackNormal/UnpackScaleNormal function" )] + [Serializable] + public class UnpackScaleNormalNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT4, false, "Value" ); + AddInputPort( WirePortDataType.FLOAT, false, "Scale" ); + m_inputPorts[ 1 ].FloatInternalData = 1; + AddOutputVectorPorts( WirePortDataType.FLOAT3, "XYZ" ); + m_useInternalPortData = true; + m_previewShaderGUID = "8b0ae05e25d280c45af81ded56f8012e"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + string src = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + + bool isScaledNormal = false; + if ( m_inputPorts[ 1 ].IsConnected ) + { + isScaledNormal = true; + } + else + { + if ( m_inputPorts[ 1 ].FloatInternalData != 1 ) + { + isScaledNormal = true; + } + } + + string normalMapUnpackMode = string.Empty; + string scaleValue = isScaledNormal?m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ):"1.0"; + normalMapUnpackMode = GeneratorUtils.GenerateUnpackNormalStr( ref dataCollector, CurrentPrecisionType, UniqueId, OutputId, src, isScaledNormal, scaleValue ); + if( isScaledNormal && !( dataCollector.IsTemplate && dataCollector.IsSRP ) ) + { + dataCollector.AddToIncludes( UniqueId, Constants.UnityStandardUtilsLibFuncs ); + } + + int outputUsage = 0; + for ( int i = 0; i < m_outputPorts.Count; i++ ) + { + if ( m_outputPorts[ i ].IsConnected ) + outputUsage += 1; + } + + + if ( outputUsage > 1 && !dataCollector.IsSRP ) + { + string varName = "localUnpackNormal" + OutputId; + dataCollector.AddLocalVariable( UniqueId, "float3 " + varName + " = " + normalMapUnpackMode + ";" ); + return GetOutputVectorItem( 0, outputId, varName ); + } + else + { + return GetOutputVectorItem( 0, outputId, normalMapUnpackMode ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/UnpackScaleNormalNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/UnpackScaleNormalNode.cs.meta new file mode 100644 index 0000000..270e519 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/UnpackScaleNormalNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ad04713692e9f124e86030d792c3e648 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/VirtualTextureObject.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/VirtualTextureObject.cs new file mode 100644 index 0000000..339cdc2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/VirtualTextureObject.cs @@ -0,0 +1,296 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + public enum VirtualPreset + { + Unity_Legacy, + Unity5, + Alloy, + UBER, + Skyshop, + Lux + } + + public enum VirtualChannel + { + Albedo = 0, + Base, + Normal, + Height, + Occlusion, + Displacement, + Specular, + SpecMet, + Material, + } + + [Serializable] + [NodeAttributes( "Virtual Texture Object", "Textures", "Represents a Virtual Texture Asset", SortOrderPriority = 1 )] + public class VirtualTextureObject : TexturePropertyNode + { + protected const string VirtualPresetStr = "Layout Preset"; + protected const string VirtualChannelStr = "Virtual Layer"; + + private const string VirtualTextureObjectInfo = "Can only be used alongside a Texture Sample node by connecting to its Tex Input Port.\n" + + "\nProperty name must match the value set on your Virtual Texture.\n" + + "Default e.g Albedo = _MainTex\n" + + "\nName your node according to the respective channel property in your Virtual Texture. The Albedo must be set to _MainTex ( temporary requirement )."; + private readonly string[] ChannelTypeStr = { + "Albedo - D.RGBA", + "Base - D.RGBA", + "Normal - N.GA", + "Height - N.B", + "Occlusion - N.R", + "Displacement - N.B", + "Specular - S.RGBA", + "Specular|Metallic - S.RGBA", + "Material - S.RGBA",}; + + private readonly string[] Dummy = { string.Empty }; + private string[] m_channelTypeStr; + + [SerializeField] + protected VirtualPreset m_virtualPreset = VirtualPreset.Unity5; + + [SerializeField] + protected VirtualChannel m_virtualChannel = VirtualChannel.Albedo; + + [SerializeField] + private int m_selectedChannelInt = 0; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + ChangeChannels(); + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + if ( UniqueId != -1 ) + UIUtils.AddVirtualTextureCount(); + } + + public override void DrawSubProperties() + { + ShowDefaults(); + + base.DrawSubProperties(); + } + + public override void DrawMaterialProperties() + { + ShowDefaults(); + + base.DrawMaterialProperties(); + } + + new void ShowDefaults() + { + EditorGUI.BeginChangeCheck(); + m_virtualPreset = ( VirtualPreset ) EditorGUILayoutEnumPopup( VirtualPresetStr, m_virtualPreset ); + if ( EditorGUI.EndChangeCheck() ) + { + ChangeChannels(); + } + + EditorGUI.BeginChangeCheck(); + m_selectedChannelInt = EditorGUILayoutPopup( VirtualChannelStr, m_selectedChannelInt, m_channelTypeStr ); + if ( EditorGUI.EndChangeCheck() ) + { + m_virtualChannel = GetChannel( m_selectedChannelInt ); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUILayout.HelpBox( VirtualTextureObjectInfo, MessageType.Info ); + } + + private VirtualChannel GetChannel( int popupInt ) + { + int remapInt = 0; + switch ( m_virtualPreset ) + { + case VirtualPreset.Unity_Legacy: + remapInt = popupInt == 0 ? 1 : popupInt == 1 ? 2 : popupInt == 2 ? 4 : popupInt == 3 ? 5 : 0; + break; + default: + case VirtualPreset.Unity5: + case VirtualPreset.UBER: + remapInt = popupInt == 0 ? 0 : popupInt == 1 ? 7 : popupInt == 2 ? 2 : popupInt == 3 ? 3 : popupInt == 4 ? 4 : 0; + break; + case VirtualPreset.Alloy: + remapInt = popupInt == 0 ? 1 : popupInt == 1 ? 2 : popupInt == 2 ? 8 : popupInt == 3 ? 3 : 0; + break; + case VirtualPreset.Skyshop: + case VirtualPreset.Lux: + remapInt = popupInt == 0 ? 1 : popupInt == 1 ? 2 : popupInt == 2 ? 6 : 0; + break; + } + + return ( VirtualChannel ) remapInt; + } + + private void ChangeChannels() + { + m_channelTypeStr = Dummy; + switch ( m_virtualPreset ) + { + case VirtualPreset.Unity_Legacy: + m_channelTypeStr = new string[] { ChannelTypeStr[ 1 ], ChannelTypeStr[ 2 ], ChannelTypeStr[ 4 ], ChannelTypeStr[ 5 ] }; + break; + default: + case VirtualPreset.Unity5: + case VirtualPreset.UBER: + m_channelTypeStr = new string[] { ChannelTypeStr[ 0 ], ChannelTypeStr[ 7 ], ChannelTypeStr[ 2 ], ChannelTypeStr[ 3 ], ChannelTypeStr[ 4 ] }; + break; + case VirtualPreset.Alloy: + m_channelTypeStr = new string[] { ChannelTypeStr[ 1 ], ChannelTypeStr[ 2 ], ChannelTypeStr[ 8 ], ChannelTypeStr[ 3 ] }; + break; + case VirtualPreset.Skyshop: + case VirtualPreset.Lux: + m_channelTypeStr = new string[] { ChannelTypeStr[ 1 ], ChannelTypeStr[ 2 ], ChannelTypeStr[ 6 ] }; + break; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + dataCollector.AddToProperties( UniqueId, "[HideInInspector] _VTInfoBlock( \"VT( auto )\", Vector ) = ( 0, 0, 0, 0 )", -1 ); + + return PropertyName; + } + + public override string GetPropertyValue() + { + string propertyValue = string.Empty; + switch ( m_virtualChannel ) + { + default: + case VirtualChannel.Albedo: + case VirtualChannel.Base: + propertyValue = PropertyName + "(\"" + m_propertyInspectorName + "\", 2D) = \"" + m_defaultTextureValue + "\" {}"; + break; + case VirtualChannel.Normal: + propertyValue = PropertyName + "(\"" + m_propertyInspectorName + "\", 2D) = \"" + m_defaultTextureValue + "\" {}"; + break; + case VirtualChannel.SpecMet: + propertyValue = PropertyName + "(\"" + m_propertyInspectorName + "\", 2D) = \"" + m_defaultTextureValue + "\" {}"; + break; + } + return PropertyAttributes + propertyValue; + } + + public override string GetUniformValue() + { + return "uniform sampler2D " + PropertyName + ";"; + } + + public override bool GetUniformData( out string dataType, out string dataName, ref bool fullValue ) + { + dataType = "sampler2D"; + dataName = PropertyName; + return true; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + string defaultTextureGUID = GetCurrentParam( ref nodeParams ); + //m_defaultValue = AssetDatabase.LoadAssetAtPath( textureName ); + if( UIUtils.CurrentShaderVersion() > 14101 ) + { + m_defaultValue = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( defaultTextureGUID ) ); + string materialTextureGUID = GetCurrentParam( ref nodeParams ); + m_materialValue = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( materialTextureGUID ) ); + } + else + { + m_defaultValue = AssetDatabase.LoadAssetAtPath( defaultTextureGUID ); + } + m_isNormalMap = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + m_defaultTextureValue = ( TexturePropertyValues ) Enum.Parse( typeof( TexturePropertyValues ), GetCurrentParam( ref nodeParams ) ); + m_autocastMode = ( AutoCastType ) Enum.Parse( typeof( AutoCastType ), GetCurrentParam( ref nodeParams ) ); + m_virtualPreset = ( VirtualPreset ) Enum.Parse( typeof( VirtualPreset ), GetCurrentParam( ref nodeParams ) ); + m_selectedChannelInt = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + ChangeChannels(); + m_virtualChannel = GetChannel( m_selectedChannelInt ); + + //m_forceNodeUpdate = true; + + //ConfigFromObject( m_defaultValue ); + if( m_materialValue == null ) + { + ConfigFromObject( m_defaultValue ); + } + else + { + CheckTextureImporter( true, true ); + } + ConfigureInputPorts(); + ConfigureOutputPorts(); + } + + public override void ReadAdditionalData( ref string[] nodeParams ) { } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + //IOUtils.AddFieldValueToString( ref nodeInfo, ( m_defaultValue != null ) ? AssetDatabase.GetAssetPath( m_defaultValue ) : Constants.NoStringValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_defaultValue != null ) ? AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_defaultValue ) ) : Constants.NoStringValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_materialValue != null ) ? AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_materialValue ) ) : Constants.NoStringValue ); + + IOUtils.AddFieldValueToString( ref nodeInfo, m_isNormalMap.ToString() ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultTextureValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_autocastMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_virtualPreset ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedChannelInt ); + } + + public override void WriteAdditionalToString( ref string nodeInfo, ref string connectionsInfo ) { } + + //public override string PropertyName + //{ + // get + // { + // string propertyName = string.Empty; + // switch ( m_virtualChannel ) + // { + // default: + // case VirtualChannel.Albedo: + // case VirtualChannel.Base: + // propertyName = "_MainTex"; + // break; + // case VirtualChannel.Normal: + // propertyName = "_BumpMap"; + // break; + // case VirtualChannel.SpecMet: + // propertyName = "_MetallicGlossMap"; + // break; + // case VirtualChannel.Occlusion: + // propertyName = "_OcclusionMap"; + // break; + // } + // return propertyName; + // } + //} + + public override void Destroy() + { + base.Destroy(); + UIUtils.RemoveVirtualTextureCount(); + } + + public override bool IsNormalMap { get { return m_isNormalMap || m_virtualChannel == VirtualChannel.Normal; } } + public VirtualChannel Channel { get { return m_virtualChannel; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/VirtualTextureObject.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/VirtualTextureObject.cs.meta new file mode 100644 index 0000000..f271911 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Textures/VirtualTextureObject.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bacb12043c5bc504aa49e0a5a9bbc534 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/UndoParentNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/UndoParentNode.cs new file mode 100644 index 0000000..b8377c1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/UndoParentNode.cs @@ -0,0 +1,722 @@ +using UnityEditor; +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class UndoParentNode : ScriptableObject + { + private const string MessageFormat = "Changing value {0} on node {1}"; + + [SerializeField] + protected NodeAttributes m_nodeAttribs; + + [SerializeField] + protected ParentGraph m_containerGraph; + + public void UndoRecordObject( string name ) + { + UIUtils.MarkUndoAction(); + Undo.RegisterCompleteObjectUndo( UIUtils.CurrentWindow, name ); + Undo.RecordObject( this, name ); + } + + public virtual void RecordObject( string Id ) + { + Undo.RecordObject( this, Id ); + } + public virtual void RecordObjectOnDestroy( string Id ) + { + Undo.RecordObject( this, Id ); + } + + public string EditorGUILayoutStringField( string name, string value, params GUILayoutOption[] options ) + { + string newValue = EditorGUILayout.TextField( name, value, options ); + if( !newValue.Equals( value ) ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUILayoutStringField", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public string EditorGUILayoutTextField( GUIContent label, string text, params GUILayoutOption[] options ) + { + string newValue = EditorGUILayout.TextField( label, text, options ); + if( !text.Equals( newValue ) ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public string EditorGUILayoutTextField( string text, params GUILayoutOption[] options ) + { + string newValue = EditorGUILayout.TextField( text, options ); + if( !text.Equals( newValue ) ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUILayoutTextField", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public string EditorGUILayoutTextField( string label, string text, params GUILayoutOption[] options ) + { + string newValue = EditorGUILayout.TextField( label, text, options ); + if( !text.Equals( newValue ) ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public Enum EditorGUILayoutEnumPopup( GUIContent label, Enum selected, params GUILayoutOption[] options ) + { + Enum newValue = EditorGUILayout.EnumPopup( label, selected, options ); + if( !newValue.ToString().Equals( selected.ToString() ) ) + { + UndoRecordObject( string.Concat( "Changing value ", label, " on node ", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + //UndoRecordObject(string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public Enum EditorGUILayoutEnumPopup( string label, Enum selected, params GUILayoutOption[] options ) + { + Enum newValue = EditorGUILayout.EnumPopup( label, selected, options ); + if( !newValue.ToString().Equals( selected.ToString() ) ) + { + UndoRecordObject( string.Concat( "Changing value ", label, " on node ", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + //UndoRecordObject(string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public Enum EditorGUILayoutEnumPopup( Enum selected, params GUILayoutOption[] options ) + { + Enum newValue = EditorGUILayout.EnumPopup( selected, options ); + if( !newValue.ToString().Equals( selected.ToString() ) ) + { + UndoRecordObject( string.Concat( "Changing value EditorGUILayoutEnumPopup on node ", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + //UndoRecordObject(string.Format( MessageFormat, "EditorGUILayoutEnumPopup", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUILayoutIntPopup( string label, int selectedValue, string[] displayedOptions, int[] optionValues, params GUILayoutOption[] options ) + { + int newValue = EditorGUILayout.IntPopup( label, selectedValue, displayedOptions, optionValues, options ); + if( newValue != selectedValue ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + + public int EditorGUILayoutPopup( string label, int selectedIndex, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options ) + { + int newValue = EditorGUILayout.Popup( label, selectedIndex, displayedOptions, style, options ); + if( newValue != selectedIndex ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + + public int EditorGUILayoutPopup( GUIContent label, int selectedIndex, GUIContent[] displayedOptions, params GUILayoutOption[] options ) + { + int newValue = EditorGUILayout.Popup( label, selectedIndex, displayedOptions, options ); + if( newValue != selectedIndex ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUILayoutPopup( GUIContent label, int selectedIndex, GUIContent[] displayedOptions, GUIStyle style, params GUILayoutOption[] options ) + { + int newValue = EditorGUILayout.Popup( label, selectedIndex, displayedOptions, style, options ); + if( newValue != selectedIndex ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUILayoutPopup( int selectedIndex, string[] displayedOptions, params GUILayoutOption[] options ) + { + int newValue = EditorGUILayout.Popup( selectedIndex, displayedOptions, options ); + if( newValue != selectedIndex ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUILayoutPopup", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUILayoutPopup( string label, int selectedIndex, string[] displayedOptions, params GUILayoutOption[] options ) + { + int newValue = EditorGUILayout.Popup( label, selectedIndex, displayedOptions, options ); + if( newValue != selectedIndex ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public bool EditorGUILayoutToggle( GUIContent label, bool value, params GUILayoutOption[] options ) + { + bool newValue = EditorGUILayout.Toggle( label, value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public bool EditorGUILayoutToggle( string label, bool value, params GUILayoutOption[] options ) + { + bool newValue = EditorGUILayout.Toggle( label, value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public bool EditorGUILayoutToggle( string label, bool value, GUIStyle style, params GUILayoutOption[] options ) + { + bool newValue = EditorGUILayout.Toggle( label, value, style, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUILayoutIntField( int value, params GUILayoutOption[] options ) + { + int newValue = EditorGUILayout.IntField( value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUILayoutIntField", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUILayoutIntField( GUIContent label, int value, params GUILayoutOption[] options ) + { + int newValue = EditorGUILayout.IntField( label, value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUILayoutIntField( string label, int value, params GUILayoutOption[] options ) + { + int newValue = EditorGUILayout.IntField( label, value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public float EditorGUILayoutFloatField( GUIContent label, float value, params GUILayoutOption[] options ) + { + float newValue = EditorGUILayout.FloatField( label, value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public float EditorGUILayoutFloatField( string label, float value, params GUILayoutOption[] options ) + { + float newValue = EditorGUILayout.FloatField( label, value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public float EditorGUILayoutRangedFloatField( string label, float value, float min, float max, params GUILayoutOption[] options ) + { + float newValue = Mathf.Clamp( EditorGUILayout.FloatField( label, value, options ), min, max ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public Color EditorGUILayoutColorField( string label, Color value, params GUILayoutOption[] options ) + { + Color newValue = EditorGUILayout.ColorField( label, value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } +#if UNITY_2018_1_OR_NEWER + public Color EditorGUILayoutColorField( GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr, params GUILayoutOption[] options ) + { + Color newValue = EditorGUILayout.ColorField( label, value, showEyedropper, showAlpha, hdr, options ); + if( newValue != value ) + { + UndoRecordObject(string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } +#else + public Color EditorGUILayoutColorField( GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr, ColorPickerHDRConfig hdrConfig, params GUILayoutOption[] options ) + { + Color newValue = EditorGUILayout.ColorField( label, value, showEyedropper, showAlpha, hdr, hdrConfig, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } +#endif + public float EditorGUILayoutSlider( string label, float value, float leftValue, float rightValue, params GUILayoutOption[] options ) + { + float newValue = EditorGUILayout.Slider( label, value, leftValue, rightValue, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public float EditorGUILayoutSlider( GUIContent label, float value, float leftValue, float rightValue, params GUILayoutOption[] options ) + { + float newValue = EditorGUILayout.Slider( label, value, leftValue, rightValue, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + public UnityEngine.Object EditorGUILayoutObjectField( string label, UnityEngine.Object obj, System.Type objType, bool allowSceneObjects, params GUILayoutOption[] options ) + { + UnityEngine.Object newValue = EditorGUILayout.ObjectField( label, obj, objType, allowSceneObjects, options ); + if( newValue != obj ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public Vector2 EditorGUIVector2Field( Rect position, string label, Vector2 value ) + { + Vector2 newValue = EditorGUI.Vector2Field( position, label, value ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + + public Vector2 EditorGUILayoutVector2Field( string label, Vector2 value, params GUILayoutOption[] options ) + { + Vector2 newValue = EditorGUILayout.Vector2Field( label, value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public Vector3 EditorGUIVector3Field( Rect position, string label, Vector3 value ) + { + Vector3 newValue = EditorGUI.Vector3Field( position, label, value ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public Vector3 EditorGUILayoutVector3Field( string label, Vector3 value, params GUILayoutOption[] options ) + { + Vector3 newValue = EditorGUILayout.Vector3Field( label, value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public Vector4 EditorGUIVector4Field( Rect position, string label, Vector4 value ) + { + Vector4 newValue = EditorGUI.Vector4Field( position, label, value ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public Vector4 EditorGUILayoutVector4Field( string label, Vector4 value, params GUILayoutOption[] options ) + { + Vector4 newValue = EditorGUILayout.Vector4Field( label, value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUILayoutIntSlider( GUIContent label, int value, int leftValue, int rightValue, params GUILayoutOption[] options ) + { + int newValue = EditorGUILayout.IntSlider( label, value, leftValue, rightValue, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUILayoutIntSlider( string label, int value, int leftValue, int rightValue, params GUILayoutOption[] options ) + { + int newValue = EditorGUILayout.IntSlider( label, value, leftValue, rightValue, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public bool EditorGUILayoutToggleLeft( string label, bool value, params GUILayoutOption[] options ) + { + bool newValue = EditorGUILayout.ToggleLeft( label, value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public bool EditorGUILayoutToggleLeft( GUIContent label, bool value, params GUILayoutOption[] options ) + { + bool newValue = EditorGUILayout.ToggleLeft( label, value, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public string EditorGUILayoutTextArea( string text, GUIStyle style, params GUILayoutOption[] options ) + { + string newValue = EditorGUILayout.TextArea( text, style, options ); + if( !newValue.Equals( text ) ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUILayoutTextArea", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public bool EditorGUILayoutFoldout( bool foldout, string content ) + { + bool newValue = EditorGUILayout.Foldout( foldout, content ); + if( newValue != foldout ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUILayoutFoldout", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public bool EditorGUIFoldout( Rect position, bool foldout, string content ) + { + bool newValue = EditorGUI.Foldout( position, foldout, content ); + if( newValue != foldout ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUIFoldout", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public string EditorGUITextField( Rect position, string label, string text ) + { + string newValue = EditorGUI.TextField( position, label, text ); + if( !newValue.Equals( text ) ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public string EditorGUITextArea( Rect position, string text ) + { + string newValue = EditorGUI.TextArea( position, text ); + if( !newValue.Equals( text ) ) + { + UndoRecordObject( string.Format( MessageFormat, "TextArea", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public string EditorGUITextArea( Rect position, string text, [UnityEngine.Internal.DefaultValue( "EditorStyles.textField" )] GUIStyle style ) + { + string newValue = EditorGUI.TextArea( position, text,style ); + if( !newValue.Equals( text ) ) + { + UndoRecordObject( string.Format( MessageFormat, "TextArea", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public string EditorGUITextField( Rect position, string label, string text, [UnityEngine.Internal.DefaultValue( "EditorStyles.textField" )] GUIStyle style ) + { + string newValue = EditorGUI.TextField( position, label, text, style ); + if( !newValue.Equals( text ) ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } +#if UNITY_2018_1_OR_NEWER + public Color EditorGUIColorField( Rect position, GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr ) + { + Color newValue = EditorGUI.ColorField( position, label, value, showEyedropper, showAlpha, hdr ); + if( newValue != value ) + { + UndoRecordObject(string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } +#else + public Color EditorGUIColorField( Rect position, GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr, ColorPickerHDRConfig hdrConfig ) + { + Color newValue = EditorGUI.ColorField( position, label, value, showEyedropper, showAlpha, hdr, hdrConfig ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } +#endif + public Color EditorGUIColorField( Rect position, string label, Color value ) + { + Color newValue = EditorGUI.ColorField( position, label, value ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + + public int EditorGUIIntField( Rect position, string label, int value ) + { + int newValue = EditorGUI.IntField( position, label, value ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUIIntField( Rect position, string label, int value, [UnityEngine.Internal.DefaultValue( "EditorStyles.numberField" )] GUIStyle style ) + { + int newValue = EditorGUI.IntField( position, label, value, style ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public float EditorGUIFloatField( Rect position, string label, float value ) + { + float newValue = EditorGUI.FloatField( position, label, value ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public float EditorGUIFloatField( Rect position, string label, float value, [UnityEngine.Internal.DefaultValue( "EditorStyles.numberField" )] GUIStyle style ) + { + float newValue = EditorGUI.FloatField( position, label, value, style ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, label, ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public float EditorGUIFloatField( Rect position, float value, [UnityEngine.Internal.DefaultValue( "EditorStyles.numberField" )] GUIStyle style ) + { + float newValue = EditorGUI.FloatField( position, value, style ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUIFloatField", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public float GUIHorizontalSlider( Rect position, float value, float leftValue, float rightValue, GUIStyle slider, GUIStyle thumb ) + { + float newValue = GUI.HorizontalSlider( position, value, leftValue, rightValue, slider, thumb ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, "GUIHorizontalSlider", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public Enum EditorGUIEnumPopup( Rect position, Enum selected ) + { + Enum newValue = EditorGUI.EnumPopup( position, selected ); + if( !newValue.ToString().Equals( selected.ToString() ) ) + { + UndoRecordObject( string.Concat( "Changing value EditorGUIEnumPopup on node ", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + //UndoRecordObject(string.Format( MessageFormat, "EditorGUIEnumPopup", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public Enum EditorGUIEnumPopup( Rect position, Enum selected, [UnityEngine.Internal.DefaultValue( "EditorStyles.popup" )] GUIStyle style ) + { + Enum newValue = EditorGUI.EnumPopup( position, selected, style ); + if( !newValue.ToString().Equals( selected.ToString() ) ) + { + UndoRecordObject( string.Concat( "Changing value EditorGUIEnumPopup on node ", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + //UndoRecordObject(string.Format( MessageFormat, "EditorGUIEnumPopup", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUIIntPopup( Rect position, int selectedValue, GUIContent[] displayedOptions, int[] optionValues, [UnityEngine.Internal.DefaultValue( "EditorStyles.popup" )] GUIStyle style ) + { + int newValue = EditorGUI.IntPopup( position, selectedValue, displayedOptions, optionValues, style ); + if( newValue != selectedValue ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUIIntEnumPopup", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUIPopup( Rect position, string label, int selectedIndex, string[] displayedOptions ) + { + int newValue = EditorGUI.Popup( position, label, selectedIndex, displayedOptions ); + if( newValue != selectedIndex ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUIEnumPopup", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUIPopup( Rect position, int selectedIndex, GUIContent[] displayedOptions, [UnityEngine.Internal.DefaultValue( "EditorStyles.popup" )] GUIStyle style ) + { + int newValue = EditorGUI.Popup( position, selectedIndex, displayedOptions, style ); + if( newValue != selectedIndex ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUIEnumPopup", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public int EditorGUIPopup( Rect position, int selectedIndex, string[] displayedOptions, [UnityEngine.Internal.DefaultValue( "EditorStyles.popup" )] GUIStyle style ) + { + int newValue = EditorGUI.Popup( position, selectedIndex, displayedOptions, style ); + if( newValue != selectedIndex ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUIEnumPopup", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public UnityEngine.Object EditorGUIObjectField( Rect position, UnityEngine.Object obj, System.Type objType, bool allowSceneObjects ) + { + UnityEngine.Object newValue = EditorGUI.ObjectField( position, obj, objType, allowSceneObjects ); + if( newValue != obj ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUIObjectField", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + public int EditorGUIIntPopup( Rect position, int selectedValue, string[] displayedOptions, int[] optionValues, [UnityEngine.Internal.DefaultValue( "EditorStyles.popup" )] GUIStyle style ) + { + int newValue = EditorGUI.IntPopup( position, selectedValue, displayedOptions, optionValues, style ); + if( newValue != selectedValue ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUIIntPopup", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public bool EditorGUIToggle( Rect position, bool value ) + { + bool newValue = EditorGUI.Toggle( position, value ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUIToggle", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public bool EditorGUIToggle( Rect position, string text, bool value ) + { + bool newValue = EditorGUI.Toggle( position,text, value ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, "EditorGUIToggle", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public string GUITextField( Rect position, string text, GUIStyle style ) + { + string newValue = GUI.TextField( position, text, style ); + if( !newValue.Equals( text ) ) + { + UndoRecordObject( string.Format( MessageFormat, "GUITextfield", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + + public bool GUILayoutToggle( bool value, string text, GUIStyle style, params GUILayoutOption[] options ) + { + bool newValue = GUILayout.Toggle( value, text, style, options ); + if( newValue != value ) + { + UndoRecordObject( string.Format( MessageFormat, "GUILayoutToggle", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return newValue; + } + + public bool GUILayoutButton( string text, GUIStyle style, params GUILayoutOption[] options ) + { + bool value = GUILayout.Button( text, style, options ); + if( value ) + { + UndoRecordObject( string.Format( MessageFormat, "GUILayoutButton", ( ( m_nodeAttribs != null ) ? m_nodeAttribs.Name : GetType().ToString() ) ) ); + } + return value; + } + + /// + /// It's the graph the node exists in, this is set after node creation and it's not available on CommonInit + /// + public ParentGraph ContainerGraph + { + get { return m_containerGraph; } + set { m_containerGraph = value; } + } + } +} + diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/UndoParentNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/UndoParentNode.cs.meta new file mode 100644 index 0000000..f320dc1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/UndoParentNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bcc69b2f388d45f43a9157ce814b5aae +timeCreated: 1490183752 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex.meta new file mode 100644 index 0000000..9c22229 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 579ecde4d9d1a0e45a655588b39f457a +folderAsset: yes +timeCreated: 1481126945 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BillboardNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BillboardNode.cs new file mode 100644 index 0000000..22ec54f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BillboardNode.cs @@ -0,0 +1,124 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Billboard", "Miscellaneous", "Calculates new Vertex positions and normals to achieve a billboard effect." )] + public sealed class BillboardNode : ParentNode + { + private const string ErrorMessage = "Billboard node should only be connected to vertex ports."; + private const string WarningMessage = "This node is a bit different from all others as it injects the necessary code into the vertex body and writes directly on the vertex position and normal.\nIt outputs a value of 0 so it can be connected directly to a vertex port.\n[Only if that port is a relative vertex offset]."; + + [SerializeField] + private BillboardType m_billboardType = BillboardType.Cylindrical; + + [SerializeField] + private bool m_rotationIndependent = false; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputPort( WirePortDataType.FLOAT3, "Out" ); + m_textLabelWidth = 115; + m_hasLeftDropdown = true; + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_billboardType ) ); + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + m_upperLeftWidget.DrawWidget( ref m_billboardType, this, OnWidgetUpdate ); + } + + private readonly Action OnWidgetUpdate = ( x ) => + { + x.SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, ( x as BillboardNode ).Type ) ); + }; + + public override void DrawProperties() + { + base.DrawProperties(); + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr, () => + { + EditorGUI.BeginChangeCheck(); + m_billboardType = (BillboardType)EditorGUILayoutEnumPopup( BillboardOpHelper.BillboardTypeStr, m_billboardType ); + if( EditorGUI.EndChangeCheck() ) + { + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_billboardType ) ); + } + m_rotationIndependent = EditorGUILayoutToggle( BillboardOpHelper.BillboardRotIndStr, m_rotationIndependent ); + } ); + EditorGUILayout.HelpBox( WarningMessage, MessageType.Warning ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsFragmentCategory ) + { + UIUtils.ShowMessage( UniqueId, ErrorMessage,MessageSeverity.Error ); + return m_outputPorts[0].ErrorValue; + } + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].ErrorValue; + + m_outputPorts[ 0 ].SetLocalValue( "0", dataCollector.PortCategory ); + string vertexPosValue = dataCollector.IsTemplate ? dataCollector.TemplateDataCollectorInstance.GetVertexPosition( WirePortDataType.OBJECT, CurrentPrecisionType ) : "v.vertex"; + string vertexNormalValue = dataCollector.IsTemplate ? dataCollector.TemplateDataCollectorInstance.GetVertexNormal( CurrentPrecisionType ) : "v.normal"; + bool vertexIsFloat3 = false; + if( dataCollector.IsTemplate ) + { + InterpDataHelper info = dataCollector.TemplateDataCollectorInstance.GetInfo( TemplateInfoOnSematics.POSITION ); + if( info != null ) + { + vertexIsFloat3 = info.VarType == WirePortDataType.FLOAT3; + } + } + + BillboardOpHelper.FillDataCollector( ref dataCollector, m_billboardType, m_rotationIndependent, vertexPosValue, vertexNormalValue, vertexIsFloat3 ); + + return "0"; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_billboardType = (BillboardType)Enum.Parse( typeof( BillboardType ), GetCurrentParam( ref nodeParams ) ); + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr , m_billboardType ) ); + m_rotationIndependent = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_billboardType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_rotationIndependent ); + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, m_billboardType ) ); + } + + public BillboardType Type { get { return m_billboardType; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BillboardNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BillboardNode.cs.meta new file mode 100644 index 0000000..7b2c540 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BillboardNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 08fd3dd8f623aca42b7eb9962a89753d +timeCreated: 1501161489 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BitangentVertexDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BitangentVertexDataNode.cs new file mode 100644 index 0000000..828a499 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BitangentVertexDataNode.cs @@ -0,0 +1,37 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Vertex Bitangent", "Vertex Data", "Calculated bitangent vector in object space, can be used in both local vertex offset and fragment outputs. Already has tangent sign and object transform into account" )] + public sealed class BitangentVertexDataNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputVectorPorts( WirePortDataType.FLOAT3, "XYZ" ); + m_drawPreviewAsSphere = true; + m_previewShaderGUID = "76873532ab67d2947beaf07151383cbe"; + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + dataCollector.DirtyNormal = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if ( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + { + dataCollector.ForceNormal = true; + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + } + + string vertexBitangent = GeneratorUtils.GenerateVertexBitangent( ref dataCollector, UniqueId, CurrentPrecisionType ); + return GetOutputVectorItem( 0, outputId, vertexBitangent ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BitangentVertexDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BitangentVertexDataNode.cs.meta new file mode 100644 index 0000000..1c5ff97 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BitangentVertexDataNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 839ecbdfc8ed4fd4d8a08ec07f7159fa +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendIndicesNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendIndicesNode.cs new file mode 100644 index 0000000..db51889 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendIndicesNode.cs @@ -0,0 +1,69 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Bone Blend Indices" , "Vertex Data" , "Bone indices for skinned Meshes" )] + public sealed class BlendIndicesNode : VertexDataNode + { + private const string IncorrectUnityVersionMessage = "This info is only available on Unity 2019.1 or above."; + private const string StandardSurfaceErrorMessage = "This info is not available on standard surface shaders."; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_outputPorts[ 1 ].ChangeType( WirePortDataType.UINT , false ); + m_outputPorts[ 2 ].ChangeType( WirePortDataType.UINT , false ); + m_outputPorts[ 3 ].ChangeType( WirePortDataType.UINT , false ); + m_outputPorts[ 4 ].ChangeType( WirePortDataType.UINT , false ); + m_currentVertexData = GeneratorUtils.VertexBlendIndicesStr; + m_errorMessageTypeIsError = NodeMessageType.Error; + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); +#if UNITY_2019_1_OR_NEWER + if( UIUtils.CurrentWindow.OutsideGraph.IsStandardSurface ) + { + if( !m_showErrorMessage ) + { + m_showErrorMessage = true; + m_errorMessageTooltip = StandardSurfaceErrorMessage; + } + } + else + { + m_showErrorMessage = false; + } +#else + if( !m_showErrorMessage ) + { + m_showErrorMessage = true; + m_errorMessageTooltip = IncorrectUnityVersionMessage; + } +#endif + } + + public override string GenerateShaderForOutput( int outputId , ref MasterNodeDataCollector dataCollector , bool ignoreLocalVar ) + { +#if UNITY_2019_1_OR_NEWER + + string blendIndices = string.Empty; + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + blendIndices = dataCollector.TemplateDataCollectorInstance.GetBlendIndices(); + return GetOutputVectorItem( 0 , outputId , blendIndices ); + } + + return GenerateErrorValue( outputId ); +#else + return GenerateErrorValue( outputId ); +#endif + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendIndicesNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendIndicesNode.cs.meta new file mode 100644 index 0000000..06bd4eb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendIndicesNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c2f0572db8612644b8e7fc2bcd16312b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendWeightsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendWeightsNode.cs new file mode 100644 index 0000000..9d2407c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendWeightsNode.cs @@ -0,0 +1,65 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Bone Blend Weights" , "Vertex Data" , "Bone blend weights for skinned Meshes" )] + public sealed class BlendWeightsNode : VertexDataNode + { + private const string IncorrectUnityVersionMessage = "This info is only available on Unity 2019.1 or above."; + private const string StandardSurfaceErrorMessage = "This info is not available on standard surface shaders."; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentVertexData = GeneratorUtils.VertexBlendWeightsStr; + m_errorMessageTypeIsError = NodeMessageType.Error; + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + base.OnNodeLogicUpdate( drawInfo ); +#if UNITY_2019_1_OR_NEWER + if( UIUtils.CurrentWindow.OutsideGraph.IsStandardSurface ) + { + if( !m_showErrorMessage ) + { + m_showErrorMessage = true; + m_errorMessageTooltip = StandardSurfaceErrorMessage; + } + } + else + { + m_showErrorMessage = false; + } +#else + if( !m_showErrorMessage ) + { + m_showErrorMessage = true; + m_errorMessageTooltip = IncorrectUnityVersionMessage; + } +#endif + } + + public override string GenerateShaderForOutput( int outputId , ref MasterNodeDataCollector dataCollector , bool ignoreLocalVar ) + { +#if UNITY_2019_1_OR_NEWER + + string blendWeights = string.Empty; + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + blendWeights = dataCollector.TemplateDataCollectorInstance.GetBlendWeights(); + return GetOutputVectorItem( 0 , outputId , blendWeights ); + } + + return GenerateErrorValue( outputId ); +#else + return GenerateErrorValue( outputId ); +#endif + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendWeightsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendWeightsNode.cs.meta new file mode 100644 index 0000000..e2e2bf4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/BlendWeightsNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cb9d9029b584a7645a3d4aa2b45e34ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ColorVertexDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ColorVertexDataNode.cs new file mode 100644 index 0000000..0cea161 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ColorVertexDataNode.cs @@ -0,0 +1,18 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "[VS] Vertex Color", "Vertex Data", "Vertex color. Only works on Vertex Shaders ports ( p.e. Local Vertex Offset Port ).", null,KeyCode.None,true,true,"Vertex Color",typeof(VertexColorNode))] + public sealed class ColorVertexDataNode : VertexDataNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentVertexData = "color"; + ConvertFromVectorToColorPorts(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ColorVertexDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ColorVertexDataNode.cs.meta new file mode 100644 index 0000000..b8990fe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ColorVertexDataNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ca76669baa9fa204b8ce5200eb07c1db +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/NormalVertexDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/NormalVertexDataNode.cs new file mode 100644 index 0000000..b5fc4b5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/NormalVertexDataNode.cs @@ -0,0 +1,44 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Vertex Normal", "Vertex Data", "Vertex normal vector in object space, can be used in both local vertex offset and fragment outputs" )] + public sealed class NormalVertexDataNode : VertexDataNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentVertexData = "normal"; + ChangeOutputProperties( 0, "XYZ", WirePortDataType.FLOAT3 ); + m_outputPorts[ 4 ].Visible = false; + m_drawPreviewAsSphere = true; + m_previewShaderGUID = "6b24b06c33f9fe84c8a2393f13ab5406"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + string vertexNormal = string.Empty; + + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + vertexNormal = dataCollector.TemplateDataCollectorInstance.GetVertexNormal( CurrentPrecisionType ); + return GetOutputVectorItem( 0, outputId, vertexNormal ); + } + + if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + if( dataCollector.DirtyNormal ) + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + dataCollector.ForceNormal = true; + } + } + + vertexNormal = GeneratorUtils.GenerateVertexNormal( ref dataCollector, UniqueId, CurrentPrecisionType ); + return GetOutputVectorItem( 0, outputId, vertexNormal ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/NormalVertexDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/NormalVertexDataNode.cs.meta new file mode 100644 index 0000000..62b8c9d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/NormalVertexDataNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4c7b60515f9cf6043bf8d03531d268f9 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ObjectScaleNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ObjectScaleNode.cs new file mode 100644 index 0000000..6dd1b8d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ObjectScaleNode.cs @@ -0,0 +1,75 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Object Scale", "Vertex Data", "Object Scale extracted directly from its transform matrix" )] + public class ObjectScaleNode : ParentNode + { + private const string RotationIndependentScaleStr = "Rotation Independent Scale"; + + [SerializeField] + private bool m_rotationIndependentScale = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputVectorPorts( WirePortDataType.FLOAT3, "XYZ" ); + m_drawPreviewAsSphere = true; + m_previewShaderGUID = "5540033c6c52f51468938c1a42bd2730"; + m_textLabelWidth = 180; + UpdateMaterialPass(); + m_autoWrapProperties = true; + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_rotationIndependentScale = EditorGUILayoutToggle( RotationIndependentScaleStr, m_rotationIndependentScale ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateMaterialPass(); + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + string objectScale = m_rotationIndependentScale ? GeneratorUtils.GenerateRotationIndependentObjectScale( ref dataCollector, UniqueId ): + GeneratorUtils.GenerateObjectScale( ref dataCollector, UniqueId ); + + return GetOutputVectorItem( 0, outputId, objectScale ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() < 17402 ) + { + m_rotationIndependentScale = false; + } + else + { + m_rotationIndependentScale = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + UpdateMaterialPass(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_rotationIndependentScale ); + } + + void UpdateMaterialPass() + { + m_previewMaterialPassId = m_rotationIndependentScale ? 1 : 0; + PreviewIsDirty = true; + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ObjectScaleNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ObjectScaleNode.cs.meta new file mode 100644 index 0000000..7103bef --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/ObjectScaleNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ef1fe46d0cc472e45ad13ac737db2c1e +timeCreated: 1493993914 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/OutlineNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/OutlineNode.cs new file mode 100644 index 0000000..18600b0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/OutlineNode.cs @@ -0,0 +1,392 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +using UnityEngine; +using UnityEditor; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Outline", "Miscellaneous", "Uses vertices to simulate an outline around the object" )] + public sealed class OutlineNode : ParentNode + { + enum OutlineAlphaModes + { + None = 0, + Masked, + Transparent, + AlphaPremultiplied + }; + + private const string CullModePortNameStr = "Cull Mode"; + private const string AlphaModePortNameStr = "Alpha"; + private const string MaskedModePortNamStr = "Opacity Mask"; + private const string OutlineAlphaModeStr = "Alpha Mode"; + private const string OpacityMaskClipValueStr = "Mask Clip Value"; + private const string ErrorMessage = "Outline node should only be connected to vertex ports."; + + [SerializeField] + private bool m_noFog = true; + + [SerializeField] + private string[] AvailableOutlineModes = { "Vertex Offset", "Vertex Scale", "Custom" }; + + [SerializeField] + private int[] AvailableOutlineValues = { 0, 1, 2 }; + + [SerializeField] + private int m_currentSelectedMode = 0; + + [SerializeField] + private OutlineAlphaModes m_currentAlphaMode = OutlineAlphaModes.None; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + [NonSerialized] + private StandardSurfaceOutputNode m_masterNode = null; + + [SerializeField] + private int m_zTestMode = 0; + + [SerializeField] + private int m_zWriteMode = 0; + + [SerializeField] + private CullMode m_cullMode = CullMode.Front; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + + AddOutputPort( WirePortDataType.FLOAT3, "Out" ); + + AddInputPort( WirePortDataType.FLOAT3, false, "Color", -1, MasterNodePortCategory.Fragment, 0 ); + AddInputPort( WirePortDataType.FLOAT, false, "Alpha", -1, MasterNodePortCategory.Fragment, 2 ); + AddInputPort( WirePortDataType.FLOAT, false, "Width", -1, MasterNodePortCategory.Fragment, 1 ); + GetInputPortByUniqueId( 2 ).Visible = false; + m_textLabelWidth = 115; + m_hasLeftDropdown = true; + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, AvailableOutlineModes[ m_currentSelectedMode ] ) ); + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + if( GetInputPortByUniqueId( 0 ).IsConnected ) + dataCollector.UsingCustomOutlineColor = true; + + if( GetInputPortByUniqueId( 1 ).IsConnected ) + dataCollector.UsingCustomOutlineWidth = true; + + if( GetInputPortByUniqueId( 2 ).IsConnected ) + dataCollector.UsingCustomOutlineAlpha = true; + + if( !dataCollector.IsTemplate ) + { + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.ZWriteMode = m_zWriteMode; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.OffsetMode = m_currentSelectedMode; + } + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_currentSelectedMode = m_upperLeftWidget.DrawWidget( this, m_currentSelectedMode, AvailableOutlineModes ); + if( EditorGUI.EndChangeCheck() ) + { + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, AvailableOutlineModes[ m_currentSelectedMode ] ) ); + UpdatePorts(); + } + } + + void CheckAlphaPortVisibility() + { + InputPort alphaPort = GetInputPortByUniqueId( 2 ); + if( m_currentAlphaMode != OutlineAlphaModes.None ) + { + if( !alphaPort.Visible ) + alphaPort.Visible = true; + + if( m_currentAlphaMode == OutlineAlphaModes.Masked ) + { + GetInputPortByUniqueId( 2 ).Name = MaskedModePortNamStr; + } + else + { + GetInputPortByUniqueId( 2 ).Name = AlphaModePortNameStr; + } + m_sizeIsDirty = true; + } + + if( m_currentAlphaMode == OutlineAlphaModes.None && alphaPort.Visible ) + { + alphaPort.Visible = false; + m_sizeIsDirty = true; + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr, () => + { + EditorGUI.BeginChangeCheck(); + m_currentSelectedMode = EditorGUILayoutIntPopup( "Type", m_currentSelectedMode, AvailableOutlineModes, AvailableOutlineValues ); + if( EditorGUI.EndChangeCheck() ) + { + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, AvailableOutlineModes[ m_currentSelectedMode ] ) ); + UpdatePorts(); + } + + EditorGUI.BeginChangeCheck(); + m_currentAlphaMode = (OutlineAlphaModes)EditorGUILayoutEnumPopup( OutlineAlphaModeStr, m_currentAlphaMode ); + if( EditorGUI.EndChangeCheck() ) + { + CheckAlphaPortVisibility(); + } + + if( m_currentAlphaMode == OutlineAlphaModes.Masked ) + { + if( m_masterNode == null ) + { + m_masterNode = UIUtils.CurrentWindow.OutsideGraph.CurrentMasterNode as StandardSurfaceOutputNode; + } + + if( m_masterNode != null ) + { + m_masterNode.ShowOpacityMaskValueUI(); + } + } + + m_cullMode = (CullMode)EditorGUILayoutEnumPopup( CullModePortNameStr, m_cullMode ); + m_zWriteMode = EditorGUILayoutPopup( ZBufferOpHelper.ZWriteModeStr, m_zWriteMode, ZBufferOpHelper.ZWriteModeValues ); + m_zTestMode = EditorGUILayoutPopup( ZBufferOpHelper.ZTestModeStr, m_zTestMode, ZBufferOpHelper.ZTestModeLabels ); + m_noFog = EditorGUILayoutToggle( "No Fog", m_noFog ); + + } ); + } + + void UpdatePorts() + { + if( m_currentSelectedMode == 2 ) //custom mode + { + GetInputPortByUniqueId( 1 ).ChangeProperties( "Offset", WirePortDataType.FLOAT3, false ); + } + else + { + GetInputPortByUniqueId( 1 ).ChangeProperties( "Width", WirePortDataType.FLOAT, false ); + } + + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.IsTemplate ) + return m_outputPorts[0].ErrorValue; + + if( dataCollector.IsFragmentCategory ) + { + UIUtils.ShowMessage( UniqueId, ErrorMessage ); + return m_outputPorts[ 0 ].ErrorValue; + } + + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].ErrorValue; + + m_outputPorts[ 0 ].SetLocalValue( "0", dataCollector.PortCategory ); + + StandardSurfaceOutputNode masterNode = UIUtils.CurrentWindow.OutsideGraph.CurrentMasterNode as StandardSurfaceOutputNode; + + MasterNodeDataCollector outlineDataCollector = new MasterNodeDataCollector(); + outlineDataCollector.IsOutlineDataCollector = true; + outlineDataCollector.DirtyNormal = true; + InputPort colorPort = GetInputPortByUniqueId( 0 ); + InputPort alphaPort = GetInputPortByUniqueId( 2 ); + InputPort vertexPort = GetInputPortByUniqueId( 1 ); + + //if( vertexPort.IsConnected ) + //{ + // outlineDataCollector.PortCategory = MasterNodePortCategory.Vertex; + // string outlineWidth = vertexPort.GenerateShaderForOutput( ref outlineDataCollector, vertexPort.DataType, true, true ); + // outlineDataCollector.AddToVertexLocalVariables( UniqueId, PrecisionType.Float, vertexPort.DataType, "outlineVar", outlineWidth ); + + // outlineDataCollector.AddVertexInstruction( outlineDataCollector.SpecialLocalVariables, UniqueId, false ); + // outlineDataCollector.ClearSpecialLocalVariables(); + + // outlineDataCollector.AddVertexInstruction( outlineDataCollector.VertexLocalVariables, UniqueId, false ); + // outlineDataCollector.ClearVertexLocalVariables(); + + // // need to check whether this breaks other outputs or not + // UIUtils.CurrentWindow.OutsideGraph.ResetNodesLocalVariables(); + //} + + outlineDataCollector.PortCategory = MasterNodePortCategory.Fragment; + string outlineColor = colorPort.GeneratePortInstructions( ref outlineDataCollector );// "\to.Emission = " + colorPort.GeneratePortInstructions( ref outlineDataCollector ) + ";"; + string alphaValue = alphaPort.Visible ? alphaPort.GeneratePortInstructions( ref outlineDataCollector ) : string.Empty; + + + + bool addTabs = outlineDataCollector.DirtySpecialLocalVariables || alphaPort.Available; + outlineDataCollector.AddInstructions( "\t" + outlineDataCollector.SpecialLocalVariables.TrimStart( '\t' ) ); + outlineDataCollector.ClearSpecialLocalVariables(); + outlineDataCollector.AddInstructions( ( addTabs ? "\t\t\t" : "" ) + "o.Emission = " + outlineColor + ";" ); + if( alphaPort.Visible ) + { + if( m_currentAlphaMode == OutlineAlphaModes.Masked ) + { + float maskClipValue = 0.5f; + + if( masterNode != null ) + maskClipValue = masterNode.OpacityMaskClipValue; + + if( masterNode.InlineOpacityMaskClipValue.IsValid ) + { + RangedFloatNode fnode = UIUtils.GetNode( masterNode.InlineOpacityMaskClipValue.NodeId ) as RangedFloatNode; + if( fnode != null ) + { + outlineDataCollector.AddToProperties( fnode.UniqueId, fnode.GetPropertyValue(), fnode.OrderIndex ); + outlineDataCollector.AddToUniforms( fnode.UniqueId, fnode.GetUniformValue() ); + } + else + { + IntNode inode = UIUtils.GetNode( masterNode.InlineOpacityMaskClipValue.NodeId ) as IntNode; + outlineDataCollector.AddToProperties( inode.UniqueId, inode.GetPropertyValue(), inode.OrderIndex ); + outlineDataCollector.AddToUniforms( inode.UniqueId, inode.GetUniformValue() ); + } + } + else + { + outlineDataCollector.AddToProperties( -1, string.Format( IOUtils.MaskClipValueProperty, OpacityMaskClipValueStr, maskClipValue ), -1 ); + outlineDataCollector.AddToUniforms( -1, string.Format( IOUtils.MaskClipValueUniform, maskClipValue ) ); + } + + outlineDataCollector.AddInstructions( ( addTabs ? "\n\t\t\t" : "" ) + "clip( " + alphaValue + " - " + masterNode.InlineOpacityMaskClipValue.GetValueOrProperty( IOUtils.MaskClipValueName, false ) + " );" ); + } + else + { + outlineDataCollector.AddInstructions( ( addTabs ? "\n\t\t\t" : "" ) + "o.Alpha = " + alphaValue + ";" ); + } + } + + if( outlineDataCollector.UsingWorldNormal ) + outlineDataCollector.AddInstructions( ( addTabs ? "\n\t\t\t" : "" ) + "o.Normal = float3(0,0,-1);" ); + + //Moved vertex port code generation from ln.227 to this after fragment ones + //to correctly include vertex instructions generated by them + UIUtils.CurrentWindow.OutsideGraph.ResetNodesLocalVariables(); + outlineDataCollector.PortCategory = MasterNodePortCategory.Vertex; + string outlineWidth = vertexPort.GenerateShaderForOutput( ref outlineDataCollector, vertexPort.DataType, true, true ); + + + outlineDataCollector.AddToVertexLocalVariables( UniqueId, PrecisionType.Float, vertexPort.DataType, "outlineVar", outlineWidth ); + + outlineDataCollector.AddVertexInstruction( outlineDataCollector.SpecialLocalVariables, UniqueId, false ); + outlineDataCollector.ClearSpecialLocalVariables(); + + outlineDataCollector.AddVertexInstruction( outlineDataCollector.VertexLocalVariables, UniqueId, false ); + outlineDataCollector.ClearVertexLocalVariables(); + + outlineDataCollector.AddASEMacros(); + + // need to check whether this breaks other outputs or not + UIUtils.CurrentWindow.OutsideGraph.ResetNodesLocalVariables(); + + if( masterNode != null ) + { + masterNode.CheckSamplingMacrosFlag(); + //masterNode.AdditionalIncludes.AddToDataCollector( ref outlineDataCollector ); + //masterNode.AdditionalPragmas.AddToDataCollector( ref outlineDataCollector ); + //masterNode.AdditionalDefines.AddToDataCollector( ref outlineDataCollector ); + if( !masterNode.CustomShadowCaster ) + masterNode.AdditionalDirectives.AddAllToDataCollector( ref outlineDataCollector ); + } + + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.InputList = outlineDataCollector.InputList; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.Inputs = outlineDataCollector.Inputs; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.DirtyInput = outlineDataCollector.DirtyInputs; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.Includes = outlineDataCollector.Includes; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.Pragmas = outlineDataCollector.Pragmas; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.Defines = outlineDataCollector.Defines; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.StandardAdditionalDirectives = outlineDataCollector.StandardAdditionalDirectives; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.Uniforms = outlineDataCollector.Uniforms; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.InstancedProperties = outlineDataCollector.InstancedProperties; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.GrabPasses = outlineDataCollector.GrabPass; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.UniformList = outlineDataCollector.UniformsList; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.InstancedPropertiesList = outlineDataCollector.InstancedPropertiesList; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.VertexData = outlineDataCollector.VertexData; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.Instructions = outlineDataCollector.Instructions; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.Functions = outlineDataCollector.Functions; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.LocalFunctions = outlineDataCollector.LocalFunctions; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.OutlineCullMode = m_cullMode; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.ZTestMode = m_zTestMode; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.ZWriteMode = m_zWriteMode; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.OffsetMode = m_currentSelectedMode; + UIUtils.CurrentWindow.OutsideGraph.CurrentStandardSurface.OutlineHelper.CustomNoFog = m_noFog; + dataCollector.CustomOutlineSelectedAlpha = (int)m_currentAlphaMode; + + for( int i = 0; i < outlineDataCollector.PropertiesList.Count; i++ ) + { + dataCollector.AddToProperties( UniqueId, outlineDataCollector.PropertiesList[ i ].PropertyName, outlineDataCollector.PropertiesList[ i ].OrderIndex ); + } + + dataCollector.UsingInternalData = dataCollector.UsingInternalData || outlineDataCollector.UsingInternalData; + UIUtils.CurrentWindow.OutsideGraph.ResetNodesLocalVariablesIfNot( MasterNodePortCategory.Vertex ); + return "0"; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_currentSelectedMode = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_noFog = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > 14202 ) + m_currentAlphaMode = (OutlineAlphaModes)Enum.Parse( typeof( OutlineAlphaModes ), GetCurrentParam( ref nodeParams ) ); + + if( UIUtils.CurrentShaderVersion() > 14302 ) + { + m_zWriteMode = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_zTestMode = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 15304 ) + { + m_cullMode = (CullMode)Enum.Parse( typeof( CullMode ), GetCurrentParam( ref nodeParams ) ); + } + + SetAdditonalTitleText( string.Format( Constants.SubTitleTypeFormatStr, AvailableOutlineModes[ m_currentSelectedMode ] ) ); + UpdatePorts(); + CheckAlphaPortVisibility(); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentSelectedMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_noFog ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentAlphaMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_zWriteMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_zTestMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_cullMode ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/OutlineNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/OutlineNode.cs.meta new file mode 100644 index 0000000..60f49a8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/OutlineNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 24f267627c002964badad2901309c96a +timeCreated: 1501161489 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/PosVertexDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/PosVertexDataNode.cs new file mode 100644 index 0000000..a71ed20 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/PosVertexDataNode.cs @@ -0,0 +1,138 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Vertex Position", "Vertex Data", "Vertex position vector in object space, can be used in both local vertex offset and fragment outputs" )] + public sealed class PosVertexDataNode : VertexDataNode + { + private const string PropertyLabel = "Size"; + private readonly string[] SizeLabels = { "XYZ", "XYZW" }; + + [SerializeField] + private int m_sizeOption = 0; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentVertexData = "vertex"; + ChangeOutputProperties( 0, "XYZ", WirePortDataType.FLOAT3 ); + m_drawPreviewAsSphere = true; + m_outputPorts[ 4 ].Visible = false; + m_hasLeftDropdown = true; + m_autoWrapProperties = true; + m_previewShaderGUID = "a5c14f759dd021b4b8d4b6eeb85ac227"; + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_sizeOption = m_upperLeftWidget.DrawWidget( this, m_sizeOption, SizeLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePorts(); + } + } + + public override void DrawProperties() + { + EditorGUI.BeginChangeCheck(); + m_sizeOption = EditorGUILayoutPopup( PropertyLabel, m_sizeOption, SizeLabels ); + if ( EditorGUI.EndChangeCheck() ) + { + UpdatePorts(); + } + } + + void UpdatePorts() + { + if ( m_sizeOption == 0 ) + { + ChangeOutputProperties( 0, SizeLabels[ 0 ], WirePortDataType.FLOAT3, false ); + m_outputPorts[ 4 ].Visible = false; + } + else + { + ChangeOutputProperties( 0, SizeLabels[ 1 ], WirePortDataType.FLOAT4, false ); + m_outputPorts[ 4 ].Visible = true; + } + } + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + + if ( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + string vertexPos = dataCollector.TemplateDataCollectorInstance.GetVertexPosition( ( m_sizeOption == 0 ) ? WirePortDataType.FLOAT3 : WirePortDataType.FLOAT4, CurrentPrecisionType ); + return GetOutputVectorItem( 0, outputId, vertexPos ); + } + + + if ( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + + WirePortDataType sizeType = m_sizeOption == 0 ? WirePortDataType.FLOAT3 : WirePortDataType.FLOAT4; + + string vertexPosition = GeneratorUtils.GenerateVertexPosition( ref dataCollector, UniqueId, sizeType ); + return GetOutputVectorItem( 0, outputId, vertexPosition ); + + //if ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + //{ + // string vertexVar = base.GenerateShaderForOutput( 0, ref dataCollector, ignoreLocalVar ); + // if ( outputId != 0 ) + // { + // return GetOutputVectorItem( 0, outputId, vertexVar ); + // } + // else if ( m_sizeOption == 0 ) + // { + // vertexVar += ".xyz"; + // } + + // return vertexVar; + //} + //else + //{ + + // string vertexVar = GeneratorUtils.GenerateVertexPositionOnFrag( ref dataCollector, UniqueId, m_currentPrecisionType ); + // if ( outputId != 0 ) + // { + // return GetOutputVectorItem( 0, outputId, vertexVar ); + // } + // else if ( m_sizeOption == 0 ) + // { + // vertexVar += ".xyz"; + // } + // return GetOutputVectorItem( 0, outputId, vertexVar ); + //} + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if ( UIUtils.CurrentShaderVersion() > 7101 ) + { + m_sizeOption = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + UpdatePorts(); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_sizeOption ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/PosVertexDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/PosVertexDataNode.cs.meta new file mode 100644 index 0000000..9ff223e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/PosVertexDataNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: fc77801277f0faf4ca0be33f565b5604 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentSignVertexDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentSignVertexDataNode.cs new file mode 100644 index 0000000..f9beb05 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentSignVertexDataNode.cs @@ -0,0 +1,23 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Vertex Tangent Sign", "Vertex Data", "Vertex tangent sign in object space, return the W value of tangent vector that contains only the sign of the tangent" )] + public sealed class TangentSignVertexDataNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputVectorPorts( WirePortDataType.FLOAT, "Sign" ); + m_drawPreviewAsSphere = true; + m_previewShaderGUID = "f5466d126f4bb1f49917eac88b1cb6af"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + return GeneratorUtils.GenerateVertexTangentSign( ref dataCollector, UniqueId, CurrentPrecisionType ); ; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentSignVertexDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentSignVertexDataNode.cs.meta new file mode 100644 index 0000000..c07ffb6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentSignVertexDataNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1f79f23d5c10c9e4fb6a59c1ef70f6fc +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentVertexDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentVertexDataNode.cs new file mode 100644 index 0000000..da6d25f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentVertexDataNode.cs @@ -0,0 +1,120 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Vertex Tangent", "Vertex Data", "Vertex tangent vector in object space, can be used in both local vertex offset and fragment outputs" )] + public sealed class TangentVertexDataNode : VertexDataNode + { + private const string PropertyLabel = "Size"; + private readonly string[] SizeLabels = { "XYZ", "XYZW" }; + + [SerializeField] + private int m_sizeOption = 0; + + private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentVertexData = "tangent"; + ChangeOutputProperties( 0, "XYZ", WirePortDataType.FLOAT3 ); + m_outputPorts[ 4 ].Visible = false; + m_drawPreviewAsSphere = true; + m_hasLeftDropdown = true; + m_previewShaderGUID = "0a44bb521d06d6143a4acbc3602037f8"; + } + + public override void Destroy() + { + base.Destroy(); + m_upperLeftWidget = null; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + EditorGUI.BeginChangeCheck(); + m_sizeOption = m_upperLeftWidget.DrawWidget( this, m_sizeOption, SizeLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePorts(); + } + } + + public override void DrawProperties() + { + EditorGUI.BeginChangeCheck(); + m_sizeOption = EditorGUILayoutPopup( PropertyLabel, m_sizeOption, SizeLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdatePorts(); + } + } + + void UpdatePorts() + { + if( m_sizeOption == 0 ) + { + ChangeOutputProperties( 0, SizeLabels[ 0 ], WirePortDataType.FLOAT3, false ); + m_outputPorts[ 4 ].Visible = false; + } + else + { + ChangeOutputProperties( 0, SizeLabels[ 1 ], WirePortDataType.FLOAT4, false ); + m_outputPorts[ 4 ].Visible = true; + } + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + dataCollector.DirtyNormal = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + string vertexTangent = string.Empty; + if ( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + vertexTangent = dataCollector.TemplateDataCollectorInstance.GetVertexTangent( WirePortDataType.FLOAT4, CurrentPrecisionType ); + if( m_sizeOption == 0 ) + vertexTangent += ".xyz"; + + return GetOutputVectorItem( 0, outputId, vertexTangent ); + } + + if ( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + { + dataCollector.ForceNormal = true; + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + } + + WirePortDataType sizeType = m_sizeOption == 0 ? WirePortDataType.FLOAT3 : WirePortDataType.FLOAT4; + + vertexTangent = GeneratorUtils.GenerateVertexTangent( ref dataCollector, UniqueId, CurrentPrecisionType, sizeType ); + return GetOutputVectorItem( 0, outputId, vertexTangent ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 16100 ) + { + m_sizeOption = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + UpdatePorts(); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_sizeOption ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentVertexDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentVertexDataNode.cs.meta new file mode 100644 index 0000000..2ce6f77 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TangentVertexDataNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b544118f39abfe84581b8249973d52c5 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation.meta new file mode 100644 index 0000000..89948ec --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 518d8e72c2385b9488817fee5368f56c +folderAsset: yes +timeCreated: 1482150091 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/DistanceBasedTessNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/DistanceBasedTessNode.cs new file mode 100644 index 0000000..c49df07 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/DistanceBasedTessNode.cs @@ -0,0 +1,30 @@ + +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Distance-based Tessellation", "Miscellaneous", "Calculates tessellation based on distance from camera" )] + public sealed class DistanceBasedTessNode : TessellationParentNode + { + private const string FunctionBody = "UnityDistanceBasedTess( v0.vertex, v1.vertex, v2.vertex, {0},{1},{2})"; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false,"Factor"); + AddInputPort( WirePortDataType.FLOAT, false, "Min Dist" ); + AddInputPort( WirePortDataType.FLOAT, false, "Max Dist" ); + AddOutputPort( WirePortDataType.FLOAT4, Constants.EmptyPortValue ); + } + + protected override string BuildTessellationFunction( ref MasterNodeDataCollector dataCollector ) + { + return string.Format( FunctionBody, + m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ), + m_inputPorts[ 2 ].GeneratePortInstructions( ref dataCollector ), + m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/DistanceBasedTessNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/DistanceBasedTessNode.cs.meta new file mode 100644 index 0000000..18016c1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/DistanceBasedTessNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5a83fb450d164d34bb756f46b3f4290e +timeCreated: 1482150091 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthCullTessNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthCullTessNode.cs new file mode 100644 index 0000000..48c5db0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthCullTessNode.cs @@ -0,0 +1,27 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Edge Length Tessellation With Cull", "Miscellaneous", "Tessellation level computed based on triangle edge length on the screen with patch frustum culling" )] + public sealed class EdgeLengthCullTessNode : TessellationParentNode + { + private const string FunctionBody = "UnityEdgeLengthBasedTessCull( v0.vertex, v1.vertex, v2.vertex, {0},{1})"; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "Edge Length" ); + AddInputPort( WirePortDataType.FLOAT, false, "Max Disp." ); + AddOutputPort( WirePortDataType.FLOAT4, Constants.EmptyPortValue ); + } + + protected override string BuildTessellationFunction( ref MasterNodeDataCollector dataCollector ) + { + return string.Format( FunctionBody, + m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ), + m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthCullTessNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthCullTessNode.cs.meta new file mode 100644 index 0000000..20d4dd2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthCullTessNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4b09c64ce2fd06a4cb4036d8cc0f8b2a +timeCreated: 1482150962 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthTessNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthTessNode.cs new file mode 100644 index 0000000..f4905bf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthTessNode.cs @@ -0,0 +1,23 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Edge Length Tessellation", "Miscellaneous", "Tessellation level computed based on triangle edge length on the screen" )] + public sealed class EdgeLengthTessNode : TessellationParentNode + { + private const string FunctionBody = "UnityEdgeLengthBasedTess (v0.vertex, v1.vertex, v2.vertex, {0})"; + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddInputPort( WirePortDataType.FLOAT, false, "Edge Length" ); + AddOutputPort( WirePortDataType.FLOAT4, Constants.EmptyPortValue ); + } + + protected override string BuildTessellationFunction( ref MasterNodeDataCollector dataCollector ) + { + return string.Format( FunctionBody, m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthTessNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthTessNode.cs.meta new file mode 100644 index 0000000..2c936ef --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/EdgeLengthTessNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: abe3e8fa4d49c9742a95ac801fd14d7d +timeCreated: 1482150962 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/TessellationParentNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/TessellationParentNode.cs new file mode 100644 index 0000000..be14feb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/TessellationParentNode.cs @@ -0,0 +1,29 @@ +namespace AmplifyShaderEditor +{ + public class TessellationParentNode : ParentNode + { + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_useInternalPortData = true; + } + + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( dataCollector.PortCategory != MasterNodePortCategory.Tessellation ) + { + UIUtils.ShowMessage( UniqueId, m_nodeAttribs.Name + " can only be used on Master Node Tessellation port" ); + return "(-1)"; + } + + return BuildTessellationFunction( ref dataCollector ); + } + + protected virtual string BuildTessellationFunction( ref MasterNodeDataCollector dataCollector ) + { + return string.Empty; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/TessellationParentNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/TessellationParentNode.cs.meta new file mode 100644 index 0000000..0799224 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/Tessellation/TessellationParentNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 79c24faef1fec884d937e74bdc9209da +timeCreated: 1482162387 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoord1VertexDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoord1VertexDataNode.cs new file mode 100644 index 0000000..5297ac7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoord1VertexDataNode.cs @@ -0,0 +1,16 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "[VS] Vertex TexCoord1", "Vertex Data", "Second set of vertex texture coordinates. Only works on Vertex Shaders ports ( p.e. Local Vertex Offset Port )." ,null,UnityEngine.KeyCode.None,true,true, "[VS] Vertex TexCoord" )] + public sealed class TexCoord1VertexDataNode : VertexDataNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentVertexData = "texcoord1"; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoord1VertexDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoord1VertexDataNode.cs.meta new file mode 100644 index 0000000..6852927 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoord1VertexDataNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ebd7eb3a7f6149e4e9dacbcda2d8089f +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoordVertexDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoordVertexDataNode.cs new file mode 100644 index 0000000..e6e0cd8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoordVertexDataNode.cs @@ -0,0 +1,241 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Vertex TexCoord", "Vertex Data", "Vertex texture coordinates, can be used in both local vertex offset and fragment outputs", tags: "uv" )] + public sealed class TexCoordVertexDataNode : VertexDataNode + { + [SerializeField] + private int m_texcoordSize = 2; + + [SerializeField] + private int m_index = 0; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentVertexData = "texcoord"; + ChangeOutputProperties( 0, "UV", WirePortDataType.FLOAT2, false ); + m_outputPorts[ 1 ].Name = "U"; + m_outputPorts[ 2 ].Name = "V"; + m_outputPorts[ 3 ].Visible = false; + m_outputPorts[ 4 ].Visible = false; + m_outputPorts[ 3 ].Name = "W"; + m_outputPorts[ 4 ].Name = "T"; + m_autoWrapProperties = true; + m_hasLeftDropdown = true; + m_previewShaderGUID = "6c1bee77276896041bbb73b1b9e7f8ac"; + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_texcoordSize = EditorGUILayoutIntPopup( Constants.AvailableUVSizesLabel, m_texcoordSize, Constants.AvailableUVSizesStr, Constants.AvailableUVSizes ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateOutput(); + } + + EditorGUI.BeginChangeCheck(); + m_index = EditorGUILayoutIntPopup( Constants.AvailableUVChannelLabel, m_index, Constants.AvailableUVSetsStr, Constants.AvailableUVChannels ); + if( EditorGUI.EndChangeCheck() ) + { + m_currentVertexData = ( m_index == 0 ) ? "texcoord" : "texcoord" + Constants.AvailableUVChannelsStr[ m_index ]; + } + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( m_dropdownEditing ) + { + EditorGUI.BeginChangeCheck(); + m_texcoordSize = EditorGUIIntPopup( m_dropdownRect, m_texcoordSize, Constants.AvailableUVSizesStr, Constants.AvailableUVSizes, UIUtils.PropertyPopUp ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateOutput(); + DropdownEditing = false; + } + } + } + + private void UpdateOutput() + { + if( m_texcoordSize == 3 ) + { + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT3, false ); + m_outputPorts[ 0 ].Name = "UVW"; + m_outputPorts[ 3 ].Visible = true; + m_outputPorts[ 4 ].Visible = false; + } + else if( m_texcoordSize == 4 ) + { + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false ); + m_outputPorts[ 0 ].Name = "UVWT"; + m_outputPorts[ 3 ].Visible = true; + m_outputPorts[ 4 ].Visible = true; + } + else + { + m_texcoordSize = 2; + m_outputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT2, false ); + m_outputPorts[ 0 ].Name = "UV"; + m_outputPorts[ 3 ].Visible = false; + m_outputPorts[ 4 ].Visible = false; + } + m_sizeIsDirty = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( dataCollector.IsTemplate ) + { + if( !dataCollector.TemplateDataCollectorInstance.HasUV( m_index ) ) + { + dataCollector.TemplateDataCollectorInstance.RegisterUV( m_index, m_outputPorts[ 0 ].DataType ); + } + + string result = string.Empty; + if( dataCollector.TemplateDataCollectorInstance.GetCustomInterpolatedData( TemplateHelperFunctions.IntToUVChannelInfo[ m_index ], m_outputPorts[ 0 ].DataType, PrecisionType.Float, ref result, false, dataCollector.PortCategory ) ) + { + return GetOutputVectorItem( 0, outputId, result ); + } + else + if( dataCollector.TemplateDataCollectorInstance.HasUV( m_index ) ) + { + InterpDataHelper info = dataCollector.TemplateDataCollectorInstance.GetUVInfo( m_index ); + if( outputId == 0 ) + { + return dataCollector.TemplateDataCollectorInstance.GetUVName( m_index, m_outputPorts[ 0 ].DataType ); + } + else if( outputId <= TemplateHelperFunctions.DataTypeChannelUsage[ info.VarType ] ) + { + return GetOutputVectorItem( 0, outputId, info.VarName ); + } + Debug.LogWarning( "Attempting to access inexisting UV channel" ); + } + else + { + Debug.LogWarning( "Attempting to access non-registered UV" ); + } + return "0"; + } + + if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + { + if( m_texcoordSize > 2 ) + dataCollector.UsingHigherSizeTexcoords = true; + } + + WirePortDataType size = (WirePortDataType)( 1 << ( m_texcoordSize + 1 ) ); + string texcoords = GeneratorUtils.GenerateAutoUVs( ref dataCollector, UniqueId, m_index, null, size ); + return GetOutputVectorItem( 0, outputId, texcoords ); + } + + /// + /// Generates UV properties and uniforms and returns the varible name to use in the fragment shader + /// + /// + /// + /// + /// frag variable name + static public string GenerateFragUVs( ref MasterNodeDataCollector dataCollector, int uniqueId, int index, string propertyName = null, WirePortDataType size = WirePortDataType.FLOAT2 ) + { + string dummyPropUV = "_texcoord" + ( index > 0 ? ( index + 1 ).ToString() : "" ); + string dummyUV = "uv" + ( index > 0 ? ( index + 1 ).ToString() : "" ) + dummyPropUV; + + dataCollector.AddToProperties( uniqueId, "[HideInInspector] " + dummyPropUV + "( \"\", 2D ) = \"white\" {}", 100 ); + dataCollector.AddToInput( uniqueId, dummyUV, size ); + + string result = Constants.InputVarStr + "." + dummyUV; + if( !string.IsNullOrEmpty( propertyName ) ) + { + dataCollector.AddToUniforms( uniqueId, "uniform float4 " + propertyName + "_ST;" ); + dataCollector.AddToLocalVariables( uniqueId, PrecisionType.Float, size, "uv" + propertyName, result + " * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw" ); + result = "uv" + propertyName; + } + + return result; + } + + static public string GenerateVertexUVs( ref MasterNodeDataCollector dataCollector, int uniqueId, int index, string propertyName = null, WirePortDataType size = WirePortDataType.FLOAT2 ) + { + + string result = Constants.VertexShaderInputStr + ".texcoord"; + if( index > 0 ) + { + result += index.ToString(); + } + + switch( size ) + { + default: + case WirePortDataType.FLOAT2: + { + result += ".xy"; + } + break; + case WirePortDataType.FLOAT3: + { + result += ".xyz"; + } + break; + case WirePortDataType.FLOAT4: break; + } + + if( !string.IsNullOrEmpty( propertyName ) ) + { + dataCollector.AddToUniforms( uniqueId, "uniform float4 " + propertyName + "_ST;" ); + dataCollector.AddToVertexLocalVariables( uniqueId, UIUtils.WirePortToCgType( size ) + " uv" + propertyName + " = " + Constants.VertexShaderInputStr + ".texcoord" + ( index > 0 ? index.ToString() : string.Empty ) + " * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw;" ); + result = "uv" + propertyName; + } + + return result; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 2502 ) + { + m_index = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 5111 ) + { + m_texcoordSize = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + UpdateOutput(); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_index ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_texcoordSize ); + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + if( dataCollector.IsTemplate ) + { + dataCollector.TemplateDataCollectorInstance.SetUVUsage( m_index, m_texcoordSize ); + } + else if( m_index > 3 ) + { + dataCollector.AddCustomAppData( string.Format( TemplateHelperFunctions.TexUVFullSemantic, m_index ) ); + } + } + + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoordVertexDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoordVertexDataNode.cs.meta new file mode 100644 index 0000000..54fd39f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/TexCoordVertexDataNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b865968ce22b9d949993e5e60126eb11 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexBinormalNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexBinormalNode.cs new file mode 100644 index 0000000..70a7d7b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexBinormalNode.cs @@ -0,0 +1,48 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Vertex Binormal World +// Donated by Community Member Kebrus + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "World Bitangent", "Surface Data", "Per pixel world bitangent vector", null, KeyCode.None, true, false, null, null, "kebrus" )] + public sealed class VertexBinormalNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputVectorPorts( WirePortDataType.FLOAT3, "XYZ" ); + m_drawPreviewAsSphere = true; + m_previewShaderGUID = "76873532ab67d2947beaf07151383cbe"; + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData, ref dataCollector ); + dataCollector.DirtyNormal = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( dataCollector.IsTemplate ) + return GetOutputVectorItem( 0, outputId, dataCollector.TemplateDataCollectorInstance.GetWorldBinormal( CurrentPrecisionType ) ); + + if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + { + dataCollector.ForceNormal = true; + + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + } + + string worldBitangent = GeneratorUtils.GenerateWorldBitangent( ref dataCollector, UniqueId ); + + return GetOutputVectorItem( 0, outputId, worldBitangent ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexBinormalNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexBinormalNode.cs.meta new file mode 100644 index 0000000..b990b9a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexBinormalNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8ae297dac4e208f4e86c8f7a022fc5bd +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexColorNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexColorNode.cs new file mode 100644 index 0000000..53ef576 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexColorNode.cs @@ -0,0 +1,47 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Vertex Color", "Vertex Data", "Vertex color interpolated on fragment" )] + public sealed class VertexColorNode : VertexDataNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentVertexData = "color"; + m_outputPorts[ 0 ].Name = "RGBA"; + ConvertFromVectorToColorPorts(); + m_drawPreviewAsSphere = true; + m_previewShaderGUID = "ca1d22db6470c5f4d9f93a9873b4f5bc"; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + string color = dataCollector.TemplateDataCollectorInstance.GetVertexColor( CurrentPrecisionType ); + return GetOutputColorItem( 0, outputId, color ); + } + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + return base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + } + else + { + dataCollector.AddToInput( UniqueId, SurfaceInputs.COLOR ); + string result = Constants.InputVarStr + "." + Constants.ColorVariable; + switch( outputId ) + { + case 1: result += ".r"; break; + case 2: result += ".g"; break; + case 3: result += ".b"; break; + case 4: result += ".a"; break; + } + return result; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexColorNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexColorNode.cs.meta new file mode 100644 index 0000000..ac1eee7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexColorNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6271f602b9ab61e4c9a96a91e473c1e0 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexDataNode.cs new file mode 100644 index 0000000..9fa8cff --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexDataNode.cs @@ -0,0 +1,50 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + //public enum VertexData + //{ + // vertex = 0, + // tangent, + // normal, + // texcoord, + // texcoord1, + // color + //} + + [Serializable] + public class VertexDataNode : ParentNode + { + [SerializeField] + protected string m_currentVertexData; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_currentVertexData = "vertex"; + +// Type type = typeof( StandardSurfaceOutputNode ); + //m_restictions.AddPortRestriction( type, 0 ); + //m_restictions.AddPortRestriction( type, 2 ); + //m_restictions.AddPortRestriction( type, 3 ); + //m_restictions.AddPortRestriction( type, 4 ); + //m_restictions.AddPortRestriction( type, 5 ); + //m_restictions.AddPortRestriction( type, 6 ); + //m_restictions.AddPortRestriction( type, 7 ); + //m_restictions.AddPortRestriction( type, 8 ); + //m_restictions.AddPortRestriction( type, 9 ); + //m_restictions.AddPortRestriction( type, 10 ); + AddOutputVectorPorts( WirePortDataType.FLOAT4, "Out" ); + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar ); + return GetOutputVectorItem( 0, outputId, Constants.VertexShaderInputStr + "." + m_currentVertexData ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexDataNode.cs.meta new file mode 100644 index 0000000..66737ec --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexDataNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e5f8fa23e49e4be478b283a704459767 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexTangentNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexTangentNode.cs new file mode 100644 index 0000000..b4e6064 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexTangentNode.cs @@ -0,0 +1,50 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Vertex Tangent World +// Donated by Community Member Kebrus + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "World Tangent", "Surface Data", "Per pixel world tangent vector", null, KeyCode.None, true, false, null, null, "kebrus" )] + public sealed class VertexTangentNode : ParentNode + { + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputVectorPorts( WirePortDataType.FLOAT3, "XYZ" ); + m_drawPreviewAsSphere = true; + m_previewShaderGUID = "61f0b80493c9b404d8c7bf56d59c3f81"; + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + base.PropagateNodeData( nodeData , ref dataCollector ); + dataCollector.DirtyNormal = true; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if ( dataCollector.IsTemplate ) + { + return GetOutputVectorItem( 0, outputId, dataCollector.TemplateDataCollectorInstance.GetWorldTangent( CurrentPrecisionType ) ); + } + + if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + { + dataCollector.ForceNormal = true; + + dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType ); + dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + } + + string worldTangent = GeneratorUtils.GenerateWorldTangent( ref dataCollector, UniqueId ); + + return GetOutputVectorItem( 0, outputId, worldTangent ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexTangentNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexTangentNode.cs.meta new file mode 100644 index 0000000..d3f0bbf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexTangentNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3aca1dfe55df44d4cbaf99d5a40f7470 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexToFragmentNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexToFragmentNode.cs new file mode 100644 index 0000000..68de3f0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexToFragmentNode.cs @@ -0,0 +1,187 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +// +// Custom Node Vertex To Fragment +// Donated by Jason Booth - http://u3d.as/DND + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [System.Serializable] + [NodeAttributes( "Vertex To Fragment", "Miscellaneous", "Pass vertex data to the pixel shader", null, KeyCode.None, true, false, null, null, "Jason Booth - http://u3d.as/DND" )] + public sealed class VertexToFragmentNode : SingleInputOp + { + private const string DisabledInterpolatorMsg = "No Interpolation option cannot be used over Standard Surface type as we must be able to directly control interpolators registry, which does't happen over this shader type. Please disable it."; + private const string NoInterpolationUsageMsg = "No interpolation is performed when passing value from vertex to fragment during rasterization. Please note this option will not work across all API's and can even throw compilation errors on some of them ( p.e. Metal and GLES 2.0 )"; + + private const string SampleInfoMessage = "Interpolate at sample location rather than at the pixel center. This causes the pixel shader to execute per-sample rather than per-pixel. Only available in shader model 4.1 or higher"; + + [SerializeField] + private bool m_noInterpolation; + + [SerializeField] + private bool m_sample; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_inputPorts[ 0 ].AddPortForbiddenTypes( WirePortDataType.FLOAT3x3, + WirePortDataType.FLOAT4x4, + WirePortDataType.SAMPLER1D, + WirePortDataType.SAMPLER2D, + WirePortDataType.SAMPLER3D, + WirePortDataType.SAMPLERCUBE, + WirePortDataType.SAMPLER2DARRAY, + WirePortDataType.SAMPLERSTATE ); + m_inputPorts[ 0 ].Name = "(VS) In"; + m_outputPorts[ 0 ].Name = "Out"; + m_useInternalPortData = false; + m_autoWrapProperties = true; + m_errorMessageTypeIsError = NodeMessageType.Warning; + m_previewShaderGUID = "74e4d859fbdb2c0468de3612145f4929"; + } + + public override void DrawProperties() + { + base.DrawProperties(); + bool isSurface = ContainerGraph.IsStandardSurface; + EditorGUI.BeginDisabledGroup( isSurface && !m_noInterpolation ); + m_noInterpolation = EditorGUILayoutToggle( "No Interpolation" , m_noInterpolation ); + EditorGUI.EndDisabledGroup(); + if( m_noInterpolation ) + { + if( isSurface ) + { + EditorGUILayout.HelpBox( DisabledInterpolatorMsg, MessageType.Warning ); + } else + { + EditorGUILayout.HelpBox( NoInterpolationUsageMsg, MessageType.Info ); + } + } + + EditorGUI.BeginDisabledGroup( isSurface && !m_sample ); + m_sample = EditorGUILayoutToggle( "Sample" , m_sample ); + EditorGUI.EndDisabledGroup(); + if( m_sample ) + EditorGUILayout.HelpBox( SampleInfoMessage , MessageType.Info ); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + m_showErrorMessage = ContainerGraph.IsStandardSurface && m_noInterpolation || + ContainerGraph.IsStandardSurface && m_sample; + } + + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) ) + return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ); + + bool noInterpolationFlag = dataCollector.IsTemplate ? m_noInterpolation : false; + bool sampleFlag = dataCollector.IsTemplate ? m_sample : false; + string varName = GenerateInputInVertex( ref dataCollector, 0, "vertexToFrag" + OutputId,true, noInterpolationFlag, sampleFlag ); + m_outputPorts[ 0 ].SetLocalValue( varName, dataCollector.PortCategory ); + + return varName; + + ////TEMPLATES + //if( dataCollector.IsTemplate ) + //{ + // if( !dataCollector.IsFragmentCategory ) + // return m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + // string varName = "vertexToFrag" + OutputId; + // if( dataCollector.TemplateDataCollectorInstance.HasCustomInterpolatedData( varName ) ) + // return varName; + + // MasterNodePortCategory category = dataCollector.PortCategory; + // dataCollector.PortCategory = MasterNodePortCategory.Vertex; + // bool dirtyVertexVarsBefore = dataCollector.DirtyVertexVariables; + // ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Vertex ); + + // string data = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + + // dataCollector.PortCategory = category; + // if( !dirtyVertexVarsBefore && dataCollector.DirtyVertexVariables ) + // { + // dataCollector.AddVertexInstruction( dataCollector.VertexLocalVariables, UniqueId, false ); + // dataCollector.ClearVertexLocalVariables(); + // ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Vertex ); + // } + + // ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Fragment ); + + // dataCollector.TemplateDataCollectorInstance.RegisterCustomInterpolatedData( varName, m_inputPorts[ 0 ].DataType, m_currentPrecisionType, data ); + // //return varName; + + // m_outputPorts[ 0 ].SetLocalValue( varName ); + // return m_outputPorts[ 0 ].LocalValue; + //} + + ////SURFACE + //{ + // if( !dataCollector.IsFragmentCategory ) + // { + // return m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + // } + + // if( dataCollector.TesselationActive ) + // { + // UIUtils.ShowMessage( "Unable to use Vertex to Frag when Tessellation is active" ); + // return m_outputPorts[ 0 ].ErrorValue; + // } + + + // string interpName = "data" + OutputId; + // dataCollector.AddToInput( UniqueId, interpName, m_inputPorts[ 0 ].DataType, m_currentPrecisionType ); + + // MasterNodePortCategory portCategory = dataCollector.PortCategory; + // dataCollector.PortCategory = MasterNodePortCategory.Vertex; + + // bool dirtyVertexVarsBefore = dataCollector.DirtyVertexVariables; + + // ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Vertex ); + + // string vertexVarValue = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector ); + // dataCollector.AddLocalVariable( UniqueId, Constants.VertexShaderOutputStr + "." + interpName, vertexVarValue + ";" ); + + // dataCollector.PortCategory = portCategory; + + // if( !dirtyVertexVarsBefore && dataCollector.DirtyVertexVariables ) + // { + // dataCollector.AddVertexInstruction( dataCollector.VertexLocalVariables, UniqueId, false ); + // dataCollector.ClearVertexLocalVariables(); + // ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Vertex ); + // } + + // ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Fragment ); + + // //return Constants.InputVarStr + "." + interpName; + + // m_outputPorts[ 0 ].SetLocalValue( Constants.InputVarStr + "." + interpName ); + // return m_outputPorts[ 0 ].LocalValue; + //} + } + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 18707 ) + m_noInterpolation = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + + if( UIUtils.CurrentShaderVersion() > 18808 ) + m_sample = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_noInterpolation ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_sample ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexToFragmentNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexToFragmentNode.cs.meta new file mode 100644 index 0000000..0131f74 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Nodes/Vertex/VertexToFragmentNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9ecea5c13558ad4499dd4bc558670b8e +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/PreMadeShaders.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/PreMadeShaders.cs new file mode 100644 index 0000000..e6fd5c6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/PreMadeShaders.cs @@ -0,0 +1,47 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; + +using System.Collections.Generic; +namespace AmplifyShaderEditor +{ + public class PreMadeShaders + { + public static readonly string FlatColorSequenceId = "Flat Color"; + private Dictionary m_actionLib; + public PreMadeShaders() + { + m_actionLib = new Dictionary(); + ActionSequence sequence = new ActionSequence( FlatColorSequenceId ); + sequence.AddToSequence( new CreateNodeActionData( 1, typeof( ColorNode ), new Vector2( -250, 125 ) ) ); + sequence.AddToSequence( new CreateConnectionActionData( 0, 4, 1, 0 ) ); + m_actionLib.Add( sequence.Name, sequence ); + } + + public ActionSequence GetSequence( string name ) + { + if ( m_actionLib.ContainsKey( name ) ) + { + return m_actionLib[ name ]; + } + return null; + } + + public void Destroy() + { + var items = m_actionLib.GetEnumerator(); + while ( items.MoveNext() ) + { + items.Current.Value.Destroy(); + } + m_actionLib.Clear(); + m_actionLib = null; + } + + public ActionSequence FlatColorSequence + { + get { return m_actionLib[ FlatColorSequenceId ]; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/PreMadeShaders.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/PreMadeShaders.cs.meta new file mode 100644 index 0000000..745f638 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/PreMadeShaders.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b4e28cbcd41f3b04ca36fc1b34d2c10f +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates.meta new file mode 100644 index 0000000..d2ecd46 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c1807893b16b7724e840f3d8099a6394 +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs new file mode 100644 index 0000000..fb4d756 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs @@ -0,0 +1,31 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateAdditionalDefinesHelper : TemplateAdditionalParentHelper + { + public TemplateAdditionalDefinesHelper() : base( "Additional Defines" ) + { + m_helpBoxMessage = "Please add your defines without the #define keywords"; + } + + public override void AddToDataCollector( ref MasterNodeDataCollector dataCollector, TemplateIncludePragmaContainter nativesContainer ) + { + for( int i = 0; i < m_additionalItems.Count; i++ ) + { + if( !string.IsNullOrEmpty( m_additionalItems[ i ] ) && !nativesContainer.HasDefine( m_additionalItems[ i ] ) ) + dataCollector.AddToDefines( -1, m_additionalItems[ i ] ); + } + + for( int i = 0; i < m_outsideItems.Count; i++ ) + { + if( !string.IsNullOrEmpty( m_outsideItems[ i ] ) && !nativesContainer.HasDefine( m_outsideItems[ i ] ) ) + dataCollector.AddToDefines( -1, m_outsideItems[ i ] ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs.meta new file mode 100644 index 0000000..3194a2a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 35a7fdfdb9a6b0048aa322a9fe58a371 +timeCreated: 1520275148 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs new file mode 100644 index 0000000..28664a8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs @@ -0,0 +1,837 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.IO; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using UnityEditorInternal; + +namespace AmplifyShaderEditor +{ + public enum AdditionalLineType + { + Include, + Define, + Pragma, + Custom + } + + public enum AdditionalContainerOrigin + { + Native, + ShaderFunction, + Custom + } + + + [Serializable] + public class AdditionalDirectiveContainerSaveItem + { + public AdditionalLineType LineType = AdditionalLineType.Include; + public string LineValue = string.Empty; + public bool GUIDToggle = false; + public string GUIDValue = string.Empty; + public AdditionalContainerOrigin Origin = AdditionalContainerOrigin.Custom; + public AdditionalDirectiveContainerSaveItem( AdditionalLineType lineType, string lineValue, bool guidToggle, string guidValue, AdditionalContainerOrigin origin ) + { + LineType = lineType; + LineValue = lineValue; + GUIDToggle = guidToggle; + GUIDValue = guidValue; + Origin = origin; + } + + public AdditionalDirectiveContainerSaveItem( AdditionalDirectiveContainer container ) + { + LineType = container.LineType; + LineValue = container.LineValue; + GUIDToggle = container.GUIDToggle; + GUIDValue = container.GUIDValue; + Origin = container.Origin; + } + } + + [Serializable] + public class AdditionalDirectiveContainer : ScriptableObject + { + public AdditionalLineType LineType = AdditionalLineType.Include; + public string LineValue = string.Empty; + public bool GUIDToggle = false; + public string GUIDValue = string.Empty; + public AdditionalContainerOrigin Origin = AdditionalContainerOrigin.Custom; + public TextAsset LibObject = null; + public string OwnerId = string.Empty; + + public void Init( string ownerId, AdditionalDirectiveContainer item ) + { + LineType = item.LineType; + LineValue = item.LineValue; + GUIDToggle = item.GUIDToggle; + GUIDValue = item.GUIDValue; + Origin = item.Origin; + LibObject = item.LibObject; + OwnerId = ownerId; + } + + public void Init( AdditionalDirectiveContainerSaveItem item ) + { + LineType = item.LineType; + LineValue = item.LineValue; + GUIDToggle = item.GUIDToggle; + GUIDValue = item.GUIDValue; + Origin = item.Origin; + if( GUIDToggle ) + { + LibObject = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( GUIDValue ) ); + } + } + + public void OnDestroy() + { + //Debug.Log( "Destoying directives" ); + LibObject = null; + } + + public string Value + { + get + { + switch( LineType ) + { + case AdditionalLineType.Include: + { + if( GUIDToggle ) + { + string shaderPath = AssetDatabase.GUIDToAssetPath( GUIDValue ); + if( !string.IsNullOrEmpty( shaderPath ) ) + return shaderPath; + } + return LineValue; + } + case AdditionalLineType.Define: return LineValue; + case AdditionalLineType.Pragma: return LineValue; + } + return LineValue; + } + } + + public string FormattedValue + { + get + { + switch( LineType ) + { + case AdditionalLineType.Include: + { + if( GUIDToggle ) + { + string shaderPath = AssetDatabase.GUIDToAssetPath( GUIDValue ); + if( !string.IsNullOrEmpty( shaderPath ) ) + return string.Format( Constants.IncludeFormat, shaderPath ); + } + + return string.Format( Constants.IncludeFormat, LineValue ); + } + case AdditionalLineType.Define: + return string.Format( Constants.DefineFormat, LineValue ); + case AdditionalLineType.Pragma: + return string.Format( Constants.PragmaFormat, LineValue ); + } + return LineValue; + } + } + } + + + + public enum ReordableAction + { + None, + Add, + Remove + } + + [Serializable] + public sealed class TemplateAdditionalDirectivesHelper : TemplateModuleParent + { + private string NativeFoldoutStr = "Native"; + + [SerializeField] + private List m_additionalDirectives = new List(); + + [SerializeField] + private List m_shaderFunctionDirectives = new List(); + + [SerializeField] + private List m_nativeDirectives = new List(); + + [SerializeField] + private int m_nativeDirectivesIndex = -1; + + [SerializeField] + private bool m_nativeDirectivesFoldout = false; + + //ONLY USED BY SHADER FUNCTIONS + // Since AdditionalDirectiveContainer must be a ScriptableObject because of serialization shenanigans it will not serialize the info correctly into the shader function when saving it into a file ( it only saves the id ) + // For it to properly work, each AdditionalDirectiveContainer should be added to the SF asset, but that would make it to have children ( which are seen on the project inspector ) + // Must revisit this later on and come up with a proper solution + [SerializeField] + private List m_directivesSaveItems = new List(); + + + private ReordableAction m_actionType = ReordableAction.None; + private int m_actionIndex = 0; + private ReorderableList m_reordableList = null; + private GUIStyle m_propertyAdjustment; + private UndoParentNode m_currOwner; + private Rect m_nativeRect = Rect.zero; + + public TemplateAdditionalDirectivesHelper( string moduleName ) : base( moduleName ) { } + + //public void AddShaderFunctionItem( AdditionalLineType type, string item ) + //{ + // UpdateShaderFunctionDictionary(); + // string id = type + item; + // if( !m_shaderFunctionDictionary.ContainsKey( id ) ) + // { + // AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance(); + // newItem.LineType = type; + // newItem.LineValue = item; + // newItem.hideFlags = HideFlags.HideAndDontSave; + // m_shaderFunctionDirectives.Add( newItem ); + // m_shaderFunctionDictionary.Add( id, newItem ); + // } + //} + + public void AddShaderFunctionItems( string ownerOutputId, List functionList ) + { + RemoveShaderFunctionItems( ownerOutputId ); + if( functionList.Count > 0 ) + { + for( int i = 0; i < functionList.Count; i++ ) + { + AdditionalDirectiveContainer item = ScriptableObject.CreateInstance(); + item.Init( ownerOutputId, functionList[ i ] ); + m_shaderFunctionDirectives.Add( item ); + } + } + //if( functionList.Count > 0 ) + //{ + + // m_shaderFunctionDirectives.AddRange( functionList ); + //} + } + + public void RemoveShaderFunctionItems( string ownerOutputId/*, List functionList */) + { + List list = m_shaderFunctionDirectives.FindAll( ( x ) => x.OwnerId.Equals( ownerOutputId )); + for( int i = 0; i < list.Count; i++ ) + { + m_shaderFunctionDirectives.Remove( list[ i ] ); + ScriptableObject.DestroyImmediate( list[ i ] ); + } + list.Clear(); + list = null; + + //for( int i = 0; i < functionList.Count; i++ ) + //{ + // m_shaderFunctionDirectives.Remove( functionList[ i ] ); + //} + } + + //public void RemoveShaderFunctionItem( AdditionalLineType type, string item ) + //{ + // m_shaderFunctionDirectives.RemoveAll( x => x.LineType == type && x.LineValue.Equals( item ) ); + //} + + public void AddItems( AdditionalLineType type, List items ) + { + int count = items.Count; + for( int i = 0; i < count; i++ ) + { + AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance(); + newItem.LineType = type; + newItem.LineValue = items[ i ]; + newItem.hideFlags = HideFlags.HideAndDontSave; + m_additionalDirectives.Add( newItem ); + } + UpdateNativeIndex(); + } + + public void AddNativeContainer() + { + if( m_nativeDirectives.Count > 0 ) + { + if( m_additionalDirectives.FindIndex( x => x.Origin.Equals( AdditionalContainerOrigin.Native ) ) == -1 ) + { + AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance(); + newItem.Origin = AdditionalContainerOrigin.Native; + newItem.hideFlags = HideFlags.HideAndDontSave; + //m_additionalDirectives.Add( newItem ); + //m_nativeDirectivesIndex = m_additionalDirectives.Count - 1; + m_additionalDirectives.Insert( 0, newItem ); + m_nativeDirectivesIndex = 0; + } + } + } + + public void FillNativeItems( List nativeItems ) + { + m_nativeDirectives.Clear(); + m_nativeDirectives.AddRange( nativeItems ); + AddNativeContainer(); + } + + void DrawNativeItems() + { + EditorGUILayout.Separator(); + EditorGUI.indentLevel++; + int count = m_nativeDirectives.Count; + for( int i = 0; i < count; i++ ) + { + EditorGUILayout.LabelField( m_nativeDirectives[ i ] ); + } + EditorGUI.indentLevel--; + EditorGUILayout.Separator(); + } + + void DrawNativeItemsRect() + { + int count = m_nativeDirectives.Count; + m_nativeRect.y += EditorGUIUtility.singleLineHeight; + for( int i = 0; i < count; i++ ) + { + EditorGUI.LabelField( m_nativeRect, m_nativeDirectives[ i ] ); + m_nativeRect.y += EditorGUIUtility.singleLineHeight; + } + } + + void DrawButtons() + { + EditorGUILayout.Separator(); + + // Add keyword + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( Constants.PlusMinusButtonLayoutWidth ) ) ) + { + AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance(); + newItem.hideFlags = HideFlags.HideAndDontSave; + m_additionalDirectives.Add( newItem ); + UpdateNativeIndex(); + EditorGUI.FocusTextInControl( null ); + m_isDirty = true; + } + + //Remove keyword + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( Constants.PlusMinusButtonLayoutWidth ) ) ) + { + if( m_additionalDirectives.Count > 0 ) + { + AdditionalDirectiveContainer itemToDelete = m_additionalDirectives[ m_additionalDirectives.Count - 1 ]; + m_additionalDirectives.RemoveAt( m_additionalDirectives.Count - 1 ); + ScriptableObject.DestroyImmediate( itemToDelete ); + EditorGUI.FocusTextInControl( null ); + } + m_isDirty = true; + } + } + + public override void Draw( UndoParentNode currOwner, bool style = true ) + { + m_currOwner = currOwner; + if( m_reordableList == null ) + { + m_reordableList = new ReorderableList( m_additionalDirectives, typeof( AdditionalDirectiveContainer ), true, false, false, false ) + { + headerHeight = 0, + footerHeight = 0, + showDefaultBackground = false, + elementHeightCallback = ( index ) => + { + if( m_additionalDirectives[ index ].Origin == AdditionalContainerOrigin.Native && m_nativeDirectivesFoldout ) + { + return ( m_nativeDirectives.Count + 1 ) * ( EditorGUIUtility.singleLineHeight ) + 5; + } + + return EditorGUIUtility.singleLineHeight + 5; + }, + drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) => + { + if( m_additionalDirectives[ index ].Origin == AdditionalContainerOrigin.Native && m_nativeDirectivesFoldout ) + { + rect.height = ( m_nativeDirectives.Count + 1 ) * ( EditorGUIUtility.singleLineHeight ) + 5; + } + + if( m_additionalDirectives[ index ] != null ) + { + float labelWidthStyleAdjust = 0; + if( style ) + { + rect.xMin -= 10; + labelWidthStyleAdjust = 15; + } + else + { + rect.xMin -= 1; + } + + float popUpWidth = style ? 80 : 65f; + float widthAdjust = m_additionalDirectives[ index ].LineType == AdditionalLineType.Include ? -14 : 0; + Rect popupPos = new Rect( rect.x, rect.y, popUpWidth, EditorGUIUtility.singleLineHeight ); + Rect GUIDTogglePos = m_additionalDirectives[ index ].LineType == AdditionalLineType.Include ? new Rect( rect.x + rect.width - 3 * Constants.PlusMinusButtonLayoutWidth, rect.y, Constants.PlusMinusButtonLayoutWidth, Constants.PlusMinusButtonLayoutWidth ) : new Rect(); + Rect buttonPlusPos = new Rect( rect.x + rect.width - 2 * Constants.PlusMinusButtonLayoutWidth, rect.y - 2, Constants.PlusMinusButtonLayoutWidth, Constants.PlusMinusButtonLayoutWidth ); + Rect buttonMinusPos = new Rect( rect.x + rect.width - Constants.PlusMinusButtonLayoutWidth, rect.y - 2, Constants.PlusMinusButtonLayoutWidth, Constants.PlusMinusButtonLayoutWidth ); + float labelWidthBuffer = EditorGUIUtility.labelWidth; + Rect labelPos = new Rect( rect.x + popupPos.width - labelWidthStyleAdjust, rect.y, labelWidthStyleAdjust + rect.width - popupPos.width - buttonPlusPos.width - buttonMinusPos.width + widthAdjust, EditorGUIUtility.singleLineHeight ); + + if( m_additionalDirectives[ index ].Origin == AdditionalContainerOrigin.Native ) + { + m_nativeRect = rect; +#if UNITY_2019_3_OR_NEWER + m_nativeRect.y -= ( m_nativeRect.height - ( EditorGUIUtility.singleLineHeight + 5 ) ) * 0.5f; +#endif + m_nativeRect.xMin += 2; + m_nativeRect.xMax -= 2; + m_nativeRect.yMax -= 2; + + NodeUtils.DrawNestedPropertyGroup( ref m_nativeDirectivesFoldout, rect, NativeFoldoutStr, DrawNativeItemsRect, 4 ); + return; + } + + m_additionalDirectives[ index ].LineType = (AdditionalLineType)m_currOwner.EditorGUIEnumPopup( popupPos, m_additionalDirectives[ index ].LineType ); + + if( m_additionalDirectives[ index ].LineType == AdditionalLineType.Include ) + { + if( m_additionalDirectives[ index ].GUIDToggle ) + { + //if( m_additionalDirectives[ index ].LibObject == null && !string.IsNullOrEmpty( m_additionalDirectives[ index ].GUIDValue ) ) + //{ + // m_additionalDirectives[ index ].LibObject = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( m_additionalDirectives[ index ].GUIDValue ) ); + //} + + EditorGUI.BeginChangeCheck(); + TextAsset obj = m_currOwner.EditorGUIObjectField( labelPos, m_additionalDirectives[ index ].LibObject, typeof( TextAsset ), false ) as TextAsset; + if( EditorGUI.EndChangeCheck() ) + { + string pathName = AssetDatabase.GetAssetPath( obj ); + string extension = Path.GetExtension( pathName ); + extension = extension.ToLower(); + if( extension.Equals( ".cginc" ) || extension.Equals( ".hlsl" ) ) + { + m_additionalDirectives[ index ].LibObject = obj; + m_additionalDirectives[ index ].GUIDValue = AssetDatabase.AssetPathToGUID( pathName ); + } + } + } + else + { + m_additionalDirectives[ index ].LineValue = m_currOwner.EditorGUITextField( labelPos, string.Empty, m_additionalDirectives[ index ].LineValue ); + } + + if( GUI.Button( GUIDTogglePos, m_additionalDirectives[ index ].GUIDToggle ? UIUtils.FloatIntIconOFF : UIUtils.FloatIntIconON, UIUtils.FloatIntPickerONOFF ) ) + m_additionalDirectives[ index ].GUIDToggle = !m_additionalDirectives[ index ].GUIDToggle; + } + else + { + m_additionalDirectives[ index ].LineValue = m_currOwner.EditorGUITextField( labelPos, string.Empty, m_additionalDirectives[ index ].LineValue ); + } + + if( GUI.Button( buttonPlusPos, string.Empty, UIUtils.PlusStyle ) ) + { + m_actionType = ReordableAction.Add; + m_actionIndex = index; + } + + if( GUI.Button( buttonMinusPos, string.Empty, UIUtils.MinusStyle ) ) + { + m_actionType = ReordableAction.Remove; + m_actionIndex = index; + } + } + }, + onReorderCallback = ( ReorderableList list ) => + { + UpdateNativeIndex(); + } + }; + } + + if( m_actionType != ReordableAction.None ) + { + switch( m_actionType ) + { + case ReordableAction.Add: + { + AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance(); + newItem.hideFlags = HideFlags.HideAndDontSave; + m_additionalDirectives.Insert( m_actionIndex + 1, newItem ); + } + break; + case ReordableAction.Remove: + AdditionalDirectiveContainer itemToDelete = m_additionalDirectives[ m_actionIndex ]; + m_additionalDirectives.RemoveAt( m_actionIndex ); + ScriptableObject.DestroyImmediate( itemToDelete ); + break; + } + m_isDirty = true; + m_actionType = ReordableAction.None; + EditorGUI.FocusTextInControl( null ); + } + bool foldoutValue = currOwner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalDirectives; + if( style ) + { + NodeUtils.DrawPropertyGroup( ref foldoutValue, m_moduleName, DrawReordableList, DrawButtons ); + } + else + { + NodeUtils.DrawNestedPropertyGroup( ref foldoutValue, m_moduleName, DrawReordableList, DrawButtons ); + } + currOwner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalDirectives = foldoutValue; + } + + void DrawReordableList() + { + if( m_reordableList != null ) + { + if( m_propertyAdjustment == null ) + { + m_propertyAdjustment = new GUIStyle(); + m_propertyAdjustment.padding.left = 17; + } + //EditorGUILayout.BeginVertical( m_propertyAdjustment ); + EditorGUILayout.Space(); + if( m_nativeDirectives.Count > 0 ) + { + //NodeUtils.DrawNestedPropertyGroup( ref m_nativeDirectivesFoldout, NativeFoldoutStr, DrawNativeItems, 4 ); + } + if( m_additionalDirectives.Count == 0 ) + { + EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one.", MessageType.Info ); + } + else + { + m_reordableList.DoLayoutList(); + } + EditorGUILayout.Space(); + //EditorGUILayout.EndVertical(); + } + } + + public void AddAllToDataCollector( ref MasterNodeDataCollector dataCollector, TemplateIncludePragmaContainter nativesContainer ) + { + //List list = m_additionalDirectives; + //int count = list.FindIndex( x => x.Origin.Equals( AdditionalContainerOrigin.Native ) ); + //for( int i = 0; i < count; i++ ) + //{ + // switch( list[ i ].LineType ) + // { + // case AdditionalLineType.Include: + // { + // string value = list[ i ].Value; + // if( !string.IsNullOrEmpty( value ) && + // !nativesContainer.HasInclude( value ) ) + // { + // dataCollector.AddToMisc( list[ i ].FormattedValue ); + // } + // } + // break; + // case AdditionalLineType.Define: + // { + // if( !string.IsNullOrEmpty( list[ i ].LineValue ) && + // !nativesContainer.HasDefine( list[ i ].LineValue ) ) + // { + // dataCollector.AddToMisc( list[ i ].FormattedValue ); + // } + // } + // break; + // case AdditionalLineType.Pragma: + // { + // if( !string.IsNullOrEmpty( list[ i ].LineValue ) && + // !nativesContainer.HasPragma( list[ i ].LineValue ) ) + // { + // dataCollector.AddToMisc( list[ i ].FormattedValue ); + // } + // } + // break; + // default: + // case AdditionalLineType.Custom: + // dataCollector.AddToMisc( list[ i ].LineValue ); + // break; + // } + //} + + AddToDataCollector( ref dataCollector, nativesContainer, false ); + AddToDataCollector( ref dataCollector, nativesContainer, true ); + } + + public void AddAllToDataCollector( ref MasterNodeDataCollector dataCollector ) + { + AddToDataCollector( ref dataCollector, false ); + AddToDataCollector( ref dataCollector, true ); + } + + void AddToDataCollector( ref MasterNodeDataCollector dataCollector, TemplateIncludePragmaContainter nativesContainer, bool fromSF ) + { + List list = fromSF ? m_shaderFunctionDirectives : m_additionalDirectives; + int count = list.Count; + for( int i = 0; i < count; i++ ) + { + int orderIdx = fromSF ? 1 : ( i > m_nativeDirectivesIndex ? 1 : -1 ); + switch( list[ i ].LineType ) + { + case AdditionalLineType.Include: + { + string value = list[ i ].Value; + if( !string.IsNullOrEmpty( value ) && + !nativesContainer.HasInclude( value ) ) + { + dataCollector.AddToDirectives( list[ i ].FormattedValue, orderIdx ); + } + } + break; + case AdditionalLineType.Define: + { + if( !string.IsNullOrEmpty( list[ i ].LineValue ) && + !nativesContainer.HasDefine( list[ i ].LineValue ) ) + { + dataCollector.AddToDirectives( list[ i ].FormattedValue, orderIdx ); + } + } + break; + case AdditionalLineType.Pragma: + { + if( !string.IsNullOrEmpty( list[ i ].LineValue ) && + !nativesContainer.HasPragma( list[ i ].LineValue ) ) + { + dataCollector.AddToDirectives( list[ i ].FormattedValue, orderIdx ); + } + } + break; + default: + case AdditionalLineType.Custom: + dataCollector.AddToDirectives( list[ i ].LineValue, orderIdx ); + break; + } + } + } + + void AddToDataCollector( ref MasterNodeDataCollector dataCollector, bool fromSF ) + { + List list = fromSF ? m_shaderFunctionDirectives : m_additionalDirectives; + int orderIdx = 1; + int count = list.Count; + for( int i = 0; i < count; i++ ) + { + switch( list[ i ].LineType ) + { + case AdditionalLineType.Include: + { + string value = list[ i ].FormattedValue; + if( !string.IsNullOrEmpty( value ) ) + { + dataCollector.AddToDirectives( value, orderIdx ); + } + } + break; + case AdditionalLineType.Define: + { + if( !string.IsNullOrEmpty( list[ i ].LineValue ) ) + { + dataCollector.AddToDirectives( list[ i ].FormattedValue, orderIdx ); + } + } + break; + case AdditionalLineType.Pragma: + { + if( !string.IsNullOrEmpty( list[ i ].LineValue ) ) + { + dataCollector.AddToDirectives( list[ i ].FormattedValue, orderIdx ); + } + } + break; + default: + case AdditionalLineType.Custom: + dataCollector.AddToDirectives( list[ i ].LineValue, orderIdx ); + break; + } + } + } + + public override void ReadFromString( ref uint index, ref string[] nodeParams ) + { + try + { + m_nativeDirectivesIndex = -1; + int count = Convert.ToInt32( nodeParams[ index++ ] ); + m_additionalDirectives.Clear(); + for( int i = 0; i < count; i++ ) + { + AdditionalLineType lineType = (AdditionalLineType)Enum.Parse( typeof( AdditionalLineType ), nodeParams[ index++ ] ); + string lineValue = nodeParams[ index++ ]; + AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance(); + newItem.hideFlags = HideFlags.HideAndDontSave; + newItem.LineType = lineType; + newItem.LineValue = lineValue.Replace( Constants.SemiColonSeparator, ';' ); + if( UIUtils.CurrentShaderVersion() > 15607 ) + { + newItem.GUIDToggle = Convert.ToBoolean( nodeParams[ index++ ] ); + newItem.GUIDValue = nodeParams[ index++ ]; + if( newItem.GUIDToggle ) + { + newItem.LibObject = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( newItem.GUIDValue ) ); + if( newItem.LibObject == null ) + { + Debug.LogWarning( "Include file not found with GUID " + newItem.GUIDValue ); + } + } + } + AdditionalContainerOrigin origin = AdditionalContainerOrigin.Custom; + if( UIUtils.CurrentShaderVersion() > 16902 ) + { + origin = (AdditionalContainerOrigin)Enum.Parse( typeof( AdditionalContainerOrigin ), nodeParams[ index++ ] ); + newItem.Origin = origin; + } + + m_additionalDirectives.Add( newItem ); + + if( origin == AdditionalContainerOrigin.Native ) + { + m_nativeDirectivesIndex = i; + } + } + AddNativeContainer(); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + + public override void WriteToString( ref string nodeInfo ) + { + if( m_additionalDirectives.Count == 1 && m_additionalDirectives[ 0 ].Origin == AdditionalContainerOrigin.Native ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, 0 ); + return; + } + + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives.Count ); + for( int i = 0; i < m_additionalDirectives.Count; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].LineType ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].LineValue.Replace( ';', Constants.SemiColonSeparator ) ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].GUIDToggle ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].GUIDValue ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].Origin ); + } + } + + // read comment on m_directivesSaveItems declaration + public void UpdateSaveItemsFromDirectives() + { + bool foundNull = false; + m_directivesSaveItems.Clear(); + for( int i = 0; i < m_additionalDirectives.Count; i++ ) + { + if( m_additionalDirectives[ i ] != null ) + { + m_directivesSaveItems.Add( new AdditionalDirectiveContainerSaveItem( m_additionalDirectives[ i ] ) ); + } + else + { + foundNull = true; + } + } + + if( foundNull ) + { + m_additionalDirectives.RemoveAll( item => item == null ); + } + } + + public void CleanNullDirectives() + { + m_additionalDirectives.RemoveAll( item => item == null ); + } + + public void ResetDirectivesOrigin() + { + for( int i = 0; i < m_directivesSaveItems.Count; i++ ) + { + m_directivesSaveItems[ i ].Origin = AdditionalContainerOrigin.Custom; + } + } + + // read comment on m_directivesSaveItems declaration + public void UpdateDirectivesFromSaveItems() + { + if( m_directivesSaveItems.Count > 0 ) + { + for( int i = 0; i < m_additionalDirectives.Count; i++ ) + { + if( m_additionalDirectives[ i ] != null ) + ScriptableObject.DestroyImmediate( m_additionalDirectives[ i ] ); + } + + m_additionalDirectives.Clear(); + + for( int i = 0; i < m_directivesSaveItems.Count; i++ ) + { + AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance(); + newItem.hideFlags = HideFlags.HideAndDontSave; + newItem.Init( m_directivesSaveItems[ i ] ); + m_additionalDirectives.Add( newItem ); + } + UpdateNativeIndex(); + //m_directivesSaveItems.Clear(); + } + } + + void UpdateNativeIndex() + { + m_nativeDirectivesIndex = -1; + int count = m_additionalDirectives.Count; + for( int i = 0; i < count; i++ ) + { + if( m_additionalDirectives[ i ].Origin == AdditionalContainerOrigin.Native ) + { + m_nativeDirectivesIndex = i; + break; + } + } + } + + public override void Destroy() + { + base.Destroy(); + + m_nativeDirectives.Clear(); + m_nativeDirectives = null; + + for( int i = 0; i < m_additionalDirectives.Count; i++ ) + { + ScriptableObject.DestroyImmediate( m_additionalDirectives[ i ] ); + } + + m_additionalDirectives.Clear(); + m_additionalDirectives = null; + + for( int i = 0; i < m_shaderFunctionDirectives.Count; i++ ) + { + ScriptableObject.DestroyImmediate( m_shaderFunctionDirectives[ i ] ); + } + + m_shaderFunctionDirectives.Clear(); + m_shaderFunctionDirectives = null; + + + m_propertyAdjustment = null; + m_reordableList = null; + } + + + public List DirectivesList { get { return m_additionalDirectives; } } + public bool IsValid { get { return m_validData; } set { m_validData = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs.meta new file mode 100644 index 0000000..43fdc89 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c6b57deeb826a674f9715fab4dfb4cb1 +timeCreated: 1528278077 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs new file mode 100644 index 0000000..7d58666 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs @@ -0,0 +1,31 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateAdditionalIncludesHelper : TemplateAdditionalParentHelper + { + public TemplateAdditionalIncludesHelper() : base( "Additional Includes" ) + { + m_helpBoxMessage = "Please add your includes without the #include \"\" keywords"; + } + + public override void AddToDataCollector( ref MasterNodeDataCollector dataCollector , TemplateIncludePragmaContainter nativesContainer ) + { + for( int i = 0; i < m_additionalItems.Count; i++ ) + { + if( !string.IsNullOrEmpty( m_additionalItems[ i ] ) && !nativesContainer.HasInclude( m_additionalItems[ i ] ) ) + dataCollector.AddToIncludes( -1, m_additionalItems[ i ] ); + } + + for( int i = 0; i < m_outsideItems.Count; i++ ) + { + if( !string.IsNullOrEmpty( m_outsideItems[ i ] ) && !nativesContainer.HasInclude( m_outsideItems[ i ] ) ) + dataCollector.AddToIncludes( -1, m_outsideItems[ i ] ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs.meta new file mode 100644 index 0000000..9a45474 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0ab4c474dfddce2429da08f56e651ed4 +timeCreated: 1520275148 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs new file mode 100644 index 0000000..da765cc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs @@ -0,0 +1,193 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateAdditionalParentHelper : TemplateModuleParent + { + private string NativeFoldoutStr = "Native"; + + protected string m_helpBoxMessage = string.Empty; + private const float ShaderKeywordButtonLayoutWidth = 15; + private ParentNode m_currentOwner; + + [SerializeField] + protected List m_nativeItems = new List(); + + [SerializeField] + protected bool m_nativeItemsFoldout = false; + + [SerializeField] + protected List m_additionalItems = new List(); + + [SerializeField] + protected List m_outsideItems = new List(); + + public TemplateAdditionalParentHelper( string moduleName ) : base( moduleName ) { } + public bool IsValid { set{ m_validData = value; } get{ return m_validData; } } + + public void FillNativeItems( List nativeItems ) + { + m_nativeItems.Clear(); + m_nativeItems.AddRange( nativeItems ); + } + + public void Draw( ParentNode owner ) + { + m_currentOwner = owner; + bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalDefines; + NodeUtils.DrawNestedPropertyGroup( ref foldout, m_moduleName, DrawMainBody, DrawButtons ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalDefines = foldout; + } + + public void CopyFrom( TemplateAdditionalParentHelper other ) + { + m_additionalItems.Clear(); + m_outsideItems.Clear(); + int otherAdditionalItemsCount = other.ItemsList.Count; + for( int i = 0; i < otherAdditionalItemsCount; i++ ) + { + m_additionalItems.Add( other.ItemsList[ i ] ); + } + + int otherOusideItemsCount = other.OutsideList.Count; + for( int i = 0; i < otherOusideItemsCount; i++ ) + { + m_outsideItems.Add( other.OutsideList[ i ] ); + } + } + + void DrawButtons() + { + EditorGUILayout.Separator(); + + // Add keyword + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_additionalItems.Add( string.Empty ); + EditorGUI.FocusTextInControl( null ); + m_isDirty = true; + } + + //Remove keyword + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + if( m_additionalItems.Count > 0 ) + { + m_additionalItems.RemoveAt( m_additionalItems.Count - 1 ); + EditorGUI.FocusTextInControl( null ); + } + m_isDirty = true; + } + } + void DrawNativeItems() + { + EditorGUILayout.Separator(); + EditorGUI.indentLevel++; + int count = m_nativeItems.Count; + for ( int i = 0; i < count; i++ ) + { + EditorGUILayout.LabelField( m_nativeItems[i] ); + } + EditorGUI.indentLevel--; + EditorGUILayout.Separator(); + } + void DrawMainBody() + { + EditorGUILayout.Separator(); + + if( m_nativeItems.Count > 0 ) + { + NodeUtils.DrawNestedPropertyGroup( ref m_nativeItemsFoldout, NativeFoldoutStr, DrawNativeItems ,4); + } + + int itemCount = m_additionalItems.Count; + int markedToDelete = -1; + for( int i = 0; i < itemCount; i++ ) + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUI.BeginChangeCheck(); + m_additionalItems[ i ] = EditorGUILayout.TextField( m_additionalItems[ i ] ); + if( EditorGUI.EndChangeCheck() ) + { + m_additionalItems[ i ] = UIUtils.RemoveShaderInvalidCharacters( m_additionalItems[ i ] ); + m_isDirty = true; + } + + // Add new port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_additionalItems.Insert( i + 1, string.Empty ); + EditorGUI.FocusTextInControl( null ); + m_isDirty = true; + } + + //Remove port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + markedToDelete = i; + m_isDirty = true; + } + } + EditorGUILayout.EndHorizontal(); + } + + if( markedToDelete > -1 ) + { + if( m_additionalItems.Count > markedToDelete ) + { + m_additionalItems.RemoveAt( markedToDelete ); + EditorGUI.FocusTextInControl( null ); + } + } + EditorGUILayout.Separator(); + EditorGUILayout.HelpBox( m_helpBoxMessage, MessageType.Info ); + } + + public override void ReadFromString( ref uint index, ref string[] nodeParams ) + { + try + { + int count = Convert.ToInt32( nodeParams[ index++ ] ); + for( int i = 0; i < count; i++ ) + { + m_additionalItems.Add( nodeParams[ index++ ] ); + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + + public override void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalItems.Count ); + for( int i = 0; i < m_additionalItems.Count; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalItems[ i ] ); + } + } + + public virtual void AddToDataCollector( ref MasterNodeDataCollector dataCollector , TemplateIncludePragmaContainter nativesContainer ) { } + + public override void Destroy() + { + m_additionalItems.Clear(); + m_additionalItems = null; + m_currentOwner = null; + m_nativeItems.Clear(); + m_nativeItems = null; + } + + public List ItemsList { get { return m_additionalItems; } set { m_additionalItems = value; } } + public List OutsideList { get { return m_outsideItems; } set { m_outsideItems = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs.meta new file mode 100644 index 0000000..6d0983f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5360ba11600eeb44786246ca70212e25 +timeCreated: 1520332262 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs new file mode 100644 index 0000000..3c08f1a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs @@ -0,0 +1,31 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateAdditionalPragmasHelper : TemplateAdditionalParentHelper + { + public TemplateAdditionalPragmasHelper() : base( "Additional Pragmas" ) + { + m_helpBoxMessage = "Please add your pragmas without the #pragma keywords"; + } + + public override void AddToDataCollector( ref MasterNodeDataCollector dataCollector, TemplateIncludePragmaContainter nativesContainer ) + { + for( int i = 0; i < m_additionalItems.Count; i++ ) + { + if( !string.IsNullOrEmpty( m_additionalItems[ i ] ) && !nativesContainer.HasPragma( m_additionalItems[ i ] )) + dataCollector.AddToPragmas( -1, m_additionalItems[ i ] ); + } + + for( int i = 0; i < m_outsideItems.Count; i++ ) + { + if( !string.IsNullOrEmpty( m_outsideItems[ i ] ) && !nativesContainer.HasPragma( m_outsideItems[ i ] ) ) + dataCollector.AddToPragmas( -1, m_outsideItems[ i ] ); + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs.meta new file mode 100644 index 0000000..4abd023 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: de89b62c2bd8eec4b915a0decba936fb +timeCreated: 1520275148 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAlphaToMaskModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAlphaToMaskModule.cs new file mode 100644 index 0000000..307a633 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAlphaToMaskModule.cs @@ -0,0 +1,128 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + public sealed class TemplateAlphaToMaskModule : TemplateModuleParent + { + private const string AlphaToMaskFormatStr = "AlphaToMask "; + private const string AlphaToMaskFormat = "AlphaToMask {0}"; + + public TemplateAlphaToMaskModule() : base( "Alpha To Coverage" ) { } + + private static readonly string AlphaToMaskStr = "Alpha To Coverage"; + + [SerializeField] + private bool m_alphaToMask = false; + + [SerializeField] + private InlineProperty m_inlineAlphaToMask = new InlineProperty(); + + public void CopyFrom( TemplateAlphaToMaskModule other , bool allData ) + { + if( allData ) + m_independentModule = other.IndependentModule; + + m_alphaToMask = other.AlphaToMask; + m_inlineAlphaToMask.CopyFrom( other.AlphaToMaskInlineProperty ); + } + + public void ConfigureFromTemplateData( TemplateAlphaToMaskData data ) + { + bool newValidData = ( data.DataCheck == TemplateDataCheck.Valid ); + + if( newValidData && m_validData != newValidData ) + { + m_independentModule = data.IndependentModule; + if( string.IsNullOrEmpty( data.InlineData ) ) + { + m_alphaToMask = data.AlphaToMaskData; + m_inlineAlphaToMask.IntValue = m_alphaToMask ? 1 : 0; + m_inlineAlphaToMask.ResetProperty(); + } + else + { + m_inlineAlphaToMask.SetInlineByName( data.InlineData ); + } + } + + m_validData = newValidData; + } + + public override void Draw( UndoParentNode owner, bool style = true ) + { + EditorGUI.BeginChangeCheck(); + m_inlineAlphaToMask.CustomDrawer( ref owner, ( x ) => { m_alphaToMask = owner.EditorGUILayoutToggle( AlphaToMaskStr, m_alphaToMask ); }, AlphaToMaskStr ); + if( EditorGUI.EndChangeCheck() ) + { + m_inlineAlphaToMask.IntValue = m_alphaToMask ? 1 : 0; + m_isDirty = true; + } + } + + public override void ReadFromString( ref uint index, ref string[] nodeParams ) + { + bool validDataOnMeta = m_validData; + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( validDataOnMeta ) + { + if( UIUtils.CurrentShaderVersion() < 15304 ) + { + m_alphaToMask = Convert.ToBoolean( nodeParams[ index++ ] ); + m_inlineAlphaToMask.IntValue = m_alphaToMask ? 1 : 0; + } + else + { + m_inlineAlphaToMask.ReadFromString( ref index, ref nodeParams ); + m_alphaToMask = m_inlineAlphaToMask.IntValue == 1; + } + } + } + + public override void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_validData ); + if( m_validData ) + { + m_inlineAlphaToMask.WriteToString( ref nodeInfo ); + } + } + + public override string GenerateShaderData( bool isSubShader ) + { + return AlphaToMaskFormatStr + m_inlineAlphaToMask.GetValueOrProperty( m_alphaToMask ? "On" : "Off"); + } + + public override void Destroy() + { + base.Destroy(); + m_inlineAlphaToMask = null; + } + + //public string CurrentAlphaToMask + //{ + // get { return string.Format( AlphaToMaskFormat, m_alphaToMask ? "On" : "Off" ); } + //} + + public bool AlphaToMask + { + get { return m_alphaToMask; } + set + { + m_alphaToMask = value; + m_inlineAlphaToMask.IntValue = value ? 1 : 0; + m_inlineAlphaToMask.Active = false; + } + } + public InlineProperty AlphaToMaskInlineProperty { get { return m_inlineAlphaToMask; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAlphaToMaskModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAlphaToMaskModule.cs.meta new file mode 100644 index 0000000..fa73b46 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAlphaToMaskModule.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 84e56f8cb109deb4da1945562567bf0c +timeCreated: 1593170303 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs new file mode 100644 index 0000000..ea717e6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs @@ -0,0 +1,102 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public enum TemplateCodeSnippetType + { + Toggle + }; + + + public enum TemplateCodeSnippetInfoIdx + { + Name = 0, + Type + }; + + [Serializable] + public class TemplateCodeSnippetElement + { + public string Id; + public string Snippet; + public TemplateCodeSnippetElement( string id, string snippet ) + { + Id = id; + Snippet = snippet; + } + } + + [Serializable] + public class TemplateCodeSnippetBase : ScriptableObject + { + [SerializeField] + private string m_nameId; + + [SerializeField] + private TemplateCodeSnippetType m_type; + + [SerializeField] + private List m_elements = new List(); + + public void Init( string nameId, TemplateCodeSnippetType type ) + { + m_nameId = nameId; + m_type = type; + } + + public void AddSnippet( TemplateCodeSnippetElement element ) + { + m_elements.Add( element ); + } + + public void Destroy() + { + for ( int i = 0; i < m_elements.Count; i++ ) + { + m_elements[ i ].Snippet = null; + } + m_elements.Clear(); + m_elements = null; + } + + public virtual void DrawProperties( ParentNode owner ) { } + public virtual bool CheckSnippet() { return true; } + + public void InsertSnippet( ref string shaderBody ) + { + bool insertSnippet = CheckSnippet(); + for ( int i = 0; i < m_elements.Count; i++ ) + { + shaderBody = shaderBody.Replace( m_elements[ i ].Id, ( insertSnippet ? m_elements[ i ].Snippet : string.Empty ) ); + } + } + public string NameId { get { return m_nameId; } } + public TemplateCodeSnippetType Type { get { return m_type; } } + public List Elements { get { return m_elements; } } + } + + [Serializable] + public class TemplateCodeSnippetToggle : TemplateCodeSnippetBase + { + private const string Label = "Activate"; + [SerializeField] + private bool m_value = false; + + + public override bool CheckSnippet() + { + return m_value; + } + + public override void DrawProperties( ParentNode owner ) + { + m_value = owner.EditorGUILayoutToggle( Label, m_value ); + } + } + +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs.meta new file mode 100644 index 0000000..612a553 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5fc48fb872ce5e74aa913f987a025ea4 +timeCreated: 1495113330 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs new file mode 100644 index 0000000..34c867c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs @@ -0,0 +1,200 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateColorMaskModule : TemplateModuleParent + { + private const string ColorMaskOp = "ColorMask "; + private const string ColorMaskOff = "ColorMask RGBA"; + private GUIContent ColorMaskContent = new GUIContent( "Color Mask", "Sets color channel writing mask, turning all off makes the object completely invisible\nDefault: RGBA" ); + private readonly char[] m_colorMaskChar = { 'R', 'G', 'B', 'A' }; + + private GUIStyle m_leftToggleColorMask; + private GUIStyle m_middleToggleColorMask; + private GUIStyle m_rightToggleColorMask; + + public TemplateColorMaskModule() : base( "Color Mask" ) { } + + [SerializeField] + private bool[] m_colorMask = { true, true, true, true }; + + [SerializeField] + private string m_target = string.Empty; + + [SerializeField] + private InlineProperty m_inlineColorMask = new InlineProperty(); + + public void CopyFrom( TemplateColorMaskModule other, bool allData ) + { + if( allData ) + m_independentModule = other.IndependentModule; + + for( int i = 0; i < m_colorMask.Length; i++ ) + { + m_colorMask[ i ] = other.ColorMask[ i ]; + } + + m_target = other.Target; + + m_inlineColorMask.CopyFrom( other.InlineColorMask ); + } + + public void ConfigureFromTemplateData( TemplateColorMaskData data ) + { + bool newValidData = ( data.DataCheck == TemplateDataCheck.Valid ); + if( newValidData && m_validData != newValidData ) + { + m_independentModule = data.IndependentModule; + m_target = data.Target; + if( string.IsNullOrEmpty( data.InlineData ) ) + { + for( int i = 0; i < 4; i++ ) + { + m_colorMask[ i ] = data.ColorMaskData[ i ]; + } + m_inlineColorMask.ResetProperty(); + } + else + { + m_inlineColorMask.SetInlineByName( data.InlineData ); + } + } + + m_validData = newValidData; + } + + public override void Draw( UndoParentNode owner, bool style = true ) + { + EditorGUI.BeginChangeCheck(); + { + m_inlineColorMask.CustomDrawer( ref owner, DrawColorMaskControls, ColorMaskContent.text + m_target ); + } + + if( EditorGUI.EndChangeCheck() ) + { + m_isDirty = true; + CustomEdited = true; + } + } + + private void DrawColorMaskControls( UndoParentNode owner ) + { + if( m_leftToggleColorMask == null || m_leftToggleColorMask.normal.background == null ) + { + m_leftToggleColorMask = GUI.skin.GetStyle( "ButtonLeft" ); + } + + if( m_middleToggleColorMask == null || m_middleToggleColorMask.normal.background == null ) + { + m_middleToggleColorMask = GUI.skin.GetStyle( "ButtonMid" ); + } + + if( m_rightToggleColorMask == null || m_rightToggleColorMask.normal.background == null ) + { + m_rightToggleColorMask = GUI.skin.GetStyle( "ButtonRight" ); + } + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField( "Color Mask"+ m_target, GUILayout.Width( EditorGUIUtility.labelWidth - 3 ) ); + + m_colorMask[ 0 ] = owner.GUILayoutToggle( m_colorMask[ 0 ], "R", m_leftToggleColorMask ); + m_colorMask[ 1 ] = owner.GUILayoutToggle( m_colorMask[ 1 ], "G", m_middleToggleColorMask ); + m_colorMask[ 2 ] = owner.GUILayoutToggle( m_colorMask[ 2 ], "B", m_middleToggleColorMask ); + m_colorMask[ 3 ] = owner.GUILayoutToggle( m_colorMask[ 3 ], "A", m_rightToggleColorMask ); + + EditorGUILayout.EndHorizontal(); + } + + public override string GenerateShaderData( bool isSubShader ) + { + if( m_inlineColorMask.IsValid ) + return ColorMaskOp + m_inlineColorMask.GetValueOrProperty() + Target; + + int count = 0; + string colorMask = string.Empty; + for( int i = 0; i < m_colorMask.Length; i++ ) + { + if( m_colorMask[ i ] ) + { + count++; + colorMask += m_colorMaskChar[ i ]; + } + } + + if( count != m_colorMask.Length ) + { + return ColorMaskOp + ( ( count == 0 ) ? "0" : colorMask ) + Target; + } + + return ColorMaskOff + Target; + } + + public override void ReadFromString( ref uint index, ref string[] nodeParams ) + { + base.ReadFromString( ref index, ref nodeParams ); + bool validDataOnMeta = m_validData; + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( validDataOnMeta ) + { + for( int i = 0; i < m_colorMask.Length; i++ ) + { + m_colorMask[ i ] = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( UIUtils.CurrentShaderVersion() > 15303 ) + { + m_inlineColorMask.ReadFromString( ref index, ref nodeParams ); + } + } + } + + public override void WriteToString( ref string nodeInfo ) + { + base.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_validData ); + if( m_validData ) + { + for( int i = 0; i < m_colorMask.Length; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_colorMask[ i ] ); + } + m_inlineColorMask.WriteToString( ref nodeInfo ); + } + } + + public bool[] ColorMask + { + get { return m_colorMask; } + set + { + m_colorMask = value; + m_inlineColorMask.Active = false; + } + } + + public string Target + { + get { return m_target; } + set { m_target = value; } + } + + public override void Destroy() + { + m_leftToggleColorMask = null; + m_middleToggleColorMask = null; + m_rightToggleColorMask = null; + m_inlineColorMask = null; + } + + public InlineProperty InlineColorMask { get { return m_inlineColorMask; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs.meta new file mode 100644 index 0000000..8cb1fbb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e1d9e34bd7946e247aa6d28b2859c6b1 +timeCreated: 1511259305 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs new file mode 100644 index 0000000..f99b5c0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs @@ -0,0 +1,128 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + public sealed class TemplateCullModeModule : TemplateModuleParent + { + private const string CullModeFormatStr = "Cull "; + + public TemplateCullModeModule() : base("Cull Mode"){ } + + private static readonly string CullModeStr = "Cull Mode"; + + [SerializeField] + private CullMode m_cullMode = CullMode.Back; + + [SerializeField] + private InlineProperty m_inlineCullMode = new InlineProperty(); + + public void CopyFrom( TemplateCullModeModule other , bool allData ) + { + if( allData ) + m_independentModule = other.IndependentModule; + + m_cullMode = other.CurrentCullMode; + m_inlineCullMode.CopyFrom( other.CullInlineProperty ); + } + + public void ConfigureFromTemplateData( TemplateCullModeData data ) + { + bool newValidData = ( data.DataCheck == TemplateDataCheck.Valid ); + + if( newValidData && m_validData != newValidData ) + { + m_independentModule = data.IndependentModule; + if( string.IsNullOrEmpty( data.InlineData ) ) + { + m_cullMode = data.CullModeData; + m_inlineCullMode.IntValue = (int)m_cullMode; + m_inlineCullMode.ResetProperty(); + } + else + { + m_inlineCullMode.SetInlineByName( data.InlineData ); + } + } + + m_validData = newValidData; + } + + public override void Draw( UndoParentNode owner, bool style = true ) + { + EditorGUI.BeginChangeCheck(); + //m_cullMode = (CullMode)owner.EditorGUILayoutEnumPopup( CullModeStr, m_cullMode ); + m_inlineCullMode.CustomDrawer( ref owner, ( x ) => { m_cullMode = (CullMode)owner.EditorGUILayoutEnumPopup( CullModeStr, m_cullMode ); }, CullModeStr ); + if( EditorGUI.EndChangeCheck() ) + { + m_inlineCullMode.IntValue = (int)m_cullMode; + m_isDirty = true; + CustomEdited = true; + } + } + + public override void ReadFromString( ref uint index, ref string[] nodeParams ) + { + base.ReadFromString( ref index, ref nodeParams ); + bool validDataOnMeta = m_validData; + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( validDataOnMeta ) + { + if( UIUtils.CurrentShaderVersion() < 15304 ) + { + m_cullMode = (CullMode)Enum.Parse( typeof( CullMode ), nodeParams[ index++ ] ); + m_inlineCullMode.IntValue = (int)m_cullMode; + } + else + { + m_inlineCullMode.ReadFromString( ref index, ref nodeParams ); + m_cullMode = (CullMode)m_inlineCullMode.IntValue; + } + } + } + + public override void WriteToString( ref string nodeInfo ) + { + base.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_validData ); + if( m_validData ) + { + //IOUtils.AddFieldValueToString( ref nodeInfo, m_cullMode ); + m_inlineCullMode.WriteToString( ref nodeInfo ); + } + } + + public override string GenerateShaderData( bool isSubShader ) + { + //return CullModeFormatStr + m_cullMode.ToString(); + return CullModeFormatStr + m_inlineCullMode.GetValueOrProperty( m_cullMode.ToString()); + } + + public override void Destroy() + { + base.Destroy(); + m_inlineCullMode = null; + } + + public CullMode CurrentCullMode + { + get { return m_cullMode; } + set + { + m_cullMode = value; + m_inlineCullMode.IntValue = (int)value; + m_inlineCullMode.Active = false; + } + } + public InlineProperty CullInlineProperty { get { return m_inlineCullMode; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs.meta new file mode 100644 index 0000000..7b3fa30 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: dcbce53ba2eeecd4a8f2c7f5f9a43b7a +timeCreated: 1511186525 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDBItem.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDBItem.cs new file mode 100644 index 0000000..602f2fb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDBItem.cs @@ -0,0 +1,21 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateDBItem + { + public string GUID; + } + + [Serializable] + public class TemplateDB : ScriptableObject + { + public List Items = new List(); + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDBItem.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDBItem.cs.meta new file mode 100644 index 0000000..7917d76 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDBItem.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b12f2516af03f3443b1f2c08c72aa490 +timeCreated: 1610016988 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs new file mode 100644 index 0000000..c563d25 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs @@ -0,0 +1,1183 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +// THIS FILE IS DEPRECATED AND SHOULD NOT BE USED + +using System; +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateDataContainer + { + public int UNITY_VERSION = -1; + public TemplateData TemplateDataRef; + } + + [Serializable] + public class VertexDataContainer + { + [SerializeField] + private List m_vertexData; + + [SerializeField] + private string m_vertexDataId = string.Empty; + + [SerializeField] + private int m_vertexDataStartIdx = -1; + + public void Reload() + { + if( m_vertexData != null ) + { + m_vertexData.Clear(); + } + } + + public void Destroy() + { + if( m_vertexData != null ) + { + m_vertexData.Clear(); + m_vertexData = null; + } + } + + + public List VertexData { get { return m_vertexData; } set { m_vertexData = value; } } + public string VertexDataId { get { return m_vertexDataId; } set { m_vertexDataId = value; } } + public int VertexDataStartIdx { get { return m_vertexDataStartIdx; } set { m_vertexDataStartIdx = value; } } + } + + [Serializable] + public sealed class TemplateData : TemplateDataParent + { + [SerializeField] + private string m_templateBody = string.Empty; + + [SerializeField] + private string m_shaderNameId = string.Empty; + + [SerializeField] + private List m_propertyList = new List(); + private Dictionary m_propertyDict = new Dictionary(); + + [SerializeField] + private List m_inputDataList = new List(); + private Dictionary m_inputDataDict = new Dictionary(); + + //[SerializeField] + //private List m_snippetElementsList = new List(); + //private Dictionary m_snippetElementsDict = new Dictionary(); + + [SerializeField] + private List m_localVarsList = new List(); + + [SerializeField] + private VertexDataContainer m_vertexDataContainer = new VertexDataContainer(); + + [SerializeField] + private TemplateInterpData m_interpolatorDataContainer; + + [SerializeField] + private List m_availableShaderProperties = new List(); + + [SerializeField] + private TemplateFunctionData m_vertexFunctionData; + + [SerializeField] + private TemplateFunctionData m_fragmentFunctionData; + + [SerializeField] + private TemplateBlendData m_blendData = new TemplateBlendData(); + + [SerializeField] + private TemplateAlphaToMaskData m_alphaToMaskData = new TemplateAlphaToMaskData(); + + [SerializeField] + private TemplateCullModeData m_cullModeData = new TemplateCullModeData(); + + [SerializeField] + private TemplateColorMaskData m_colorMaskData = new TemplateColorMaskData(); + + [SerializeField] + private TemplateStencilData m_stencilData = new TemplateStencilData(); + + [SerializeField] + private TemplateDepthData m_depthData = new TemplateDepthData(); + + [SerializeField] + private TemplateTagsModuleData m_tagData = new TemplateTagsModuleData(); + + public TemplateData() + { + m_templateType = TemplateDataType.LegacySinglePass; + } + + public TemplateData( string name ) + { + m_templateType = TemplateDataType.LegacySinglePass; + Name = name; + } + + public TemplateData( string name, string guid ) + { + m_templateType = TemplateDataType.LegacySinglePass; + m_communityTemplate = false; + if( !string.IsNullOrEmpty( guid ) ) + { + string datapath = AssetDatabase.GUIDToAssetPath( guid ); + if( string.IsNullOrEmpty( datapath ) ) + { + m_isValid = false; + return; + } + + string body = string.Empty; + try + { + body = IOUtils.LoadTextFileFromDisk( datapath ); + } + catch( Exception e ) + { + Debug.LogException( e ); + m_isValid = false; + return; + } + + if( !string.IsNullOrEmpty( body ) ) + { + LoadTemplateBody( body ); + Name = string.IsNullOrEmpty( name ) ? m_defaultShaderName : name; + m_guid = guid; + } + } + } + + public TemplateData( string name, string guid, string body ) + { + m_templateType = TemplateDataType.LegacySinglePass; + m_communityTemplate = true; + if( !string.IsNullOrEmpty( body ) ) + { + LoadTemplateBody( body ); + Name = string.IsNullOrEmpty( name ) ? m_defaultShaderName : name; + m_guid = guid; + } + } + + public override bool Reload() + { + if( m_vertexDataContainer != null ) + { + m_vertexDataContainer.Reload(); + } + + if( m_interpolatorDataContainer != null ) + { + m_interpolatorDataContainer.Destroy(); + } + + if( m_availableShaderProperties != null ) + { + m_availableShaderProperties.Clear(); + } + + if( m_propertyDict != null ) + { + m_propertyDict.Clear(); + } + + if( m_propertyList != null ) + { + m_propertyList.Clear(); + } + + if( m_inputDataDict != null ) + { + m_inputDataDict.Clear(); + } + + if( m_inputDataList != null ) + { + m_inputDataList.Clear(); + } + + if( m_localVarsList != null ) + { + m_localVarsList.Clear(); + } + + //if( m_snippetElementsDict != null ) + //{ + // m_snippetElementsDict.Clear(); + //} + + //if( m_snippetElementsList != null ) + //{ + // for( int i = 0; i < m_snippetElementsList.Count; i++ ) + // { + // GameObject.DestroyImmediate( m_snippetElementsList[ i ] ); + // m_snippetElementsList[ i ] = null; + // } + // m_snippetElementsList.Clear(); + //} + + string datapath = AssetDatabase.GUIDToAssetPath( m_guid ); + string body = string.Empty; + try + { + body = IOUtils.LoadTextFileFromDisk( datapath ); + body = UIUtils.ForceLFLineEnding( body ); + } + catch( Exception e ) + { + Debug.LogException( e ); + m_isValid = false; + } + LoadTemplateBody( body ); + if( m_communityTemplate ) + { + Name = m_defaultShaderName; + } + return true; + } + + void LoadTemplateBody( string body ) + { + + m_templateBody = UIUtils.ForceLFLineEnding( body ) ; + + if( m_templateBody.IndexOf( TemplatesManager.TemplateShaderNameBeginTag ) < 0 ) + { + m_isValid = false; + return; + } + + //Fetching common tags + FetchCommonTags(); + + //Fetch function code areas + FetchCodeAreas( TemplatesManager.TemplateVertexCodeBeginArea, MasterNodePortCategory.Vertex ); + FetchCodeAreas( TemplatesManager.TemplateFragmentCodeBeginArea, MasterNodePortCategory.Fragment ); + + //Fetching inputs + FetchInputs( MasterNodePortCategory.Fragment ); + FetchInputs( MasterNodePortCategory.Vertex ); + + + //Fetch local variables must be done after fetching code areas as it needs them to see is variable is on vertex or fragment + TemplateHelperFunctions.FetchLocalVars( m_templateBody, ref m_localVarsList, m_vertexFunctionData, m_fragmentFunctionData ); + + //Fetch snippets + } + + void FetchSubShaderProperties() + { + Match match = Regex.Match( m_templateBody, @"Pass\s*{" ); + if( match.Groups.Count == 0 ) + { + return; + } + + int beginSubShader = m_templateBody.IndexOf( "SubShader" ); + int endSubShader = match.Groups[ 0 ].Index; + if( beginSubShader > 0 && endSubShader > 0 && endSubShader > beginSubShader ) + { + // ADD A PLACE TO INSERT GRAB PASSES + int passIndex = m_templateBody.IndexOf( TemplatesManager.TemplatePassTag ); + if( passIndex < 0 ) + { + int currIdx = endSubShader - 1; + string identation = string.Empty; + for( ; currIdx > 0; currIdx-- ) + { + if( m_templateBody[ currIdx ] != '\n' ) + { + identation = m_templateBody[ currIdx ] + identation; + } + else + { + identation = m_templateBody[ currIdx ] + identation; + break; + } + } + if( currIdx > 0 ) + { + m_templateBody = m_templateBody.Insert( currIdx, identation + TemplatesManager.TemplatePassTag ); + } + } + + // GET ALL THE MODULES + string subBody = m_templateBody.Substring( beginSubShader, endSubShader - beginSubShader ); + //CULL MODE + { + int cullIdx = subBody.IndexOf( "Cull" ); + if( cullIdx > 0 ) + { + int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, cullIdx ); + string cullParams = subBody.Substring( cullIdx, end - cullIdx ); + m_cullModeData.CullModeId = cullParams; + TemplateHelperFunctions.CreateCullMode( cullParams, ref m_cullModeData ); + if( m_cullModeData.DataCheck == TemplateDataCheck.Valid ) + AddId( cullParams, false, string.Empty ); + } + } + //COLOR MASK + { + int colorMaskIdx = subBody.IndexOf( "ColorMask" ); + if( colorMaskIdx > 0 ) + { + int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, colorMaskIdx ); + string colorMaskParams = subBody.Substring( colorMaskIdx, end - colorMaskIdx ); + m_colorMaskData.ColorMaskId = colorMaskParams; + TemplateHelperFunctions.CreateColorMask( colorMaskParams, ref m_colorMaskData, TemplateHelperFunctions.ColorMaskPattern ); + if( m_colorMaskData.DataCheck == TemplateDataCheck.Valid ) + AddId( colorMaskParams, false ); + } + } + //BlEND MODE + { + int blendModeIdx = subBody.IndexOf( "Blend" ); + if( blendModeIdx > 0 ) + { + int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, blendModeIdx ); + string blendParams = subBody.Substring( blendModeIdx, end - blendModeIdx ); + m_blendData.BlendModeId = blendParams; + TemplateHelperFunctions.CreateBlendMode( blendParams, ref m_blendData, TemplateHelperFunctions.BlendModePattern ); + if( m_blendData.ValidBlendMode ) + { + AddId( blendParams, false ); + } + } + } + //BLEND OP + { + int blendOpIdx = subBody.IndexOf( "BlendOp" ); + if( blendOpIdx > 0 ) + { + int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, blendOpIdx ); + string blendOpParams = subBody.Substring( blendOpIdx, end - blendOpIdx ); + BlendData.BlendOpId = blendOpParams; + TemplateHelperFunctions.CreateBlendOp( blendOpParams, ref m_blendData, TemplateHelperFunctions.BlendOpPattern ); + if( m_blendData.ValidBlendOp ) + { + AddId( blendOpParams, false ); + } + } + + m_blendData.DataCheck = ( m_blendData.ValidBlendMode || m_blendData.ValidBlendOp ) ? TemplateDataCheck.Valid : TemplateDataCheck.Invalid; + } + + //STENCIL + { + int stencilIdx = subBody.IndexOf( "Stencil" ); + if( stencilIdx > -1 ) + { + int stencilEndIdx = subBody.IndexOf( "}", stencilIdx ); + if( stencilEndIdx > 0 ) + { + string stencilParams = subBody.Substring( stencilIdx, stencilEndIdx + 1 - stencilIdx ); + m_stencilData.StencilBufferId = stencilParams; + TemplateHelperFunctions.CreateStencilOps( stencilParams, ref m_stencilData ); + if( m_stencilData.DataCheck == TemplateDataCheck.Valid ) + { + AddId( stencilParams, true ); + } + } + } + } + + //ZWRITE + { + int zWriteOpIdx = subBody.IndexOf( "ZWrite" ); + if( zWriteOpIdx > -1 ) + { + int zWriteEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zWriteOpIdx ); + if( zWriteEndIdx > 0 ) + { + m_depthData.ZWriteModeId = subBody.Substring( zWriteOpIdx, zWriteEndIdx + 1 - zWriteOpIdx ); + TemplateHelperFunctions.CreateZWriteMode( m_depthData.ZWriteModeId, ref m_depthData ); + if( m_depthData.DataCheck == TemplateDataCheck.Valid ) + { + AddId( m_depthData.ZWriteModeId, true ); + } + } + } + } + + //ZTEST + { + int zTestOpIdx = subBody.IndexOf( "ZTest" ); + if( zTestOpIdx > -1 ) + { + int zTestEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zTestOpIdx ); + if( zTestEndIdx > 0 ) + { + m_depthData.ZTestModeId = subBody.Substring( zTestOpIdx, zTestEndIdx + 1 - zTestOpIdx ); + TemplateHelperFunctions.CreateZTestMode( m_depthData.ZTestModeId, ref m_depthData ); + if( m_depthData.DataCheck == TemplateDataCheck.Valid ) + { + AddId( m_depthData.ZTestModeId, true ); + } + } + } + } + + //ZOFFSET + { + int zOffsetIdx = subBody.IndexOf( "Offset" ); + if( zOffsetIdx > -1 ) + { + int zOffsetEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zOffsetIdx ); + if( zOffsetEndIdx > 0 ) + { + m_depthData.OffsetId = subBody.Substring( zOffsetIdx, zOffsetEndIdx + 1 - zOffsetIdx ); + TemplateHelperFunctions.CreateZOffsetMode( m_depthData.OffsetId, ref m_depthData ); + if( m_depthData.DataCheck == TemplateDataCheck.Valid ) + { + AddId( m_depthData.OffsetId, true ); + } + } + } + + m_depthData.SetDataCheck(); + } + + //TAGS + { + int tagsIdx = subBody.IndexOf( "Tags" ); + if( tagsIdx > -1 ) + { + int tagsEndIdx = subBody.IndexOf( "}", tagsIdx ); + if( tagsEndIdx > -1 ) + { + m_tagData.Reset(); + m_tagData.TagsId = subBody.Substring( tagsIdx, tagsEndIdx + 1 - tagsIdx ); + TemplateHelperFunctions.CreateTags( ref m_tagData, true ); + m_tagData.DataCheck = TemplateDataCheck.Valid; + AddId( m_tagData.TagsId, false ); + } + else + { + m_tagData.DataCheck = TemplateDataCheck.Invalid; + } + } + else + { + m_tagData.DataCheck = TemplateDataCheck.Invalid; + } + } + } + } + + void FetchCommonTags() + { + // Name + try + { + int nameBegin = m_templateBody.IndexOf( TemplatesManager.TemplateShaderNameBeginTag ); + if( nameBegin < 0 ) + { + // Not a template + return; + } + + int nameEnd = m_templateBody.IndexOf( TemplatesManager.TemplateFullEndTag, nameBegin ); + int defaultBegin = nameBegin + TemplatesManager.TemplateShaderNameBeginTag.Length; + int defaultLength = nameEnd - defaultBegin; + m_defaultShaderName = m_templateBody.Substring( defaultBegin, defaultLength ); + int[] nameIdx = m_defaultShaderName.AllIndexesOf( "\"" ); + nameIdx[ 0 ] += 1; // Ignore the " character from the string + m_defaultShaderName = m_defaultShaderName.Substring( nameIdx[ 0 ], nameIdx[ 1 ] - nameIdx[ 0 ] ); + m_shaderNameId = m_templateBody.Substring( nameBegin, nameEnd + TemplatesManager.TemplateFullEndTag.Length - nameBegin ); + AddId( m_shaderNameId, false ); + + } + catch( Exception e ) + { + Debug.LogException( e ); + m_isValid = false; + } + + FetchSubShaderProperties(); + // Vertex Data + { + int vertexDataTagBegin = m_templateBody.IndexOf( TemplatesManager.TemplateVertexDataTag ); + if( vertexDataTagBegin > -1 ) + { + m_vertexDataContainer.VertexDataStartIdx = vertexDataTagBegin; + int vertexDataTagEnd = m_templateBody.IndexOf( TemplatesManager.TemplateEndOfLine, vertexDataTagBegin ); + m_vertexDataContainer.VertexDataId = m_templateBody.Substring( vertexDataTagBegin, vertexDataTagEnd + TemplatesManager.TemplateEndOfLine.Length - vertexDataTagBegin ); + int dataBeginIdx = m_templateBody.LastIndexOf( '{', vertexDataTagBegin, vertexDataTagBegin ); + string vertexData = m_templateBody.Substring( dataBeginIdx + 1, vertexDataTagBegin - dataBeginIdx ); + + int parametersBegin = vertexDataTagBegin + TemplatesManager.TemplateVertexDataTag.Length; + string parameters = m_templateBody.Substring( parametersBegin, vertexDataTagEnd - parametersBegin ); + m_vertexDataContainer.VertexData = TemplateHelperFunctions.CreateVertexDataList( vertexData, parameters ); + AddId( m_vertexDataContainer.VertexDataId ); + } + } + + // Available interpolators + try + { + int interpDataBegin = m_templateBody.IndexOf( TemplatesManager.TemplateInterpolatorBeginTag ); + if( interpDataBegin > -1 ) + { + int interpDataEnd = m_templateBody.IndexOf( TemplatesManager.TemplateEndOfLine, interpDataBegin ); + string interpDataId = m_templateBody.Substring( interpDataBegin, interpDataEnd + TemplatesManager.TemplateEndOfLine.Length - interpDataBegin ); + + int dataBeginIdx = m_templateBody.LastIndexOf( '{', interpDataBegin, interpDataBegin ); + string interpData = m_templateBody.Substring( dataBeginIdx + 1, interpDataBegin - dataBeginIdx ); + + m_interpolatorDataContainer = TemplateHelperFunctions.CreateInterpDataList( interpData, interpDataId, 8 ); + m_interpolatorDataContainer.InterpDataId = interpDataId; + m_interpolatorDataContainer.InterpDataStartIdx = interpDataBegin; + AddId( interpDataId ); + } + } + catch( Exception e ) + { + Debug.LogException( e ); + m_isValid = false; + } + + + try + { + Dictionary duplicatesHelper = new Dictionary(); + m_availableShaderProperties = new List(); + + // Common Tags + for( int i = 0; i < TemplatesManager.CommonTags.Length; i++ ) + { + int idx = m_templateBody.IndexOf( TemplatesManager.CommonTags[ i ].Id ); + if( idx > -1 ) + { + string currentId = TemplatesManager.CommonTags[ i ].Id; + + TemplateCommonTagId commonTagId = (TemplateCommonTagId)i; + switch( commonTagId ) + { + // Properties + case TemplateCommonTagId.Property: + { + TemplateHelperFunctions.CreateShaderPropertiesList( m_templateBody.Substring( 0, idx + TemplatesManager.CommonTags[ i ].Id.Length ), ref m_availableShaderProperties, ref duplicatesHelper,-1,-1 ); + } + break; + // Globals + case TemplateCommonTagId.Global: + { + TemplateHelperFunctions.CreateShaderGlobalsList( m_templateBody.Substring( 0, idx + TemplatesManager.CommonTags[ i ].Id.Length ), ref m_availableShaderProperties, ref duplicatesHelper,-1,-1 ); + } + break; + + //Tags + //case TemplateCommonTagId.Tag: + //{ + // m_propertyList[ m_propertyList.Count - 1 ].Indentation = " "; + //} + //break; + //case TemplateCommonTagId.CullMode: + //{ + // int newId = idx + TemplatesManager.CommonTags[ i ].Id.Length; + // int end = m_templateBody.IndexOf( TemplatesManager.TemplateNewLine, newId ); + // string cullParams = m_templateBody.Substring( newId, end - newId ); + // currentId = m_templateBody.Substring( idx, end - idx ); + // m_cullModeData.CullModeId = currentId; + // TemplateHelperFunctions.CreateCullMode( cullParams, ref m_cullModeData ); + //} + //break; + //Blend Mode + //case TemplateCommonTagId.BlendMode: + //{ + // int newId = idx + TemplatesManager.CommonTags[ i ].Id.Length; + // int end = m_templateBody.IndexOf( TemplatesManager.TemplateNewLine, newId ); + // string blendParams = m_templateBody.Substring( newId, end - newId ); + // currentId = m_templateBody.Substring( idx, end - idx ); + // m_blendData.BlendModeId = currentId; + // TemplateHelperFunctions.CreateBlendMode( blendParams, ref m_blendData ); + //}break; + //case TemplateCommonTagId.BlendOp: + //{ + // int newId = idx + TemplatesManager.CommonTags[ i ].Id.Length; + // int end = m_templateBody.IndexOf( TemplatesManager.TemplateNewLine, newId ); + // currentId = m_templateBody.Substring( idx, end - idx ); + // BlendData.BlendOpId = currentId; + // TemplateHelperFunctions.CreateBlendOp( m_templateBody.Substring( newId, end - newId ), ref m_blendData ); + //}break; + //case TemplateCommonTagId.ColorMask: + //{ + // int newId = idx + TemplatesManager.CommonTags[ i ].Id.Length; + // int end = m_templateBody.IndexOf( TemplatesManager.TemplateNewLine, newId ); + // string colorMaskParams = m_templateBody.Substring( newId, end - newId ); + // currentId = m_templateBody.Substring( idx, end - idx ); + // m_colorMaskData.ColorMaskId = currentId; + // TemplateHelperFunctions.CreateColorMask( colorMaskParams, ref m_colorMaskData ); + //} + //break; + //case TemplateCommonTagId.StencilOp: + //{ + // int id = m_templateBody.LastIndexOf( "Stencil" ); + // if( id > -1 ) + // { + // string stencilParams = m_templateBody.Substring( id, idx - id ); + // currentId = stencilParams + TemplatesManager.TemplateStencilOpTag; + // m_stencilData.StencilBufferId = currentId; + // TemplateHelperFunctions.CreateStencilOps( stencilParams, ref m_stencilData ); + // } + + //} + //break; + default: + break; + } + + //AddId( TemplatesManager.CommonTags[ i ] ); + AddId( currentId, TemplatesManager.CommonTags[ i ].SearchIndentation, TemplatesManager.CommonTags[ i ].CustomIndentation ); + } + } + + duplicatesHelper.Clear(); + duplicatesHelper = null; + } + catch( Exception e ) + { + Debug.LogException( e ); + m_isValid = false; + } + } + + void FetchCodeAreas( string begin, MasterNodePortCategory category ) + { + int areaBeginIndexes = m_templateBody.IndexOf( begin ); + + if( areaBeginIndexes > -1 ) + { + int beginIdx = areaBeginIndexes + begin.Length; + int endIdx = m_templateBody.IndexOf( TemplatesManager.TemplateEndOfLine, beginIdx ); + int length = endIdx - beginIdx; + + string parameters = m_templateBody.Substring( beginIdx, length ); + + string[] parametersArr = parameters.Split( IOUtils.FIELD_SEPARATOR ); + + string id = m_templateBody.Substring( areaBeginIndexes, endIdx + TemplatesManager.TemplateEndOfLine.Length - areaBeginIndexes ); + string inParameters = parametersArr[ 0 ]; + string outParameters = ( parametersArr.Length > 1 ) ? parametersArr[ 1 ] : string.Empty; + if( category == MasterNodePortCategory.Fragment ) + { + m_fragmentFunctionData = new TemplateFunctionData(-1, string.Empty, id, areaBeginIndexes, inParameters, outParameters, category ); + } + else + { + m_vertexFunctionData = new TemplateFunctionData( -1, string.Empty,id, areaBeginIndexes, inParameters, outParameters, category ); + } + AddId( id, true ); + } + } + + void FetchInputs( MasterNodePortCategory portCategory ) + { + string beginTag = ( portCategory == MasterNodePortCategory.Fragment ) ? TemplatesManager.TemplateInputsFragBeginTag : TemplatesManager.TemplateInputsVertBeginTag; + int[] inputBeginIndexes = m_templateBody.AllIndexesOf( beginTag ); + if( inputBeginIndexes != null && inputBeginIndexes.Length > 0 ) + { + for( int i = 0; i < inputBeginIndexes.Length; i++ ) + { + int inputEndIdx = m_templateBody.IndexOf( TemplatesManager.TemplateEndSectionTag, inputBeginIndexes[ i ] ); + int defaultValueBeginIdx = inputEndIdx + TemplatesManager.TemplateEndSectionTag.Length; + int endLineIdx = m_templateBody.IndexOf( TemplatesManager.TemplateFullEndTag, defaultValueBeginIdx ); + + string defaultValue = m_templateBody.Substring( defaultValueBeginIdx, endLineIdx - defaultValueBeginIdx ); + string tagId = m_templateBody.Substring( inputBeginIndexes[ i ], endLineIdx + TemplatesManager.TemplateFullEndTag.Length - inputBeginIndexes[ i ] ); + + int beginIndex = inputBeginIndexes[ i ] + beginTag.Length; + int length = inputEndIdx - beginIndex; + string inputData = m_templateBody.Substring( beginIndex, length ); + string[] inputDataArray = inputData.Split( IOUtils.FIELD_SEPARATOR ); + if( inputDataArray != null && inputDataArray.Length > 0 ) + { + try + { + string portName = inputDataArray[ (int)TemplatePortIds.Name ]; + WirePortDataType dataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), inputDataArray[ (int)TemplatePortIds.DataType ].ToUpper() ); + + int portUniqueIDArrIdx = (int)TemplatePortIds.UniqueId; + int portUniqueId = ( portUniqueIDArrIdx < inputDataArray.Length ) ? Convert.ToInt32( inputDataArray[ portUniqueIDArrIdx ] ) : -1; + if( portUniqueId < 0 ) + portUniqueId = m_inputDataList.Count; + + int portOrderArrayIdx = (int)TemplatePortIds.OrderId; + int portOrderId = ( portOrderArrayIdx < inputDataArray.Length ) ? Convert.ToInt32( inputDataArray[ portOrderArrayIdx ] ) : -1; + if( portOrderId < 0 ) + portOrderId = m_inputDataList.Count; + + AddInput( inputBeginIndexes[ i ], tagId, portName, defaultValue, dataType, portCategory, portUniqueId, portOrderId ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + } + } + } + + //void FetchSnippets() + //{ + // int[] codeSnippetAttribBeginIndexes = m_templateBody.AllIndexesOf( TemplatesManager.TemplateCodeSnippetAttribBegin ); + // int[] codeSnippetAttribEndIndexes = m_templateBody.AllIndexesOf( TemplatesManager.TemplateCodeSnippetAttribEnd ); + // int[] codeSnippetEndIndexes = m_templateBody.AllIndexesOf( TemplatesManager.TemplateCodeSnippetEnd ); + + // if( codeSnippetAttribBeginIndexes != null && codeSnippetAttribBeginIndexes.Length > 0 && + // codeSnippetAttribEndIndexes != null && codeSnippetAttribEndIndexes.Length > 0 && + // codeSnippetEndIndexes != null && codeSnippetEndIndexes.Length > 0 && + // codeSnippetEndIndexes.Length == codeSnippetAttribBeginIndexes.Length && + // codeSnippetAttribBeginIndexes.Length == codeSnippetAttribEndIndexes.Length ) + // { + // for( int i = 0; i < codeSnippetAttribBeginIndexes.Length; i++ ) + // { + // // get attributes + // int startAttribIndex = codeSnippetAttribBeginIndexes[ i ] + TemplatesManager.TemplateCodeSnippetAttribBegin.Length; + // int lengthAttrib = codeSnippetAttribEndIndexes[ i ] - startAttribIndex; + // string snippetAttribs = m_templateBody.Substring( startAttribIndex, lengthAttrib ); + // string[] snippetAttribsArr = snippetAttribs.Split( IOUtils.FIELD_SEPARATOR ); + // if( snippetAttribsArr != null && snippetAttribsArr.Length > 0 ) + // { + // string attribName = snippetAttribsArr[ (int)TemplateCodeSnippetInfoIdx.Name ]; + // TemplateCodeSnippetType attribType = (TemplateCodeSnippetType)Enum.Parse( typeof( TemplateCodeSnippetType ), snippetAttribsArr[ (int)TemplateCodeSnippetInfoIdx.Type ] ); + // if( m_snippetElementsDict.ContainsKey( attribName ) ) + // { + // if( m_snippetElementsDict[ attribName ].Type != attribType ) + // { + // if( DebugConsoleWindow.DeveloperMode ) + // Debug.LogWarning( "Found incompatible types for snippet " + attribName ); + // } + // } + // else + // { + // switch( attribType ) + // { + // case TemplateCodeSnippetType.Toggle: + // { + // //Register must be done by first instantiang the correct type and register it on both containers + // //Overrides don't work if we use the container reference into the other + // TemplateCodeSnippetToggle newSnippet = ScriptableObject.CreateInstance(); + // newSnippet.Init( attribName, attribType ); + // m_snippetElementsDict.Add( attribName, newSnippet ); + // m_snippetElementsList.Add( newSnippet ); + // } + // break; + // } + + // } + // // Add initial tag indentation + // int indentationIndex = codeSnippetAttribBeginIndexes[ i ]; + // int lengthAdjust = 0; + // for( ; indentationIndex > 0; indentationIndex--, lengthAdjust++ ) + // { + // if( m_templateBody[ indentationIndex ] == TemplatesManager.TemplateNewLine ) + // { + // indentationIndex += 1; + // lengthAdjust -= 1; + // break; + // } + // } + + // if( indentationIndex > 0 ) + // { + // string snippetId = m_templateBody.Substring( indentationIndex, + // codeSnippetEndIndexes[ i ] + TemplatesManager.TemplateCodeSnippetEnd.Length - codeSnippetAttribBeginIndexes[ i ] + lengthAdjust ); + + // int snippetCodeStart = codeSnippetAttribEndIndexes[ i ] + TemplatesManager.TemplateCodeSnippetAttribEnd.Length; + // int snippetCodeLength = codeSnippetEndIndexes[ i ] - snippetCodeStart; + // //Remove possible identation characters present between tag and last instruction + // if( m_templateBody[ snippetCodeStart + snippetCodeLength - 1 ] != TemplatesManager.TemplateNewLine ) + // { + // for( ; snippetCodeLength > 0; snippetCodeLength-- ) + // { + // if( m_templateBody[ snippetCodeStart + snippetCodeLength - 1 ] == TemplatesManager.TemplateNewLine ) + // break; + // } + // } + + // if( snippetCodeLength > 0 ) + // { + // string snippetCode = m_templateBody.Substring( snippetCodeStart, snippetCodeLength ); + // TemplateCodeSnippetElement element = new TemplateCodeSnippetElement( snippetId, snippetCode ); + // m_snippetElementsDict[ attribName ].AddSnippet( element ); + // } + // } + // } + // } + // } + //} + + //void RefreshSnippetInfo() + //{ + // if( m_snippetElementsDict == null ) + // { + // m_snippetElementsDict = new Dictionary(); + // } + + // if( m_snippetElementsDict.Count != m_snippetElementsList.Count ) + // { + // m_snippetElementsDict.Clear(); + // for( int i = 0; i < m_snippetElementsList.Count; i++ ) + // { + // m_snippetElementsDict.Add( m_snippetElementsList[ i ].NameId, m_snippetElementsList[ i ] ); + // } + // } + //} + + //public void DrawSnippetProperties( ParentNode owner ) + //{ + // for( int i = 0; i < m_snippetElementsList.Count; i++ ) + // { + // m_snippetElementsList[ i ].DrawProperties( owner ); + // } + //} + + //public void InsertSnippets( ref string shaderBody ) + //{ + // for( int i = 0; i < m_snippetElementsList.Count; i++ ) + // { + // m_snippetElementsList[ i ].InsertSnippet( ref shaderBody ); + // } + //} + + public void AddId( string ID, bool searchIndentation = true ) + { + AddId( ID, searchIndentation, string.Empty ); + } + + public void AddId( string ID, bool searchIndentation, string customIndentation ) + { + int propertyIndex = m_templateBody.IndexOf( ID ); + if( propertyIndex > -1 ) + { + if( searchIndentation ) + { + int indentationIndex = -1; + for( int i = propertyIndex; i > 0; i-- ) + { + if( m_templateBody[ i ] == TemplatesManager.TemplateNewLine ) + { + indentationIndex = i + 1; + break; + } + } + if( indentationIndex > -1 ) + { + int length = propertyIndex - indentationIndex; + string indentation = ( length > 0 ) ? m_templateBody.Substring( indentationIndex, length ) : string.Empty; + m_propertyList.Add( new TemplateProperty( ID, indentation, false ) ); + } + } + else + { + m_propertyList.Add( new TemplateProperty( ID, customIndentation, true ) ); + } + } + } + + void BuildInfo() + { + if( m_propertyDict == null ) + { + m_propertyDict = new Dictionary(); + } + + if( m_propertyList.Count != m_propertyDict.Count ) + { + m_propertyDict.Clear(); + for( int i = 0; i < m_propertyList.Count; i++ ) + { + m_propertyDict.Add( m_propertyList[ i ].Id, m_propertyList[ i ] ); + } + } + } + + public void ResetTemplateUsageData() + { + BuildInfo(); + for( int i = 0; i < m_propertyList.Count; i++ ) + { + m_propertyList[ i ].Used = false; + } + } + + public void AddInput( int tagStartIdx, string tagId, string portName, string defaultValue, WirePortDataType dataType, MasterNodePortCategory portCategory, int portUniqueId, int portOrderId ) + { + TemplateInputData inputData = new TemplateInputData( tagStartIdx, tagStartIdx, tagId, portName, defaultValue, dataType, portCategory, portUniqueId, portOrderId, string.Empty ); + m_inputDataList.Add( inputData ); + m_inputDataDict.Add( inputData.PortUniqueId, inputData ); + AddId( tagId, false ); + } + + public override void Destroy() + { + if( m_vertexDataContainer != null ) + { + m_vertexDataContainer.Destroy(); + m_vertexDataContainer = null; + } + + if( m_interpolatorDataContainer != null ) + { + m_interpolatorDataContainer.Destroy(); + m_interpolatorDataContainer = null; + } + + if( m_availableShaderProperties != null ) + { + m_availableShaderProperties.Clear(); + m_availableShaderProperties = null; + } + + if( m_propertyDict != null ) + { + m_propertyDict.Clear(); + m_propertyDict = null; + } + + if( m_propertyList != null ) + { + m_propertyList.Clear(); + m_propertyList = null; + } + + if( m_inputDataDict != null ) + { + m_inputDataDict.Clear(); + m_inputDataDict = null; + } + + if( m_inputDataList != null ) + { + m_inputDataList.Clear(); + m_inputDataList = null; + } + + if( m_localVarsList != null ) + { + m_localVarsList.Clear(); + m_localVarsList = null; + } + //if( m_snippetElementsDict != null ) + //{ + // m_snippetElementsDict.Clear(); + // m_snippetElementsDict = null; + //} + + //if( m_snippetElementsList != null ) + //{ + // for( int i = 0; i < m_snippetElementsList.Count; i++ ) + // { + // GameObject.DestroyImmediate( m_snippetElementsList[ i ] ); + // m_snippetElementsList[ i ] = null; + // } + // m_snippetElementsList.Clear(); + // m_snippetElementsList = null; + //} + + m_alphaToMaskData = null; + m_cullModeData = null; + m_blendData = null; + m_colorMaskData = null; + m_stencilData = null; + if( m_tagData != null ) + { + m_tagData.Destroy(); + m_tagData = null; + } + } + + public void FillEmptyTags( ref string body ) + { + body = body.Replace( TemplatesManager.TemplateLocalVarTag, string.Empty ); + for( int i = 0; i < m_propertyList.Count; i++ ) + { + if( !m_propertyList[ i ].Used ) + { + if( m_propertyList[ i ].UseCustomIndentation ) + { + body = body.Replace( m_propertyList[ i ].Id, string.Empty ); + } + else + { + body = body.Replace( m_propertyList[ i ].Indentation + m_propertyList[ i ].Id, string.Empty ); + } + } + } + } + + public bool FillVertexInstructions( ref string body, params string[] values ) + { + if( m_vertexFunctionData != null && !string.IsNullOrEmpty( m_vertexFunctionData.Id ) ) + { + return FillTemplateBody( m_vertexFunctionData.Id, ref body, values ); + } + + if( values.Length > 0 ) + { + UIUtils.ShowMessage( "Attemping to add vertex instructions on a template with no assigned vertex code area", MessageSeverity.Error ); + return false; + } + return true; + } + + public bool FillFragmentInstructions( ref string body, params string[] values ) + { + if( m_fragmentFunctionData != null && !string.IsNullOrEmpty( m_fragmentFunctionData.Id ) ) + { + return FillTemplateBody( m_fragmentFunctionData.Id, ref body, values ); + } + + if( values.Length > 0 ) + { + UIUtils.ShowMessage( "Attemping to add fragment instructions on a template with no assigned vertex code area", MessageSeverity.Error ); + return false; + } + return true; + } + + // values must be unindented an without line feed + public bool FillTemplateBody( string id, ref string body, params string[] values ) + { + if( values.Length == 0 ) + { + return true; + } + + BuildInfo(); + + if( m_propertyDict.ContainsKey( id ) ) + { + string finalValue = string.Empty; + for( int i = 0; i < values.Length; i++ ) + { + + if( m_propertyDict[ id ].AutoLineFeed ) + { + string[] valuesArr = values[ i ].Split( '\n' ); + for( int j = 0; j < valuesArr.Length; j++ ) + { + //first value will be automatically indented by the string replace + finalValue += ( ( i == 0 && j == 0 ) ? string.Empty : m_propertyDict[ id ].Indentation ) + valuesArr[ j ]; + finalValue += TemplatesManager.TemplateNewLine; + } + + } + else + { + //first value will be automatically indented by the string replace + finalValue += ( i == 0 ? string.Empty : m_propertyDict[ id ].Indentation ) + values[ i ]; + } + } + + body = body.Replace( id, finalValue ); + m_propertyDict[ id ].Used = true; + return true; + } + + if( values.Length > 1 || !string.IsNullOrEmpty( values[ 0 ] ) ) + { + UIUtils.ShowMessage( string.Format( "Attempting to write data into inexistant tag {0}. Please review the template {1} body and consider adding the missing tag.", id, m_name ), MessageSeverity.Error ); + return false; + } + + return true; + + } + + public bool FillTemplateBody( string id, ref string body, List values ) + { + if( values.Count == 0 ) + { + return true; + } + + string[] array = new string[ values.Count ]; + for( int i = 0; i < values.Count; i++ ) + { + array[ i ] = values[ i ].PropertyName; + } + return FillTemplateBody( id, ref body, array ); + } + + public TemplateInputData InputDataFromId( int id ) + { + if( m_inputDataDict == null ) + m_inputDataDict = new Dictionary(); + + if( m_inputDataDict.Count != m_inputDataList.Count ) + { + m_inputDataDict.Clear(); + for( int i = 0; i < m_inputDataList.Count; i++ ) + { + m_inputDataDict.Add( m_inputDataList[ i ].PortUniqueId, m_inputDataList[ i ] ); + } + } + + if( m_inputDataDict.ContainsKey( id ) ) + return m_inputDataDict[ id ]; + + return null; + } + + public string GetVertexData( TemplateInfoOnSematics info ) + { + int count = m_vertexDataContainer.VertexData.Count; + for( int i = 0; i < count; i++ ) + { + if( m_vertexDataContainer.VertexData[ i ].DataInfo == info ) + { + return string.Format( TemplateHelperFunctions.TemplateVarFormat, m_vertexFunctionData.InVarName, m_vertexDataContainer.VertexData[ i ].VarName ); + } + } + return string.Empty; + } + + public string GetInterpolatedData( TemplateInfoOnSematics info ) + { + int count = m_interpolatorDataContainer.Interpolators.Count; + for( int i = 0; i < count; i++ ) + { + if( m_interpolatorDataContainer.Interpolators[ i ].DataInfo == info ) + { + return string.Format( TemplateHelperFunctions.TemplateVarFormat, m_fragmentFunctionData.InVarName, m_interpolatorDataContainer.Interpolators[ i ].VarName ); + } + } + return string.Empty; + } + + public string InterpDataId { get { return m_interpolatorDataContainer.InterpDataId; } } + public string VertexDataId { get { return m_vertexDataContainer.VertexDataId; } } + public string ShaderNameId { get { return m_shaderNameId; } set { m_shaderNameId = value; } } + public string TemplateBody { get { return m_templateBody; } set { m_templateBody = value; } } + public List InputDataList { get { return m_inputDataList; } set { m_inputDataList = value; } } + public List LocalVarsList { get { return m_localVarsList; } } + public List VertexDataList { get { return m_vertexDataContainer.VertexData; } } + public TemplateInterpData InterpolatorData { get { return m_interpolatorDataContainer; } } + public TemplateFunctionData VertexFunctionData { get { return m_vertexFunctionData; } set { m_vertexFunctionData = value; } } + public TemplateFunctionData FragmentFunctionData { get { return m_fragmentFunctionData; } set { m_fragmentFunctionData = value; } } + public List AvailableShaderProperties { get { return m_availableShaderProperties; } set { m_availableShaderProperties = value; } } + public TemplateBlendData BlendData { get { return m_blendData; } set { m_blendData = value; } } + public TemplateAlphaToMaskData AlphaToMaskData { get { return m_alphaToMaskData; } set { m_alphaToMaskData = value; } } + public TemplateCullModeData CullModeData { get { return m_cullModeData; } set { m_cullModeData = value; } } + public TemplateColorMaskData ColorMaskData { get { return m_colorMaskData; } set { m_colorMaskData = value; } } + public TemplateStencilData StencilData { get { return m_stencilData; } set { m_stencilData = value; } } + public TemplateDepthData DepthData { get { return m_depthData; } set { m_depthData = value; } } + public TemplateTagsModuleData TagData { get { return m_tagData; } set { m_tagData = value; } } + private List PropertyList { get { return m_propertyList; } set { m_propertyList = value; } } + public VertexDataContainer VertexDataContainer { get { return m_vertexDataContainer; } set { m_vertexDataContainer = value; } } + public TemplateInterpData InterpolatorDataContainer { get { return m_interpolatorDataContainer; } set { m_interpolatorDataContainer = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs.meta new file mode 100644 index 0000000..2002009 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b03340e569366ae4dbd502e14c62e225 +timeCreated: 1493904667 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs new file mode 100644 index 0000000..f7c5a04 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs @@ -0,0 +1,2153 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System; + +namespace AmplifyShaderEditor +{ + public enum NormalizeType + { + Off, + Regular, + Safe + } + + public class InterpDataHelper + { + public string VarName; + public WirePortDataType VarType; + public bool IsSingleComponent; + public bool SetAtCompileTime; + public InterpDataHelper( WirePortDataType varType, string varName, bool isSingleComponent = true , bool setAtCompileTime = false ) + { + VarName = varName; + VarType = varType; + IsSingleComponent = isSingleComponent; + SetAtCompileTime = setAtCompileTime; + } + } + + public class TemplateCustomData + { + public WirePortDataType DataType; + public string Name; + public bool IsVertex; + public bool IsFragment; + public TemplateCustomData( string name, WirePortDataType dataType ) + { + name = Name; + DataType = dataType; + IsVertex = false; + IsFragment = false; + } + } + + public class TemplateInputParameters + { + public WirePortDataType Type; + public string Name; + public string Declaration; + public TemplateSemantics Semantic; + public TemplateInputParameters( WirePortDataType type, PrecisionType precision, string name, TemplateSemantics semantic, string custom = null ) + { + Type = type; + Name = name; + Semantic = semantic; + Declaration = string.Format( "{0} {1} : {2}", UIUtils.PrecisionWirePortToCgType( precision, type ), Name, Semantic ); + if( !string.IsNullOrEmpty( custom ) ) + Declaration = custom; + } + } + + public class TemplateDataCollector + { +#if UNITY_2018_2_OR_NEWER + private const int MaxUV = 8; + private int[] m_UVUsage = { 0, 0, 0, 0, 0, 0, 0, 0 }; +#else + private const int MaxUV = 4; + private int[] m_UVUsage = { 0, 0, 0, 0 }; +#endif + private int m_multipassSubshaderIdx = 0; + private int m_multipassPassIdx = 0; + private TemplateMultiPass m_currentTemplate; + private TemplateSRPType m_currentSRPType = TemplateSRPType.BuiltIn; + + private Dictionary m_customInterpolatedData; + private Dictionary m_registeredVertexData; + + private Dictionary m_availableFragData; + private Dictionary m_availableVertData; + private TemplateInterpData m_interpolatorData; + private Dictionary m_vertexDataDict; + private TemplateData m_currentTemplateData; + private MasterNodeDataCollector m_currentDataCollector; + public Dictionary m_vertexInputParams; + public Dictionary m_fragmentInputParams; + + private Dictionary m_specialVertexLocalVars; + private Dictionary m_specialFragmentLocalVars; + + private List m_lateDirectivesList = new List(); + private Dictionary m_lateDirectivesDict = new Dictionary(); + + private List m_srpBatcherPropertiesList = new List(); + private List m_fullSrpBatcherPropertiesList = new List(); + private Dictionary m_srpBatcherPropertiesDict = new Dictionary(); + + public void CopySRPPropertiesFromDataCollector( int nodeId, TemplateDataCollector dataCollector ) + { + for( int i = 0; i < dataCollector.SrpBatcherPropertiesList.Count; i++ ) + { + AddSRPBatcherProperty( nodeId, dataCollector.SrpBatcherPropertiesList[ i ].PropertyName ); + } + } + + public void AddSRPBatcherProperty( int nodeID, string property ) + { + if( !m_srpBatcherPropertiesDict.ContainsKey( property ) ) + { + PropertyDataCollector newValue = new PropertyDataCollector( nodeID, property ); + m_srpBatcherPropertiesDict.Add( property, newValue ); + m_srpBatcherPropertiesList.Add( newValue ); + } + } + + public void SetUVUsage( int uv, WirePortDataType type ) + { + if( uv >= 0 && uv < MaxUV ) + { + m_UVUsage[ uv ] = Mathf.Max( m_UVUsage[ uv ], TemplateHelperFunctions.DataTypeChannelUsage[ type ] ); + } + } + + public void SetUVUsage( int uv, int size ) + { + if( uv >= 0 && uv < MaxUV ) + { + m_UVUsage[ uv ] = Mathf.Max( m_UVUsage[ uv ], size ); + } + } + + public void CloseLateDirectives() + { + if( m_lateDirectivesList.Count > 0 ) + { + m_lateDirectivesList.Add( new PropertyDataCollector( -1, string.Empty ) ); + } + } + + public void AddHDLightInfo() + { +#if !UNITY_2018_3_OR_NEWER + AddLateDirective( AdditionalLineType.Custom, "#if (SHADERPASS != SHADERPASS_FORWARD) //On forward this info is already included" ); + AddLateDirective( AdditionalLineType.Include, "HDRP/Lighting/LightDefinition.cs.hlsl" ); + AddLateDirective( AdditionalLineType.Include, "HDRP/Lighting/LightLoop/Shadow.hlsl" ); + AddLateDirective( AdditionalLineType.Include, "HDRP/Lighting/LightLoop/LightLoopDef.hlsl" ); + AddLateDirective( AdditionalLineType.Custom, "#endif // End of light info includes" ); +#endif + } + + public void AddLateDirective( AdditionalLineType type, string value ) + { + + if( !m_lateDirectivesDict.ContainsKey( value ) ) + { + string formattedValue = string.Empty; + switch( type ) + { + case AdditionalLineType.Include: formattedValue = string.Format( Constants.IncludeFormat, value ); break; + case AdditionalLineType.Define: formattedValue = string.Format( Constants.DefineFormat, value ); break; + case AdditionalLineType.Pragma: formattedValue = string.Format( Constants.PragmaFormat, value ); break; + case AdditionalLineType.Custom: formattedValue = value; break; + } + PropertyDataCollector property = new PropertyDataCollector( -1, formattedValue ); + m_lateDirectivesDict.Add( value, property ); + m_lateDirectivesList.Add( property ); + } + } + + public void SetMultipassInfo( TemplateMultiPass currentTemplate, int subShaderIdx, int passIdx, TemplateSRPType currentSRPType ) + { + m_currentTemplate = currentTemplate; + m_multipassSubshaderIdx = subShaderIdx; + m_multipassPassIdx = passIdx; + m_currentSRPType = currentSRPType; + } + + public bool HasDirective( AdditionalLineType type, string value ) + { + switch( type ) + { + case AdditionalLineType.Include: + { + return m_currentTemplate.SubShaders[ m_multipassSubshaderIdx ].Modules.IncludePragmaContainer.HasInclude( value ) || + m_currentTemplate.SubShaders[ m_multipassSubshaderIdx ].Passes[ m_multipassPassIdx ].Modules.IncludePragmaContainer.HasInclude( value ); + } + case AdditionalLineType.Define: + { + return m_currentTemplate.SubShaders[ m_multipassSubshaderIdx ].Modules.IncludePragmaContainer.HasDefine( value ) || + m_currentTemplate.SubShaders[ m_multipassSubshaderIdx ].Passes[ m_multipassPassIdx ].Modules.IncludePragmaContainer.HasDefine( value ); + } + case AdditionalLineType.Pragma: + { + return m_currentTemplate.SubShaders[ m_multipassSubshaderIdx ].Modules.IncludePragmaContainer.HasPragma( value ) || + m_currentTemplate.SubShaders[ m_multipassSubshaderIdx ].Passes[ m_multipassPassIdx ].Modules.IncludePragmaContainer.HasPragma( value ); + } + } + + return false; + } + + public void FillSpecialVariables( TemplatePass currentPass ) + { + m_specialVertexLocalVars = new Dictionary(); + m_specialFragmentLocalVars = new Dictionary(); + int localVarAmount = currentPass.LocalVarsList.Count; + for( int i = 0; i < localVarAmount; i++ ) + { + if( currentPass.LocalVarsList[ i ].IsSpecialVar ) + { + if( currentPass.LocalVarsList[ i ].Category == MasterNodePortCategory.Vertex ) + { + m_specialVertexLocalVars.Add( currentPass.LocalVarsList[ i ].SpecialVarType, currentPass.LocalVarsList[ i ] ); + } + else + { + m_specialFragmentLocalVars.Add( currentPass.LocalVarsList[ i ].SpecialVarType, currentPass.LocalVarsList[ i ] ); + } + } + } + } + + public void BuildFromTemplateData( MasterNodeDataCollector dataCollector, TemplateData templateData ) + { + m_registeredVertexData = new Dictionary(); + m_customInterpolatedData = new Dictionary(); + + + m_currentDataCollector = dataCollector; + m_currentTemplateData = templateData; + + m_vertexDataDict = new Dictionary(); + if( templateData.VertexDataList != null ) + { + for( int i = 0; i < templateData.VertexDataList.Count; i++ ) + { + m_vertexDataDict.Add( templateData.VertexDataList[ i ].Semantics, new TemplateVertexData( templateData.VertexDataList[ i ] ) ); + } + } + + m_availableFragData = new Dictionary(); + if( templateData.InterpolatorData != null && templateData.FragmentFunctionData != null ) + { + m_interpolatorData = new TemplateInterpData( templateData.InterpolatorData ); + int fragCount = templateData.InterpolatorData.Interpolators.Count; + for( int i = 0; i < fragCount; i++ ) + { + string varName = string.Empty; + if( templateData.InterpolatorData.Interpolators[ i ].ExcludeStructPrefix ) + { + varName = templateData.InterpolatorData.Interpolators[ i ].VarName; + } + else if( templateData.InterpolatorData.Interpolators[ i ].IsSingleComponent ) + { + varName = string.Format( TemplateHelperFunctions.TemplateVarFormat, + templateData.FragmentFunctionData.InVarName, + templateData.InterpolatorData.Interpolators[ i ].VarNameWithSwizzle ); + } + else + { + varName = string.Format( templateData.InterpolatorData.Interpolators[ i ].VarNameWithSwizzle, templateData.FragmentFunctionData.InVarName ); + } + + m_availableFragData.Add( templateData.InterpolatorData.Interpolators[ i ].DataInfo, + new InterpDataHelper( templateData.InterpolatorData.Interpolators[ i ].SwizzleType, + varName, + templateData.InterpolatorData.Interpolators[ i ].IsSingleComponent ) ); + } + } + + + m_availableVertData = new Dictionary(); + if( templateData.VertexFunctionData != null && templateData.VertexDataList != null ) + { + int vertCount = templateData.VertexDataList.Count; + for( int i = 0; i < vertCount; i++ ) + { + string varName = string.Empty; + if( templateData.VertexDataList[ i ].ExcludeStructPrefix ) + { + varName = templateData.VertexDataList[ i ].VarName; + } + else + { + varName = string.Format( TemplateHelperFunctions.TemplateVarFormat, templateData.VertexFunctionData.InVarName, templateData.VertexDataList[ i ].VarNameWithSwizzle ); + } + + m_availableVertData.Add( templateData.VertexDataList[ i ].DataInfo, + new InterpDataHelper( templateData.VertexDataList[ i ].SwizzleType, + varName, + templateData.VertexDataList[ i ].IsSingleComponent ) ); + } + } + } + + public void RegisterFragInputParams( WirePortDataType type, PrecisionType precision, string name, TemplateSemantics semantic, string custom ) + { + if( m_fragmentInputParams == null ) + m_fragmentInputParams = new Dictionary(); + + m_fragmentInputParams.Add( semantic, new TemplateInputParameters( type, precision, name, semantic, custom ) ); + } + + public void RegisterFragInputParams( WirePortDataType type, PrecisionType precision, string name, TemplateSemantics semantic ) + { + if( m_fragmentInputParams == null ) + m_fragmentInputParams = new Dictionary(); + + m_fragmentInputParams.Add( semantic, new TemplateInputParameters( type, precision, name, semantic ) ); + } + + public void RegisterVertexInputParams( WirePortDataType type, PrecisionType precision, string name, TemplateSemantics semantic ) + { + if( m_vertexInputParams == null ) + m_vertexInputParams = new Dictionary(); + + m_vertexInputParams.Add( semantic, new TemplateInputParameters( type, precision, name, semantic ) ); + } + + public string GetVertexId() + { + var precision = PrecisionType.Float; + bool useMasterNodeCategory = true; + MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment; + + WirePortDataType type = WirePortDataType.UINT; + if( HasInfo( TemplateInfoOnSematics.VERTEXID, useMasterNodeCategory, customCategory ) ) + { + InterpDataHelper info = GetInfo( TemplateInfoOnSematics.VERTEXID, useMasterNodeCategory, customCategory ); + return TemplateHelperFunctions.AutoSwizzleData( info.VarName, info.VarType, type, true ); + } + else + { + MasterNodePortCategory portCategory = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory; + string name = "ase_vertexID"; + return RegisterInfoOnSemantic( portCategory, TemplateInfoOnSematics.VERTEXID, TemplateSemantics.SV_VertexID, name, WirePortDataType.UINT, precision, true ); + } + + // need to review this later + //if( m_vertexInputParams != null && m_vertexInputParams.ContainsKey( TemplateSemantics.SV_VertexID ) ) + //{ + // if( m_currentDataCollector.PortCategory == MasterNodePortCategory.Vertex ) + // return m_vertexInputParams[ TemplateSemantics.SV_VertexID ].Name; + //} + //else + //{ + // RegisterVertexInputParams( WirePortDataType.UINT, PrecisionType.Float, TemplateHelperFunctions.SemanticsDefaultName[ TemplateSemantics.SV_VertexID ], TemplateSemantics.SV_VertexID ); + //} + + //if( m_currentDataCollector.PortCategory != MasterNodePortCategory.Vertex ) + // RegisterCustomInterpolatedData( m_vertexInputParams[ TemplateSemantics.SV_VertexID ].Name, WirePortDataType.INT, PrecisionType.Float, m_vertexInputParams[ TemplateSemantics.SV_VertexID ].Name ); + + //return m_vertexInputParams[ TemplateSemantics.SV_VertexID ].Name; + } +#if UNITY_EDITOR_WIN + public string GetPrimitiveId() + { + if( m_fragmentInputParams != null && m_fragmentInputParams.ContainsKey( TemplateSemantics.SV_PrimitiveID ) ) + return m_fragmentInputParams[ TemplateSemantics.SV_PrimitiveID ].Name; + + RegisterFragInputParams( WirePortDataType.UINT, PrecisionType.Half, TemplateHelperFunctions.SemanticsDefaultName[ TemplateSemantics.SV_PrimitiveID ], TemplateSemantics.SV_PrimitiveID ); + return m_fragmentInputParams[ TemplateSemantics.SV_PrimitiveID ].Name; + } +#endif + public string GetVFace( int uniqueId ) + { + #if UNITY_2018_3_OR_NEWER + if( IsSRP && ASEPackageManagerHelper.CurrentHDVersion >= ASESRPVersions.ASE_SRP_6_9_0 ) + { + string result = string.Empty; + if( GetCustomInterpolatedData( TemplateInfoOnSematics.VFACE, WirePortDataType.FLOAT, PrecisionType.Float, ref result, true, MasterNodePortCategory.Fragment ) ) + { + m_currentDataCollector.AddToDirectives( "#if !defined(ASE_NEED_CULLFACE)" ); + m_currentDataCollector.AddToDirectives( "#define ASE_NEED_CULLFACE 1" ); + m_currentDataCollector.AddToDirectives( "#endif //ASE_NEED_CULLFACE" ); + return result; + } + else + { + if( m_fragmentInputParams != null && m_fragmentInputParams.ContainsKey( TemplateSemantics.VFACE ) ) + return m_fragmentInputParams[ TemplateSemantics.VFACE ].Name; + + string custom = "FRONT_FACE_TYPE "+ TemplateHelperFunctions.SemanticsDefaultName[ TemplateSemantics.VFACE ] + " : FRONT_FACE_SEMANTIC"; + RegisterFragInputParams( WirePortDataType.FLOAT, PrecisionType.Half, TemplateHelperFunctions.SemanticsDefaultName[ TemplateSemantics.VFACE ], TemplateSemantics.VFACE, custom ); + return m_fragmentInputParams[ TemplateSemantics.VFACE ].Name; + } + } + else + #endif + { + m_currentDataCollector.AddFaceMacros(); + + //if( m_fragmentInputParams != null && m_fragmentInputParams.ContainsKey( TemplateSemantics.VFACE ) ) + // return m_fragmentInputParams[ TemplateSemantics.VFACE ].Name; + + //RegisterFragInputParams( WirePortDataType.FLOAT, PrecisionType.Half, TemplateHelperFunctions.SemanticsDefaultName[ TemplateSemantics.VFACE ], TemplateSemantics.VFACE ); + //return m_fragmentInputParams[ TemplateSemantics.VFACE ].Name; + if( m_fragmentInputParams != null && m_fragmentInputParams.ContainsKey( TemplateSemantics.VFACE ) ) + return m_fragmentInputParams[ TemplateSemantics.VFACE ].Name; + + string custom = "FRONT_FACE_TYPE " + TemplateHelperFunctions.SemanticsDefaultName[ TemplateSemantics.VFACE ] + " : FRONT_FACE_SEMANTIC"; + RegisterFragInputParams( WirePortDataType.FLOAT , PrecisionType.Half , TemplateHelperFunctions.SemanticsDefaultName[ TemplateSemantics.VFACE ] , TemplateSemantics.VFACE , custom ); + return m_fragmentInputParams[ TemplateSemantics.VFACE ].Name; + + } + } + + public string GetShadowCoords( int uniqueId, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + // overriding precision + var precision = PrecisionType.Float; + + string worldPos = GetWorldPos( false, m_currentDataCollector.PortCategory ); + + string result = string.Empty; + if( GetCustomInterpolatedData( TemplateInfoOnSematics.SHADOWCOORDS, WirePortDataType.FLOAT4, precision, ref result, useMasterNodeCategory, customCategory ) ) + { + return result; + } + + string varName = GeneratorUtils.ShadowCoordsStr; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + + string shadowCoordsValue = string.Format( "TransformWorldToShadowCoord({0})", worldPos ); + if( m_currentDataCollector.PortCategory == MasterNodePortCategory.Fragment ) + { + worldPos = GetWorldPos( false, MasterNodePortCategory.Vertex ); + m_currentDataCollector.AddLocalVariable( uniqueId, "#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) //la" ); + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT4, precision, string.Format( "TransformWorldToShadowCoord({0})", worldPos ), false, MasterNodePortCategory.Fragment ); + m_currentDataCollector.AddLocalVariable( uniqueId, "#elif defined(MAIN_LIGHT_CALCULATE_SHADOWS) //la" ); + m_currentDataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, varName, shadowCoordsValue ); + m_currentDataCollector.AddLocalVariable( uniqueId, "#else //la" ); + m_currentDataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, varName, "0" ); + m_currentDataCollector.AddLocalVariable( uniqueId, "#endif //la" ); + } else + { + m_currentDataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, varName, shadowCoordsValue ); + } + return varName; + } + + public bool HasUV( int uvChannel ) + { + return ( m_currentDataCollector.PortCategory == MasterNodePortCategory.Fragment ) ? m_availableFragData.ContainsKey( TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ) : m_availableVertData.ContainsKey( TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ); + } + + public string GetUVName( int uvChannel, WirePortDataType dataType = WirePortDataType.FLOAT2 ) + { + InterpDataHelper info = ( m_currentDataCollector.PortCategory == MasterNodePortCategory.Fragment ) ? m_availableFragData[ TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ] : m_availableVertData[ TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ]; + if( dataType != info.VarType ) + return info.VarName + UIUtils.GetAutoSwizzle( dataType ); + else + return info.VarName; + } + + public string GetTextureCoord( int uvChannel, string propertyName, int uniqueId, PrecisionType precisionType ) + { + bool isVertex = ( m_currentDataCollector.PortCategory == MasterNodePortCategory.Vertex || m_currentDataCollector.PortCategory == MasterNodePortCategory.Tessellation ); + string uvChannelName = string.Empty; + string propertyHelperVar = propertyName + "_ST"; + m_currentDataCollector.AddToUniforms( uniqueId, "float4", propertyHelperVar, IsSRP ); + string uvName = string.Empty; + string result = string.Empty; + if( GetCustomInterpolatedData( TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ], WirePortDataType.FLOAT2, PrecisionType.Float, ref result, false, m_currentDataCollector.PortCategory ) ) + { + uvName = result; + } + else + if( m_currentDataCollector.TemplateDataCollectorInstance.HasUV( uvChannel ) ) + { + uvName = m_currentDataCollector.TemplateDataCollectorInstance.GetUVName( uvChannel ); + } + else + { + uvName = m_currentDataCollector.TemplateDataCollectorInstance.RegisterUV( uvChannel ); + } + + uvChannelName = "uv" + propertyName; + if( isVertex ) + { + string value = string.Format( Constants.TilingOffsetFormat, uvName, propertyHelperVar + ".xy", propertyHelperVar + ".zw" ); + string lodLevel = "0"; + + value = "float4( " + value + ", 0 , " + lodLevel + " )"; + m_currentDataCollector.AddLocalVariable( uniqueId, precisionType, WirePortDataType.FLOAT4, uvChannelName, value ); + } + else + { + m_currentDataCollector.AddLocalVariable( uniqueId, precisionType, WirePortDataType.FLOAT2, uvChannelName, string.Format( Constants.TilingOffsetFormat, uvName, propertyHelperVar + ".xy", propertyHelperVar + ".zw" ) ); + } + return uvChannelName; + } + + public string GenerateAutoUVs( int uvChannel, WirePortDataType size = WirePortDataType.FLOAT2 ) + { + string uvName = string.Empty; + string result = string.Empty; + if( GetCustomInterpolatedData( TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ], size, PrecisionType.Float, ref result, false, m_currentDataCollector.PortCategory ) ) + { + uvName = result; + } + else + if( HasUV( uvChannel ) ) + { + uvName = GetUVName( uvChannel, size ); + } + else + { + uvName = RegisterUV( uvChannel, size ); + } + return uvName; + } + + public string GetUV( int uvChannel, MasterNodePortCategory category = MasterNodePortCategory.Fragment, WirePortDataType size = WirePortDataType.FLOAT4 ) + { + if( !HasUV( uvChannel ) ) + { + RegisterUV( uvChannel, size ); + } + + InterpDataHelper info = ( category == MasterNodePortCategory.Fragment ) ? m_availableFragData[ TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ] : m_availableVertData[ TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ]; + return info.VarName; + } + + public InterpDataHelper GetUVInfo( int uvChannel ) + { + return ( m_currentDataCollector.PortCategory == MasterNodePortCategory.Fragment ) ? m_availableFragData[ TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ] : m_availableVertData[ TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ]; + } + + public string RegisterUV( int UVChannel, WirePortDataType size = WirePortDataType.FLOAT2 ) + { + int channelsSize = TemplateHelperFunctions.DataTypeChannelUsage[ size ]; + WirePortDataType originalSize = size; + if( m_UVUsage[ UVChannel ] > channelsSize ) + { + size = TemplateHelperFunctions.ChannelToDataType[ m_UVUsage[ UVChannel ] ]; + } + + if( m_currentDataCollector.PortCategory == MasterNodePortCategory.Vertex ) + { + TemplateSemantics semantic = TemplateHelperFunctions.IntToSemantic[ UVChannel ]; + + if( m_vertexDataDict.ContainsKey( semantic ) ) + { + return m_vertexDataDict[ semantic ].VarName; + } + + string varName = TemplateHelperFunctions.BaseInterpolatorName + ( ( UVChannel > 0 ) ? UVChannel.ToString() : string.Empty ); + m_availableVertData.Add( TemplateHelperFunctions.IntToUVChannelInfo[ UVChannel ], + new InterpDataHelper( WirePortDataType.FLOAT4, + string.Format( TemplateHelperFunctions.TemplateVarFormat, + m_currentTemplateData.VertexFunctionData.InVarName, + varName ) ) ); + + m_currentDataCollector.AddToVertexInput( + string.Format( TemplateHelperFunctions.TexFullSemantic, + varName, + semantic ) ); + RegisterOnVertexData( semantic, size, varName ); + string finalVarName = m_availableVertData[ TemplateHelperFunctions.IntToUVChannelInfo[ UVChannel ] ].VarName; + switch( size ) + { + case WirePortDataType.FLOAT: + case WirePortDataType.INT: + case WirePortDataType.UINT: + finalVarName += ".x"; + break; + case WirePortDataType.FLOAT2: + finalVarName += ".xy"; + break; + case WirePortDataType.FLOAT3: + finalVarName += ".xyz"; + break; + case WirePortDataType.UINT4: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + case WirePortDataType.SAMPLERSTATE: + case WirePortDataType.OBJECT: + default: + break; + } + return finalVarName; + } + else + { + //search if the correct vertex data is set ... + TemplateInfoOnSematics info = TemplateHelperFunctions.IntToInfo[ UVChannel ]; + TemplateSemantics vertexSemantics = TemplateSemantics.NONE; + foreach( KeyValuePair kvp in m_vertexDataDict ) + { + if( kvp.Value.DataInfo == info ) + { + vertexSemantics = kvp.Key; + break; + } + } + + // if not, add vertex data and create interpolator + if( vertexSemantics == TemplateSemantics.NONE ) + { + vertexSemantics = TemplateHelperFunctions.IntToSemantic[ UVChannel ]; + + if( !m_vertexDataDict.ContainsKey( vertexSemantics ) ) + { + string varName = TemplateHelperFunctions.BaseInterpolatorName + ( ( UVChannel > 0 ) ? UVChannel.ToString() : string.Empty ); + m_availableVertData.Add( TemplateHelperFunctions.IntToUVChannelInfo[ UVChannel ], + new InterpDataHelper( WirePortDataType.FLOAT4, + string.Format( TemplateHelperFunctions.TemplateVarFormat, + m_currentTemplateData.VertexFunctionData.InVarName, + varName ) ) ); + + m_currentDataCollector.AddToVertexInput( + string.Format( TemplateHelperFunctions.TexFullSemantic, + varName, + vertexSemantics ) ); + RegisterOnVertexData( vertexSemantics, size, varName ); + } + } + + // either way create interpolator + TemplateVertexData availableInterp = RequestNewInterpolator( size, false ); + if( availableInterp != null ) + { + bool isPosition = vertexSemantics == TemplateSemantics.POSITION || vertexSemantics == TemplateSemantics.POSITION; + + string interpVarName = m_currentTemplateData.VertexFunctionData.OutVarName + "." + availableInterp.VarNameWithSwizzle; + InterpDataHelper vertInfo = m_availableVertData[ TemplateHelperFunctions.IntToUVChannelInfo[ UVChannel ] ]; + string interpDecl = string.Format( TemplateHelperFunctions.TemplateVariableDecl, interpVarName, TemplateHelperFunctions.AutoSwizzleData( vertInfo.VarName, vertInfo.VarType, size , isPosition ) ); + m_currentDataCollector.AddToVertexInterpolatorsDecl( interpDecl ); + string finalVarName = m_currentTemplateData.FragmentFunctionData.InVarName + "." + availableInterp.VarNameWithSwizzle; + m_availableFragData.Add( TemplateHelperFunctions.IntToUVChannelInfo[ UVChannel ], new InterpDataHelper( size, finalVarName ) ); + if( size != originalSize ) + { + //finalVarName = m_currentTemplateData.FragmentFunctionData.InVarName + "." + availableInterp.VarName + UIUtils.GetAutoSwizzle( originalSize ); + finalVarName = m_availableFragData[ TemplateHelperFunctions.IntToUVChannelInfo[ UVChannel ] ].VarName + UIUtils.GetAutoSwizzle( originalSize ); + } + return finalVarName; + } + } + return string.Empty; + } + //////////////////////////////////////////////////////////////////////////////////////////////// + bool IsSemanticUsedOnInterpolator( TemplateSemantics semantics ) + { + for( int i = 0; i < m_interpolatorData.Interpolators.Count; i++ ) + { + if( m_interpolatorData.Interpolators[ i ].Semantics == semantics ) + { + return true; + } + } + return false; + } + + public bool HasInfo( TemplateInfoOnSematics info, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory; + return ( category == MasterNodePortCategory.Fragment ) ? m_availableFragData.ContainsKey( info ) : m_availableVertData.ContainsKey( info ); + } + + public InterpDataHelper GetInfo( TemplateInfoOnSematics info, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory; + if( category == MasterNodePortCategory.Fragment ) + { + if( !m_availableFragData[ info ].SetAtCompileTime ) + { + string defineValue = string.Empty; + if( TemplateHelperFunctions.InfoToDefineFrag.TryGetValue( info, out defineValue ) ) + m_currentDataCollector.AddToDefines( -1, defineValue ); + } + return m_availableFragData[ info ]; + } + else + { + if( !m_availableVertData[ info ].SetAtCompileTime ) + { + string defineValue = string.Empty; + if( TemplateHelperFunctions.InfoToDefineVertex.TryGetValue( info, out defineValue ) ) + m_currentDataCollector.AddToDefines( -1, defineValue ); + } + return m_availableVertData[ info ]; + } + } + + public string RegisterInfoOnSemantic( TemplateInfoOnSematics info, TemplateSemantics semantic, string name, WirePortDataType dataType, PrecisionType precisionType, bool requestNewInterpolator, string dataName = null ) + { + return RegisterInfoOnSemantic( m_currentDataCollector.PortCategory, info, semantic, name, dataType, precisionType, requestNewInterpolator, dataName ); + } + // This should only be used to semantics outside the text coord set + public string RegisterInfoOnSemantic( MasterNodePortCategory portCategory, TemplateInfoOnSematics info, TemplateSemantics semantic, string name, WirePortDataType dataType, PrecisionType precisionType, bool requestNewInterpolator, string dataName = null ) + { + if( portCategory == MasterNodePortCategory.Vertex ) + { + if( m_vertexDataDict.ContainsKey( semantic ) ) + { + return m_vertexDataDict[ semantic ].VarName; + } + + m_availableVertData.Add( info, + new InterpDataHelper( dataType, + string.Format( TemplateHelperFunctions.TemplateVarFormat, + m_currentTemplateData.VertexFunctionData.InVarName, + name ),true,true ) ); + + string vertInputVarType = UIUtils.PrecisionWirePortToCgType( precisionType, dataType ); + m_currentDataCollector.AddToVertexInput( + string.Format( TemplateHelperFunctions.InterpFullSemantic, + vertInputVarType, + name, + semantic ) ); + RegisterOnVertexData( semantic, dataType, name ); + return m_availableVertData[ info ].VarName; + } + else + { + //search if the correct vertex data is set ... + TemplateSemantics vertexSemantics = TemplateSemantics.NONE; + foreach( KeyValuePair kvp in m_vertexDataDict ) + { + if( kvp.Value.DataInfo == info ) + { + vertexSemantics = kvp.Key; + break; + } + } + + // if not, add vertex data and create interpolator + if( vertexSemantics == TemplateSemantics.NONE ) + { + vertexSemantics = semantic; + + if( !m_vertexDataDict.ContainsKey( vertexSemantics ) ) + { + m_availableVertData.Add( info, + new InterpDataHelper( dataType, + string.Format( TemplateHelperFunctions.TemplateVarFormat, + m_currentTemplateData.VertexFunctionData.InVarName, + name ),true,true ) ); + + string vertInputVarType = UIUtils.PrecisionWirePortToCgType( precisionType, dataType ); + m_currentDataCollector.AddToVertexInput( + string.Format( TemplateHelperFunctions.InterpFullSemantic, + vertInputVarType, + name, + vertexSemantics ) ); + RegisterOnVertexData( vertexSemantics, dataType, name ); + } + } + + // either way create interpolator + + TemplateVertexData availableInterp = null; + if( requestNewInterpolator || IsSemanticUsedOnInterpolator( semantic ) ) + { + availableInterp = RequestNewInterpolator( dataType, false, dataName ); + } + else + { + availableInterp = RegisterOnInterpolator( semantic, dataType, dataName ); + } + + if( availableInterp != null ) + { + bool isPosition = vertexSemantics == TemplateSemantics.POSITION || vertexSemantics == TemplateSemantics.POSITION; + + string interpVarName = m_currentTemplateData.VertexFunctionData.OutVarName + "." + availableInterp.VarNameWithSwizzle; + string interpDecl = string.Format( TemplateHelperFunctions.TemplateVariableDecl, interpVarName, TemplateHelperFunctions.AutoSwizzleData( m_availableVertData[ info ].VarName, m_availableVertData[ info ].VarType, dataType, isPosition ) ); + m_currentDataCollector.AddToVertexInterpolatorsDecl( interpDecl ); + string finalVarName = m_currentTemplateData.FragmentFunctionData.InVarName + "." + availableInterp.VarNameWithSwizzle; + m_availableFragData.Add( info, new InterpDataHelper( dataType, finalVarName ) ); + return finalVarName; + } + } + return string.Empty; + } + + TemplateVertexData RegisterOnInterpolator( TemplateSemantics semantics, WirePortDataType dataType, string vertexDataName = null ) + { + if( vertexDataName == null ) + { + if( TemplateHelperFunctions.SemanticsDefaultName.ContainsKey( semantics ) ) + { + vertexDataName = TemplateHelperFunctions.SemanticsDefaultName[ semantics ]; + } + else + { + vertexDataName = string.Empty; + Debug.LogError( "No valid name given to vertex data" ); + } + } + + TemplateVertexData data = new TemplateVertexData( semantics, dataType, vertexDataName ); + m_interpolatorData.Interpolators.Add( data ); + string interpolator = string.Format( TemplateHelperFunctions.InterpFullSemantic, UIUtils.WirePortToCgType( dataType ), data.VarName, data.Semantics ); + m_currentDataCollector.AddToInterpolators( interpolator ); + return data; + } + + public void RegisterOnVertexData( TemplateSemantics semantics, WirePortDataType dataType, string varName ) + { + m_vertexDataDict.Add( semantics, new TemplateVertexData( semantics, dataType, varName ) ); + } + + public TemplateVertexData RequestMacroInterpolator( string varName ) + { + if( varName != null && m_registeredVertexData.ContainsKey( varName ) ) + { + return m_registeredVertexData[ varName ]; + } + + for( int i = 0; i < m_interpolatorData.AvailableInterpolators.Count; i++ ) + { + if( !m_interpolatorData.AvailableInterpolators[ i ].IsFull ) + { + TemplateVertexData data = m_interpolatorData.AvailableInterpolators[ i ].RequestChannels( WirePortDataType.FLOAT4, false, varName ); + if( data != null ) + { + if( !m_registeredVertexData.ContainsKey( data.VarName ) ) + { + m_registeredVertexData.Add( data.VarName, data ); + } + if( m_interpolatorData.AvailableInterpolators[ i ].Usage == 1 ) + { + string interpolator = string.Format( TemplateHelperFunctions.InterpMacro, varName, TemplateHelperFunctions.SemanticToInt[ data.Semantics ] ); + m_currentDataCollector.AddToInterpolators( interpolator ); + } + return data; + } + } + } + return null; + } + + public bool HasRawInterpolatorOfName( string name ) + { + return m_interpolatorData.HasRawInterpolatorOfName( name ); + } + + public TemplateVertexData RequestNewInterpolator( WirePortDataType dataType, bool isColor, string varName = null , bool noInterpolationFlag = false, bool sampleFlag = false ) + { + if( varName != null && m_registeredVertexData.ContainsKey( varName ) ) + { + return m_registeredVertexData[ varName ]; + } + + for( int i = 0; i < m_interpolatorData.AvailableInterpolators.Count; i++ ) + { + if( !m_interpolatorData.AvailableInterpolators[ i ].IsFull ) + { + if( m_interpolatorData.AvailableInterpolators[ i ].Usage != 0 && + (m_interpolatorData.AvailableInterpolators[ i ].NoInterpolation != noInterpolationFlag || + m_interpolatorData.AvailableInterpolators[ i ].Sample != sampleFlag )) + continue; + + TemplateVertexData data = m_interpolatorData.AvailableInterpolators[ i ].RequestChannels( dataType, isColor, varName ); + if( data != null ) + { + if( !m_registeredVertexData.ContainsKey( data.VarName ) ) + { + m_registeredVertexData.Add( data.VarName, data ); + } + + if( m_interpolatorData.AvailableInterpolators[ i ].Usage == 1 ) + { + m_interpolatorData.AvailableInterpolators[ i ].NoInterpolation = noInterpolationFlag; + m_interpolatorData.AvailableInterpolators[ i ].Sample = sampleFlag; + // First time using this interpolator, so we need to register it + string interpolator = string.Format( TemplateHelperFunctions.TexFullSemantic, + data.VarName, data.Semantics ); + if( noInterpolationFlag ) + interpolator = "nointerpolation " + interpolator; + + if( sampleFlag) + interpolator = "sample " + interpolator; + + m_currentDataCollector.AddToInterpolators( interpolator ); + } + return data; + } + } + } + + // This area is reached if max available interpolators from shader model is reached + // Nevertheless, we register all new interpolators to that list so no imediate compilation errors are thrown + // A warning message is then thrown to warn the user about this + int newInterpId = 1 + TemplateHelperFunctions.SemanticToInt[ m_interpolatorData.AvailableInterpolators[ m_interpolatorData.AvailableInterpolators.Count - 1 ].Semantic ]; + if( TemplateHelperFunctions.IntToSemantic.ContainsKey( newInterpId ) ) + { + TemplateInterpElement item = new TemplateInterpElement( TemplateHelperFunctions.IntToSemantic[ newInterpId ] ); + m_interpolatorData.AvailableInterpolators.Add( item ); + TemplateVertexData data = item.RequestChannels( dataType, isColor, varName ); + if( data != null ) + { + if( !m_registeredVertexData.ContainsKey( data.VarName ) ) + { + m_registeredVertexData.Add( data.VarName, data ); + } + + if( item.Usage == 1 ) + { + string interpolator = string.Format( TemplateHelperFunctions.TexFullSemantic, data.VarName, data.Semantics ); + m_currentDataCollector.AddToInterpolators( interpolator ); + } + return data; + } + } + + UIUtils.ShowMessage( "Maximum amount of interpolators exceeded", MessageSeverity.Error ); + return null; + } + + // Unused channels in interpolators must be set to something so the compiler doesn't generate warnings + public List GetInterpUnusedChannels() + { + List resetInstrucctions = new List(); + + if( m_interpolatorData != null ) + { + for( int i = 0; i < m_interpolatorData.AvailableInterpolators.Count; i++ ) + { + if( m_interpolatorData.AvailableInterpolators[ i ].Usage > 0 && !m_interpolatorData.AvailableInterpolators[ i ].IsFull ) + { + string channels = string.Empty; + bool[] availableChannels = m_interpolatorData.AvailableInterpolators[ i ].AvailableChannels; + for( int j = 0; j < availableChannels.Length; j++ ) + { + if( availableChannels[ j ] ) + { + channels += TemplateHelperFunctions.VectorSwizzle[ j ]; + } + } + + resetInstrucctions.Add( string.Format( "{0}.{1}.{2} = 0;", m_currentTemplateData.VertexFunctionData.OutVarName, m_interpolatorData.AvailableInterpolators[ i ].Name, channels ) ); + } + } + } + + if( resetInstrucctions.Count > 0 ) + { + resetInstrucctions.Insert( 0, "\n//setting value to unused interpolator channels and avoid initialization warnings" ); + } + + return resetInstrucctions; + } + + public bool ContainsSpecialLocalFragVar( TemplateInfoOnSematics info, WirePortDataType type, ref string result ) + { + if( m_specialFragmentLocalVars.ContainsKey( info ) ) + { + result = m_specialFragmentLocalVars[ info ].LocalVarName; + if( m_specialFragmentLocalVars[ info ].DataType != type ) + { + result = TemplateHelperFunctions.AutoSwizzleData( result, m_specialFragmentLocalVars[ info ].DataType, type, false ); + } + return true; + } + return false; + } + + public bool GetCustomInterpolatedData( TemplateInfoOnSematics info, WirePortDataType type, PrecisionType precisionType, ref string result, bool useMasterNodeCategory, MasterNodePortCategory customCategory ) + { + bool isPosition = info == TemplateInfoOnSematics.POSITION || + info == TemplateInfoOnSematics.CLIP_POS || + info == TemplateInfoOnSematics.SCREEN_POSITION || + info == TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED || + info == TemplateInfoOnSematics.WORLD_POSITION || + info == TemplateInfoOnSematics.RELATIVE_WORLD_POS; + + + MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory; + if( category == MasterNodePortCategory.Vertex ) + { + if( m_specialVertexLocalVars.ContainsKey( info ) ) + { + result = m_specialVertexLocalVars[ info ].LocalVarName; + if( m_specialVertexLocalVars[ info ].DataType != type ) + { + result = TemplateHelperFunctions.AutoSwizzleData( result, m_specialVertexLocalVars[ info ].DataType, type , isPosition ); + } + + string defineValue = string.Empty; + if( TemplateHelperFunctions.InfoToDefineVertex.TryGetValue( info, out defineValue ) ) + m_currentDataCollector.AddToDefines( -1, defineValue ); + + return true; + } + } + + if( category == MasterNodePortCategory.Fragment ) + { + if( m_specialFragmentLocalVars.ContainsKey( info ) ) + { + result = m_specialFragmentLocalVars[ info ].LocalVarName; + if( m_specialFragmentLocalVars[ info ].DataType != type ) + { + result = TemplateHelperFunctions.AutoSwizzleData( result, m_specialFragmentLocalVars[ info ].DataType, type, isPosition ); + } + + string defineValue = string.Empty; + if( TemplateHelperFunctions.InfoToDefineFrag.TryGetValue( info, out defineValue )) + m_currentDataCollector.AddToDefines( -1, defineValue ); + return true; + } + + if( m_availableFragData.ContainsKey( info ) ) + { + if( m_availableFragData[ info ].IsSingleComponent ) + { + result = m_availableFragData[ info ].VarName; + if( m_availableFragData[ info ].VarType != type ) + { + result = TemplateHelperFunctions.AutoSwizzleData( result, m_availableFragData[ info ].VarType, type, isPosition ); + } + return true; + } + else if( TemplateHelperFunctions.InfoToLocalVar.ContainsKey( info ) && TemplateHelperFunctions.InfoToWirePortType.ContainsKey( info ) ) + { + result = TemplateHelperFunctions.InfoToLocalVar[ info ]; + m_currentDataCollector.AddLocalVariable( -1, precisionType, TemplateHelperFunctions.InfoToWirePortType[ info ], result, m_availableFragData[ info ].VarName ); + return true; + } + } + } + return false; + } + + public WirePortDataType GetVertexPositionDataType() + { + InterpDataHelper info = GetInfo( TemplateInfoOnSematics.POSITION , false, MasterNodePortCategory.Vertex); + return info.VarType; + } + + public string GetVertexPosition( WirePortDataType type, PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + if( HasInfo( TemplateInfoOnSematics.POSITION, useMasterNodeCategory, customCategory ) ) + { + InterpDataHelper info = GetInfo( TemplateInfoOnSematics.POSITION, useMasterNodeCategory, customCategory ); + if( type != WirePortDataType.OBJECT && type != info.VarType ) + return TemplateHelperFunctions.AutoSwizzleData( info.VarName, info.VarType, type,true ); + else + return info.VarName; + } + else + { + MasterNodePortCategory portCategory = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory; + string name = "ase_vertex_pos"; + string varName = RegisterInfoOnSemantic( portCategory, TemplateInfoOnSematics.POSITION, TemplateSemantics.POSITION, name, WirePortDataType.FLOAT4, precisionType, true ); + if( type != WirePortDataType.OBJECT && type != WirePortDataType.FLOAT4 ) + return TemplateHelperFunctions.AutoSwizzleData( varName, WirePortDataType.FLOAT4, type,true ); + else + return varName; + } + } + + private const string InstancingLibStandard = "UnityInstancing.cginc"; + private const string InstancingLibSRP = "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"; + + public void SetupInstancing() + { + if( !HasInfo( TemplateInfoOnSematics.INSTANCE_ID ) ) + { + m_currentDataCollector.AddToPragmas( -1, IOUtils.InstancedPropertiesHeader ); + m_currentDataCollector.AddToIncludes( -1, IsSRP ? InstancingLibSRP : InstancingLibStandard ); + m_currentDataCollector.AddToVertexInput( Constants.InstanceIdMacro ); + m_currentDataCollector.AddToInterpolators( Constants.InstanceIdMacro ); + m_currentDataCollector.AddToLocalVariables( MasterNodePortCategory.Vertex, -1, string.Format( "UNITY_SETUP_INSTANCE_ID({0});", m_currentTemplateData.VertexFunctionData.InVarName ) ); + m_currentDataCollector.AddToLocalVariables( MasterNodePortCategory.Vertex, -1, string.Format( "UNITY_TRANSFER_INSTANCE_ID({0}, {1});", m_currentTemplateData.VertexFunctionData.InVarName, m_currentTemplateData.VertexFunctionData.OutVarName ) ); + m_currentDataCollector.AddToLocalVariables( MasterNodePortCategory.Fragment, -1, string.Format( "UNITY_SETUP_INSTANCE_ID({0});", m_currentTemplateData.FragmentFunctionData.InVarName ) ); + } + } + + public string GetVertexColor( PrecisionType precisionType ) + { + if( HasInfo( TemplateInfoOnSematics.COLOR ) ) + { + return GetInfo( TemplateInfoOnSematics.COLOR ).VarName; + } + else + { + string name = "ase_color"; + return RegisterInfoOnSemantic( TemplateInfoOnSematics.COLOR, TemplateSemantics.COLOR, name, WirePortDataType.FLOAT4, precisionType, false ); + } + } + + public string GetVertexNormal( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + if( HasInfo( TemplateInfoOnSematics.NORMAL, useMasterNodeCategory, customCategory ) ) + { + InterpDataHelper info = GetInfo( TemplateInfoOnSematics.NORMAL, useMasterNodeCategory, customCategory ); + return TemplateHelperFunctions.AutoSwizzleData( info.VarName, info.VarType, WirePortDataType.FLOAT3 , false); + } + else + { + MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory; + string name = "ase_normal"; + return RegisterInfoOnSemantic( category, TemplateInfoOnSematics.NORMAL, TemplateSemantics.NORMAL, name, WirePortDataType.FLOAT3, precisionType, false ); + } + } + + public string GetWorldNormal( PrecisionType precisionType = PrecisionType.Float, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment, bool normalize = false ) + { + string result = string.Empty; + if( GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_NORMAL, WirePortDataType.FLOAT3, precisionType, ref result, useMasterNodeCategory, customCategory ) ) + { + if( normalize ) + return string.Format( "normalize( {0} )", result ); + else + return result; + } + + string varName = normalize ? "normalizeWorldNormal" : GeneratorUtils.WorldNormalStr; + + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string worldNormalValue = string.Empty; + + if( !GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_NORMAL, WirePortDataType.FLOAT3, precisionType, ref worldNormalValue, false, MasterNodePortCategory.Vertex ) ) + { + string vertexNormal = GetVertexNormal( precisionType, false, MasterNodePortCategory.Vertex ); + string formatStr = string.Empty; + if( IsSRP ) + formatStr = "TransformObjectToWorldNormal({0})"; + else + formatStr = "UnityObjectToWorldNormal({0})"; + worldNormalValue = string.Format( formatStr, vertexNormal ); + } + + if( normalize ) + worldNormalValue = string.Format( "normalize( {0} )", worldNormalValue ); + + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, precisionType, worldNormalValue, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetWorldNormal( int uniqueId, PrecisionType precisionType, string normal, string outputId ) + { + string tanToWorld0 = string.Empty; + string tanToWorld1 = string.Empty; + string tanToWorld2 = string.Empty; + + GetWorldTangentTf( precisionType, out tanToWorld0, out tanToWorld1, out tanToWorld2, true ); + + string tanNormal = "tanNormal" + outputId; + m_currentDataCollector.AddLocalVariable( uniqueId, "float3 " + tanNormal + " = " + normal + ";" ); + return string.Format( "float3(dot({1},{0}), dot({2},{0}), dot({3},{0}))", tanNormal, tanToWorld0, tanToWorld1, tanToWorld2 ); + } + + public string GetVertexTangent( WirePortDataType type, PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + if( HasInfo( TemplateInfoOnSematics.TANGENT, useMasterNodeCategory, customCategory ) ) + { + InterpDataHelper info = GetInfo( TemplateInfoOnSematics.TANGENT, useMasterNodeCategory, customCategory ); + if( type != WirePortDataType.OBJECT && type != info.VarType ) + return TemplateHelperFunctions.AutoSwizzleData( info.VarName, info.VarType, type , false); + else + return info.VarName; + } + else + { + MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory; + string name = "ase_tangent"; + string varName = RegisterInfoOnSemantic( category, TemplateInfoOnSematics.TANGENT, TemplateSemantics.TANGENT, name, WirePortDataType.FLOAT4, precisionType, false ); + if( type != WirePortDataType.OBJECT && type != WirePortDataType.FLOAT4 ) + return TemplateHelperFunctions.AutoSwizzleData( varName, WirePortDataType.FLOAT4, type , false ); + else + return varName; + } + } + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + public string GetBlendWeights( bool useMasterNodeCategory = true , MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + if( HasInfo( TemplateInfoOnSematics.BLENDWEIGHTS , useMasterNodeCategory , customCategory ) ) + { + InterpDataHelper info = GetInfo( TemplateInfoOnSematics.BLENDWEIGHTS , useMasterNodeCategory , customCategory ); + return info.VarName; + } + else + { + MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory; + string name = GeneratorUtils.VertexBlendWeightsStr; + string varName = RegisterInfoOnSemantic( category , TemplateInfoOnSematics.BLENDWEIGHTS , TemplateSemantics.BLENDWEIGHTS , name , WirePortDataType.FLOAT4 ,PrecisionType.Float , false , name ); + return varName; + } + } + + public string GetBlendIndices( bool useMasterNodeCategory = true , MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + if( HasInfo( TemplateInfoOnSematics.BLENDINDICES , useMasterNodeCategory , customCategory ) ) + { + InterpDataHelper info = GetInfo( TemplateInfoOnSematics.BLENDINDICES , useMasterNodeCategory , customCategory ); + return info.VarName; + } + else + { + MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory; + string name = GeneratorUtils.VertexBlendIndicesStr; + string varName = RegisterInfoOnSemantic( category , TemplateInfoOnSematics.BLENDINDICES , TemplateSemantics.BLENDINDICES , name , WirePortDataType.UINT4 , PrecisionType.Float , false , name ); + return varName; + } + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + public string GetVertexBitangent( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + string varName = GeneratorUtils.VertexBitangentStr; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string tangentValue = GetVertexTangent( WirePortDataType.FLOAT4, precisionType, false, MasterNodePortCategory.Vertex ); + string normalValue = GetVertexNormal( precisionType, false, MasterNodePortCategory.Vertex ); + + string bitangentValue = string.Format( "cross( {0}, {1}.xyz ) * {1}.w * unity_WorldTransformParams.w", normalValue, tangentValue ); + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, precisionType, bitangentValue, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetWorldTangent( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + string result = string.Empty; + if( GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_TANGENT, WirePortDataType.FLOAT3, precisionType, ref result, useMasterNodeCategory, customCategory ) ) + { + return result; + } + + string varName = GeneratorUtils.WorldTangentStr; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string worldTangentValue = string.Empty; + if( !GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_TANGENT, WirePortDataType.FLOAT3, precisionType, ref worldTangentValue, false, MasterNodePortCategory.Vertex ) ) + { + string vertexTangent = GetVertexTangent( WirePortDataType.FLOAT4, precisionType, false, MasterNodePortCategory.Vertex ); + string formatStr = string.Empty; + + if( IsSRP ) + formatStr = "TransformObjectToWorldDir({0}.xyz)"; + else + formatStr = "UnityObjectToWorldDir({0})"; + + worldTangentValue = string.Format( formatStr, vertexTangent ); + } + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, precisionType, worldTangentValue, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetTangentSign( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + string varName = GeneratorUtils.VertexTangentSignStr; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string tangentValue = GetVertexTangent( WirePortDataType.FLOAT4, precisionType, false, MasterNodePortCategory.Vertex ); + string tangentSignValue = string.Format( "{0}.w * unity_WorldTransformParams.w", tangentValue ); + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT, precisionType, tangentSignValue, useMasterNodeCategory, customCategory ); + return varName; + } + + + public string GetWorldBinormal( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + string result = string.Empty; + if( GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_BITANGENT, WirePortDataType.FLOAT3, precisionType, ref result, useMasterNodeCategory, customCategory ) ) + { + return result; + } + + string varName = GeneratorUtils.WorldBitangentStr; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string worldBinormal = string.Empty; + if( !GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_BITANGENT, WirePortDataType.FLOAT3, precisionType, ref worldBinormal, false, MasterNodePortCategory.Vertex ) ) + { + string worldNormal = GetWorldNormal( precisionType, false, MasterNodePortCategory.Vertex ); + string worldtangent = GetWorldTangent( precisionType, false, MasterNodePortCategory.Vertex ); + string tangentSign = GetTangentSign( precisionType, false, MasterNodePortCategory.Vertex ); + worldBinormal = string.Format( "cross( {0}, {1} ) * {2}", worldNormal, worldtangent, tangentSign ); + } + + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, PrecisionType.Float, worldBinormal, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetWorldReflection( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment, bool normalize = false ) + { + string varName = GeneratorUtils.WorldReflectionStr;//UIUtils.GetInputValueFromType( SurfaceInputs.WORLD_REFL ); + if( normalize ) + varName = "normalized" + varName; + + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string worldNormal = GetWorldNormal( precisionType ); + string worldViewDir = GetViewDir(); + string worldRefl = string.Format( "reflect(-{0}, {1})", worldViewDir, worldNormal ); + + if( normalize ) + worldRefl = string.Format( "normalize( {0} )", worldRefl ); + + m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3, varName, worldRefl ); + return varName; + } + + public string GetWorldReflection( PrecisionType precisionType, string normal ) + { + string tanToWorld0 = string.Empty; + string tanToWorld1 = string.Empty; + string tanToWorld2 = string.Empty; + + GetWorldTangentTf( precisionType, out tanToWorld0, out tanToWorld1, out tanToWorld2 ); + string worldRefl = GetViewDir(); + + return string.Format( "reflect( -{0}, float3( dot( {2}, {1} ), dot( {3}, {1} ), dot( {4}, {1} ) ) )", worldRefl, normal, tanToWorld0, tanToWorld1, tanToWorld2 ); + } + + public string GetLightAtten( int uniqueId, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + //string result = string.Empty; + //if( GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_POSITION, PrecisionType.Float, ref result, useMasterNodeCategory, customCategory ) ) + //{ + // return result; + //} + + //string varName = GeneratorUtils.WorldPositionStr;//UIUtils.GetInputValueFromType( SurfaceInputs.WORLD_POS ); + //if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + // return varName; + + //if( !m_availableVertData.ContainsKey( TemplateInfoOnSematics.POSITION ) ) + //{ + // UIUtils.ShowMessage( "Attempting to access inexisting vertex position to calculate world pos" ); + // return "fixed3(0,0,0)"; + //} + + //string vertexPos = m_availableVertData[ TemplateInfoOnSematics.POSITION ].VarName; + //string worldPosConversion = string.Format( "mul(unity_ObjectToWorld, {0}).xyz", vertexPos ); + + //RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, PrecisionType.Float, worldPosConversion, useMasterNodeCategory, customCategory ); + //return varName; + + m_currentDataCollector.AddToIncludes( uniqueId, Constants.UnityAutoLightLib ); + m_currentDataCollector.AddToDefines( uniqueId, "ASE_SHADOWS 1" ); +#if UNITY_5_6_OR_NEWER + RequestMacroInterpolator( "UNITY_SHADOW_COORDS" ); +#else + RequestMacroInterpolator( "SHADOW_COORDS" ); + m_currentDataCollector.AddToPragmas( uniqueId, "multi_compile_fwdbase" ); +#endif + //string vOutName = CurrentTemplateData.VertexFunctionData.OutVarName; + string fInName = CurrentTemplateData.FragmentFunctionData.InVarName; + string worldPos = GetWorldPos(); + m_currentDataCollector.AddLocalVariable( uniqueId, "UNITY_LIGHT_ATTENUATION(ase_atten, " + fInName + ", " + worldPos + ")" ); + return "ase_atten"; + + } + + public string GenerateRotationIndependentObjectScale( ref MasterNodeDataCollector dataCollector, int uniqueId ) + { + string value = string.Empty; + + if( m_currentSRPType != TemplateSRPType.BuiltIn ) + { + value = "float3( length( GetWorldToObjectMatrix()[ 0 ].xyz ), length( GetWorldToObjectMatrix()[ 1 ].xyz ), length( GetWorldToObjectMatrix()[ 2 ].xyz ) )"; + } + else + { + value = "float3( length( unity_WorldToObject[ 0 ].xyz ), length( unity_WorldToObject[ 1 ].xyz ), length( unity_WorldToObject[ 2 ].xyz ) )"; + } + value = "( 1.0 / "+ value +" )"; + dataCollector.AddLocalVariable( uniqueId, PrecisionType.Float, WirePortDataType.FLOAT3, GeneratorUtils.ParentObjectScaleStr, value ); + return GeneratorUtils.ParentObjectScaleStr; + } + + public string GenerateObjectScale( ref MasterNodeDataCollector dataCollector, int uniqueId ) + { + string value = string.Empty; + + if( m_currentSRPType != TemplateSRPType.BuiltIn ) + { + value = "float3( length( GetObjectToWorldMatrix()[ 0 ].xyz ), length( GetObjectToWorldMatrix()[ 1 ].xyz ), length( GetObjectToWorldMatrix()[ 2 ].xyz ) )"; + } + else + { + value = "float3( length( unity_ObjectToWorld[ 0 ].xyz ), length( unity_ObjectToWorld[ 1 ].xyz ), length( unity_ObjectToWorld[ 2 ].xyz ) )"; + } + dataCollector.AddLocalVariable( uniqueId, PrecisionType.Float, WirePortDataType.FLOAT3, GeneratorUtils.ObjectScaleStr, value ); + return GeneratorUtils.ObjectScaleStr; + } + + public string GetWorldPos( bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + // overriding precision + var precision = PrecisionType.Float; + + string result = string.Empty; + if( GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_POSITION, WirePortDataType.FLOAT3, precision, ref result, useMasterNodeCategory, customCategory ) ) + { + return result; + } + else if( m_currentSRPType == TemplateSRPType.HD ) + { + if( GetCustomInterpolatedData( TemplateInfoOnSematics.RELATIVE_WORLD_POS, WirePortDataType.FLOAT3, precision, ref result, useMasterNodeCategory, customCategory ) ) + { + string worldPosVarName = GeneratorUtils.WorldPositionStr; + string relWorldPosConversion = string.Format( "GetAbsolutePositionWS( {0} )", result ); + m_currentDataCollector.AddLocalVariable( -1, precision, WirePortDataType.FLOAT3, worldPosVarName, relWorldPosConversion ); + return worldPosVarName; + } + } + + string varName = GeneratorUtils.WorldPositionStr;//UIUtils.GetInputValueFromType( SurfaceInputs.WORLD_POS ); + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + if( !m_availableVertData.ContainsKey( TemplateInfoOnSematics.POSITION ) ) + { + UIUtils.ShowMessage( "Attempting to access inexisting vertex position to calculate world pos" ); + return "half3(0,0,0)"; + } + + string vertexPos = m_availableVertData[ TemplateInfoOnSematics.POSITION ].VarName; + + string worldPosConversion = string.Empty; + + //Check if world pos already defined in the vertex body + if( !GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_POSITION, WirePortDataType.FLOAT3, precision, ref worldPosConversion, false, MasterNodePortCategory.Vertex ) ) + { + if( m_currentSRPType == TemplateSRPType.HD ) + { +#if UNITY_2018_3_OR_NEWER + worldPosConversion = string.Format( "GetAbsolutePositionWS( TransformObjectToWorld( ({0}).xyz ) )", vertexPos ); +#else + worldPosConversion = string.Format( "GetAbsolutePositionWS( mul( GetObjectToWorldMatrix(), {0}).xyz )", vertexPos ); +#endif + } + else if( m_currentSRPType == TemplateSRPType.Lightweight ) + { + worldPosConversion = string.Format( "mul(GetObjectToWorldMatrix(), {0}).xyz", vertexPos ); + } + else + { + worldPosConversion = string.Format( "mul(unity_ObjectToWorld, {0}).xyz", vertexPos ); + } + } + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, precision, worldPosConversion, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetClipPosForValue( string customVertexPos, string outputId, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + string varName = GeneratorUtils.ClipPositionStr + outputId; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + if( !m_availableVertData.ContainsKey( TemplateInfoOnSematics.POSITION ) ) + { + UIUtils.ShowMessage( "Attempting to access inexisting vertex position to calculate clip pos" ); + return "half4(0,0,0,0)"; + } + + string formatStr = string.Empty; + switch( m_currentSRPType ) + { + default: + case TemplateSRPType.BuiltIn: + formatStr = "UnityObjectToClipPos({0})"; + break; + case TemplateSRPType.HD: + formatStr = "TransformWorldToHClip( TransformObjectToWorld({0}))"; + break; + case TemplateSRPType.Lightweight: + formatStr = "TransformObjectToHClip(({0}).xyz)"; + break; + } + + string clipSpaceConversion = string.Format( formatStr, customVertexPos ); + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT4, PrecisionType.Float, clipSpaceConversion, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetClipPos( bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + string varName = GeneratorUtils.ClipPositionStr;// "clipPos"; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + if( !m_availableVertData.ContainsKey( TemplateInfoOnSematics.POSITION ) ) + { + UIUtils.ShowMessage( "Attempting to access inexisting vertex position to calculate clip pos" ); + return "half4(0,0,0,0)"; + } + + string vertexPos = m_availableVertData[ TemplateInfoOnSematics.POSITION ].VarName; + + string formatStr = string.Empty; + switch( m_currentSRPType ) + { + default: + case TemplateSRPType.BuiltIn: + formatStr = "UnityObjectToClipPos({0})"; + break; + case TemplateSRPType.HD: + formatStr = "TransformWorldToHClip( TransformObjectToWorld({0}))"; + break; + case TemplateSRPType.Lightweight: + formatStr = "TransformObjectToHClip(({0}).xyz)"; + break; + } + + string clipSpaceConversion = string.Format( formatStr, vertexPos ); + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT4, PrecisionType.Float, clipSpaceConversion, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetScreenPosForValue( PrecisionType precision, string customVertexPos, string outputId, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + // overriding precision + precision = PrecisionType.Float; + + string varName = UIUtils.GetInputValueFromType( SurfaceInputs.SCREEN_POS ) + outputId; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string clipSpacePos = GetClipPosForValue( customVertexPos, outputId, false, MasterNodePortCategory.Vertex ); + string screenPosConversion = string.Empty; + if( m_currentSRPType == TemplateSRPType.HD ) + { + screenPosConversion = string.Format( "ComputeScreenPos( {0} , _ProjectionParams.x )", clipSpacePos ); + } + else + { + screenPosConversion = string.Format( "ComputeScreenPos({0})", clipSpacePos ); + } + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT4, precision, screenPosConversion, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetScreenPos( PrecisionType precision, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + // overriding precision + precision = PrecisionType.Float; + + string result = string.Empty; + if( GetCustomInterpolatedData( TemplateInfoOnSematics.SCREEN_POSITION, WirePortDataType.FLOAT4, precision, ref result, useMasterNodeCategory, customCategory ) ) + { + return result; + } + + string varName = UIUtils.GetInputValueFromType( SurfaceInputs.SCREEN_POS ); + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string clipSpacePos = GetClipPos( false, MasterNodePortCategory.Vertex ); + string screenPosConversion = string.Empty; + if( m_currentSRPType == TemplateSRPType.HD ) + { + screenPosConversion = string.Format( "ComputeScreenPos( {0} , _ProjectionParams.x )", clipSpacePos ); + } + else + { + screenPosConversion = string.Format( "ComputeScreenPos({0})", clipSpacePos ); + } + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT4, precision, screenPosConversion, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetScreenPosNormalized( PrecisionType precision, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + string result = string.Empty; + if( GetCustomInterpolatedData( TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED, WirePortDataType.FLOAT4, precision, ref result, useMasterNodeCategory, customCategory ) ) + { + return result; + } + + string varName = GeneratorUtils.ScreenPositionNormalizedStr;// "norm" + UIUtils.GetInputValueFromType( SurfaceInputs.SCREEN_POS ); + string screenPos = GetScreenPos( precision, useMasterNodeCategory, customCategory ); + string clipPlaneTestOp = string.Format( "{0}.z = ( UNITY_NEAR_CLIP_VALUE >= 0 ) ? {0}.z : {0}.z * 0.5 + 0.5;", varName ); + m_currentDataCollector.AddLocalVariable( -1, precision, WirePortDataType.FLOAT4, varName, string.Format( GeneratorUtils.NormalizedScreenPosFormat, screenPos ) ); + m_currentDataCollector.AddLocalVariable( -1, clipPlaneTestOp ); + return varName; + } + + public string GetViewDir( bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment, NormalizeType normalizeType = NormalizeType.Regular ) + { + // overriding precision + var precision = PrecisionType.Float; + + string result = string.Empty; + if( GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_VIEW_DIR, WirePortDataType.FLOAT3, precision, ref result, useMasterNodeCategory, customCategory ) ) + return result; + + string varName = GeneratorUtils.WorldViewDirectionStr;//UIUtils.GetInputValueFromType( SurfaceInputs.VIEW_DIR ); + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string worldPos = GetWorldPos(); + + string formatStr = string.Empty; + if( IsSRP ) + formatStr = "( _WorldSpaceCameraPos.xyz - {0} )"; + else + formatStr = "UnityWorldSpaceViewDir({0})"; + + string viewDir = string.Format( formatStr, worldPos ); + m_currentDataCollector.AddLocalVariable( -1, precision, WirePortDataType.FLOAT3, varName, viewDir ); + + switch( normalizeType ) + { + default: + case NormalizeType.Off: + break; + case NormalizeType.Regular: + m_currentDataCollector.AddLocalVariable( -1, varName + " = normalize(" + varName + ");" ); + break; + case NormalizeType.Safe: + m_currentDataCollector.AddLocalVariable( -1, varName + " = " + TemplateHelperFunctions.SafeNormalize( m_currentDataCollector, varName ) + ";" ); + break; + } + + + //RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, PrecisionType.Float, viewDir, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetTangentViewDir( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment, NormalizeType normalizeType = NormalizeType.Regular ) + { + string varName = GeneratorUtils.TangentViewDirectionStr; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string tanToWorld0 = string.Empty; + string tanToWorld1 = string.Empty; + string tanToWorld2 = string.Empty; + + GetWorldTangentTf( precisionType, out tanToWorld0, out tanToWorld1, out tanToWorld2 ); + string viewDir = GetViewDir(); + string tanViewDir = string.Format( " {0} * {3}.x + {1} * {3}.y + {2} * {3}.z", tanToWorld0, tanToWorld1, tanToWorld2, viewDir ); + + m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3, varName, tanViewDir ); + switch( normalizeType ) + { + default: + case NormalizeType.Off: break; + case NormalizeType.Regular: + m_currentDataCollector.AddLocalVariable( -1, varName + " = normalize(" + varName + ");" ); + break; + case NormalizeType.Safe: + m_currentDataCollector.AddLocalVariable( -1, varName + " = " + TemplateHelperFunctions.SafeNormalize( m_currentDataCollector, varName ) + ";" ); + break; + } + + return varName; + } + + public void GetWorldTangentTf( PrecisionType precisionType, out string tanToWorld0, out string tanToWorld1, out string tanToWorld2, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + tanToWorld0 = "tanToWorld0"; + tanToWorld1 = "tanToWorld1"; + tanToWorld2 = "tanToWorld2"; + + if( HasCustomInterpolatedData( tanToWorld0, useMasterNodeCategory, customCategory ) || + HasCustomInterpolatedData( tanToWorld1, useMasterNodeCategory, customCategory ) || + HasCustomInterpolatedData( tanToWorld2, useMasterNodeCategory, customCategory ) ) + return; + + string worldTangent = GetWorldTangent( precisionType, useMasterNodeCategory, customCategory ); + string worldNormal = GetWorldNormal( precisionType, useMasterNodeCategory, customCategory ); + string worldBinormal = GetWorldBinormal( precisionType, useMasterNodeCategory, customCategory ); + + string tanToWorldVar0 = string.Format( "float3( {0}.x, {1}.x, {2}.x )", worldTangent, worldBinormal, worldNormal ); + string tanToWorldVar1 = string.Format( "float3( {0}.y, {1}.y, {2}.y )", worldTangent, worldBinormal, worldNormal ); + string tanToWorldVar2 = string.Format( "float3( {0}.z, {1}.z, {2}.z )", worldTangent, worldBinormal, worldNormal ); + + if( customCategory == MasterNodePortCategory.Vertex ) + { + RegisterCustomInterpolatedData( tanToWorld0, WirePortDataType.FLOAT3, precisionType, tanToWorldVar0, useMasterNodeCategory, customCategory ); + RegisterCustomInterpolatedData( tanToWorld1, WirePortDataType.FLOAT3, precisionType, tanToWorldVar1, useMasterNodeCategory, customCategory ); + RegisterCustomInterpolatedData( tanToWorld2, WirePortDataType.FLOAT3, precisionType, tanToWorldVar2, useMasterNodeCategory, customCategory ); + } + else + { + m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3, tanToWorld0, tanToWorldVar0 ); + m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3, tanToWorld1, tanToWorldVar1 ); + m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3, tanToWorld2, tanToWorldVar2 ); + } + } + + public string GetTangentToWorldMatrixFast( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + string worldTangent = GetWorldTangent( precisionType ); + string worldNormal = GetWorldNormal( precisionType ); + string worldBinormal = GetWorldBinormal( precisionType ); + + string varName = GeneratorUtils.TangentToWorldFastStr; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string result = string.Format( "float3x3({0}.x,{1}.x,{2}.x,{0}.y,{1}.y,{2}.y,{0}.z,{1}.z,{2}.z)", worldTangent, worldBinormal, worldNormal ); + m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3x3, GeneratorUtils.TangentToWorldFastStr, result ); + return GeneratorUtils.TangentToWorldFastStr; + } + + public string GetTangentToWorldMatrixPrecise( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + string worldToTangent = GetWorldToTangentMatrix( precisionType, useMasterNodeCategory, customCategory ); + GeneratorUtils.Add3x3InverseFunction( ref m_currentDataCollector, UIUtils.PrecisionWirePortToCgType( precisionType, WirePortDataType.FLOAT ) ); + m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3x3, GeneratorUtils.TangentToWorldPreciseStr, string.Format( GeneratorUtils.Inverse3x3Header, worldToTangent ) ); + return GeneratorUtils.TangentToWorldPreciseStr; + } + + public string GetWorldToTangentMatrix( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + string worldTangent = GetWorldTangent( precisionType ); + string worldNormal = GetWorldNormal( precisionType ); + string worldBinormal = GetWorldBinormal( precisionType ); + + string varName = GeneratorUtils.WorldToTangentStr;// "worldToTanMat"; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + string worldTanMat = string.Format( "float3x3({0},{1},{2})", worldTangent, worldBinormal, worldNormal ); + + m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3x3, varName, worldTanMat ); + return varName; + } + + public string GetObjectToViewPos( PrecisionType precision, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + // overriding precision + precision = PrecisionType.Float; + + string varName = "objectToViewPos"; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + string vertexPos = GetVertexPosition( WirePortDataType.FLOAT3, precision, false, MasterNodePortCategory.Vertex ); + + string formatStr = string.Empty; + if( IsSRP ) + formatStr = "TransformWorldToView(TransformObjectToWorld({0}))"; + else + formatStr = "UnityObjectToViewPos({0})"; + + string objectToViewPosValue = string.Format( formatStr, vertexPos ); + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, precision, objectToViewPosValue, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetEyeDepth( PrecisionType precision, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment, int viewSpace = 0 ) + { + // overriding precision + precision = PrecisionType.Float; + + string varName = "eyeDepth"; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + string objectToView = GetObjectToViewPos( precision, false, MasterNodePortCategory.Vertex ); + string eyeDepthValue = string.Format( "-{0}.z", objectToView ); + if( viewSpace == 1 ) + { + eyeDepthValue += " * _ProjectionParams.w"; + } + + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT, precision, eyeDepthValue, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetObjectSpaceLightDir( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + if( !IsSRP ) + { + m_currentDataCollector.AddToIncludes( -1, Constants.UnityLightingLib ); + m_currentDataCollector.AddToIncludes( -1, Constants.UnityAutoLightLib ); + } + + string varName = "objectSpaceLightDir"; + + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string vertexPos = GetVertexPosition( WirePortDataType.FLOAT4, precisionType, false, MasterNodePortCategory.Vertex ); + + string objectSpaceLightDir = string.Empty; + switch( m_currentSRPType ) + { + default: + case TemplateSRPType.BuiltIn: + objectSpaceLightDir = string.Format( "ObjSpaceLightDir({0})", vertexPos ); + break; + case TemplateSRPType.HD: + string worldSpaceLightDir = GetWorldSpaceLightDir( precisionType, useMasterNodeCategory, customCategory ); + objectSpaceLightDir = string.Format( "mul( GetWorldToObjectMatrix(), {0} ).xyz", worldSpaceLightDir ); + break; + case TemplateSRPType.Lightweight: + objectSpaceLightDir = "mul( GetWorldToObjectMatrix(), _MainLightPosition ).xyz"; + break; + } + + RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, precisionType, objectSpaceLightDir, useMasterNodeCategory, customCategory ); + return varName; + } + + public string GetWorldSpaceLightDir( PrecisionType precision, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + if( !IsSRP ) + { + m_currentDataCollector.AddToIncludes( -1, Constants.UnityLightingLib ); + m_currentDataCollector.AddToIncludes( -1, Constants.UnityAutoLightLib ); + AddLateDirective( AdditionalLineType.Custom, "//This is a late directive" ); + } + else + { + + string lightVar; + if( m_currentSRPType == TemplateSRPType.HD ) + { + AddHDLightInfo(); + lightVar = "-" + string.Format( TemplateHelperFunctions.HDLightInfoFormat, "0", "forward" ); + } + else + { + lightVar = "_MainLightPosition.xyz"; + } + return m_currentDataCollector.SafeNormalizeLightDir ? string.Format( "SafeNormalize({0})", lightVar ) : lightVar; + } + + string varName = "worldSpaceLightDir"; + if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) ) + return varName; + + string worldPos = GetWorldPos( useMasterNodeCategory, customCategory ); + string worldSpaceLightDir = string.Format( "UnityWorldSpaceLightDir({0})", worldPos ); + if( m_currentDataCollector.SafeNormalizeLightDir ) + { + if( IsSRP ) + { + worldSpaceLightDir = string.Format( "SafeNormalize{0})", worldSpaceLightDir ); + } + else + { + m_currentDataCollector.AddToIncludes( -1, Constants.UnityBRDFLib ); + worldSpaceLightDir = string.Format( "Unity_SafeNormalize({0})", worldSpaceLightDir ); + } + } + + m_currentDataCollector.AddLocalVariable( -1, precision, WirePortDataType.FLOAT3, varName, worldSpaceLightDir ); + return varName; + } + + public void RegisterCustomInterpolatedData( string name, WirePortDataType dataType, PrecisionType precision, string vertexInstruction, bool useMasterNodeCategory = true, + MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment, bool noInterpolationFlag = false, bool sampleFlag = false ) + { + bool addLocalVariable = !name.Equals( vertexInstruction ); + + MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory; + + if( !m_customInterpolatedData.ContainsKey( name ) ) + { + m_customInterpolatedData.Add( name, new TemplateCustomData( name, dataType ) ); + } + + if( !m_customInterpolatedData[ name ].IsVertex ) + { + m_customInterpolatedData[ name ].IsVertex = true; + if( addLocalVariable ) + m_currentDataCollector.AddToVertexLocalVariables( -1, precision, dataType, name, vertexInstruction ); + } + + if( category == MasterNodePortCategory.Fragment ) + { + if( !m_customInterpolatedData[ name ].IsFragment ) + { + m_customInterpolatedData[ name ].IsFragment = true; + TemplateVertexData interpData = RequestNewInterpolator( dataType, false,null, noInterpolationFlag,sampleFlag ); + if( interpData == null ) + { + Debug.LogErrorFormat( "Could not assign interpolator of type {0} to variable {1}", dataType, name ); + return; + } + + m_currentDataCollector.AddToVertexLocalVariables( -1, m_currentTemplateData.VertexFunctionData.OutVarName + "." + interpData.VarNameWithSwizzle, name ); + m_currentDataCollector.AddToLocalVariables( -1, precision, dataType, name, m_currentTemplateData.FragmentFunctionData.InVarName + "." + interpData.VarNameWithSwizzle ); + } + } + } + + public bool HasCustomInterpolatedData( string name, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment ) + { + if( m_customInterpolatedData.ContainsKey( name ) ) + { + MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory; + return ( category == MasterNodePortCategory.Fragment ) ? m_customInterpolatedData[ name ].IsFragment : m_customInterpolatedData[ name ].IsVertex; + } + return false; + } + + public bool HasFragmentInputParams + { + get + { + if( m_fragmentInputParams != null ) + return m_fragmentInputParams.Count > 0; + + return false; + } + } + + public string FragInputParamsStr + { + get + { + string value = string.Empty; + if( m_fragmentInputParams != null && m_fragmentInputParams.Count > 0 ) + { + int count = m_fragmentInputParams.Count; + if( count > 0 ) + { + value = ", "; + foreach( KeyValuePair kvp in m_fragmentInputParams ) + { + value += kvp.Value.Declaration; + + if( --count > 0 ) + { + value += " , "; + } + } + } + } + return value; + } + } + + public string VertexInputParamsStr + { + get + { + string value = string.Empty; + if( m_vertexInputParams != null && m_vertexInputParams.Count > 0 ) + { + int count = m_vertexInputParams.Count; + if( count > 0 ) + { + value = ", "; + foreach( KeyValuePair kvp in m_vertexInputParams ) + { + value += kvp.Value.Declaration; + + if( --count > 0 ) + { + value += " , "; + } + } + } + } + return value; + } + } + + public void Destroy() + { + m_currentTemplate = null; + + m_currentTemplateData = null; + + m_currentDataCollector = null; + + if( m_fullSrpBatcherPropertiesList != null ) + { + m_fullSrpBatcherPropertiesList.Clear(); + m_fullSrpBatcherPropertiesList = null; + } + + if( m_srpBatcherPropertiesList != null ) + { + m_srpBatcherPropertiesList.Clear(); + m_srpBatcherPropertiesList = null; + } + + if( m_srpBatcherPropertiesDict != null ) + { + m_srpBatcherPropertiesDict.Clear(); + m_srpBatcherPropertiesDict = null; + } + + if( m_lateDirectivesList != null ) + { + m_lateDirectivesList.Clear(); + m_lateDirectivesList = null; + } + + if( m_lateDirectivesDict != null ) + { + m_lateDirectivesDict.Clear(); + m_lateDirectivesDict = null; + } + + if( m_registeredVertexData != null ) + { + m_registeredVertexData.Clear(); + m_registeredVertexData = null; + } + + if( m_vertexInputParams != null ) + { + m_vertexInputParams.Clear(); + m_vertexInputParams = null; + } + + if( m_fragmentInputParams != null ) + { + m_fragmentInputParams.Clear(); + m_fragmentInputParams = null; + } + + if( m_vertexDataDict != null ) + { + m_vertexDataDict.Clear(); + m_vertexDataDict = null; + } + + if( m_interpolatorData != null ) + { + m_interpolatorData.Destroy(); + m_interpolatorData = null; + } + + if( m_availableFragData != null ) + { + m_availableFragData.Clear(); + m_availableFragData = null; + } + + if( m_availableVertData != null ) + { + m_availableVertData.Clear(); + m_availableVertData = null; + } + + if( m_customInterpolatedData != null ) + { + m_customInterpolatedData.Clear(); + m_customInterpolatedData = null; + } + + if( m_specialVertexLocalVars != null ) + { + m_specialVertexLocalVars.Clear(); + m_specialVertexLocalVars = null; + } + + if( m_specialFragmentLocalVars != null ) + { + m_specialFragmentLocalVars.Clear(); + m_specialFragmentLocalVars = null; + } + } + + public void BuildCBuffer( int nodeId ) + { + m_fullSrpBatcherPropertiesList.Clear(); + if( m_srpBatcherPropertiesList.Count > 0 ) + { + var regex = new Regex( @"(\d)\s+\b" ); + m_srpBatcherPropertiesList.Sort( ( a, b ) => + { + var matchA = regex.Match( a.PropertyName ); + int sizeA = 0; + if( matchA.Groups.Count > 1 && matchA.Groups[ 1 ].Value.Length > 0 ) + sizeA = Convert.ToInt32( matchA.Groups[ 1 ].Value, System.Globalization.CultureInfo.InvariantCulture ); + + var matchB = regex.Match( b.PropertyName ); + int sizeB = 0; + if( matchB.Groups.Count > 1 && matchB.Groups[ 1 ].Value.Length > 0 ) + sizeB = Convert.ToInt32( matchB.Groups[ 1 ].Value, System.Globalization.CultureInfo.InvariantCulture ); + + return sizeB.CompareTo( sizeA ); + } ); + + m_fullSrpBatcherPropertiesList.Insert(0, new PropertyDataCollector( nodeId, IOUtils.SRPCBufferPropertiesBegin )); + m_fullSrpBatcherPropertiesList.AddRange( m_srpBatcherPropertiesList ); + m_fullSrpBatcherPropertiesList.Add( new PropertyDataCollector( nodeId, IOUtils.SRPCBufferPropertiesEnd ) ); + } + } + + + public void DumpSRPBatcher() + { + for( int i = 0; i < m_srpBatcherPropertiesList.Count; i++ ) + { + Debug.Log( i + "::" + m_srpBatcherPropertiesList[ i ].PropertyName ); + } + } + + public const string GlobalMaxInterpolatorReachedMsg = "Maximum amount of interpolators reached!\nPlease consider optmizing your shader!"; + public const string MaxInterpolatorSMReachedMsg = "Maximum amount of interpolators reached for current shader model on pass {0}! Please consider increasing the shader model to {1}!"; + public void CheckInterpolatorOverflow( string currShaderModel, string passName ) + { + int maxInterpolatorAmount = TemplateHelperFunctions.AvailableInterpolators[ currShaderModel ]; + int currInterpolatorAmount = 1 + TemplateHelperFunctions.SemanticToInt[ InterpData.AvailableInterpolators[ InterpData.AvailableInterpolators.Count - 1 ].Semantic ]; + if( currInterpolatorAmount > maxInterpolatorAmount ) + { + string shaderModel = string.Empty; + if( TemplateHelperFunctions.GetShaderModelForInterpolatorAmount( currInterpolatorAmount, ref shaderModel ) ) + { + UIUtils.ShowMessage( string.Format( MaxInterpolatorSMReachedMsg, passName, shaderModel ), MessageSeverity.Error ); + } + else + { + UIUtils.ShowMessage( GlobalMaxInterpolatorReachedMsg, MessageSeverity.Error ); + } + } + } + + public Dictionary FragInputParameters { get { return m_fragmentInputParams; } } + + public bool HasVertexInputParams + { + get + { + if( m_vertexInputParams != null ) + return m_vertexInputParams.Count > 0; + + return false; + } + } + + public Dictionary VertexInputParameters { get { return m_vertexInputParams; } } + public TemplateData CurrentTemplateData { get { return m_currentTemplateData; } } + public int MultipassSubshaderIdx { get { return m_multipassSubshaderIdx; } } + public int MultipassPassIdx { get { return m_multipassPassIdx; } } + public TemplateSRPType CurrentSRPType { get { return m_currentSRPType; } set { m_currentSRPType = value; } } + public bool IsHDRP { get { return m_currentSRPType == TemplateSRPType.HD; } } + public bool IsLWRP { get { return m_currentSRPType == TemplateSRPType.Lightweight; } } + public bool IsSRP { get { return ( m_currentSRPType == TemplateSRPType.Lightweight || m_currentSRPType == TemplateSRPType.HD ); } } + public TemplateInterpData InterpData { get { return m_interpolatorData; } } + public List LateDirectivesList { get { return m_lateDirectivesList; } } + public List SrpBatcherPropertiesList { get { return m_srpBatcherPropertiesList; } } + public List FullSrpBatcherPropertiesList { get { return m_fullSrpBatcherPropertiesList; } } + public Dictionary VertexDataDict { get { return m_vertexDataDict; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs.meta new file mode 100644 index 0000000..9386f5f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c757602c408f7354b96c2a5eb21662a4 +timeCreated: 1495710491 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs new file mode 100644 index 0000000..b7c3fd0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs @@ -0,0 +1,217 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public enum TemplateDataType + { + LegacySinglePass, + MultiPass + } + + [Serializable] + public class TemplateIncludePragmaContainter + { + [SerializeField] + private int m_nativeTopIndex = -1; + + [SerializeField] + private List m_nativeDirectivesList = new List(); + + [SerializeField] + private List m_includesList = new List(); + private Dictionary m_includesDict = new Dictionary(); + + [SerializeField] + private List m_pragmasList = new List(); + private Dictionary m_pragmasDict = new Dictionary(); + + [SerializeField] + private List m_definesList = new List(); + private Dictionary m_definesDict = new Dictionary(); + + public void RefreshIncludesList() + { + if ( m_includesDict.Count != m_includesList.Count ) + { + m_includesDict.Clear(); + int count = m_includesList.Count; + for ( int i = 0; i < count; i++ ) + { + m_includesDict.Add( m_includesList[ i ], m_includesList[ i ] ); + } + } + } + + public void RefreshPragmasList() + { + if ( m_pragmasDict.Count != m_pragmasList.Count ) + { + m_pragmasDict.Clear(); + int count = m_pragmasList.Count; + for ( int i = 0; i < count; i++ ) + { + m_pragmasDict.Add( m_pragmasList[ i ], m_pragmasList[ i ] ); + } + } + } + + + public void RefreshDefinesList() + { + if ( m_definesDict.Count != m_definesList.Count ) + { + m_definesDict.Clear(); + int count = m_definesList.Count; + for ( int i = 0; i < count; i++ ) + { + m_definesDict.Add( m_definesList[ i ], m_definesList[ i ] ); + } + } + } + + public bool HasInclude( string include ) + { + RefreshIncludesList(); + return m_includesDict.ContainsKey( include ); + } + + public bool HasPragma( string pragma ) + { + RefreshPragmasList(); + return m_pragmasDict.ContainsKey( pragma ); + } + + public bool HasDefine( string pragma ) + { + RefreshDefinesList(); + return m_definesDict.ContainsKey( pragma ); + } + + public void AddInclude( string include ) + { + RefreshIncludesList(); + if ( !m_includesDict.ContainsKey( include ) ) + { + m_includesList.Add( include ); + m_includesDict.Add( include, include ); + } + } + + public void AddPragma( string pragma ) + { + RefreshPragmasList(); + if ( !m_pragmasDict.ContainsKey( pragma ) ) + { + m_pragmasList.Add( pragma ); + m_pragmasDict.Add( pragma, pragma ); + } + } + + public void AddDefine( string define ) + { + RefreshDefinesList(); + if ( !m_definesDict.ContainsKey( define ) ) + { + m_definesList.Add( define ); + m_definesDict.Add( define, define ); + } + } + + public void AddNativeDirective( string native, int topIndex ) + { + m_nativeTopIndex = topIndex; + m_nativeDirectivesList.Add( native ); + } + + public void Destroy() + { + m_nativeDirectivesList.Clear(); + m_nativeDirectivesList = null; + + + m_includesList.Clear(); + m_includesDict.Clear(); + m_includesList = null; + m_includesDict = null; + + m_pragmasList.Clear(); + m_pragmasDict.Clear(); + m_pragmasList = null; + m_pragmasDict = null; + + m_definesList.Clear(); + m_definesDict.Clear(); + m_definesList = null; + m_definesDict = null; + } + + public List IncludesList { get { return m_includesList; } } + public List PragmasList { get { return m_pragmasList; } } + public List DefinesList { get { return m_definesList; } } + public List NativeDirectivesList { get { return m_nativeDirectivesList; } } + public int NativeTopIndex { get { return m_nativeTopIndex; } } + + } + + [Serializable] + public class TemplateInfoContainer + { + public string Id = string.Empty; + public string Data = string.Empty; + public int Index = -1; + public bool IsValid { get { return Index > -1; } } + public void Reset() + { + Id = string.Empty; + Data = string.Empty; + Index = -1; + } + } + + [Serializable] + public class TemplateDataParent : ScriptableObject + { + [SerializeField] + protected TemplateDataType m_templateType; + + [SerializeField] + protected string m_name; + + [SerializeField] + protected string m_guid; + + [SerializeField] + protected int m_orderId; + + [SerializeField] + protected string m_defaultShaderName = string.Empty; + + [SerializeField] + protected bool m_isValid = true; + + [SerializeField] + protected bool m_communityTemplate = false; + + public virtual void Destroy() { } + public virtual bool Reload() { return true; } + public string Name + { + get { return m_name; } + set + { + m_name = value.StartsWith( "Hidden/" ) ? value.Replace( "Hidden/", string.Empty ) : value; + } + } + public string GUID { get { return m_guid; } set { m_guid = value; } } + public int OrderId { get { return m_orderId; } set { m_orderId = value; } } + public string DefaultShaderName { get { return m_defaultShaderName; } set { m_defaultShaderName = value; } } + public bool IsValid { get { return m_isValid; } } + public TemplateDataType TemplateType { get { return m_templateType; } } + public virtual void Init( string name, string guid, bool isCommunity ) { m_communityTemplate = isCommunity; } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs.meta new file mode 100644 index 0000000..49aee2a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4e8f3788c7c239042b3cc3d086311227 +timeCreated: 1518720013 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs new file mode 100644 index 0000000..a3f6c7f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs @@ -0,0 +1,397 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public sealed class TemplateDepthModule : TemplateModuleParent + { + private const string ZWriteFormatter = "ZWrite {0}\n"; + private const string ZTestFormatter = "ZTest {0}\n"; + + [SerializeField] + private bool m_validZTest = false; + + [SerializeField] + private InlineProperty m_zTestMode = new InlineProperty( 0 ); + + [SerializeField] + private bool m_validZWrite = false; + + [SerializeField] + private InlineProperty m_zWriteMode = new InlineProperty( 0 ); + + [SerializeField] + private InlineProperty m_offsetFactor = new InlineProperty( 0 ); + + [SerializeField] + private InlineProperty m_offsetUnits = new InlineProperty( 0 ); + + [SerializeField] + private bool m_offsetEnabled = false; + + [SerializeField] + private bool m_validOffset = false; + + public TemplateDepthModule() : base( "Depth" ) { } + + public void CopyFrom( TemplateDepthModule other, bool allData ) + { + if( allData ) + { + m_independentModule = other.IndependentModule; + m_validZTest = other.ValidZTest; + m_validZWrite = other.ValidZWrite; + m_validOffset = other.ValidOffset; + } + + m_zTestMode.CopyFrom( other.ZTestMode ); + m_zWriteMode.CopyFrom( other.ZWriteMode ); + m_offsetFactor.CopyFrom( other.OffsetFactor ); + m_offsetUnits.CopyFrom( other.OffsetUnits ); + m_offsetEnabled = other.OffsetEnabled; + } + + public void ConfigureFromTemplateData( TemplateDepthData depthData ) + { + m_independentModule = depthData.IndependentModule; + if( depthData.ValidZTest && m_validZTest != depthData.ValidZTest ) + { + if( string.IsNullOrEmpty( depthData.ZTestInlineValue ) ) + { + m_zTestMode.IntValue = ZBufferOpHelper.ZTestModeDict[ depthData.ZTestModeValue ]; + m_zTestMode.ResetProperty(); + } + else + { + m_zTestMode.SetInlineByName( depthData.ZTestInlineValue ); + } + } + + + + if( depthData.ValidZWrite && m_validZWrite != depthData.ValidZWrite ) + { + if( string.IsNullOrEmpty( depthData.ZWriteInlineValue ) ) + { + m_zWriteMode.IntValue = ZBufferOpHelper.ZWriteModeDict[ depthData.ZWriteModeValue ]; + m_zWriteMode.ResetProperty(); + } + else + { + m_zWriteMode.SetInlineByName( depthData.ZWriteInlineValue ); + } + } + + if( depthData.ValidOffset && m_validOffset != depthData.ValidOffset ) + { + if( string.IsNullOrEmpty( depthData.OffsetFactorInlineValue ) ) + { + m_offsetFactor.FloatValue = depthData.OffsetFactor; + m_offsetFactor.ResetProperty(); + } + else + { + m_offsetFactor.SetInlineByName( depthData.OffsetFactorInlineValue ); + } + + if( string.IsNullOrEmpty( depthData.OffsetUnitsInlineValue ) ) + { + m_offsetUnits.FloatValue = depthData.OffsetUnits; + m_offsetUnits.ResetProperty(); + } + else + { + m_offsetUnits.SetInlineByName( depthData.OffsetUnitsInlineValue ); + } + m_offsetEnabled = depthData.ValidOffset; + } + + m_validZTest = depthData.ValidZTest; + m_validZWrite = depthData.ValidZWrite; + m_validOffset = depthData.ValidOffset; + m_validData = m_validZTest || m_validZWrite || m_validOffset; + } + + public override void ShowUnreadableDataMessage( ParentNode owner ) + { + bool foldoutValue = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDepth; + NodeUtils.DrawPropertyGroup( ref foldoutValue, ZBufferOpHelper.DepthParametersStr, base.ShowUnreadableDataMessage ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDepth = foldoutValue; + } + + public override void Draw( UndoParentNode owner, bool style = true ) + { + bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDepth; + if( style ) + { + NodeUtils.DrawPropertyGroup( ref foldout, ZBufferOpHelper.DepthParametersStr, () => + { + EditorGUI.indentLevel++; + DrawBlock( owner ); + EditorGUI.indentLevel--; + } ); + } + else + { + NodeUtils.DrawNestedPropertyGroup( ref foldout, ZBufferOpHelper.DepthParametersStr, () => + { + DrawBlock( owner ); + } ); + } + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDepth = foldout; + } + + void DrawBlock( UndoParentNode owner ) + { + EditorGUI.BeginChangeCheck(); + var cache = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = EditorGUIUtility.labelWidth - 20; + + Color cachedColor = GUI.color; + GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) ); + //EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle ); + GUI.color = cachedColor; + + EditorGUILayout.Separator(); + + if( m_validZWrite ) + m_zWriteMode.EnumTypePopup( ref owner, ZBufferOpHelper.ZWriteModeStr, ZBufferOpHelper.ZWriteModeValues ); + + if( m_validZTest ) + m_zTestMode.EnumTypePopup( ref owner, ZBufferOpHelper.ZTestModeStr, ZBufferOpHelper.ZTestModeLabels ); + + + if( m_validOffset ) + { + m_offsetEnabled = owner.EditorGUILayoutToggle( ZBufferOpHelper.OffsetStr, m_offsetEnabled ); + if( m_offsetEnabled ) + { + EditorGUI.indentLevel++; + m_offsetFactor.FloatField( ref owner, ZBufferOpHelper.OffsetFactorStr ); + m_offsetUnits.FloatField( ref owner, ZBufferOpHelper.OffsetUnitsStr ); + EditorGUI.indentLevel--; + } + } + EditorGUILayout.Separator(); + EditorGUIUtility.labelWidth = cache; + //EditorGUILayout.EndVertical(); + if( EditorGUI.EndChangeCheck() ) + { + m_isDirty = true; + CustomEdited = true; + } + } + + public void ReadZWriteFromString( ref uint index, ref string[] nodeParams ) + { + bool validDataOnMeta = m_validZWrite; + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( validDataOnMeta ) + { + if( UIUtils.CurrentShaderVersion() < 15304 ) + { + m_zWriteMode.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + } + else + { + m_zWriteMode.ReadFromString( ref index, ref nodeParams ); + } + } + } + + public void ReadZTestFromString( ref uint index, ref string[] nodeParams ) + { + bool validDataOnMeta = m_validZTest; + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( validDataOnMeta ) + { + if( UIUtils.CurrentShaderVersion() < 15304 ) + { + m_zTestMode.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + } + else + { + m_zTestMode.ReadFromString( ref index, ref nodeParams ); + } + } + } + + public void ReadOffsetFromString( ref uint index, ref string[] nodeParams ) + { + bool validDataOnMeta = m_validOffset; + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( validDataOnMeta ) + { + m_offsetEnabled = Convert.ToBoolean( nodeParams[ index++ ] ); + if( UIUtils.CurrentShaderVersion() < 15304 ) + { + m_offsetFactor.FloatValue = Convert.ToSingle( nodeParams[ index++ ] ); + m_offsetUnits.FloatValue = Convert.ToSingle( nodeParams[ index++ ] ); + } + else + { + m_offsetFactor.ReadFromString( ref index, ref nodeParams, false ); + m_offsetUnits.ReadFromString( ref index, ref nodeParams, false ); + } + } + } + + public override void ReadFromString( ref uint index, ref string[] nodeParams ) + { + base.ReadFromString( ref index, ref nodeParams ); + ReadZWriteFromString( ref index, ref nodeParams ); + ReadZTestFromString( ref index, ref nodeParams ); + ReadOffsetFromString( ref index, ref nodeParams ); + } + + public void WriteZWriteToString( ref string nodeInfo ) + { + base.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_validZWrite ); + if( m_validZWrite ) + m_zWriteMode.WriteToString( ref nodeInfo ); + } + + public void WriteZTestToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_validZTest ); + if( m_validZTest ) + m_zTestMode.WriteToString( ref nodeInfo ); + } + + public void WriteOffsetToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_validOffset ); + if( m_validOffset ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_offsetEnabled ); + m_offsetFactor.WriteToString( ref nodeInfo ); + m_offsetUnits.WriteToString( ref nodeInfo ); + } + } + + public override void WriteToString( ref string nodeInfo ) + { + WriteZWriteToString( ref nodeInfo ); + WriteZTestToString( ref nodeInfo ); + WriteOffsetToString( ref nodeInfo ); + } + + public bool IsActive { get { return ( m_zTestMode.IsValid || m_zTestMode.IntValue != 0 ) || ( m_zWriteMode.IsValid || m_zWriteMode.IntValue != 0 ) || m_offsetEnabled; } } + public string CurrentZWriteMode + { + get + { + if( m_zWriteMode.IsValid ) + { + return string.Format( ZWriteFormatter, m_zWriteMode.GetValueOrProperty() ); ; + } + + int finalZWrite = ( m_zWriteMode.IntValue == 0 ) ? 1 : m_zWriteMode.IntValue; + return string.Format( ZWriteFormatter, ZBufferOpHelper.ZWriteModeValues[ finalZWrite ] ); ; + } + } + public string CurrentZTestMode + { + get + { + if( m_zTestMode.IsValid ) + return string.Format( ZTestFormatter, m_zTestMode.GetValueOrProperty() ); + + int finalZTestMode = ( m_zTestMode.IntValue == 0 ) ? 3 : m_zTestMode.IntValue; + return string.Format( ZTestFormatter, ZBufferOpHelper.ZTestModeValues[ finalZTestMode ] ); + } + } + + public string CurrentOffset + { + get + { + if( m_offsetEnabled ) + return "Offset " + m_offsetFactor.GetValueOrProperty() + " , " + m_offsetUnits.GetValueOrProperty() + "\n"; + else + return "Offset 0,0\n"; + } + } + + public bool ValidZTest { get { return m_validZTest; } } + public bool ValidZWrite { get { return m_validZWrite; } } + public bool ValidOffset { get { return m_validOffset; } } + public InlineProperty ZTestMode { get { return m_zTestMode; } } + public InlineProperty ZWriteMode { get { return m_zWriteMode; } } + public InlineProperty OffsetFactor { get { return m_offsetFactor; } } + public InlineProperty OffsetUnits { get { return m_offsetUnits; } } + public bool OffsetEnabled { get { return m_offsetEnabled; } } + + + public ZTestMode ZTestModeValue + { + set + { + m_zTestMode.IntValue = ZBufferOpHelper.ZTestModeDict[ value ]; + m_zTestMode.Active = false; + } + get + { + return (ZTestMode)( m_zTestMode.IntValue - 1 ); + } + } + public ZWriteMode ZWriteModeValue + { + set + { + m_zWriteMode.IntValue = ZBufferOpHelper.ZWriteModeDict[ value ]; + m_zWriteMode.Active = false; + } + get + { + return (ZWriteMode)( m_zWriteMode.IntValue - 1 ); + } + } + public float OffsetFactorValue + { + set + { + m_offsetEnabled = true; + m_offsetFactor.FloatValue = value; + m_offsetFactor.Active = false; + } + get + { + return m_offsetFactor.FloatValue; + } + } + + public float OffsetUnitsValue + { + set + { + m_offsetEnabled = true; + m_offsetUnits.FloatValue = value; + m_offsetUnits.Active = false; + } + get + { + return m_offsetUnits.FloatValue; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs.meta new file mode 100644 index 0000000..a559fe7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 91bbf209a618780459e775d6816a4b06 +timeCreated: 1513873547 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs new file mode 100644 index 0000000..4857ebb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs @@ -0,0 +1,280 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Template Fragment Data", "Surface Data", "Select and use available interpolated fragment data from the template" )] + public class TemplateFragmentDataNode : TemplateNodeParent + { + private List m_interpolatorData = null; + + [SerializeField] + private int m_currentDataIdx = -1; + + [SerializeField] + private string m_dataName = string.Empty; + [SerializeField] + private string m_inVarName = string.Empty; + + private string[] m_dataLabels = null; + + private bool m_fetchDataId = false; + private UpperLeftWidgetHelper m_upperLeftWidgetHelper = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_autoWrapProperties = true; + } + + void FetchDataId() + { + if( m_interpolatorData != null ) + { + m_currentDataIdx = 0; + int count = m_interpolatorData.Count; + m_dataLabels = new string[ count ]; + for( int i = 0; i < count; i++ ) + { + m_dataLabels[ i ] = m_interpolatorData[ i ].VarName; + if( m_interpolatorData[ i ].VarName.Equals( m_dataName ) ) + { + m_currentDataIdx = i; + } + } + UpdateFromId(); + } + else + { + m_currentDataIdx = -1; + } + } + + void UpdateFromId() + { + if( m_interpolatorData != null ) + { + if( m_interpolatorData.Count == 0 ) + { + for( int i = 0; i < 4; i++ ) + m_containerGraph.DeleteConnection( false, UniqueId, i, false, true ); + + m_headerColor = UIUtils.GetColorFromCategory( "Default" ); + m_content.text = "None"; + m_additionalContent.text = string.Empty; + m_outputPorts[ 0 ].ChangeProperties( "None", WirePortDataType.OBJECT, false ); + ConfigurePorts(); + return; + } + + bool areCompatible = TemplateHelperFunctions.CheckIfCompatibles( m_outputPorts[ 0 ].DataType, m_interpolatorData[ m_currentDataIdx ].DataType ); + switch( m_interpolatorData[ m_currentDataIdx ].DataType ) + { + default: + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, m_interpolatorData[ m_currentDataIdx ].DataType, false ); + break; + case WirePortDataType.FLOAT2: + m_outputPorts[ 0 ].ChangeProperties( "XY", m_interpolatorData[ m_currentDataIdx ].DataType, false ); + break; + case WirePortDataType.FLOAT3: + m_outputPorts[ 0 ].ChangeProperties( "XYZ", m_interpolatorData[ m_currentDataIdx ].DataType, false ); + break; + case WirePortDataType.FLOAT4: + m_outputPorts[ 0 ].ChangeProperties( "XYZW", m_interpolatorData[ m_currentDataIdx ].DataType, false ); + break; + case WirePortDataType.COLOR: + m_outputPorts[ 0 ].ChangeProperties( "RGBA", m_interpolatorData[ m_currentDataIdx ].DataType, false ); + break; + } + + ConfigurePorts(); + + if( !areCompatible ) + { + m_containerGraph.DeleteConnection( false, UniqueId, 0, false, true ); + } + + m_dataName = m_interpolatorData[ m_currentDataIdx ].VarName; + m_content.text = m_dataName; + m_sizeIsDirty = true; + CheckWarningState(); + } + } + + + public override void DrawProperties() + { + base.DrawProperties(); + if( m_multiPassMode ) + { + DrawMultipassProperties(); + } + + if( m_currentDataIdx > -1 ) + { + EditorGUI.BeginChangeCheck(); + m_currentDataIdx = EditorGUILayoutPopup( DataLabelStr, m_currentDataIdx, m_dataLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromId(); + } + } + } + + protected override void OnSubShaderChange() + { + base.OnSubShaderChange(); + FetchInterpolator(); + FetchDataId(); + } + + protected override void OnPassChange() + { + FetchInterpolator(); + FetchDataId(); + } + + void DrawMultipassProperties() + { + DrawSubShaderUI(); + DrawPassUI(); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader ) + return; + + if( m_interpolatorData == null || m_interpolatorData.Count == 0 ) + { + MasterNode masterNode = m_containerGraph.CurrentMasterNode; + FetchInterpolator( masterNode ); + } + + if( m_fetchDataId ) + { + m_fetchDataId = false; + FetchDataId(); + } + + if( m_currentDataIdx > -1 ) + { + EditorGUI.BeginChangeCheck(); + m_currentDataIdx = m_upperLeftWidgetHelper.DrawWidget( this, m_currentDataIdx, m_dataLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromId(); + } + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.MasterNodeCategory != AvailableShaderTypes.Template ) + { + UIUtils.ShowMessage( UniqueId, "Template Fragmment Data node is only intended for templates use only" ); + return m_outputPorts[ 0 ].ErrorValue; + } + + if( !dataCollector.IsFragmentCategory ) + { + UIUtils.ShowMessage( UniqueId, "Template Fragment Data node node is only intended for fragment use use only" ); + return m_outputPorts[ 0 ].ErrorValue; + } + + if( m_multiPassMode ) + { + if( dataCollector.TemplateDataCollectorInstance.MultipassSubshaderIdx != SubShaderIdx || + dataCollector.TemplateDataCollectorInstance.MultipassPassIdx != PassIdx + ) + { + UIUtils.ShowMessage( UniqueId, string.Format( "{0} is only intended for subshader {1} and pass {2}", m_dataLabels[ m_currentDataIdx ], SubShaderIdx, PassIdx ) ); + return m_outputPorts[ outputId ].ErrorValue; + } + } + + return GetOutputVectorItem( 0, outputId, m_inVarName + m_dataName ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_dataName = GetCurrentParam( ref nodeParams ); + m_fetchDataId = true; + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_dataName ); + } + + public override void OnMasterNodeReplaced( MasterNode newMasterNode ) + { + base.OnMasterNodeReplaced( newMasterNode ); + if( newMasterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template ) + { + FetchInterpolator( newMasterNode ); + } + else + { + m_interpolatorData = null; + m_currentDataIdx = -1; + } + } + + protected override bool ValidatePass( int passIdx ) + { + return ( m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ passIdx ].FragmentFunctionData != null && + m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ passIdx ].InterpolatorDataContainer != null ); + } + + void FetchInterpolator( MasterNode masterNode = null ) + { + FetchMultiPassTemplate( masterNode ); + if( m_multiPassMode ) + { + if( m_templateMPData != null ) + { + m_inVarName = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].FragmentFunctionData.InVarName + "."; + m_interpolatorData = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].InterpolatorDataContainer.RawInterpolators; + m_fetchDataId = true; + } + } + else + { + if( masterNode == null ) + masterNode = m_containerGraph.CurrentMasterNode; + + TemplateData currentTemplate = ( masterNode as TemplateMasterNode ).CurrentTemplate; + if( currentTemplate != null ) + { + m_inVarName = currentTemplate.FragmentFunctionData.InVarName + "."; + m_interpolatorData = currentTemplate.InterpolatorData.RawInterpolators; + FetchDataId(); + } + else + { + m_interpolatorData = null; + m_currentDataIdx = -1; + } + } + } + + public override void Destroy() + { + base.Destroy(); + m_dataLabels = null; + m_interpolatorData = null; + m_upperLeftWidgetHelper = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs.meta new file mode 100644 index 0000000..8e3e69f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2b53cc116abb0df45b028f41b8f0305e +timeCreated: 1506595629 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs new file mode 100644 index 0000000..2e022ef --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs @@ -0,0 +1,2550 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.IO; +using System.Text.RegularExpressions; +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public enum CustomTemplatePropertyUIEnum + { + None, + HDPBR + } + + public enum TemplateSemantics + { + NONE, + POSITION, + SV_POSITION, + COLOR, + COLOR0, + COLOR1, + TEXCOORD0, + TEXCOORD1, + TEXCOORD2, + TEXCOORD3, + TEXCOORD4, + TEXCOORD5, + TEXCOORD6, + TEXCOORD7, + TEXCOORD8, + TEXCOORD9, + TEXCOORD10, + TEXCOORD11, + TEXCOORD12, + TEXCOORD13, + TEXCOORD14, + TEXCOORD15, + NORMAL, + TANGENT, + VFACE, + SV_VertexID, + SV_PrimitiveID, + SV_InstanceID, + INTERNALTESSPOS, + INSTANCEID_SEMANTIC, + BLENDWEIGHTS, + BLENDINDICES + + } + + public enum TemplateInfoOnSematics + { + NONE, + POSITION, + CLIP_POS, + SCREEN_POSITION, + SCREEN_POSITION_NORMALIZED, + COLOR, + TEXTURE_COORDINATES0, + TEXTURE_COORDINATES1, + TEXTURE_COORDINATES2, + TEXTURE_COORDINATES3, + TEXTURE_COORDINATES4, + TEXTURE_COORDINATES5, + TEXTURE_COORDINATES6, + TEXTURE_COORDINATES7, + NORMAL, + TANGENT, + WORLD_NORMAL, + WORLD_TANGENT, + WORLD_BITANGENT, + WORLD_VIEW_DIR, + WORLD_POSITION, + RELATIVE_WORLD_POS, + INSTANCE_ID, + OTHER, + VFACE, + SHADOWCOORDS, + VERTEXID, + BLENDWEIGHTS, + BLENDINDICES + } + + public enum TemplateShaderPropertiesIdx + { + Identation = 1, + Name = 3, + InspectorName, + Type + } + + public enum TemplateShaderGlobalsIdx + { + Type = 1, + Name = 2 + } + public enum TemplateDataCheck + { + Valid, + Invalid + } + + public enum InvisibleOptionsEnum + { + SyncProperties = 1 << 0 + } + + public enum TemplateSpecialTags + { + RenderType, + Queue, + DisableBatching, + None + } + + public class TemplateReplaceHelper + { + public TemplateMultiPassMasterNode MasterNode = null; + public bool Used = false; + public TemplateReplaceHelper( TemplateMultiPassMasterNode masterNode ) { MasterNode = masterNode; } + } + + [Serializable] + public class TemplatesTagData + { + public string Name; + public string Value; + public TemplatesTagData( string name, string value ) + { + Name = name; + Value = value; + } + } + + [Serializable] + public class TemplateModuleData + { + public bool IndependentModule = true; + public TemplateDataCheck DataCheck = TemplateDataCheck.Invalid; + public string InlineData = string.Empty; + public int StartIdx; + public bool IsValid { get { return DataCheck == TemplateDataCheck.Valid; } } + public virtual void SetAllModulesDefault() { IndependentModule = false; DataCheck = TemplateDataCheck.Valid; } + } + + [Serializable] + public sealed class TemplateTagsModuleData : TemplateModuleData + { + public string TagsId; + public List Tags = new List(); + public void Destroy() + { + Tags.Clear(); + Tags = null; + } + + public void Reset() + { + Tags.Clear(); + } + + public void Dump() + { + string dump = string.Empty; + for( int i = 0; i < Tags.Count; i++ ) + { + dump += string.Format( "[{0}] Name: {1} Value: {2}\n", i, Tags[ i ].Name, Tags[ i ].Value ); + } + Debug.Log( dump ); + } + } + + [Serializable] + public class TemplateShaderModelData : TemplateModuleData + { + public string Id = string.Empty; + public string Value = "2.5"; + public int InterpolatorAmount = 8; + public bool Encapsulate = false; + public override void SetAllModulesDefault() + { + base.SetAllModulesDefault(); + Id = string.Empty; + Value = "3.0"; + InterpolatorAmount = 10; + Encapsulate = true; + } + } + + [Serializable] + public sealed class TemplateDepthData : TemplateModuleData + { + public bool ValidZWrite; + public string ZWriteModeId; + public ZWriteMode ZWriteModeValue; + public int ZWriteStartIndex; + public string ZWriteInlineValue; + + + public bool ValidZTest; + public string ZTestModeId; + public ZTestMode ZTestModeValue; + public int ZTestStartIndex; + public string ZTestInlineValue; + + public bool ValidOffset; + public string OffsetId; + public float OffsetFactor; + public float OffsetUnits; + public int OffsetStartIndex; + public string OffsetFactorInlineValue; + public string OffsetUnitsInlineValue; + + public override void SetAllModulesDefault() + { + base.SetAllModulesDefault(); + ValidZWrite = true; + ZWriteModeId = string.Empty; + ZWriteModeValue = ZWriteMode.On; + ZWriteStartIndex = -1; + ZWriteInlineValue = string.Empty; + + + ValidZTest = true; + ZTestModeId = string.Empty; + ZTestModeValue = ZTestMode.LEqual; + ZTestStartIndex = -1; + ZTestInlineValue = string.Empty; + + ValidOffset = true; + OffsetId = string.Empty; + OffsetFactor = 0; + OffsetUnits = 0; + OffsetStartIndex = -1; + OffsetFactorInlineValue = string.Empty; + OffsetUnitsInlineValue = string.Empty; + } + + public void SetDataCheck() + { + DataCheck = ( ValidZWrite || ValidZTest || ValidOffset )?TemplateDataCheck.Valid:TemplateDataCheck.Invalid; + } + } + + [Serializable] + public sealed class TemplateStencilData : TemplateModuleData + { + public string StencilBufferId; + public bool Active = true; + + public int Reference; + public string ReferenceInline; + + public int ReadMask = 255; + public string ReadMaskInline; + + public int WriteMask = 255; + public string WriteMaskInline; + + public string ComparisonFront; + public string ComparisonFrontInline; + + public string PassFront; + public string PassFrontInline; + + public string FailFront; + public string FailFrontInline; + + public string ZFailFront; + public string ZFailFrontInline; + + public string ComparisonBack; + public string ComparisonBackInline; + + public string PassBack; + public string PassBackInline; + + public string FailBack; + public string FailBackInline; + + public string ZFailBack; + public string ZFailBackInline; + + public void SetDefaultValues() + { + Active = false; + + StencilBufferId = string.Empty; + + Reference = 255; + ReferenceInline = string.Empty; + + ReadMask = 255; + ReadMaskInline = string.Empty; + + WriteMask = 255; + WriteMaskInline = string.Empty; + + ComparisonFront = "always"; + ComparisonFrontInline = string.Empty; + + PassFront = "keep"; + PassFrontInline = string.Empty; + + FailFront = "keep"; + FailFrontInline = string.Empty; + + ZFailFront = "keep"; + ZFailFrontInline = string.Empty; + + + ComparisonBack = "always"; + ComparisonBackInline = string.Empty; + + PassBack = "keep"; + PassBackInline = string.Empty; + + FailBack = "keep"; + FailBackInline = string.Empty; + + ZFailBack = "keep"; + ZFailBackInline = string.Empty; + } + + public void SetIndependentDefault() + { + IndependentModule = true; + DataCheck = TemplateDataCheck.Valid; + SetDefaultValues(); + } + + public override void SetAllModulesDefault() + { + base.SetAllModulesDefault(); + SetDefaultValues(); + } + } + + [Serializable] + public sealed class TemplateBlendData : TemplateModuleData + { + public bool ValidBlendMode = false; + public bool BlendModeOff = true; + + public string Target = string.Empty; + + public string BlendModeId; + public bool SeparateBlendFactors = false; + public AvailableBlendFactor SourceFactorRGB = AvailableBlendFactor.One; + public string SourceFactorRGBInline; + public AvailableBlendFactor DestFactorRGB = AvailableBlendFactor.Zero; + public string DestFactorRGBInline; + public int BlendModeStartIndex; + + public AvailableBlendFactor SourceFactorAlpha = AvailableBlendFactor.One; + public string SourceFactorAlphaInline; + public AvailableBlendFactor DestFactorAlpha = AvailableBlendFactor.Zero; + public string DestFactorAlphaInline; + + public bool ValidBlendOp = false; + public string BlendOpId; + public bool SeparateBlendOps = false; + public AvailableBlendOps BlendOpRGB = AvailableBlendOps.OFF; + public string BlendOpRGBInline; + public AvailableBlendOps BlendOpAlpha = AvailableBlendOps.OFF; + public string BlendOpAlphaInline; + public int BlendOpStartIndex; + + + public override void SetAllModulesDefault() + { + base.SetAllModulesDefault(); + + + if( !ValidBlendMode ) + { + ValidBlendMode = true; + BlendModeOff = true; + BlendModeId = string.Empty; + SeparateBlendFactors = false; + SourceFactorRGB = AvailableBlendFactor.One; + SourceFactorRGBInline = string.Empty; + DestFactorRGB = AvailableBlendFactor.Zero; + DestFactorRGBInline = string.Empty; + BlendModeStartIndex = -1; + SourceFactorAlpha = AvailableBlendFactor.One; + SourceFactorAlphaInline = string.Empty; + DestFactorAlpha = AvailableBlendFactor.Zero; + DestFactorAlphaInline = string.Empty; + } + + if( !ValidBlendOp ) + { + ValidBlendOp = true; + BlendOpId = string.Empty; + SeparateBlendOps = false; + BlendOpRGB = AvailableBlendOps.OFF; + BlendOpRGBInline = string.Empty; + BlendOpAlpha = AvailableBlendOps.OFF; + BlendOpAlphaInline = string.Empty; + BlendOpStartIndex = -1; + } + + DataCheck = TemplateDataCheck.Valid; + } + + } + + [Serializable] + public sealed class TemplateAlphaToMaskData : TemplateModuleData + { + public string AlphaToMaskId; + public bool AlphaToMaskData = false; + public override void SetAllModulesDefault() + { + base.SetAllModulesDefault(); + AlphaToMaskId = string.Empty; + AlphaToMaskData = false; + } + } + + [Serializable] + public sealed class TemplateCullModeData : TemplateModuleData + { + public string CullModeId; + public CullMode CullModeData = CullMode.Back; + public override void SetAllModulesDefault() + { + base.SetAllModulesDefault(); + CullModeId = string.Empty; + CullModeData = CullMode.Back; + } + } + + [Serializable] + public sealed class TemplateColorMaskData : TemplateModuleData + { + public string ColorMaskId; + public bool[] ColorMaskData = { true, true, true, true }; + public string Target = string.Empty; + public override void SetAllModulesDefault() + { + base.SetAllModulesDefault(); + ColorMaskId = string.Empty; + Target = string.Empty; + for( int i = 0; i < ColorMaskData.Length; i++ ) + { + ColorMaskData[ i ] = true; + } + } + } + + public static class TemplateHelperFunctions + { + /* + struct DirectionalLightData + { + uint lightLayers; + float3 positionRWS; + float3 color; + int cookieIndex; + float volumetricDimmer; + float3 right; + float3 up; + float3 forward; + int tileCookie; + int shadowIndex; + int contactShadowIndex; + float4 shadowMaskSelector; + int nonLightmappedOnly; + float diffuseScale; + float specularScale; + }; + */ + public static string HDLightInfoFormat = "_DirectionalLightDatas[{0}].{1}"; + + public static string[] VectorSwizzle = { "x", "y", "z", "w" }; + public static string[] ColorSwizzle = { "r", "g", "b", "a" }; + + public static readonly Dictionary CustomTemplatePropertyUI = new Dictionary + { + { "None", CustomTemplatePropertyUIEnum.None}, + { "HDPBR", CustomTemplatePropertyUIEnum.HDPBR} + }; + + public static readonly Dictionary InvisibleOptions = new Dictionary() + { + { "SyncP", InvisibleOptionsEnum.SyncProperties } + }; + + public static readonly Dictionary StringToReservedTags = new Dictionary() + { + { TemplateSpecialTags.RenderType.ToString(), TemplateSpecialTags.RenderType}, + { TemplateSpecialTags.Queue.ToString(), TemplateSpecialTags.Queue}, + { TemplateSpecialTags.DisableBatching.ToString(), TemplateSpecialTags.DisableBatching}, + }; + + public static readonly Dictionary StringToDisableBatching = new Dictionary + { + {"true",DisableBatching.True}, + {"True",DisableBatching.True}, + {"false",DisableBatching.False}, + {"False",DisableBatching.False}, + {"LOD Fading",DisableBatching.LODFading}, + {"LODFading",DisableBatching.LODFading} + }; + + public static readonly Dictionary StringToRenderType = new Dictionary + { + {"Opaque",RenderType.Opaque}, + {"Transparent",RenderType.Transparent}, + {"TransparentCutout",RenderType.TransparentCutout}, + {"Background",RenderType.Background}, + {"Overlay",RenderType.Overlay}, + {"TreeOpaque",RenderType.TreeOpaque}, + {"TreeTransparentCutout",RenderType.TreeTransparentCutout}, + {"TreeBillboard",RenderType.TreeBillboard}, + {"Grass",RenderType.Grass}, + {"GrassBillboard",RenderType.GrassBillboard} + }; + + public static readonly Dictionary StringToRenderQueue = new Dictionary + { + {"Background",RenderQueue.Background }, + {"Geometry",RenderQueue.Geometry }, + {"AlphaTest",RenderQueue.AlphaTest }, + {"Transparent",RenderQueue.Transparent }, + {"Overlay",RenderQueue.Overlay } + }; + + public static readonly Dictionary PropertyToWireType = new Dictionary + { + {"Float",WirePortDataType.FLOAT}, + {"Range",WirePortDataType.FLOAT}, + {"Int",WirePortDataType.INT}, + {"Color",WirePortDataType.COLOR}, + {"Vector",WirePortDataType.FLOAT4}, + {"2D",WirePortDataType.SAMPLER2D}, + {"3D",WirePortDataType.SAMPLER3D}, + {"Cube",WirePortDataType.SAMPLERCUBE}, + {"2DArray",WirePortDataType.SAMPLER2DARRAY}, + }; + + public static readonly Dictionary DataTypeChannelUsage = new Dictionary + { + {WirePortDataType.OBJECT,0 }, + {WirePortDataType.FLOAT,1 }, + {WirePortDataType.FLOAT2,2 }, + {WirePortDataType.FLOAT3,3 }, + {WirePortDataType.FLOAT4,4 }, + {WirePortDataType.FLOAT3x3,0 }, + {WirePortDataType.FLOAT4x4,0 }, + {WirePortDataType.COLOR,4 }, + {WirePortDataType.INT,1 }, + {WirePortDataType.UINT,1 }, + {WirePortDataType.UINT4,4 }, + {WirePortDataType.SAMPLER1D,0 }, + {WirePortDataType.SAMPLER2D,0 }, + {WirePortDataType.SAMPLER3D,0 }, + {WirePortDataType.SAMPLERCUBE,0 }, + {WirePortDataType.SAMPLER2DARRAY,0 }, + {WirePortDataType.SAMPLERSTATE,0 } + }; + + public static readonly Dictionary ChannelToDataType = new Dictionary + { + {1,WirePortDataType.FLOAT}, + {2,WirePortDataType.FLOAT2}, + {3,WirePortDataType.FLOAT3}, + {4,WirePortDataType.FLOAT4} + }; + + public static readonly Dictionary SemanticsDefaultName = new Dictionary + { + {TemplateSemantics.COLOR ,"ase_color"}, + {TemplateSemantics.NORMAL ,"ase_normal"}, + {TemplateSemantics.POSITION ,"ase_position"}, + {TemplateSemantics.SV_POSITION ,"ase_sv_position"}, + {TemplateSemantics.TANGENT ,"ase_tangent"}, + {TemplateSemantics.VFACE ,"ase_vface"}, + {TemplateSemantics.SV_VertexID ,"ase_vertexId"}, + {TemplateSemantics.SV_PrimitiveID ,"ase_primitiveId"}, + {TemplateSemantics.INTERNALTESSPOS ,"ase_internalTessPos"}, + {TemplateSemantics.TEXCOORD0 ,"ase_tex_coord0"}, + {TemplateSemantics.TEXCOORD1 ,"ase_tex_coord1"}, + {TemplateSemantics.TEXCOORD2 ,"ase_tex_coord2"}, + {TemplateSemantics.TEXCOORD3 ,"ase_tex_coord3"}, + {TemplateSemantics.TEXCOORD4 ,"ase_tex_coord4"}, + {TemplateSemantics.TEXCOORD5 ,"ase_tex_coord5"}, + {TemplateSemantics.TEXCOORD6 ,"ase_tex_coord6"}, + {TemplateSemantics.TEXCOORD7 ,"ase_tex_coord7"}, + {TemplateSemantics.TEXCOORD8 ,"ase_tex_coord8"}, + {TemplateSemantics.TEXCOORD9 ,"ase_tex_coord9"}, + {TemplateSemantics.TEXCOORD10 ,"ase_tex_coord10"}, + {TemplateSemantics.TEXCOORD11 ,"ase_tex_coord11"}, + {TemplateSemantics.TEXCOORD12 ,"ase_tex_coord12"}, + {TemplateSemantics.TEXCOORD13 ,"ase_tex_coord13"}, + {TemplateSemantics.TEXCOORD14 ,"ase_tex_coord14"}, + {TemplateSemantics.TEXCOORD15 ,"ase_tex_coord15"}, + }; + + public static readonly Dictionary IntToInfo = new Dictionary + { + {0,TemplateInfoOnSematics.TEXTURE_COORDINATES0 }, + {1,TemplateInfoOnSematics.TEXTURE_COORDINATES1 }, + {2,TemplateInfoOnSematics.TEXTURE_COORDINATES2 }, + {3,TemplateInfoOnSematics.TEXTURE_COORDINATES3 }, + {4,TemplateInfoOnSematics.TEXTURE_COORDINATES4 }, + {5,TemplateInfoOnSematics.TEXTURE_COORDINATES5 }, + {6,TemplateInfoOnSematics.TEXTURE_COORDINATES6 }, + {7,TemplateInfoOnSematics.TEXTURE_COORDINATES7 }, + }; + + public static readonly Dictionary ShortcutToInfo = new Dictionary + { + {"p" ,TemplateInfoOnSematics.POSITION }, + {"sp" ,TemplateInfoOnSematics.CLIP_POS }, + {"spu" ,TemplateInfoOnSematics.SCREEN_POSITION }, + {"spn" ,TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED }, + {"c" ,TemplateInfoOnSematics.COLOR }, + {"uv0" ,TemplateInfoOnSematics.TEXTURE_COORDINATES0 }, + {"uv1" ,TemplateInfoOnSematics.TEXTURE_COORDINATES1 }, + {"uv2" ,TemplateInfoOnSematics.TEXTURE_COORDINATES2 }, + {"uv3" ,TemplateInfoOnSematics.TEXTURE_COORDINATES3 }, + {"uv4" ,TemplateInfoOnSematics.TEXTURE_COORDINATES4 }, + {"uv5" ,TemplateInfoOnSematics.TEXTURE_COORDINATES5 }, + {"uv6" ,TemplateInfoOnSematics.TEXTURE_COORDINATES6 }, + {"uv7" ,TemplateInfoOnSematics.TEXTURE_COORDINATES7 }, + {"n" ,TemplateInfoOnSematics.NORMAL }, + {"t" ,TemplateInfoOnSematics.TANGENT }, + {"wn" ,TemplateInfoOnSematics.WORLD_NORMAL}, + {"wt" ,TemplateInfoOnSematics.WORLD_TANGENT}, + {"wbt" ,TemplateInfoOnSematics.WORLD_BITANGENT}, + {"wvd" ,TemplateInfoOnSematics.WORLD_VIEW_DIR}, + {"wp" ,TemplateInfoOnSematics.WORLD_POSITION}, + {"rwp" ,TemplateInfoOnSematics.RELATIVE_WORLD_POS}, + {"vf" ,TemplateInfoOnSematics.VFACE}, + {"sc" ,TemplateInfoOnSematics.SHADOWCOORDS} + }; + + public static readonly Dictionary InfoToDefineFrag = new Dictionary + { + {TemplateInfoOnSematics.POSITION ,"ASE_NEEDS_FRAG_POSITION"}, + {TemplateInfoOnSematics.CLIP_POS ,"ASE_NEEDS_FRAG_CLIP_POS"}, + {TemplateInfoOnSematics.SCREEN_POSITION,"ASE_NEEDS_FRAG_SCREEN_POSITION" }, + {TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED,"ASE_NEEDS_FRAG_SCREEN_POSITION_NORMALIZED" }, + {TemplateInfoOnSematics.COLOR, "ASE_NEEDS_FRAG_COLOR"}, + {TemplateInfoOnSematics.TEXTURE_COORDINATES0,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES0" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES1,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES1" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES2,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES2" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES3,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES3" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES4,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES4" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES5,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES5" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES6,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES6" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES7,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES7" }, + {TemplateInfoOnSematics.NORMAL,"ASE_NEEDS_FRAG_NORMAL" }, + {TemplateInfoOnSematics.TANGENT ,"ASE_NEEDS_FRAG_TANGENT"}, + {TemplateInfoOnSematics.WORLD_NORMAL,"ASE_NEEDS_FRAG_WORLD_NORMAL"}, + {TemplateInfoOnSematics.WORLD_TANGENT,"ASE_NEEDS_FRAG_WORLD_TANGENT"}, + {TemplateInfoOnSematics.WORLD_BITANGENT,"ASE_NEEDS_FRAG_WORLD_BITANGENT"}, + {TemplateInfoOnSematics.WORLD_VIEW_DIR,"ASE_NEEDS_FRAG_WORLD_VIEW_DIR"}, + {TemplateInfoOnSematics.WORLD_POSITION,"ASE_NEEDS_FRAG_WORLD_POSITION"}, + {TemplateInfoOnSematics.RELATIVE_WORLD_POS,"ASE_NEEDS_FRAG_RELATIVE_WORLD_POS"}, + {TemplateInfoOnSematics.VFACE,"ASE_NEEDS_FRAG_VFACE"}, + {TemplateInfoOnSematics.SHADOWCOORDS,"ASE_NEEDS_FRAG_SHADOWCOORDS"} + }; + + public static readonly Dictionary InfoToDefineVertex = new Dictionary + { + {TemplateInfoOnSematics.POSITION ,"ASE_NEEDS_VERT_POSITION"}, + {TemplateInfoOnSematics.CLIP_POS ,"ASE_NEEDS_VERT_CLIP_POS"}, + {TemplateInfoOnSematics.SCREEN_POSITION,"ASE_NEEDS_VERT_SCREEN_POSITION" }, + {TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED,"ASE_NEEDS_VERT_SCREEN_POSITION_NORMALIZED" }, + {TemplateInfoOnSematics.COLOR, "ASE_NEEDS_VERT_COLOR"}, + {TemplateInfoOnSematics.TEXTURE_COORDINATES0,"ASE_NEEDS_VERT_TEXTURE_COORDINATES0" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES1,"ASE_NEEDS_VERT_TEXTURE_COORDINATES1" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES2,"ASE_NEEDS_VERT_TEXTURE_COORDINATES2" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES3,"ASE_NEEDS_VERT_TEXTURE_COORDINATES3" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES4,"ASE_NEEDS_VERT_TEXTURE_COORDINATES4" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES5,"ASE_NEEDS_VERT_TEXTURE_COORDINATES5" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES6,"ASE_NEEDS_VERT_TEXTURE_COORDINATES6" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES7,"ASE_NEEDS_VERT_TEXTURE_COORDINATES7" }, + {TemplateInfoOnSematics.NORMAL,"ASE_NEEDS_VERT_NORMAL" }, + {TemplateInfoOnSematics.TANGENT ,"ASE_NEEDS_VERT_TANGENT"}, + {TemplateInfoOnSematics.WORLD_NORMAL,"ASE_NEEDS_VERT_WORLD_NORMAL"}, + {TemplateInfoOnSematics.WORLD_TANGENT,"ASE_NEEDS_VERT_WORLD_TANGENT"}, + {TemplateInfoOnSematics.WORLD_BITANGENT,"ASE_NEEDS_VERT_WORLD_BITANGENT"}, + {TemplateInfoOnSematics.WORLD_VIEW_DIR,"ASE_NEEDS_VERT_WORLD_VIEW_DIR"}, + {TemplateInfoOnSematics.WORLD_POSITION,"ASE_NEEDS_VERT_WORLD_POSITION"}, + {TemplateInfoOnSematics.RELATIVE_WORLD_POS,"ASE_NEEDS_VERT_RELATIVE_WORLD_POS"}, + {TemplateInfoOnSematics.VFACE,"ASE_NEEDS_VERT_VFACE"}, + {TemplateInfoOnSematics.SHADOWCOORDS,"ASE_NEEDS_VERT_SHADOWCOORDS"} + }; + + public static readonly Dictionary InfoToLocalVar = new Dictionary + { + {TemplateInfoOnSematics.POSITION,GeneratorUtils.VertexPosition4Str }, + {TemplateInfoOnSematics.CLIP_POS,GeneratorUtils.ClipPositionStr }, + {TemplateInfoOnSematics.SCREEN_POSITION,GeneratorUtils.ScreenPositionStr }, + {TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED,GeneratorUtils.ScreenPositionNormalizedStr }, + {TemplateInfoOnSematics.COLOR, "ase_color" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES0, "ase_uv0" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES1, "ase_uv1" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES2, "ase_uv2" }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES3, "ase_uv3" }, + {TemplateInfoOnSematics.NORMAL, GeneratorUtils.VertexNormalStr }, + {TemplateInfoOnSematics.TANGENT, GeneratorUtils.VertexTangentStr }, + {TemplateInfoOnSematics.WORLD_NORMAL, GeneratorUtils.WorldNormalStr}, + {TemplateInfoOnSematics.WORLD_TANGENT, GeneratorUtils.WorldTangentStr}, + {TemplateInfoOnSematics.WORLD_BITANGENT, GeneratorUtils.WorldBitangentStr}, + {TemplateInfoOnSematics.WORLD_VIEW_DIR, GeneratorUtils.WorldViewDirectionStr}, + {TemplateInfoOnSematics.WORLD_POSITION, GeneratorUtils.WorldPositionStr}, + {TemplateInfoOnSematics.RELATIVE_WORLD_POS, GeneratorUtils.RelativeWorldPositionStr}, + {TemplateInfoOnSematics.VFACE, GeneratorUtils.VFaceStr}, + {TemplateInfoOnSematics.SHADOWCOORDS, GeneratorUtils.ShadowCoordsStr} + }; + + + public static readonly Dictionary InfoToWirePortType = new Dictionary + { + {TemplateInfoOnSematics.POSITION,WirePortDataType.FLOAT4 }, + {TemplateInfoOnSematics.CLIP_POS,WirePortDataType.FLOAT4 }, + {TemplateInfoOnSematics.SCREEN_POSITION,WirePortDataType.FLOAT4 }, + {TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED,WirePortDataType.FLOAT4 }, + {TemplateInfoOnSematics.COLOR, WirePortDataType.COLOR }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES0, WirePortDataType.FLOAT4 }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES1, WirePortDataType.FLOAT4 }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES2, WirePortDataType.FLOAT4 }, + {TemplateInfoOnSematics.TEXTURE_COORDINATES3, WirePortDataType.FLOAT4 }, + {TemplateInfoOnSematics.NORMAL, WirePortDataType.FLOAT3 }, + {TemplateInfoOnSematics.TANGENT, WirePortDataType.FLOAT4 }, + {TemplateInfoOnSematics.WORLD_NORMAL, WirePortDataType.FLOAT3}, + {TemplateInfoOnSematics.WORLD_TANGENT, WirePortDataType.FLOAT3}, + {TemplateInfoOnSematics.WORLD_BITANGENT, WirePortDataType.FLOAT3}, + {TemplateInfoOnSematics.WORLD_VIEW_DIR, WirePortDataType.FLOAT3}, + {TemplateInfoOnSematics.WORLD_POSITION, WirePortDataType.FLOAT3}, + {TemplateInfoOnSematics.RELATIVE_WORLD_POS, WirePortDataType.FLOAT3}, + {TemplateInfoOnSematics.VFACE, WirePortDataType.FLOAT}, + {TemplateInfoOnSematics.SHADOWCOORDS, WirePortDataType.FLOAT4}, + }; + public static readonly Dictionary IntToUVChannelInfo = new Dictionary + { + {0,TemplateInfoOnSematics.TEXTURE_COORDINATES0 }, + {1,TemplateInfoOnSematics.TEXTURE_COORDINATES1 }, + {2,TemplateInfoOnSematics.TEXTURE_COORDINATES2 }, + {3,TemplateInfoOnSematics.TEXTURE_COORDINATES3 }, + {4,TemplateInfoOnSematics.TEXTURE_COORDINATES4 }, + {5,TemplateInfoOnSematics.TEXTURE_COORDINATES5 }, + {6,TemplateInfoOnSematics.TEXTURE_COORDINATES6 }, + {7,TemplateInfoOnSematics.TEXTURE_COORDINATES7 } + }; + + public static readonly Dictionary IntToSemantic = new Dictionary + { + { 0,TemplateSemantics.TEXCOORD0 }, + { 1,TemplateSemantics.TEXCOORD1 }, + { 2,TemplateSemantics.TEXCOORD2 }, + { 3,TemplateSemantics.TEXCOORD3 }, + { 4,TemplateSemantics.TEXCOORD4 }, + { 5,TemplateSemantics.TEXCOORD5 }, + { 6,TemplateSemantics.TEXCOORD6 }, + { 7,TemplateSemantics.TEXCOORD7 }, + { 8,TemplateSemantics.TEXCOORD8 }, + { 9,TemplateSemantics.TEXCOORD9 }, + { 10,TemplateSemantics.TEXCOORD10 }, + { 11,TemplateSemantics.TEXCOORD11 }, + { 12,TemplateSemantics.TEXCOORD12 }, + { 13,TemplateSemantics.TEXCOORD13 }, + { 14,TemplateSemantics.TEXCOORD14 }, + { 15,TemplateSemantics.TEXCOORD15 } + }; + + public static readonly Dictionary SemanticToInt = new Dictionary + { + { TemplateSemantics.TEXCOORD0,0 }, + { TemplateSemantics.TEXCOORD1,1 }, + { TemplateSemantics.TEXCOORD2,2 }, + { TemplateSemantics.TEXCOORD3,3 }, + { TemplateSemantics.TEXCOORD4,4 }, + { TemplateSemantics.TEXCOORD5,5 }, + { TemplateSemantics.TEXCOORD6,6 }, + { TemplateSemantics.TEXCOORD7,7 }, + { TemplateSemantics.TEXCOORD8,8 }, + { TemplateSemantics.TEXCOORD9,9 }, + { TemplateSemantics.TEXCOORD10,10 }, + { TemplateSemantics.TEXCOORD11,11 }, + { TemplateSemantics.TEXCOORD12,12 }, + { TemplateSemantics.TEXCOORD13,13 }, + { TemplateSemantics.TEXCOORD14,14 }, + { TemplateSemantics.TEXCOORD15,15 }, + }; + + public static readonly Dictionary ShortcutToSemantic = new Dictionary + { + { "p" ,TemplateSemantics.POSITION }, + { "sp" ,TemplateSemantics.SV_POSITION }, + { "c" ,TemplateSemantics.COLOR }, + { "n" ,TemplateSemantics.NORMAL }, + { "t" ,TemplateSemantics.TANGENT }, + { "tc0" ,TemplateSemantics.TEXCOORD0 }, + { "tc1" ,TemplateSemantics.TEXCOORD1 }, + { "tc2" ,TemplateSemantics.TEXCOORD2 }, + { "tc3" ,TemplateSemantics.TEXCOORD3 }, + { "tc4" ,TemplateSemantics.TEXCOORD4 }, + { "tc5" ,TemplateSemantics.TEXCOORD5 }, + { "tc6" ,TemplateSemantics.TEXCOORD6 }, + { "tc7" ,TemplateSemantics.TEXCOORD7 }, + { "tc8" ,TemplateSemantics.TEXCOORD8 }, + { "tc9" ,TemplateSemantics.TEXCOORD9 }, + { "tc10" ,TemplateSemantics.TEXCOORD10 }, + { "tc11" ,TemplateSemantics.TEXCOORD11 }, + { "tc12" ,TemplateSemantics.TEXCOORD12 }, + { "tc13" ,TemplateSemantics.TEXCOORD13 }, + { "tc14" ,TemplateSemantics.TEXCOORD14 }, + { "tc15" ,TemplateSemantics.TEXCOORD15 } + }; + + public static readonly Dictionary CgToWirePortType = new Dictionary() + { + {"float" ,WirePortDataType.FLOAT}, + {"float2" ,WirePortDataType.FLOAT2}, + {"float3" ,WirePortDataType.FLOAT3}, + {"float4" ,WirePortDataType.FLOAT4}, + {"float3x3" ,WirePortDataType.FLOAT3x3}, + {"float4x4" ,WirePortDataType.FLOAT4x4}, + {"half" ,WirePortDataType.FLOAT}, + {"half2" ,WirePortDataType.FLOAT2}, + {"half3" ,WirePortDataType.FLOAT3}, + {"half4" ,WirePortDataType.FLOAT4}, + {"half3x3" ,WirePortDataType.FLOAT3x3}, + {"half4x4" ,WirePortDataType.FLOAT4x4}, + {"fixed" ,WirePortDataType.FLOAT}, + {"fixed2" ,WirePortDataType.FLOAT2}, + {"fixed3" ,WirePortDataType.FLOAT3}, + {"fixed4" ,WirePortDataType.FLOAT4}, + {"fixed3x3" ,WirePortDataType.FLOAT3x3}, + {"fixed4x4" ,WirePortDataType.FLOAT4x4}, + {"int" ,WirePortDataType.INT}, + {"uint" ,WirePortDataType.INT}, + {"sampler1D" ,WirePortDataType.SAMPLER1D}, + {"sampler2D" ,WirePortDataType.SAMPLER2D}, + {"sampler2D_float" ,WirePortDataType.SAMPLER2D}, + {"sampler3D" ,WirePortDataType.SAMPLER3D}, + {"samplerCUBE" ,WirePortDataType.SAMPLERCUBE}, + {"sampler2DArray" ,WirePortDataType.SAMPLER2DARRAY}, + {"SamplerState" ,WirePortDataType.SAMPLERSTATE} + }; + + public static readonly Dictionary AvailableInterpolators = new Dictionary() + { + {"2.0",8 }, + {"2.5",8 }, + {"3.0",10}, + {"3.5",10}, + {"4.0",16}, + {"4.5",16}, + {"4.6",16}, + {"5.0",16} + }; + + public static readonly string[] AvailableShaderModels = + { "2.0", "2.5", "3.0", "3.5", "4.0", "4.5", "4.6", "5.0" }; + + public static readonly Dictionary ShaderModelToArrayIdx = new Dictionary() + { + {"2.0",0}, + {"2.5",1}, + {"3.0",2}, + {"3.5",3}, + {"4.0",4}, + {"4.5",5}, + {"4.6",6}, + {"5.0",7} + }; + + public static readonly string HDPBRTag = "UNITY_MATERIAL_LIT"; + public static readonly Dictionary TagToRenderPipeline = new Dictionary() + { + { "UniversalPipeline",TemplateSRPType.Lightweight }, + { "LightweightPipeline",TemplateSRPType.Lightweight }, + { "HDRenderPipeline",TemplateSRPType.HD } + }; +#if UNITY_2018_3_OR_NEWER + public static string CoreColorLib = "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"; + public static string CoreCommonLib = "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"; +#else + public static string CoreCommonLib = "CoreRP/ShaderLibrary/Common.hlsl"; + public static string CoreColorLib = "CoreRP/ShaderLibrary/Color.hlsl"; +#endif + + public static string PragmaOnlyRendersPattern = @"#pragma\s+only_renderers\s+([\w .]*)"; + public static string PragmaExcludeRendersPattern = @"#pragma\s+exclude_renderers\s+([\w .]*)"; + public static string PragmaRendererElement = @"(\w+)"; + + public static string FetchSubShaderBody = @"(SubShader.*)\/\*ase_lod\*\/"; + public static string TemplateCustomUI = @"\/\*CustomNodeUI:(\w*)\*\/"; + public static string HidePassPattern = @"\/\*ase_hide_pass[:]*([a-zA-Z:]*)\*\/"; + public static string ASEPassPattern = @"\/\*ase_pass[:]*([a-zA-Z:]*)\*\/"; + public static string BlendWholeWordPattern = @"\bBlend\b"; + public static string BlendOpWholeWordPattern = @"\bBlendOp\b"; + public static string AlphaToMaskPattern = @"\bAlphaToMask\s+(\[*\w+\]*)"; + public static string CullWholeWordPattern = @"\bCull\b"; + public static string ColorMaskWholeWordPattern = @"\bColorMask\b"; + public static string StencilWholeWordPattern = @"\bStencil\b"; + public static string ZWriteWholeWordPattern = @"\bZWrite\b"; + public static string ZTestWholeWordPattern = @"\bZTest\b"; + public static string ZOffsetWholeWordPattern = @"\bOffset\b"; + public static string TagsWholeWordPattern = @"\bTags\b"; + + + public static string CustomInspectorPattern = "^\\s*CustomEditor\\s+\\\"([\\w\\.]*)\\\""; + public static string FallbackPattern = "^\\s*Fallback\\s+\\\"([\\w\\/\\\\]*)\\\""; + public static string DefinesPattern = @"^\s*#define\s+([\w .]*)"; + public static string PragmasPattern = @"^\s*#pragma\s+([\w .]*)"; + public static string IncludesPattern = "^\\s*#include\\s+\"([\\w.\\/]*)\""; + public static string GlobalDirectivesPattern = "[#]+(define|pragma|include)\\s+([\\w .\\/\\\"]*)"; + public static string BeforePragmaPattern = @"(?:CGPROGRAM|HLSLPROGRAM|GLSLPROGRAM).*?\n(\s*)(.)"; + public static string GlobalTOPDirectivesPattern = @"(CGPROGRAM|CGINCLUDE|HLSLPROGRAM|HLSLINCLUDE).*?\n\s*(.)"; + + public static string VertexPragmaPattern = @"#pragma vertex\s+(\w+)"; + public static string FragmentPragmaPattern = @"#pragma fragment\s+(\w+)"; + public static string FunctionBodyStartPattern = @"\s+{0}\s*\("; + + public static string ShaderModelPattern = @"#pragma\s+target\s+([0-9]*[.]*[0-9]*)"; + + public static readonly string LocalVarPattern = @"\/\*ase_local_var[:]*(\w*)\*\/\s*(\w*)\s+(\w*)"; + + public static readonly string InlinePattern = @"\/\*ase_inline_begin\*\/(.*?)\/\*ase_inline_end\*\/"; + + public static readonly string SubShaderLODPattern = @"\sLOD\s+(\d+)"; + + public static readonly string PassNamePattern = "Name\\s+\\\"([\\w\\+\\-\\*\\/\\(\\) ]*)\\\""; + + public static readonly string TagsPattern = "\"(\\w+)\"\\s*=\\s*\"(\\w+\\+*\\w*)\""; + public static readonly string ZTestPattern = @"^\s*ZTest\s+(\[*\w+\]*)"; + public static readonly string ZWritePattern = @"^\s*ZWrite\s+(\[*\w+\]*)"; + //public static readonly string ZOffsetPattern = @"\s*Offset\s+([-+]?[0-9]*\.?[0-9]+)\s*,\s*([-+]?[0-9]*\.?[0-9]+)"; + public static readonly string ZOffsetPattern = @"^\s*Offset\s+([-+]?[0-9]*\.?[0-9]+|\[*\w+\]*)\s*,\s*([-+]?[0-9]*\.?[0-9]+|\[*\w+\]*)\s*"; + public static readonly string VertexDataPattern = @"([a-z0-9D_]+|samplerCUBE|sampler2DArray)\s+(\w+)\s*:\s*([A-Z0-9_]+);"; + public static readonly string InterpRangePattern = @"ase_interp\((\d\.{0,1}\w{0,4}),(\d*)\)"; + //public static readonly string PropertiesPatternB = "(\\w*)\\s*\\(\\s*\"([\\w ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)"; + //public static readonly string PropertiesPatternC = "^\\s*(\\w*)\\s*\\(\\s*\"([\\w\\(\\)\\+\\-\\\\* ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)"; + //public static readonly string PropertiesPatternD = "(\\/\\/\\s*)*(\\w*)\\s*\\(\\s*\"([\\w\\(\\)\\+\\-\\\\* ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)"; + //public static readonly string PropertiesPatternE = "(\\/\\/\\s*)*(\\w*)\\s*\\(\\s*\"([\\w\\(\\)\\+\\-\\\\* ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)\\s*=\\s*[\\w,()\" {}]*"; + //public static readonly string PropertiesPatternF = "^(\\/\\/)*\\s*(\\[[\\[\\]\\w\\s\\(\\)\\_\\,]*\\])*\\s*(\\w*)\\s*\\(\\s*\"([\\w\\(\\)\\+\\-\\\\* ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)\\s*=\\s*[\\w,()\" {}]*"; + //public static readonly string PropertiesPatternG = "^(\\s*)(\\[[\\[\\]\\w\\s\\(\\)\\_\\,]*\\])*\\s*(\\w*)\\s*\\(\\s*\"([\\w\\(\\)\\+\\-\\\\* ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)\\s*=\\s*[\\w,()\" {}]*"; + public static readonly string PropertiesPatternG = "^(\\s*)(\\[[\\[\\]\\w\\s\\(\\)_,\\.]*\\])*[\\s\\/]*(\\w*)\\s*\\(\\s*\"([\\w\\(\\)\\+\\-\\\\* ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)\\s*=\\s*[\\w,()\" {}\\.]*"; + public static readonly string CullModePattern = @"^\s*Cull\s+(\[*\w+\]*)"; + + public static readonly string ColorMaskPatternFirst = @"\bColorMask\s+([\d\w\[\]]+)(\s+0)*"; + + public static readonly string ColorMaskPattern = @"\bColorMask\s+([\d\w\[\]]+)(\s+0)"; + public static readonly string ColorMask1Pattern = @"\bColorMask\s+([\d\w\[\]]+)(\s+1)"; + public static readonly string ColorMask2Pattern = @"\bColorMask\s+([\d\w\[\]]+)(\s+2)"; + public static readonly string ColorMask3Pattern = @"\bColorMask\s+([\d\w\[\]]+)(\s+3)"; + //public static readonly string BlendModePattern = @"\s*Blend\s+(\w+)\s+(\w+)(?:[\s,]+(\w+)\s+(\w+)|)"; + //public static readonly string BlendModePattern = @"\s*Blend\s+(\[*\w+\]*)\s+(\[*\w+\]*)(?:[\s,]+(\[*\w+\]*)\s+(\[*\w+\]*)|)"; + //public static readonly string BlendModePattern = @"^\s*Blend\s+(?:(?=\d)|(\[*\w+\]*)\s+(\[*\w+\]*)(?:[\s,]+(\[*\w+\]*)\s+(\[*\w+\]*)|))"; + public static readonly string BlendModePatternFirst = @"\bBlend([ \t]+0)*[ \t]+(?:Off|(\[*\w+\]*)[ \t]+(\[*\w+\]*)(?:(?=[ \t]+Blend)|(?:[ \t,]+(\[*\w+\]*)[ \t]+(\[*\w+\]*)|)))"; + public static readonly string BlendModePattern = @"\bBlend([ \t]+0)[ \t]+(?:Off|(\[*\w+\]*)[ \t]+(\[*\w+\]*)(?:(?=[ \t]+Blend)|(?:[ \t,]+(\[*\w+\]*)[ \t]+(\[*\w+\]*)|)))"; + public static readonly string BlendModePattern1 = @"\bBlend([ \t]+1)[ \t]+(?:Off|(\[*\w+\]*)[ \t]+(\[*\w+\]*)(?:(?=[ \t]+Blend)|(?:[ \t,]+(\[*\w+\]*)[ \t]+(\[*\w+\]*)|)))"; + public static readonly string BlendModePattern2 = @"\bBlend([ \t]+2)[ \t]+(?:Off|(\[*\w+\]*)[ \t]+(\[*\w+\]*)(?:(?=[ \t]+Blend)|(?:[ \t,]+(\[*\w+\]*)[ \t]+(\[*\w+\]*)|)))"; + public static readonly string BlendModePattern3 = @"\bBlend([ \t]+3)[ \t]+(?:Off|(\[*\w+\]*)[ \t]+(\[*\w+\]*)(?:(?=[ \t]+Blend)|(?:[ \t,]+(\[*\w+\]*)[ \t]+(\[*\w+\]*)|)))"; + //public static readonly string BlendOpPattern = @"\s*BlendOp\s+(\w+)[\s,]*(?:(\w+)|)"; + //public static readonly string BlendOpPattern = @"\s*BlendOp\s+(\[*\w+\]*)[\s,]*(?:(\[*\w+\]*)|)"; + //public static readonly string BlendOpPattern = @"^\s*BlendOp\s+(?:(?=\d)|(\[*\w+\]*)[\s,]*(?:(\[*\w+\]*)|))"; + public static readonly string BlendOpPatternFirst = @"\bBlendOp([ \t]+0)*[ \t]+(\[*\w+\]*)(?:(?=[ \t]+Blend)|[ \t,]*(?:(\[*\w+\]*)|))"; + public static readonly string BlendOpPattern = @"\bBlendOp([ \t]+0)[ \t]+(\[*\w+\]*)(?:(?=[ \t]+Blend)|[ \t,]*(?:(\[*\w+\]*)|))"; + public static readonly string BlendOpPattern1 = @"\bBlendOp([ \t]+1)[ \t]+(\[*\w+\]*)(?:(?=[ \t]+Blend)|[ \t,]*(?:(\[*\w+\]*)|))"; + public static readonly string BlendOpPattern2 = @"\bBlendOp([ \t]+2)[ \t]+(\[*\w+\]*)(?:(?=[ \t]+Blend)|[ \t,]*(?:(\[*\w+\]*)|))"; + public static readonly string BlendOpPattern3 = @"\bBlendOp([ \t]+3)[ \t]+(\[*\w+\]*)(?:(?=[ \t]+Blend)|[ \t,]*(?:(\[*\w+\]*)|))"; + public static readonly string StencilOpGlobalPattern = @"Stencil\s*{([\w\W\s]*)}"; + public static readonly string StencilOpLinePattern = @"(\w+)\s*(\[*\w+\]*)"; + + public static readonly string ShaderGlobalsOverallPattern = @"(?:\/\*ase_pragma\*\/|[\}\#])[\#\&\|\!\<\>\(\)\=\w\s\;\/\*\.\\""]*\/\*ase_globals\*\/"; + public static readonly string ShaderGlobalsMultilinePattern = @"^\s*(?:uniform\s*)*(\w*)\s*(\w*);$"; + + public static readonly string TexSemantic = "float4 {0} : TEXCOORD{1};"; + public static readonly string TexFullSemantic = "float4 {0} : {1};"; + public static readonly string InterpFullSemantic = "{0} {1} : {2};"; + public static readonly string BaseInterpolatorName = "ase_texcoord"; + public static readonly string TexUVFullSemantic = "float4 ase_texcoord{0} : TEXCOORD{0};"; + public static readonly string InterpMacro = "{0}({1})"; + + public static readonly string InterpolatorDecl = Constants.VertexShaderOutputStr + ".{0} = " + Constants.VertexShaderInputStr + ".{0};"; + public static readonly string TemplateVariableDecl = "{0} = {1};"; + public static readonly string TemplateVarFormat = "{0}.{1}"; + + //public static readonly string StructsRemoval = @"struct\s+\w+\s+{[\s\w;\/\*]+};"; + public static readonly string StructsRemoval = @"struct\s+\w+\s+{[\#\&\|\!\<\>\s\w\(\).;:=,\/\*]+};"; + + public static readonly string SRPBatcherFindTag = @"CBUFFER_START\s*\(\s*UnityPerMaterial\s*\)\s*\n(\s*)"; + + public static string ReplaceAt( this string body, string oldStr, string newStr, int startIndex ) + { + return body.Remove( startIndex, oldStr.Length ).Insert( startIndex, newStr ); + } + + public static bool GetPassUniqueId( TemplateTagData tagData, TemplatePropertyContainer propertyContainer, TemplateIdManager idManager, string uniquePrefix, int offsetIdx, string subBody, ref string passUniqueID ) + { + Match match = Regex.Match( subBody, ASEPassPattern ); + if( match.Success && match.Groups.Count > 1 && match.Groups[1].Length > 0 ) + { + passUniqueID = match.Groups[ 1 ].Value; + + tagData.StartIdx = offsetIdx + match.Index; + tagData.Id = match.Value; + + idManager.RegisterId( tagData.StartIdx, uniquePrefix + tagData.Id, tagData.Id ); + propertyContainer.AddId( subBody, tagData.Id, tagData.SearchIndentation ); + return true; + } + return false; + } + + public static CustomTemplatePropertyUIEnum FetchCustomUI( string data ) + { + Match match = Regex.Match( data, TemplateCustomUI ); + if( match.Success && CustomTemplatePropertyUI.ContainsKey( match.Groups[ 1 ].Value ) ) + { + return CustomTemplatePropertyUI[ match.Groups[ 1 ].Value ]; + } + return CustomTemplatePropertyUIEnum.None; + } + + public static bool FetchInvisibleInfo( string input, ref int optionsArr, ref string id, ref int idIndex ) + { + Match match = Regex.Match( input, HidePassPattern ); + if( match.Success ) + { + id = match.Value; + idIndex = match.Index; + if( match.Groups.Count > 1 ) + { + string[] properties = match.Groups[ 1 ].Value.Split( ':' ); + for( int i = 0; i < properties.Length; i++ ) + { + if( InvisibleOptions.ContainsKey( properties[ i ] ) ) + { + optionsArr |= (int)InvisibleOptions[ properties[ i ] ]; + } + } + } + } + return match.Success; + } + + static public string GenerateTextureSemantic( ref MasterNodeDataCollector dataCollector, int uv ) + { + string texCoordName = BaseInterpolatorName; + if( uv > 0 ) + { + texCoordName += uv.ToString(); + } + + string texCoordData = string.Format( TexSemantic, texCoordName, uv ); + dataCollector.AddToVertexInput( texCoordData ); + dataCollector.AddToInterpolators( texCoordData ); + dataCollector.AddToVertexInterpolatorsDecl( string.Format( InterpolatorDecl, texCoordName ) ); + return texCoordName; + } + + public static void CreatePragmaIncludeList( string data, TemplateIncludePragmaContainter includePragmaContainer ) + { + // this finds the topmost position for including directives + int topIndex = -1; + foreach( Match match in Regex.Matches( data, GlobalTOPDirectivesPattern, RegexOptions.Singleline ) ) + { + if( match.Groups.Count == 3 ) + { + topIndex = match.Groups[ 2 ].Index; + } + } + + foreach( Match match in Regex.Matches( data, GlobalDirectivesPattern, RegexOptions.Multiline ) ) + { + if( match.Success ) + { + includePragmaContainer.AddNativeDirective( match.Groups[ 0 ].Value, topIndex ); + } + } + + foreach( Match match in Regex.Matches( data, PragmasPattern, RegexOptions.Multiline ) ) + { + if( match.Groups.Count == 2 ) + { + includePragmaContainer.AddPragma( match.Groups[ 1 ].Value ); + } + } + + foreach( Match match in Regex.Matches( data, DefinesPattern, RegexOptions.Multiline ) ) + { + if( match.Groups.Count == 2 ) + { + includePragmaContainer.AddDefine( match.Groups[ 1 ].Value ); + } + } + + foreach( Match match in Regex.Matches( data, IncludesPattern, RegexOptions.Multiline ) ) + { + if( match.Groups.Count == 2 ) + { + includePragmaContainer.AddInclude( match.Groups[ 1 ].Value ); + } + } + } + + public static void CreateShaderPropertiesList( string propertyData, ref List propertiesList, ref Dictionary duplicatesHelper, int subShaderId, int passId) + { + int identationIdx = (int)TemplateShaderPropertiesIdx.Identation; + int nameIdx = (int)TemplateShaderPropertiesIdx.Name; + int typeIdx = (int)TemplateShaderPropertiesIdx.Type; + int inspectorNameIdx = (int)TemplateShaderPropertiesIdx.InspectorName; + + foreach( Match match in Regex.Matches( propertyData, PropertiesPatternG,RegexOptions.Multiline ) ) + { + if( match.Groups.Count > 1 ) + { + if( !duplicatesHelper.ContainsKey( match.Groups[ nameIdx ].Value ) && PropertyToWireType.ContainsKey( match.Groups[ typeIdx ].Value ) ) + { + TemplateShaderPropertyData newData = new TemplateShaderPropertyData( match.Index, + match.Value, + match.Groups[ identationIdx ].Value, + match.Groups[ inspectorNameIdx ].Value, + match.Groups[ nameIdx ].Value, + PropertyToWireType[ match.Groups[ typeIdx ].Value ], + PropertyType.Property, + subShaderId, + passId); + propertiesList.Add( newData ); + duplicatesHelper.Add( newData.PropertyName, newData ); + } + } + } + } + public const string DepthMacroDeclRegex = @"UNITY_DECLARE_DEPTH_TEXTURE\(\s*_CameraDepthTexture"; + public static void CheckUnityBuiltinGlobalMacros( string propertyData, ref List propertiesList, ref Dictionary duplicatesHelper, int subShaderId, int passId ) + { + Match match = Regex.Match( propertyData, DepthMacroDeclRegex ); + if( match.Success ) + { + TemplateShaderPropertyData newData = new TemplateShaderPropertyData( -1, + string.Empty, + string.Empty, + string.Empty, + Constants.CameraDepthTextureValue, + WirePortDataType.SAMPLER2D, + PropertyType.Global, + subShaderId, + passId, + true ); + duplicatesHelper.Add( newData.PropertyName, newData ); + propertiesList.Add( newData ); + } + } + + public static void CreateShaderGlobalsList( string propertyData, ref List propertiesList, ref Dictionary duplicatesHelper,int subShaderId, int passId ) + { + int typeIdx = (int)TemplateShaderGlobalsIdx.Type; + int nameIdx = (int)TemplateShaderGlobalsIdx.Name; + + // removes structs + propertyData = Regex.Replace( propertyData, StructsRemoval, "" ); + MatchCollection matchCollection = Regex.Matches( propertyData, ShaderGlobalsOverallPattern ); + string value = ( matchCollection.Count > 0 ) ? matchCollection[ 0 ].Groups[ 0 ].Value : propertyData; + foreach( Match lineMatch in Regex.Matches( value, ShaderGlobalsMultilinePattern, RegexOptions.Multiline ) ) + { + if( lineMatch.Groups.Count > 1 ) + { + if( !duplicatesHelper.ContainsKey( lineMatch.Groups[ nameIdx ].Value ) && CgToWirePortType.ContainsKey( lineMatch.Groups[ typeIdx ].Value ) ) + { + TemplateShaderPropertyData newData = new TemplateShaderPropertyData( -1, + string.Empty, + string.Empty, + string.Empty, + lineMatch.Groups[ nameIdx ].Value, + CgToWirePortType[ lineMatch.Groups[ typeIdx ].Value ], + PropertyType.Global, + subShaderId, + passId); + duplicatesHelper.Add( newData.PropertyName, newData ); + propertiesList.Add( newData ); + } + } + } + } + + public static void CreateStencilOps( string stencilData, ref TemplateStencilData stencilDataObj ) + { + stencilDataObj.DataCheck = TemplateDataCheck.Invalid; + MatchCollection overallGlobalMatch = Regex.Matches( stencilData, StencilOpGlobalPattern ); + if( overallGlobalMatch.Count == 1 && overallGlobalMatch[ 0 ].Groups.Count == 2 ) + { + string property = string.Empty; + string value = overallGlobalMatch[ 0 ].Groups[ 1 ].Value; + foreach( Match match in Regex.Matches( value, StencilOpLinePattern ) ) + { + stencilDataObj.DataCheck = TemplateDataCheck.Valid; + if( match.Groups.Count == 3 ) + { + switch( match.Groups[ 1 ].Value ) + { + default: + { + stencilDataObj.DataCheck = TemplateDataCheck.Invalid; + return; + } + case "Ref": + { + if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + stencilDataObj.ReferenceInline = property; + } + else + { + try + { + stencilDataObj.Reference = Convert.ToInt32( match.Groups[ 2 ].Value ); + } + catch( Exception e ) + { + Debug.LogException( e ); + stencilDataObj.DataCheck = TemplateDataCheck.Invalid; + return; + } + } + } + break; + case "ReadMask": + { + if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + stencilDataObj.ReadMaskInline = property; + } + else + { + try + { + stencilDataObj.ReadMask = Convert.ToInt32( match.Groups[ 2 ].Value ); + } + catch( Exception e ) + { + Debug.LogException( e ); + stencilDataObj.DataCheck = TemplateDataCheck.Invalid; + return; + } + } + } + break; + case "WriteMask": + { + if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + stencilDataObj.WriteMaskInline = property; + } + else + { + try + { + stencilDataObj.WriteMask = Convert.ToInt32( match.Groups[ 2 ].Value ); + } + catch( Exception e ) + { + Debug.LogException( e ); + stencilDataObj.DataCheck = TemplateDataCheck.Invalid; + return; + } + } + } + break; + case "CompFront": + case "Comp": + { + if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + stencilDataObj.ComparisonFrontInline = property; + } + else + { + stencilDataObj.ComparisonFront = match.Groups[ 2 ].Value; + } + } + break; + case "PassFront": + case "Pass": + { + if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + stencilDataObj.PassFrontInline = property; + } + else + { + stencilDataObj.PassFront = match.Groups[ 2 ].Value; + } + } + break; + case "FailFront": + case "Fail": + { + if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + stencilDataObj.FailFrontInline = property; + } + else + { + stencilDataObj.FailFront = match.Groups[ 2 ].Value; + } + } + break; + case "ZFail": + case "ZFailFront": + { + if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + stencilDataObj.ZFailFrontInline = property; + } + else + { + stencilDataObj.ZFailFront = match.Groups[ 2 ].Value; + } + } + break; + case "CompBack": + { + if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + stencilDataObj.ComparisonBackInline = property; + } + else + { + stencilDataObj.ComparisonBack = match.Groups[ 2 ].Value; + } + } + break; + case "PassBack": + { + if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + stencilDataObj.PassBackInline = property; + } + else + { + stencilDataObj.PassBack = match.Groups[ 2 ].Value; + } + } + break; + case "FailBack": + { + if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + stencilDataObj.FailBackInline = property; + } + else + { + stencilDataObj.FailBack = match.Groups[ 2 ].Value; + } + } + break; + case "ZFailBack": + { + if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + stencilDataObj.ZFailBackInline = property; + } + else + { + stencilDataObj.ZFailBack = match.Groups[ 2 ].Value; + } + } + break; + } + } + } + } + } + + public static void CreateColorMask( string colorMaskData, ref TemplateColorMaskData colorMaskObj, string pattern ) + { + colorMaskObj.DataCheck = TemplateDataCheck.Invalid; + Match match = Regex.Match( colorMaskData, pattern ); + //if( match.Groups.Count == 3 /*&& !match.Groups[ 2 ].Success*/ ) // second group is the colormask MRT which isn't implemented yet + { + string property = string.Empty; + if( match.Groups[ 1 ].Success && IsInlineProperty( match.Groups[ 1 ].Value, ref property ) ) + { + colorMaskObj.InlineData = property; + colorMaskObj.DataCheck = TemplateDataCheck.Valid; + colorMaskObj.Target = match.Groups[ 2 ].Value; + } + else + { + for( int i = 0; i < 4; i++ ) + { + colorMaskObj.ColorMaskData[ i ] = false; + } + + colorMaskObj.Target = match.Groups[ 2 ].Value; + colorMaskObj.DataCheck = TemplateDataCheck.Valid; + try + { + for( int i = 0; i < match.Groups[ 1 ].Value.Length; i++ ) + { + switch( Char.ToLower( match.Groups[ 1 ].Value[ i ] ) ) + { + case 'r': colorMaskObj.ColorMaskData[ 0 ] = true; break; + case 'g': colorMaskObj.ColorMaskData[ 1 ] = true; break; + case 'b': colorMaskObj.ColorMaskData[ 2 ] = true; break; + case 'a': colorMaskObj.ColorMaskData[ 3 ] = true; break; + case '0': + { + for( int j = 0; j < 4; j++ ) + { + colorMaskObj.ColorMaskData[ j ] = false; + } + return; + } + default: + { + colorMaskObj.DataCheck = TemplateDataCheck.Invalid; + return; + } + } + } + } + catch( Exception e ) + { + Debug.LogException( e ); + colorMaskObj.DataCheck = TemplateDataCheck.Invalid; + return; + } + } + } + } + + public static void CreateAlphaToMask( string alphaToMaskData, ref TemplateAlphaToMaskData alphaToMaskObj ) + { + alphaToMaskObj.DataCheck = TemplateDataCheck.Invalid; + Match match = Regex.Match( alphaToMaskData, AlphaToMaskPattern ); + if( match.Groups.Count == 2 ) + { + string property = string.Empty; + if( match.Groups[ 1 ].Success && IsInlineProperty( match.Groups[ 1 ].Value, ref property ) ) + { + alphaToMaskObj.InlineData = property; + alphaToMaskObj.DataCheck = TemplateDataCheck.Valid; + } + else + { + try + { + alphaToMaskObj.AlphaToMaskData = match.Groups[ 1 ].Value == "On" ? true : false; + alphaToMaskObj.DataCheck = TemplateDataCheck.Valid; + } + catch( Exception e ) + { + alphaToMaskObj.DataCheck = TemplateDataCheck.Invalid; + Debug.LogException( e ); + return; + } + } + } + } + + public static void CreateCullMode( string cullModeData, ref TemplateCullModeData cullDataObj ) + { + cullDataObj.DataCheck = TemplateDataCheck.Invalid; + Match match = Regex.Match( cullModeData, CullModePattern ); + if( match.Groups.Count == 2 ) + { + string property = string.Empty; + if( match.Groups[ 1 ].Success && IsInlineProperty( match.Groups[ 1 ].Value, ref property ) ) + { + cullDataObj.InlineData = property; + cullDataObj.DataCheck = TemplateDataCheck.Valid; + } + else + { + try + { + cullDataObj.CullModeData = (CullMode)Enum.Parse( typeof( CullMode ), match.Groups[ 1 ].Value ); + cullDataObj.DataCheck = TemplateDataCheck.Valid; + } + catch( Exception e ) + { + cullDataObj.DataCheck = TemplateDataCheck.Invalid; + Debug.LogException( e ); + return; + } + } + } + } + + public static void CreateBlendMode( string blendModeData, ref TemplateBlendData blendDataObj, string pattern ) + { + blendDataObj.ValidBlendMode = true; + string property = string.Empty; + bool noMatches = true; + // TODO: OPTIMIZE REGEX EXPRESSIONS TO NOT CATCH EMPTY GROUPS + Match match = Regex.Match( blendModeData, pattern ); + //Debug.Log( blendModeData + " | " + match.Groups.Count + "|" + match.Groups[ 0 ].Value + " " + match.Groups[ 0 ].Success + " " + match.Groups[ 1 ].Success + " " + match.Groups[ 2 ].Success + " " + match.Groups[ 3 ].Success + " " + match.Groups[ 4 ].Success + " " + match.Groups[ 5 ].Success ); + { + if( match.Groups.Count <= 4 && match.Groups.Count >= 3 ) + { + if( match.Groups[ 0 ].Success && match.Groups[ 2 ].Success ) + { + try + { + if( IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + blendDataObj.SourceFactorRGBInline = property; + } + else + { + AvailableBlendFactor sourceAll = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), match.Groups[ 2 ].Value ); + blendDataObj.SourceFactorRGB = sourceAll; + } + if( match.Groups[ 3 ].Success && IsInlineProperty( match.Groups[ 3 ].Value, ref property ) ) + { + blendDataObj.DestFactorRGBInline = property; + } + else + { + AvailableBlendFactor destAll = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), match.Groups[ 3 ].Value ); + blendDataObj.DestFactorRGB = destAll; + } + blendDataObj.Target = match.Groups[ 1 ].Value; + blendDataObj.SeparateBlendFactors = false; + blendDataObj.BlendModeOff = false; + noMatches = false; + } + catch( Exception e ) + { + Debug.LogException( e ); + blendDataObj.DataCheck = TemplateDataCheck.Invalid; + blendDataObj.ValidBlendMode = false; + return; + } + } + } + else if( match.Groups.Count >= 5 ) + { + if( match.Groups[ 1 ].Success ) + blendDataObj.Target = match.Groups[ 1 ].Value; + + if( !match.Groups[ 2 ].Success && !match.Groups[ 3 ].Success ) + { + if( match.Groups[ 0 ].Value.IndexOf("Off") > -1 ) + { + blendDataObj.BlendModeOff = true; + noMatches = false; + } + } + + if( match.Groups[ 0 ].Success && match.Groups[ 2 ].Success ) + { + try + { + if( IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + blendDataObj.SourceFactorRGBInline = property; + } + else + { + AvailableBlendFactor sourceRGB = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), match.Groups[ 2 ].Value ); + blendDataObj.SourceFactorRGB = sourceRGB; + } + + if( match.Groups[ 3 ].Success && IsInlineProperty( match.Groups[ 3 ].Value, ref property ) ) + { + blendDataObj.DestFactorRGBInline = property; + } + else + { + AvailableBlendFactor destRGB = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), match.Groups[ 3 ].Value ); + blendDataObj.DestFactorRGB = destRGB; + } + + if( match.Groups[ 4 ].Success && match.Groups[ 5 ].Success ) + { + if( IsInlineProperty( match.Groups[ 4 ].Value, ref property ) ) + { + blendDataObj.SourceFactorAlphaInline = property; + } + else + { + AvailableBlendFactor sourceA = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), match.Groups[ 4 ].Value ); + blendDataObj.SourceFactorAlpha = sourceA; + } + + if( IsInlineProperty( match.Groups[ 5 ].Value, ref property ) ) + { + blendDataObj.DestFactorAlphaInline = property; + } + else + { + AvailableBlendFactor destA = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), match.Groups[ 5 ].Value ); + blendDataObj.DestFactorAlpha = destA; + } + + blendDataObj.SeparateBlendFactors = true; + } + else + { + blendDataObj.SeparateBlendFactors = false; + } + blendDataObj.Target = match.Groups[ 1 ].Value; + blendDataObj.BlendModeOff = false; + noMatches = false; + } + catch( Exception e ) + { + Debug.LogException( e ); + blendDataObj.DataCheck = TemplateDataCheck.Invalid; + blendDataObj.ValidBlendMode = false; + return; + } + } + } + } + + if( noMatches ) + blendDataObj.ValidBlendMode = false; + } + + public static void CreateBlendOp( string blendOpData, ref TemplateBlendData blendDataObj, string pattern ) + { + bool noMatches = true; + blendDataObj.ValidBlendOp = true; + string property = string.Empty; + // TODO: OPTIMIZE REGEX EXPRESSIONS TO NOT CATCH EMPTY GROUPS + Match match = Regex.Match( blendOpData, pattern ); + { + if( match.Groups.Count == 3 ) + { + if( match.Groups[ 0 ].Success && match.Groups[ 2 ].Success ) + { + + try + { + if( IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + blendDataObj.BlendOpRGBInline = property; + } + else + { + AvailableBlendOps blendOpsAll = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), match.Groups[ 2 ].Value ); + blendDataObj.BlendOpRGB = blendOpsAll; + } + blendDataObj.SeparateBlendOps = false; + blendDataObj.Target = match.Groups[ 1 ].Value; + noMatches = false; + } + catch( Exception e ) + { + Debug.LogException( e ); + blendDataObj.DataCheck = TemplateDataCheck.Invalid; + blendDataObj.ValidBlendOp = false; + return; + } + } + } + else if( match.Groups.Count == 4 ) + { + if( match.Groups[ 0 ].Success && match.Groups[ 2 ].Success ) + { + try + { + if( IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + blendDataObj.BlendOpRGBInline = property; + } + else + { + AvailableBlendOps blendOpsRGB = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), match.Groups[ 2 ].Value ); + blendDataObj.BlendOpRGB = blendOpsRGB; + } + + if( match.Groups[ 3 ].Success ) + { + if( IsInlineProperty( match.Groups[ 3 ].Value, ref property ) ) + { + blendDataObj.BlendOpAlphaInline = property; + } + else + { + AvailableBlendOps blendOpsA = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), match.Groups[ 3 ].Value ); + blendDataObj.BlendOpAlpha = blendOpsA; + } + blendDataObj.SeparateBlendOps = true; + } + else + { + blendDataObj.SeparateBlendOps = false; + } + blendDataObj.Target = match.Groups[ 1 ].Value; + noMatches = false; + } + catch( Exception e ) + { + Debug.LogException( e ); + blendDataObj.DataCheck = TemplateDataCheck.Invalid; + blendDataObj.ValidBlendOp = false; + return; + } + } + } + } + + if( noMatches ) + blendDataObj.ValidBlendOp = false; + } + + public static void FetchLocalVars( string body, ref List localVarList, TemplateFunctionData vertexFunction, TemplateFunctionData fragFunction ) + { + foreach( Match match in Regex.Matches( body, LocalVarPattern ) ) + { + if( match.Groups.Count == 4 ) + { + if( CgToWirePortType.ContainsKey( match.Groups[ 2 ].Value ) ) + { + MasterNodePortCategory category; + if( fragFunction.MainBodyLocalIdx > vertexFunction.MainBodyLocalIdx ) + { + if( match.Index < fragFunction.MainBodyLocalIdx ) + { + category = MasterNodePortCategory.Vertex; + } + else + { + category = MasterNodePortCategory.Fragment; + } + } + else + { + if( match.Index < vertexFunction.MainBodyLocalIdx ) + { + category = MasterNodePortCategory.Fragment; + } + else + { + category = MasterNodePortCategory.Vertex; + } + } + + if( !string.IsNullOrEmpty( match.Groups[ 1 ].Value ) && ShortcutToInfo.ContainsKey( match.Groups[ 1 ].Value ) ) + { + string id = match.Groups[ 0 ].Value.Substring( 0, match.Groups[ 0 ].Value.IndexOf( "*/" ) + 2 ); + TemplateLocalVarData data = new TemplateLocalVarData( ShortcutToInfo[ match.Groups[ 1 ].Value ], id, CgToWirePortType[ match.Groups[ 2 ].Value ], category, match.Groups[ 3 ].Value, match.Index ); + localVarList.Add( data ); + } + else + { + TemplateLocalVarData data = new TemplateLocalVarData( CgToWirePortType[ match.Groups[ 2 ].Value ], category, match.Groups[ 3 ].Value, match.Index ); + localVarList.Add( data ); + } + + } + } + } + } + + public static void FetchInlineVars( string body, ref TemplateIdManager idManager ) + { + foreach( Match match in Regex.Matches( body, InlinePattern ) ) + { + if( match.Success && match.Groups.Count == 2 ) + { + string id = match.Groups[ 0 ].Value; + string prop = match.Groups[ 1 ].Value; + idManager.RegisterTag( id, prop ); + } + } + } + + public static TemplateSRPType CreateTags( ref TemplateTagsModuleData tagsObj, bool isSubShader ) + { + TemplateSRPType srpType = TemplateSRPType.BuiltIn; + MatchCollection matchColl = Regex.Matches( tagsObj.TagsId, TagsPattern, RegexOptions.IgnorePatternWhitespace ); + int count = matchColl.Count; + if( count > 0 ) + { + for( int i = 0; i < count; i++ ) + { + if( matchColl[ i ].Groups.Count == 3 ) + { + if( isSubShader && matchColl[ i ].Groups[ 1 ].Value.Equals( "RenderPipeline" ) ) + { + if( TagToRenderPipeline.ContainsKey( matchColl[ i ].Groups[ 2 ].Value ) ) + srpType = TagToRenderPipeline[ matchColl[ i ].Groups[ 2 ].Value ]; + } + tagsObj.Tags.Add( new TemplatesTagData( matchColl[ i ].Groups[ 1 ].Value, matchColl[ i ].Groups[ 2 ].Value ) ); + } + } + } + return srpType; + } + + public static void CreateZWriteMode( string zWriteData, ref TemplateDepthData depthDataObj ) + { + depthDataObj.DataCheck = TemplateDataCheck.Invalid; + Match match = Regex.Match( zWriteData, ZWritePattern ); + if( match.Groups.Count == 2 ) + { + string property = string.Empty; + if( match.Groups[ 1 ].Success && IsInlineProperty( match.Groups[ 1 ].Value, ref property ) ) + { + depthDataObj.ZWriteInlineValue = property; + depthDataObj.DataCheck = TemplateDataCheck.Valid; + depthDataObj.ValidZWrite = true; + } + else + { + try + { + depthDataObj.ZWriteModeValue = (ZWriteMode)Enum.Parse( typeof( ZWriteMode ), match.Groups[ 1 ].Value ); + depthDataObj.DataCheck = TemplateDataCheck.Valid; + depthDataObj.ValidZWrite = true; + } + catch + { + depthDataObj.DataCheck = TemplateDataCheck.Invalid; + } + } + } + } + + public static void CreateZTestMode( string zTestData, ref TemplateDepthData depthDataObj ) + { + depthDataObj.DataCheck = TemplateDataCheck.Invalid; + Match match = Regex.Match( zTestData, ZTestPattern ); + if( match.Groups.Count == 2 ) + { + string property = string.Empty; + if( match.Groups[ 1 ].Success && IsInlineProperty( match.Groups[ 1 ].Value, ref property ) ) + { + depthDataObj.ZTestInlineValue = property; + depthDataObj.DataCheck = TemplateDataCheck.Valid; + depthDataObj.ValidZTest = true; + } + else + { + try + { + depthDataObj.ZTestModeValue = (ZTestMode)Enum.Parse( typeof( ZTestMode ), match.Groups[ 1 ].Value ); + depthDataObj.DataCheck = TemplateDataCheck.Valid; + depthDataObj.ValidZTest = true; + } + catch + { + depthDataObj.DataCheck = TemplateDataCheck.Invalid; + } + } + } + } + + public static void CreateZOffsetMode( string zOffsetData, ref TemplateDepthData depthDataObj ) + { + depthDataObj.DataCheck = TemplateDataCheck.Invalid; + Match match = Regex.Match( zOffsetData, ZOffsetPattern ); + if( match.Groups.Count == 3 ) + { + try + { + string property = string.Empty; + + if( match.Groups[ 1 ].Success && IsInlineProperty( match.Groups[ 1 ].Value, ref property ) ) + { + depthDataObj.OffsetFactorInlineValue = property; + } + else + { + depthDataObj.OffsetFactor = Convert.ToSingle( match.Groups[ 1 ].Value ); + } + + if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) ) + { + depthDataObj.OffsetUnitsInlineValue = property; + } + else + { + depthDataObj.OffsetUnits = Convert.ToSingle( match.Groups[ 2 ].Value ); + } + + depthDataObj.ValidOffset = true; + depthDataObj.DataCheck = TemplateDataCheck.Valid; + } + catch + { + depthDataObj.DataCheck = TemplateDataCheck.Invalid; + } + } + } + + public static List CreateVertexDataList( string vertexData, string parametersBody ) + { + List vertexDataList = null; + Dictionary vertexDataDict = null; + + foreach( Match match in Regex.Matches( vertexData, VertexDataPattern ) ) + { + if( match.Groups.Count > 1 ) + { + if( vertexDataList == null ) + { + vertexDataList = new List(); + vertexDataDict = new Dictionary(); + } + + WirePortDataType dataType = CgToWirePortType[ match.Groups[ 1 ].Value ]; + string varName = match.Groups[ 2 ].Value; + TemplateSemantics semantics = TemplateSemantics.NONE; + try + { + semantics = (TemplateSemantics)Enum.Parse( typeof( TemplateSemantics ), match.Groups[ 3 ].Value ); + } + catch(Exception e) + { + Debug.LogException( e ); + } + TemplateVertexData templateVertexData = new TemplateVertexData( semantics, dataType, varName ); + vertexDataList.Add( templateVertexData ); + vertexDataDict.Add( semantics, templateVertexData ); + } + } + + if( vertexData.Contains( Constants.InstanceIdMacro ) ) + { + TemplateVertexData templateVertexData = new TemplateVertexData( TemplateSemantics.SV_InstanceID, WirePortDataType.UINT, Constants.InstanceIdVariable ); + templateVertexData.DataInfo = TemplateInfoOnSematics.INSTANCE_ID; + templateVertexData.Available = true; + templateVertexData.ExcludeStructPrefix = true; + + vertexDataList.Add( templateVertexData ); + vertexDataDict.Add( TemplateSemantics.SV_InstanceID, templateVertexData ); + } + + if( !string.IsNullOrEmpty( parametersBody ) ) + { + string[] paramsArray = parametersBody.Split( IOUtils.FIELD_SEPARATOR ); + if( paramsArray.Length > 0 ) + { + for( int i = 0; i < paramsArray.Length; i++ ) + { + string[] paramDataArr = paramsArray[ i ].Split( IOUtils.VALUE_SEPARATOR ); + if( paramDataArr.Length == 2 ) + { + string[] swizzleInfoArr = paramDataArr[ 1 ].Split( IOUtils.FLOAT_SEPARATOR ); + TemplateSemantics semantic = ShortcutToSemantic[ swizzleInfoArr[ 0 ] ]; + if( vertexDataDict.ContainsKey( semantic ) ) + { + TemplateVertexData templateVertexData = vertexDataDict[ semantic ]; + if( templateVertexData != null ) + { + if( swizzleInfoArr.Length > 1 ) + { + templateVertexData.DataSwizzle = "." + swizzleInfoArr[ 1 ]; + } + templateVertexData.DataInfo = ShortcutToInfo[ paramDataArr[ 0 ] ]; + templateVertexData.Available = true; + } + } + } + } + } + } + + if( vertexDataDict != null ) + { + vertexDataDict.Clear(); + vertexDataDict = null; + } + + return vertexDataList; + } + + public static TemplateInterpData CreateInterpDataList( string interpData, string fullLine, int maxInterpolators ) + { + TemplateInterpData interpDataObj = null; + List interpDataList = null; + Dictionary interpDataDict = null; + Match rangeMatch = Regex.Match( fullLine, InterpRangePattern ); + if( rangeMatch.Groups.Count > 0 ) + { + interpDataObj = new TemplateInterpData(); + // Get range of available interpolators + int minVal = 0; + int maxVal = 0; + try + { + string[] minValArgs = rangeMatch.Groups[ 1 ].Value.Split( IOUtils.FLOAT_SEPARATOR ); + minVal = Convert.ToInt32( minValArgs[ 0 ] ); + if( string.IsNullOrEmpty( rangeMatch.Groups[ 2 ].Value ) ) + { + maxVal = maxInterpolators - 1; + interpDataObj.DynamicMax = true; + } + else + { + maxVal = Convert.ToInt32( rangeMatch.Groups[ 2 ].Value ); + } + if( minVal > maxVal ) + { + //int aux = minVal; + //minVal = maxVal; + //maxVal = aux; + maxVal = minVal; + } + + for( int i = minVal; i <= maxVal; i++ ) + { + interpDataObj.AvailableInterpolators.Add( new TemplateInterpElement( IntToSemantic[ i ] ) ); + } + if( minValArgs.Length > 1 ) + { + interpDataObj.AvailableInterpolators[ 0 ].SetAvailableChannelsFromString( minValArgs[ 1 ] ); + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + interpDataList = new List(); + interpDataDict = new Dictionary(); + + //Get Current interpolators + int parametersBeginIdx = fullLine.IndexOf( ":" ) + 1; + int parametersEnd = fullLine.IndexOf( TemplatesManager.TemplateEndOfLine ); + string parametersBody = fullLine.Substring( parametersBeginIdx, parametersEnd - parametersBeginIdx ); + + foreach( Match match in Regex.Matches( interpData, VertexDataPattern ) ) + { + if( match.Groups.Count > 1 ) + { + WirePortDataType dataType = CgToWirePortType[ match.Groups[ 1 ].Value ]; + string varName = match.Groups[ 2 ].Value; + TemplateSemantics semantics = TemplateSemantics.NONE; + try + { + semantics = (TemplateSemantics)Enum.Parse( typeof( TemplateSemantics ), match.Groups[ 3 ].Value ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + TemplateVertexData templateVertexData = new TemplateVertexData( semantics, dataType, varName ); + //interpDataList.Add( templateVertexData ); + interpDataDict.Add( semantics, templateVertexData ); + interpDataObj.RawInterpolators.Add( templateVertexData ); + //Check if they are also on the free channels list and update their names + interpDataObj.ReplaceNameOnInterpolator( semantics, varName ); + } + } + + if( interpData.Contains( Constants.InstanceIdMacro ) ) + { + TemplateVertexData templateInterpData = new TemplateVertexData( TemplateSemantics.SV_InstanceID, WirePortDataType.UINT, Constants.InstanceIdVariable ); + templateInterpData.DataInfo = TemplateInfoOnSematics.INSTANCE_ID; + templateInterpData.Available = true; + templateInterpData.ExcludeStructPrefix = true; + interpDataList.Add( templateInterpData ); + interpDataDict.Add( TemplateSemantics.SV_InstanceID, templateInterpData ); + } + + Dictionary auxDict = new Dictionary(); + // Get info for available interpolators + string[] paramsArray = parametersBody.Split( IOUtils.FIELD_SEPARATOR ); + if( paramsArray.Length > 0 ) + { + for( int i = 0; i < paramsArray.Length; i++ ) + { + string[] paramDataArr = paramsArray[ i ].Split( IOUtils.VALUE_SEPARATOR ); + if( paramDataArr.Length == 2 ) + { + string[] swizzleInfoArr = paramDataArr[ 1 ].Split( IOUtils.FLOAT_SEPARATOR ); + TemplateSemantics semantic = ShortcutToSemantic[ swizzleInfoArr[ 0 ] ]; + if( interpDataDict.ContainsKey( semantic ) ) + { + if( interpDataDict[ semantic ] != null ) + { + string[] multiComponent = paramDataArr[ 0 ].Split( IOUtils.FLOAT_SEPARATOR ); + + if( multiComponent.Length > 1 ) + { + TemplateVertexData templateInterpData = null; + if( auxDict.ContainsKey( multiComponent[ 0 ] ) ) + { + templateInterpData = auxDict[ multiComponent[ 0 ] ]; + } + else + { + templateInterpData = new TemplateVertexData( interpDataDict[ semantic ] ); + //if( swizzleInfoArr.Length > 1 ) + //{ + // templateInterpData.DataSwizzle = "." + swizzleInfoArr[ 1 ]; + //} + templateInterpData.DataInfo = ShortcutToInfo[ multiComponent[ 0 ] ]; + templateInterpData.Available = true; + interpDataList.Add( templateInterpData ); + auxDict.Add( multiComponent[ 0 ], templateInterpData ); + } + + if( swizzleInfoArr[ 1 ].Length == multiComponent[ 1 ].Length ) + { + for( int channelIdx = 0; channelIdx < swizzleInfoArr[ 1 ].Length; channelIdx++ ) + { + templateInterpData.RegisterComponent( multiComponent[ 1 ][ channelIdx ], interpDataDict[ semantic ].VarName + "." + swizzleInfoArr[ 1 ][ channelIdx ] ); + } + } + } + else + { + TemplateVertexData templateInterpData = new TemplateVertexData( interpDataDict[ semantic ] ); + if( swizzleInfoArr.Length > 1 ) + { + templateInterpData.DataSwizzle = "." + swizzleInfoArr[ 1 ]; + } + templateInterpData.DataInfo = ShortcutToInfo[ paramDataArr[ 0 ] ]; + templateInterpData.Available = true; + interpDataList.Add( templateInterpData ); + } + } + } + } + } + } + + /*TODO: + 1) Remove interpDataList.Add( templateVertexData ); from initial foreach + 2) When looping though each foreach array element, create a new TemplateVertexData + from the one containted on the interpDataDict and add it to interpDataList + */ + for( int i = 0; i < interpDataList.Count; i++ ) + { + interpDataList[ i ].BuildVar(); + } + + auxDict.Clear(); + auxDict = null; + + interpDataObj.Interpolators = interpDataList; + interpDataDict.Clear(); + interpDataDict = null; + } + return interpDataObj; + } + + public static void FetchDependencies( TemplateInfoContainer dependencies, ref string body ) + { + int index = body.IndexOf( TemplatesManager.TemplateDependenciesListTag ); + if( index > 0 ) + { + dependencies.Index = index; + dependencies.Id = TemplatesManager.TemplateDependenciesListTag; + dependencies.Data = TemplatesManager.TemplateDependenciesListTag; + } + else + { + int lastIndex = body.LastIndexOf( '}' ); + if( lastIndex > 0 ) + { + body = body.Insert( lastIndex, "\t" + TemplatesManager.TemplateDependenciesListTag + "\n" ); + FetchDependencies( dependencies, ref body ); + } + } + } + + public static void FetchCustomInspector( TemplateInfoContainer inspectorContainer, ref string body ) + { + Match match = Regex.Match( body, CustomInspectorPattern, RegexOptions.Multiline ); + if( match != null && match.Groups.Count > 1 ) + { + inspectorContainer.Index = match.Index; + inspectorContainer.Id = match.Groups[ 0 ].Value; + inspectorContainer.Data = match.Groups[ 1 ].Value; + +#if UNITY_2019_3_OR_NEWER + if( ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_6_9_1 ) + { + if( inspectorContainer.Data.Equals( "UnityEditor.Experimental.Rendering.HDPipeline.HDLitGUI" ) ) + inspectorContainer.Data = "UnityEditor.Rendering.HighDefinition.HDLitGUI"; + } +#endif + } + else + { + int index = body.LastIndexOf( '}' ); + if( index > 0 ) + { + body = body.Insert( index, string.Format( "\tCustomEditor \"{0}\"\n", Constants.DefaultCustomInspector ) ); + FetchCustomInspector( inspectorContainer, ref body ); + } + } + } + + public static void FetchFallback( TemplateInfoContainer fallbackContainer, ref string body ) + { + Match match = Regex.Match( body, FallbackPattern, RegexOptions.Multiline | RegexOptions.IgnoreCase ); + if( match != null && match.Groups.Count > 1 ) + { + fallbackContainer.Index = match.Index; + fallbackContainer.Id = match.Groups[ 0 ].Value; + fallbackContainer.Data = match.Groups[ 1 ].Value; + } + else + { + int index = body.LastIndexOf( '}' ); + if( index > 0 ) + { + body = body.Insert( index, "\tFallback \"\"\n" ); + FetchFallback( fallbackContainer, ref body ); + } + } + } + + public static string AutoSwizzleData( string dataVar, WirePortDataType from, WirePortDataType to, bool isPosition ) + { + switch( from ) + { + case WirePortDataType.COLOR: + case WirePortDataType.FLOAT4: + { + switch( to ) + { + case WirePortDataType.FLOAT3: dataVar += ".xyz"; break; + case WirePortDataType.FLOAT2: dataVar += ".xy"; break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: dataVar += ".x"; break; + } + } + break; + case WirePortDataType.FLOAT3: + { + switch( to ) + { + case WirePortDataType.FLOAT4: dataVar = string.Format( "float4({0},{1})", dataVar,(isPosition?1:0) ); break; + case WirePortDataType.FLOAT2: dataVar += ".xy"; break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: dataVar += ".x"; break; + } + } + break; + case WirePortDataType.FLOAT2: + { + switch( to ) + { + case WirePortDataType.FLOAT4: dataVar = string.Format( "float4({0},0,{1})", dataVar , (isPosition ? 1 : 0) ); break; + case WirePortDataType.FLOAT3: dataVar = string.Format( "float3({0},0)", dataVar ); break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: dataVar += ".x"; break; + } + } + break; + case WirePortDataType.FLOAT: + { + switch( to ) + { + case WirePortDataType.FLOAT4: dataVar = string.Format( "float4({0},0,0,{1})", dataVar, ( isPosition ? 1 : 0 ) ); break; + case WirePortDataType.FLOAT3: dataVar = string.Format( "float3({0},0,0)", dataVar ); break; + case WirePortDataType.FLOAT2: dataVar = string.Format( "float2({0},0)", dataVar ); break; + } + } + break; + } + return dataVar; + } + + public static bool CheckIfTemplate( string assetPath ) + { + if( assetPath.EndsWith( ".shader" ) ) + { + if( File.Exists( assetPath ) ) + { + string body = IOUtils.LoadTextFileFromDisk( assetPath ); + return ( body.IndexOf( TemplatesManager.TemplateShaderNameBeginTag ) > -1 ); + } + } + return false; + } + + public static bool CheckIfCompatibles( WirePortDataType first, WirePortDataType second ) + { + switch( first ) + { + case WirePortDataType.OBJECT: + return true; + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + case WirePortDataType.INT: + { + switch( second ) + { + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + case WirePortDataType.SAMPLERSTATE: + return false; + } + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + switch( second ) + { + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + case WirePortDataType.INT: + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + case WirePortDataType.SAMPLERSTATE: + return false; + } + } + break; + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + { + switch( second ) + { + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + case WirePortDataType.COLOR: + case WirePortDataType.INT: + case WirePortDataType.SAMPLERSTATE: + return false; + } + } + break; + case WirePortDataType.SAMPLERSTATE: + { + switch( second ) + { + default: + return false; + case WirePortDataType.SAMPLERSTATE: + case WirePortDataType.OBJECT: + break; + } + } + break; + } + return true; + } + // Lightweight <-> Default functions + public static string WorldSpaceViewDir( MasterNodeDataCollector dataCollector, string worldPosVec3, bool normalize ) + { + string value = string.Empty; + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + value = string.Format( "_WorldSpaceCameraPos.xyz - {0}", worldPosVec3 ); + } + else + { + value = string.Format( "UnityWorldSpaceViewDir( {0} )", worldPosVec3 ); + } + + if( normalize ) + { + value = SafeNormalize( dataCollector, value ); + } + + return value; + } + + public static string SafeNormalize( MasterNodeDataCollector dataCollector, string value ) + { + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + value = string.Format( "SafeNormalize( {0} )", value ); + } + else + { + dataCollector.AddToIncludes( -1, Constants.UnityBRDFLib ); + value = string.Format( "Unity_SafeNormalize( {0} )", value ); + } + return value; + } + + public static bool IsInlineProperty( string data, ref string property ) + { + if( data.Length > 0 && data[ 0 ] == '[' && data[ data.Length - 1 ] == ']' ) + { + property = data.Substring( 1, data.Length - 2 ); + return true; + } + return false; + } + + // public static readonly string FetchDefaultDepthFormat = "UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture,UNITY_PROJ_COORD( {0} )))"; + public static readonly string FetchDefaultDepthFormat = "SAMPLE_DEPTH_TEXTURE( _CameraDepthTexture, {0}.xy )"; + public static readonly string FetchDefaultDepthFormatVertex = "SAMPLE_DEPTH_TEXTURE_LOD( _CameraDepthTexture, float4( {0}.xy, 0, 0 ) )"; + + public static readonly string FetchLWDepthFormat = "SHADERGRAPH_SAMPLE_SCENE_DEPTH( {0}.xy )"; + public static readonly string FetchLWDepthFormatVertex = "SHADERGRAPH_SAMPLE_SCENE_DEPTH_LOD( {0}.xy )"; +#if UNITY_2018_3_OR_NEWER + public static readonly string FetchHDDepthFormat = "SampleCameraDepth( {0}.xy )"; +#else + public static readonly string FetchHDDepthFormat = "SAMPLE_TEXTURE2D( _CameraDepthTexture, s_point_clamp_sampler, {0}.xy ).r"; +#endif + public static string CreateDepthFetch( MasterNodeDataCollector dataCollector, string screenPos ) + { + string screenDepthInstruction = string.Empty; + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.Lightweight ) + { + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex ) + { + string m_functionBody = string.Empty; + GenerateLW( ref m_functionBody ); + dataCollector.AddFunctions( FetchLWDepthFormatVertex, m_functionBody, "0" ); + screenDepthInstruction = string.Format( FetchLWDepthFormatVertex, screenPos ); + } + else + screenDepthInstruction = string.Format( FetchLWDepthFormat, screenPos ); + } + else if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + screenDepthInstruction = string.Format( FetchHDDepthFormat, screenPos ); + } + else + { + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex ) + screenDepthInstruction = string.Format( FetchDefaultDepthFormatVertex, screenPos ); + else + screenDepthInstruction = string.Format( FetchDefaultDepthFormat, screenPos ); + } + return screenDepthInstruction; + } + + public static void GenerateLW( ref string body ) + { + body = string.Empty; + IOUtils.AddFunctionHeader( ref body, "float SHADERGRAPH_SAMPLE_SCENE_DEPTH_LOD(float2 uv)" ); + IOUtils.AddFunctionLine( ref body, "#if defined(REQUIRE_DEPTH_TEXTURE)" ); + IOUtils.AddFunctionLine( ref body, "#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)" ); + IOUtils.AddFunctionLine( ref body, " \tfloat rawDepth = SAMPLE_TEXTURE2D_ARRAY_LOD(_CameraDepthTexture, sampler_CameraDepthTexture, uv, unity_StereoEyeIndex, 0).r;" ); + IOUtils.AddFunctionLine( ref body, "#else" ); + IOUtils.AddFunctionLine( ref body, " \tfloat rawDepth = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, sampler_CameraDepthTexture, uv, 0);" ); + IOUtils.AddFunctionLine( ref body, "#endif" ); + IOUtils.AddFunctionLine( ref body, "return rawDepth;" ); + IOUtils.AddFunctionLine( ref body, "#endif // REQUIRE_DEPTH_TEXTURE" ); + IOUtils.AddFunctionLine( ref body, "return 0;" ); + IOUtils.CloseFunctionBody( ref body ); + } + + public static bool GetShaderModelForInterpolatorAmount( int interpAmount, ref string shaderModel ) + { + for( int i = 0; i < AvailableShaderModels.Length; i++ ) + { + if( AvailableInterpolators[ AvailableShaderModels[ i ] ] >= interpAmount ) + { + shaderModel = AvailableShaderModels[ i ]; + return true; + } + } + return false; + } + + public static string GetSubShaderFrom( string shaderBody ) + { + Match match = Regex.Match( shaderBody, FetchSubShaderBody, RegexOptions.Singleline ); + if( match.Success && match.Groups.Count > 1 ) + { + return match.Groups[ 1 ].Value; + } + + return string.Empty; + } + + public static void FillRenderingPlatform( TemplateRenderPlatformHelper renderPlatforms , string shaderBody ) + { + int tagIndex = shaderBody.IndexOf( TemplatesManager.TemplateRenderPlatformsTag ); + if( tagIndex > -1 ) + { + renderPlatforms.InitByTag( tagIndex ); + } + else + { + //Excluded + Match excludePlatformsMatch = Regex.Match( shaderBody , PragmaExcludeRendersPattern ); + if( excludePlatformsMatch.Success ) + { + renderPlatforms.InitByExcludeRenders( excludePlatformsMatch.Index, excludePlatformsMatch.Value ); + MatchCollection platformElements = Regex.Matches( excludePlatformsMatch.Groups[ 1 ].Value , PragmaRendererElement ); + try + { + for( int i = 0 ; i < platformElements.Count ; i++ ) + { + if( platformElements[ i ].Success ) + renderPlatforms.SetupPlatform( platformElements[ i ].Groups[ 1 ].Value , false ); + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + else //Only Renders + { + Match onlyRendersPlatformsMatch = Regex.Match( shaderBody , PragmaOnlyRendersPattern ); + if( onlyRendersPlatformsMatch.Success ) + { + renderPlatforms.InitByOnlyRenders( onlyRendersPlatformsMatch.Index, onlyRendersPlatformsMatch.Value ); + MatchCollection platformElements = Regex.Matches( onlyRendersPlatformsMatch.Groups[ 1 ].Value , PragmaRendererElement ); + try + { + for( int i = 0 ; i < platformElements.Count ; i++ ) + { + if( platformElements[ i ].Success ) + renderPlatforms.SetupPlatform( platformElements[ i ].Groups[ 1 ].Value, true ); + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + } + + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs.meta new file mode 100644 index 0000000..8cbfe8c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 517aad6764d713946bc566f0a83cd44d +timeCreated: 1495548641 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs new file mode 100644 index 0000000..a9d242d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs @@ -0,0 +1,236 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplatePassId + { + public string PassId; + public bool RemoveFromShader; + } + + + [Serializable] + public class TemplateTag + { + public string Tag = string.Empty; + public string Replacement = string.Empty; + public string Output = string.Empty; + public TemplateTag( string tag, string replacement = null ) + { + Tag = tag; + if( replacement != null ) + { + Replacement = replacement; + Output = replacement; + } + } + } + + [Serializable] + public class TemplateId + { + public int StartIdx = -1; + public string UniqueID; + public string Tag; + public string ReplacementText; + public bool IsReplaced = false; + public bool EmptyReplacer = false; + public TemplateId( int bodyIdx, string uniqueID, string tag, bool emptyReplacer = false ) + { + StartIdx = bodyIdx; + UniqueID = uniqueID; + Tag = tag; + EmptyReplacer = emptyReplacer; + ReplacementText = emptyReplacer ? string.Empty : tag; + } + + public void SetReplacementText( string replacementText ) + { + ReplacementText = replacementText; + IsReplaced = true; + } + + public void Reset() + { + ReplacementText = EmptyReplacer?string.Empty:Tag; + IsReplaced = false; + } + } + + [Serializable] + public class TemplateIdManager + { + [SerializeField] + private bool m_isSorted = false; + [SerializeField] + private string m_shaderBody; + [SerializeField] + private List m_registeredIds = new List(); + + [SerializeField] + private List m_registeredTags = new List(); + + [SerializeField] + private List m_registeredPassIds = new List(); + + private Dictionary m_registeredIdsDict = new Dictionary(); + + public TemplateIdManager( string shaderBody ) + { + m_shaderBody = shaderBody; + } + + public void Destroy() + { + m_registeredPassIds.Clear(); + m_registeredPassIds = null; + + m_registeredTags.Clear(); + m_registeredTags = null; + + m_registeredIds.Clear(); + m_registeredIds = null; + if( m_registeredIdsDict != null ) + { + m_registeredIdsDict.Clear(); + m_registeredIdsDict = null; + } + } + + void RefreshIds() + { + if( m_registeredIdsDict == null ) + { + m_registeredIdsDict = new Dictionary(); + } + + if( m_registeredIdsDict.Count != m_registeredIds.Count ) + { + m_registeredIdsDict.Clear(); + int count = m_registeredIds.Count; + for( int i = 0; i < count; i++ ) + { + m_registeredIdsDict.Add( m_registeredIds[ i ].UniqueID, m_registeredIds[ i ] ); + } + } + } + + public void RegisterId( int bodyIdx, string uniqueID, string tag, bool emptyReplacer = false ) + { + if( bodyIdx < 0 ) + return; + + RefreshIds(); + + TemplateId templateId = new TemplateId( bodyIdx, uniqueID, tag, emptyReplacer ); + m_registeredIds.Add( templateId ); + m_registeredIdsDict.Add( uniqueID, templateId ); + } + + public void RegisterTag( string tag, string replacement = null ) + { + m_registeredTags.Add( new TemplateTag( tag, replacement ) ); + } + + public void RegisterPassId( string passId ) + { + m_registeredPassIds.Add( new TemplatePassId() { PassId = passId, RemoveFromShader = false } ); + } + + public void SetPassIdUsage( int idx , bool removeFromShader ) + { + m_registeredPassIds[ idx ].RemoveFromShader = removeFromShader; + } + + public void SetReplacementText( string uniqueId, string replacementText ) + { + RefreshIds(); + + if( m_registeredIdsDict.ContainsKey( uniqueId ) && m_registeredIdsDict[ uniqueId ].StartIdx >= 0 ) + m_registeredIdsDict[ uniqueId ].SetReplacementText( replacementText ); + } + + + public string BuildShader() + { + if( !m_isSorted ) + { + m_registeredIds.Sort( ( x, y ) => { return x.StartIdx.CompareTo( y.StartIdx ); } ); + } + + int idCount = m_registeredIds.Count; + int offset = 0; + string finalShaderBody = m_shaderBody; + for( int i = 0; i < idCount; i++ ) + { + if( m_registeredIds[ i ].StartIdx >= 0 && m_registeredIds[ i ].IsReplaced ) + { + finalShaderBody = finalShaderBody.ReplaceAt( m_registeredIds[ i ].Tag, m_registeredIds[ i ].ReplacementText, offset + m_registeredIds[ i ].StartIdx ); + offset += ( m_registeredIds[ i ].ReplacementText.Length - m_registeredIds[ i ].Tag.Length ); + } + } + + int count = m_registeredPassIds.Count; + for( int i = 0; i < count; i++ ) + { + if( m_registeredPassIds[ i ].RemoveFromShader ) + finalShaderBody = finalShaderBody.Replace( m_registeredPassIds[ i ].PassId, string.Empty ); + } + + for( int i = 0; i < idCount; i++ ) + { + if( !m_registeredIds[ i ].IsReplaced && !m_registeredIds[ i ].Tag.Equals( m_registeredIds[ i ].ReplacementText ) ) + { + finalShaderBody = finalShaderBody.Replace( m_registeredIds[ i ].Tag, m_registeredIds[ i ].ReplacementText ); + } + } + + count = m_registeredTags.Count; + for( int i = 0; i < count; i++ ) + { + finalShaderBody = finalShaderBody.Replace( m_registeredTags[ i ].Tag, m_registeredTags[ i ].Replacement ); + m_registeredTags[ i ].Replacement = m_registeredTags[ i ].Output; + } + + //finalShaderBody = finalShaderBody.Replace( TemplatesManager.TemplateExcludeFromGraphTag, string.Empty ); + //finalShaderBody = finalShaderBody.Replace( TemplatesManager.TemplateMainPassTag, string.Empty ); + + return finalShaderBody; + } + + public void ResetRegistersState() + { + int count = m_registeredIds.Count; + for( int i = 0; i < count; i++ ) + { + m_registeredIds[ i ].Reset(); + } + } + + public void Reset() + { + m_registeredIds.Clear(); + if( m_registeredIdsDict == null ) + { + m_registeredIdsDict = new Dictionary(); + } + else + { + m_registeredIdsDict.Clear(); + } + } + + public string ShaderBody + { + get { return m_shaderBody; } + set { m_shaderBody = value; } + } + + public List RegisteredTags { get { return m_registeredTags; } set { m_registeredTags = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs.meta new file mode 100644 index 0000000..887ff5a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b0d2e93061ffcbd45b085a61e5000daa +timeCreated: 1517315635 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs new file mode 100644 index 0000000..d71b057 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs @@ -0,0 +1,239 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateInterpElement + { + public TemplateSemantics Semantic; + public bool[] AvailableChannels = { true, true, true, true }; + public bool IsFull = false; + public int Usage = 0; + public string Name; + //https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-struct + public bool NoInterpolation; + public bool Sample; + + public TemplateInterpElement( TemplateInterpElement other ) + { + Semantic = other.Semantic; + for ( int i = 0; i < AvailableChannels.Length; i++ ) + { + AvailableChannels[ i ] = other.AvailableChannels[ i ]; + } + IsFull = other.IsFull; + Usage = other.Usage; + Name = other.Name; + NoInterpolation = other.NoInterpolation; + Sample = other.Sample; + } + + public TemplateInterpElement( TemplateSemantics semantic ) + { + Semantic = semantic; + int semanticId = TemplateHelperFunctions.SemanticToInt[ Semantic ]; + Name = ( semanticId == 0 ) ? TemplateHelperFunctions.BaseInterpolatorName : TemplateHelperFunctions.BaseInterpolatorName + semanticId.ToString(); + } + + public void SetAvailableChannelsFromString( string channels ) + { + for ( int i = 0; i < AvailableChannels.Length; i++ ) + { + AvailableChannels[ i ] = false; + } + Usage = AvailableChannels.Length; + + for ( int i = 0; i < channels.Length; i++ ) + { + switch ( channels[ i ] ) + { + case 'x': if ( !AvailableChannels[ 0 ] ) { AvailableChannels[ 0 ] = true; Usage--; } break; + case 'y': if ( !AvailableChannels[ 1 ] ) { AvailableChannels[ 1 ] = true; Usage--; } break; + case 'z': if ( !AvailableChannels[ 2 ] ) { AvailableChannels[ 2 ] = true; Usage--; } break; + case 'w': if ( !AvailableChannels[ 3 ] ) { AvailableChannels[ 3 ] = true; Usage--; } break; + } + } + } + + public TemplateVertexData RequestChannels( WirePortDataType type, bool isColor, string customName = null ) + { + if ( IsFull ) + return null; + + int channelsRequired = TemplateHelperFunctions.DataTypeChannelUsage[ type ]; + if ( channelsRequired == 0 ) + return null; + + int firstChannel = -1; + for ( int i = 0; i < AvailableChannels.Length; i++ ) + { + if ( AvailableChannels[ i ] ) + { + if ( firstChannel < 0 ) + { + firstChannel = i; + } + channelsRequired -= 1; + if ( channelsRequired == 0 ) + break; + } + } + + //did not found enough channels to fill request + if ( channelsRequired > 0 ) + return null; + + if( Usage == 0 && customName != null ) + { + Name = customName; + } + + Usage += 1; + TemplateVertexData data = null; + + if ( type == WirePortDataType.COLOR || type == WirePortDataType.FLOAT4 ) + { + // Automatically lock all channels + for ( int i = firstChannel; i < ( firstChannel + channelsRequired ); i++ ) + { + AvailableChannels[ i ] = false; + } + IsFull = true; + data = new TemplateVertexData( Semantic, type, Name ); + } + else + { + string[] swizzleArray = ( isColor ) ? TemplateHelperFunctions.ColorSwizzle : TemplateHelperFunctions.VectorSwizzle; + string channels = "."; + int count = firstChannel + TemplateHelperFunctions.DataTypeChannelUsage[ type ]; + for ( int i = firstChannel; i < count; i++ ) + { + AvailableChannels[ i ] = false; + channels += swizzleArray[ i ]; + if ( i == ( AvailableChannels.Length - 1 ) ) + { + IsFull = true; + } + } + + data = new TemplateVertexData( Semantic, type, Name, channels ); + } + return data; + } + } + + [Serializable] + public class TemplateInterpData + { + [SerializeField] + private string m_interpDataId = string.Empty; + + [SerializeField] + private int m_interpDataStartIdx = -1; + + [SerializeField] + private bool m_dynamicMax = false; + + public List AvailableInterpolators = new List(); + public List Interpolators = new List(); + public List RawInterpolators = new List(); + + public TemplateInterpData() { } + + public bool HasRawInterpolatorOfName( string name ) + { + return RawInterpolators.Exists( ( x ) => x.VarName.Equals( name )); + } + + public TemplateInterpData( TemplateInterpData other ) + { + m_dynamicMax = other.DynamicMax; + + foreach ( TemplateInterpElement data in other.AvailableInterpolators ) + { + AvailableInterpolators.Add( new TemplateInterpElement( data ) ); + } + + for ( int i = 0; i < other.Interpolators.Count; i++ ) + { + Interpolators.Add( new TemplateVertexData( other.Interpolators[ i ] ) ); + } + + for( int i = 0; i < other.RawInterpolators.Count; i++ ) + { + RawInterpolators.Add( new TemplateVertexData( other.RawInterpolators[ i ] ) ); + } + } + + + public void RecalculateAvailableInterpolators( int newMax ) + { + if( m_dynamicMax ) + { + if( !TemplateHelperFunctions.IntToSemantic.ContainsKey( ( newMax - 1 ) ) ) + { + Debug.LogWarning( "Attempting to add inexisting available interpolators" ); + return; + } + + if( AvailableInterpolators.Count > 0 ) + { + int currMax = 1 + TemplateHelperFunctions.SemanticToInt[ AvailableInterpolators[ AvailableInterpolators.Count - 1 ].Semantic ]; + if( newMax > currMax ) + { + int count = newMax - currMax; + for( int i = 0; i < count; i++ ) + { + AvailableInterpolators.Add( new TemplateInterpElement( TemplateHelperFunctions.IntToSemantic[ currMax + i ] )); + } + } + else if( newMax < currMax ) + { + int min = TemplateHelperFunctions.SemanticToInt[ AvailableInterpolators[ 0 ].Semantic ]; + if( newMax > min ) + { + int count = currMax - newMax; + for( int i = 0; i < count; i++ ) + { + AvailableInterpolators.RemoveAt( AvailableInterpolators.Count - 1 ); + } + } + } + } + } + } + + public void ReplaceNameOnInterpolator( TemplateSemantics semantic, string newName ) + { + for ( int i = 0; i < AvailableInterpolators.Count; i++ ) + { + if ( AvailableInterpolators[ i ].Semantic == semantic ) + { + AvailableInterpolators[ i ].Name = newName; + break; + } + } + } + + public void Destroy() + { + AvailableInterpolators.Clear(); + AvailableInterpolators = null; + + Interpolators.Clear(); + Interpolators = null; + + RawInterpolators.Clear(); + RawInterpolators = null; + } + + public string InterpDataId { get { return m_interpDataId; } set { m_interpDataId = value; } } + public int InterpDataStartIdx { get { return m_interpDataStartIdx; } set { m_interpDataStartIdx = value; } } + public bool DynamicMax { get { return m_dynamicMax; } set { m_dynamicMax = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs.meta new file mode 100644 index 0000000..cf31bc9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8f700ba5366bcda45beea5c0e2db9f3e +timeCreated: 1496053368 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs new file mode 100644 index 0000000..3cde2f0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs @@ -0,0 +1,59 @@ +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateLocalVarData + { + [SerializeField] + private WirePortDataType m_dataType = WirePortDataType.OBJECT; + + [SerializeField] + private string m_localVarName = string.Empty; + + [SerializeField] + private int m_position = -1; + + [SerializeField] + private bool m_isSpecialVar = false; + + [SerializeField] + private TemplateInfoOnSematics m_specialVarType; + + [SerializeField] + private MasterNodePortCategory m_category; + + [SerializeField] + private string m_id; + + public TemplateLocalVarData( WirePortDataType dataType, MasterNodePortCategory category, string localVarName, int position ) + { + m_dataType = dataType; + m_localVarName = localVarName; + m_position = position; + m_category = category; + //Debug.Log( m_localVarName + " " + m_inputData.PortCategory + " " + m_inputData.PortName ); + } + + public TemplateLocalVarData( TemplateInfoOnSematics specialVarType,string id, WirePortDataType dataType, MasterNodePortCategory category, string localVarName, int position ) + { + m_id = id; + m_dataType = dataType; + m_localVarName = localVarName; + m_position = position; + m_specialVarType = specialVarType; + m_isSpecialVar = true; + m_category = category; + //Debug.Log( m_localVarName + " " + m_inputData.PortCategory + " " + m_inputData.PortName ); + } + + public WirePortDataType DataType { get { return m_dataType; } } + public string LocalVarName { get { return m_localVarName; } } + public int Position { get { return m_position; } } + public bool IsSpecialVar { get { return m_isSpecialVar; } } + public TemplateInfoOnSematics SpecialVarType{ get { return m_specialVarType; } } + public MasterNodePortCategory Category { get { return m_category; } } + public string Id { get { return m_id; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs.meta new file mode 100644 index 0000000..267c352 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4c6ad22d8633c7142ae0237479df76ed +timeCreated: 1518017743 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs new file mode 100644 index 0000000..e767678 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs @@ -0,0 +1,264 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Template Local Var Data", "Surface Data", "Select and use available local variable data from the template" )] + public sealed class TemplateLocalVarsNode : TemplateNodeParent + { + private List m_localVarsData = null; + + [SerializeField] + private int m_currentDataIdx = -1; + + [SerializeField] + private string m_dataName = string.Empty; + + private string[] m_dataLabels = null; + + private bool m_fetchDataId = false; + private UpperLeftWidgetHelper m_upperLeftWidgetHelper = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_autoWrapProperties = true; + } + + void FetchDataId() + { + if( m_localVarsData != null && m_localVarsData.Count > 0 ) + { + m_currentDataIdx = 0; + int count = m_localVarsData.Count; + m_dataLabels = new string[ count ]; + for( int i = 0; i < count; i++ ) + { + m_dataLabels[ i ] = m_localVarsData[ i ].LocalVarName; + if( m_localVarsData[ i ].LocalVarName.Equals( m_dataName ) ) + { + m_currentDataIdx = i; + } + } + UpdateFromId(); + } + else + { + m_currentDataIdx = -1; + } + } + + void UpdateFromId() + { + if( m_localVarsData != null ) + { + if( m_localVarsData.Count == 0 ) + { + for( int i = 0; i < 4; i++ ) + m_containerGraph.DeleteConnection( false, UniqueId, i, false, true ); + + m_headerColor = UIUtils.GetColorFromCategory( "Default" ); + m_content.text = "None"; + m_additionalContent.text = string.Empty; + m_outputPorts[ 0 ].ChangeProperties( "None", WirePortDataType.OBJECT, false ); + ConfigurePorts(); + return; + } + + bool areCompatible = TemplateHelperFunctions.CheckIfCompatibles( m_outputPorts[ 0 ].DataType, m_localVarsData[ m_currentDataIdx ].DataType ); + string category = m_localVarsData[ m_currentDataIdx ].Category == MasterNodePortCategory.Fragment ? "Surface Data" : "Vertex Data"; + m_headerColor = UIUtils.GetColorFromCategory( category ); + switch( m_localVarsData[ m_currentDataIdx ].DataType ) + { + default: + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, m_localVarsData[ m_currentDataIdx ].DataType, false ); + break; + case WirePortDataType.FLOAT2: + m_outputPorts[ 0 ].ChangeProperties( "XY", m_localVarsData[ m_currentDataIdx ].DataType, false ); + break; + case WirePortDataType.FLOAT3: + m_outputPorts[ 0 ].ChangeProperties( "XYZ", m_localVarsData[ m_currentDataIdx ].DataType, false ); + break; + case WirePortDataType.FLOAT4: + m_outputPorts[ 0 ].ChangeProperties( "XYZW", m_localVarsData[ m_currentDataIdx ].DataType, false ); + break; + case WirePortDataType.COLOR: + m_outputPorts[ 0 ].ChangeProperties( "RGBA", m_localVarsData[ m_currentDataIdx ].DataType, false ); + break; + } + + ConfigurePorts(); + + if( !areCompatible ) + { + m_containerGraph.DeleteConnection( false, UniqueId, 0, false, true ); + } + + m_dataName = m_localVarsData[ m_currentDataIdx ].LocalVarName; + m_content.text = m_dataName; + m_sizeIsDirty = true; + CheckWarningState(); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + if( m_multiPassMode ) + { + DrawMultipassProperties(); + } + + if( m_currentDataIdx > -1 ) + { + EditorGUI.BeginChangeCheck(); + m_currentDataIdx = EditorGUILayoutPopup( DataLabelStr, m_currentDataIdx, m_dataLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromId(); + } + } + } + protected override void OnSubShaderChange() + { + FetchLocalVarData(); + FetchDataId(); + } + + protected override void OnPassChange() + { + base.OnPassChange(); + FetchLocalVarData(); + FetchDataId(); + } + + void DrawMultipassProperties() + { + DrawSubShaderUI(); + DrawPassUI(); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader ) + return; + + if( m_localVarsData == null || m_localVarsData.Count == 0 ) + { + MasterNode masterNode = m_containerGraph.CurrentMasterNode; + if( masterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template ) + { + FetchLocalVarData( masterNode ); + } + } + + if( m_fetchDataId ) + { + m_fetchDataId = false; + FetchDataId(); + } + + if( m_currentDataIdx > -1 ) + { + EditorGUI.BeginChangeCheck(); + m_currentDataIdx = m_upperLeftWidgetHelper.DrawWidget( this, m_currentDataIdx, m_dataLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromId(); + } + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( m_localVarsData[ m_currentDataIdx ].Category != dataCollector.PortCategory ) + { + UIUtils.ShowMessage( UniqueId, string.Format( "Local Var {0} can only work on ports of type {1}", m_localVarsData[ m_currentDataIdx ].LocalVarName, m_localVarsData[ m_currentDataIdx ].Category ) ); + return m_outputPorts[ 0 ].ErrorValue; + } + + if( m_multiPassMode ) + { + if( dataCollector.TemplateDataCollectorInstance.MultipassSubshaderIdx != SubShaderIdx || + dataCollector.TemplateDataCollectorInstance.MultipassPassIdx != PassIdx + ) + { + UIUtils.ShowMessage( UniqueId, string.Format( "{0} is only intended for subshader {1} and pass {2}", m_dataLabels[ m_currentDataIdx ], SubShaderIdx, PassIdx ) ); + return m_outputPorts[ outputId ].ErrorValue; + } + } + + return GetOutputVectorItem( 0, outputId, m_dataName ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_dataName = GetCurrentParam( ref nodeParams ); + m_fetchDataId = true; + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_dataName ); + } + + public override void OnMasterNodeReplaced( MasterNode newMasterNode ) + { + base.OnMasterNodeReplaced( newMasterNode ); + if( newMasterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template ) + { + FetchLocalVarData( newMasterNode ); + } + else + { + m_localVarsData = null; + m_currentDataIdx = -1; + } + } + + void FetchLocalVarData( MasterNode masterNode = null ) + { + FetchMultiPassTemplate( masterNode ); + if( m_multiPassMode ) + { + if( m_templateMPData != null ) + { + m_localVarsData = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].LocalVarsList; + m_fetchDataId = true; + } + } + else + { + TemplateData currentTemplate = ( masterNode as TemplateMasterNode ).CurrentTemplate; + if( currentTemplate != null ) + { + m_localVarsData = currentTemplate.LocalVarsList; + m_fetchDataId = true; + } + else + { + m_localVarsData = null; + m_currentDataIdx = -1; + } + } + } + + public override void Destroy() + { + base.Destroy(); + m_dataLabels = null; + m_localVarsData = null; + m_upperLeftWidgetHelper = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs.meta new file mode 100644 index 0000000..f7453d9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f708a5bf672ab004a9363a4a71f48f28 +timeCreated: 1518104790 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs new file mode 100644 index 0000000..883368b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs @@ -0,0 +1,770 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +// THIS FILE IS DEPRECATED AND SHOULD NOT BE USED + +#define SHOW_TEMPLATE_HELP_BOX + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Template Master Node", "Master", "Shader Generated according to template rules", null, KeyCode.None, false, true, "Template MultiPass Master Node", typeof( TemplateMultiPassMasterNode ) )] + public sealed class TemplateMasterNode : MasterNode + { + private const string WarningMessage = "Templates is a feature that is still heavily under development and users may experience some problems.\nPlease email support@amplify.pt if any issue occurs."; + private const string CurrentTemplateLabel = "Current Template"; + private const string OpenTemplateStr = "Edit Template"; + + //protected const string SnippetsFoldoutStr = " Snippets"; + //[SerializeField] + //private bool m_snippetsFoldout = true; + + [NonSerialized] + private TemplateData m_currentTemplate = null; + + private bool m_fireTemplateChange = false; + private bool m_fetchMasterNodeCategory = false; + private bool m_reRegisterTemplateData = false; + + [SerializeField] + private string m_templateGUID = string.Empty; + + [SerializeField] + private string m_templateName = string.Empty; + + [SerializeField] + private TemplatesBlendModule m_blendOpHelper = new TemplatesBlendModule(); + + [SerializeField] + private TemplateAlphaToMaskModule m_alphaToMaskHelper = new TemplateAlphaToMaskModule(); + + [SerializeField] + private TemplateCullModeModule m_cullModeHelper = new TemplateCullModeModule(); + + [SerializeField] + private TemplateColorMaskModule m_colorMaskHelper = new TemplateColorMaskModule(); + + [SerializeField] + private TemplatesStencilBufferModule m_stencilBufferHelper = new TemplatesStencilBufferModule(); + + [SerializeField] + private TemplateDepthModule m_depthOphelper = new TemplateDepthModule(); + + [SerializeField] + private TemplateTagsModule m_tagsHelper = new TemplateTagsModule(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_masterNodeCategory = 1;// First Template + m_marginPreviewLeft = 20; + m_insideSize.y = 60; + m_customPrecision = true; + } + + public override void ReleaseResources() + { + if( m_currentTemplate != null && m_currentTemplate.AvailableShaderProperties != null ) + { + // Unregister old template properties + int oldPropertyCount = m_currentTemplate.AvailableShaderProperties.Count; + for( int i = 0; i < oldPropertyCount; i++ ) + { + UIUtils.ReleaseUniformName( UniqueId, m_currentTemplate.AvailableShaderProperties[ i ].PropertyName ); + } + } + } + + public override void OnEnable() + { + base.OnEnable(); + m_reRegisterTemplateData = true; + } + + void FetchInfoFromTemplate() + { + if( m_currentTemplate.BlendData.DataCheck == TemplateDataCheck.Valid ) + m_blendOpHelper.ConfigureFromTemplateData( m_currentTemplate.BlendData ); + + if( m_currentTemplate.AlphaToMaskData.DataCheck == TemplateDataCheck.Valid ) + m_alphaToMaskHelper.ConfigureFromTemplateData( m_currentTemplate.AlphaToMaskData ); + + if( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid ) + m_cullModeHelper.ConfigureFromTemplateData( m_currentTemplate.CullModeData ); + + if( m_currentTemplate.ColorMaskData.DataCheck == TemplateDataCheck.Valid ) + m_colorMaskHelper.ConfigureFromTemplateData( m_currentTemplate.ColorMaskData ); + + if( m_currentTemplate.StencilData.DataCheck == TemplateDataCheck.Valid ) + m_stencilBufferHelper.ConfigureFromTemplateData( m_currentTemplate.StencilData ); + + if( m_currentTemplate.DepthData.DataCheck == TemplateDataCheck.Valid ) + m_depthOphelper.ConfigureFromTemplateData( m_currentTemplate.DepthData ); + + if( m_currentTemplate.TagData.DataCheck == TemplateDataCheck.Valid ) + m_tagsHelper.ConfigureFromTemplateData( m_currentTemplate.TagData ); + } + + void FetchCurrentTemplate() + { + m_currentTemplate = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( m_templateGUID ) as TemplateData; + if( m_currentTemplate == null ) + { + m_currentTemplate = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( m_templateName ) as TemplateData; + } + + if( m_currentTemplate != null ) + { + if( m_inputPorts.Count != m_currentTemplate.InputDataList.Count ) + { + DeleteAllInputConnections( true ); + + List inputDataList = m_currentTemplate.InputDataList; + int count = inputDataList.Count; + for( int i = 0; i < count; i++ ) + { + AddInputPort( inputDataList[ i ].DataType, false, inputDataList[ i ].PortName, inputDataList[ i ].OrderId, inputDataList[ i ].PortCategory, inputDataList[ i ].PortUniqueId ); + } + FetchInfoFromTemplate(); + } + else + { + List inputDataList = m_currentTemplate.InputDataList; + int count = inputDataList.Count; + for( int i = 0; i < count; i++ ) + { + m_inputPorts[ i ].ChangeProperties( inputDataList[ i ].PortName, inputDataList[ i ].DataType, false ); + } + } + } + } + + public override void RefreshAvailableCategories() + { + FetchCurrentTemplate(); + + int templateCount = m_containerGraph.ParentWindow.TemplatesManagerInstance.TemplateCount; + m_availableCategories = new MasterNodeCategoriesData[ templateCount + 1 ]; + m_availableCategoryLabels = new GUIContent[ templateCount + 1 ]; + + m_availableCategories[ 0 ] = new MasterNodeCategoriesData( AvailableShaderTypes.SurfaceShader, string.Empty ); + m_availableCategoryLabels[ 0 ] = new GUIContent( "Surface" ); + if( m_currentTemplate == null ) + { + m_masterNodeCategory = -1; + } + + for( int i = 0; i < templateCount; i++ ) + { + int idx = i + 1; + TemplateData templateData = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( i ) as TemplateData; + + if( m_currentTemplate != null && m_currentTemplate.GUID.Equals( templateData.GUID ) ) + m_masterNodeCategory = idx; + + m_availableCategories[ idx ] = new MasterNodeCategoriesData( AvailableShaderTypes.Template, templateData.GUID ); + m_availableCategoryLabels[ idx ] = new GUIContent( templateData.Name ); + } + } + + void SetCategoryIdxFromTemplate() + { + int templateCount = m_containerGraph.ParentWindow.TemplatesManagerInstance.TemplateCount; + for( int i = 0; i < templateCount; i++ ) + { + int idx = i + 1; + TemplateData templateData = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( i ) as TemplateData; + if( templateData != null && m_currentTemplate != null && m_currentTemplate.GUID.Equals( templateData.GUID ) ) + m_masterNodeCategory = idx; + } + } + + public void SetTemplate( TemplateData newTemplate, bool writeDefaultData, bool fetchMasterNodeCategory ) + { + ReleaseResources(); + + if( newTemplate == null || newTemplate.InputDataList == null ) + return; + + m_fetchMasterNodeCategory = fetchMasterNodeCategory; + + DeleteAllInputConnections( true ); + m_currentTemplate = newTemplate; + m_currentShaderData = newTemplate.Name; + + List inputDataList = newTemplate.InputDataList; + int count = inputDataList.Count; + for( int i = 0; i < count; i++ ) + { + AddInputPort( inputDataList[ i ].DataType, false, inputDataList[ i ].PortName, inputDataList[ i ].OrderId, inputDataList[ i ].PortCategory, inputDataList[ i ].PortUniqueId ); + } + + if( writeDefaultData ) + { + ShaderName = newTemplate.DefaultShaderName; + } + + RegisterProperties(); + m_fireTemplateChange = true; + m_templateGUID = newTemplate.GUID; + m_templateName = newTemplate.DefaultShaderName; + FetchInfoFromTemplate(); + } + + void RegisterProperties() + { + if( m_currentTemplate != null ) + { + m_reRegisterTemplateData = false; + // Register old template properties + int newPropertyCount = m_currentTemplate.AvailableShaderProperties.Count; + for( int i = 0; i < newPropertyCount; i++ ) + { + int nodeId = UIUtils.CheckUniformNameOwner( m_currentTemplate.AvailableShaderProperties[ i ].PropertyName ); + if( nodeId > -1 ) + { + ParentNode node = m_containerGraph.GetNode( nodeId ); + if( node != null ) + { + UIUtils.ShowMessage( string.Format( "Template requires property name {0} which is currently being used by {1}. Please rename it and reload template.", m_currentTemplate.AvailableShaderProperties[ i ].PropertyName, node.Attributes.Name ) ); + } + else + { + UIUtils.ShowMessage( string.Format( "Template requires property name {0} which is currently being on your graph. Please rename it and reload template.", m_currentTemplate.AvailableShaderProperties[ i ].PropertyName ) ); + } + } + else + { + UIUtils.RegisterUniformName( UniqueId, m_currentTemplate.AvailableShaderProperties[ i ].PropertyName ); + } + } + } + } + + public override void DrawProperties() + { + if( m_currentTemplate == null ) + return; + + base.DrawProperties(); + + bool generalIsVisible = ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedGeneralShaderOptions; + NodeUtils.DrawPropertyGroup( ref generalIsVisible, GeneralFoldoutStr, DrawGeneralOptions ); + ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedGeneralShaderOptions = generalIsVisible; + + if( m_currentTemplate.AlphaToMaskData.DataCheck == TemplateDataCheck.Valid ) + m_alphaToMaskHelper.Draw( this ); + + if( m_currentTemplate.BlendData.DataCheck == TemplateDataCheck.Valid ) + m_blendOpHelper.Draw( this ); + + + if( m_currentTemplate.StencilData.DataCheck == TemplateDataCheck.Valid ) + { + CullMode cullMode = ( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid ) ? m_cullModeHelper.CurrentCullMode : CullMode.Back; + m_stencilBufferHelper.Draw( this, cullMode ); + } + + if( m_currentTemplate.DepthData.DataCheck == TemplateDataCheck.Valid ) + m_depthOphelper.Draw( this ); + + if( m_currentTemplate.TagData.DataCheck == TemplateDataCheck.Valid ) + m_tagsHelper.Draw( this ); + + DrawMaterialInputs( UIUtils.MenuItemToolbarStyle ); + + // NodeUtils.DrawPropertyGroup( ref m_snippetsFoldout, SnippetsFoldoutStr, DrawSnippetOptions ); + if( GUILayout.Button( OpenTemplateStr ) && m_currentTemplate != null ) + { + try + { + string pathname = AssetDatabase.GUIDToAssetPath( m_currentTemplate.GUID ); + if( !string.IsNullOrEmpty( pathname ) ) + { + Shader selectedTemplate = AssetDatabase.LoadAssetAtPath( pathname ); + if( selectedTemplate != null ) + { + AssetDatabase.OpenAsset( selectedTemplate, 1 ); + } + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + +#if SHOW_TEMPLATE_HELP_BOX + EditorGUILayout.HelpBox( WarningMessage, MessageType.Warning ); +#endif + + } + + public void DrawGeneralOptions() + { + DrawShaderName(); + DrawCurrentShaderType(); + EditorGUI.BeginChangeCheck(); + DrawPrecisionProperty( false ); + if( EditorGUI.EndChangeCheck() ) + ContainerGraph.CurrentPrecision = m_currentPrecisionType; + + DrawSamplingMacros(); + + if( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid ) + m_cullModeHelper.Draw( this ); + + if( m_currentTemplate.ColorMaskData.DataCheck == TemplateDataCheck.Valid ) + m_colorMaskHelper.Draw( this ); + } + + //public void DrawSnippetOptions() + //{ + // m_currentTemplate.DrawSnippetProperties( this ); + //} + + bool CreateInstructionsForList( ref List ports, ref string shaderBody, ref List vertexInstructions, ref List fragmentInstructions ) + { + if( ports.Count == 0 ) + return true; + + bool isValid = true; + UIUtils.CurrentWindow.CurrentGraph.ResetNodesLocalVariables(); + for( int i = 0; i < ports.Count; i++ ) + { + TemplateInputData inputData = m_currentTemplate.InputDataFromId( ports[ i ].PortId ); + if( ports[ i ].IsConnected ) + { + m_currentDataCollector.ResetInstructions(); + m_currentDataCollector.ResetVertexInstructions(); + + m_currentDataCollector.PortCategory = ports[ i ].Category; + string newPortInstruction = ports[ i ].GeneratePortInstructions( ref m_currentDataCollector ); + + + if( m_currentDataCollector.DirtySpecialLocalVariables ) + { + string cleanVariables = m_currentDataCollector.SpecialLocalVariables.Replace( "\t", string.Empty ); + m_currentDataCollector.AddInstructions( cleanVariables, false ); + m_currentDataCollector.ClearSpecialLocalVariables(); + } + + if( m_currentDataCollector.DirtyVertexVariables ) + { + string cleanVariables = m_currentDataCollector.VertexLocalVariables.Replace( "\t", string.Empty ); + m_currentDataCollector.AddVertexInstruction( cleanVariables, UniqueId, false ); + m_currentDataCollector.ClearVertexLocalVariables(); + } + + // fill functions + for( int j = 0; j < m_currentDataCollector.InstructionsList.Count; j++ ) + { + fragmentInstructions.Add( m_currentDataCollector.InstructionsList[ j ].PropertyName ); + } + + for( int j = 0; j < m_currentDataCollector.VertexDataList.Count; j++ ) + { + vertexInstructions.Add( m_currentDataCollector.VertexDataList[ j ].PropertyName ); + } + + isValid = m_currentTemplate.FillTemplateBody( inputData.TagId, ref shaderBody, newPortInstruction ) && isValid; + } + else + { + isValid = m_currentTemplate.FillTemplateBody( inputData.TagId, ref shaderBody, inputData.DefaultValue ) && isValid; + } + } + return isValid; + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( m_currentTemplate == null ) + { + FetchCurrentTemplate(); + } + + if( m_reRegisterTemplateData ) + { + RegisterProperties(); + } + + if( m_containerGraph.IsInstancedShader ) + { + DrawInstancedIcon( drawInfo ); + } + + if( m_fetchMasterNodeCategory ) + { + if( m_availableCategories != null ) + { + m_fetchMasterNodeCategory = false; + SetCategoryIdxFromTemplate(); + } + } + + if( m_fireTemplateChange ) + { + m_fireTemplateChange = false; + m_containerGraph.FireMasterNodeReplacedEvent(); + } + } + + public override void UpdateFromShader( Shader newShader ) + { + if( m_currentMaterial != null ) + { + m_currentMaterial.shader = newShader; + } + CurrentShader = newShader; + } + + public override void UpdateMasterNodeMaterial( Material material ) + { + m_currentMaterial = material; + FireMaterialChangedEvt(); + } + + public override Shader Execute( string pathname, bool isFullPath ) + { + if( m_currentTemplate == null ) + return m_currentShader; + + //Create data collector + ForceReordering(); + base.Execute( pathname, isFullPath ); + + SetupNodeCategories(); + + m_currentDataCollector.TemplateDataCollectorInstance.BuildFromTemplateData( m_currentDataCollector, m_currentTemplate ); + int shaderPropertiesAmount = m_currentTemplate.AvailableShaderProperties.Count; + for( int i = 0; i < shaderPropertiesAmount; i++ ) + { + m_currentDataCollector.SoftRegisterUniform( m_currentTemplate.AvailableShaderProperties[ i ] ); + } + m_containerGraph.CheckPropertiesAutoRegister( ref m_currentDataCollector ); + + //Sort ports by both + List fragmentPorts = new List(); + List vertexPorts = new List(); + SortInputPorts( ref vertexPorts, ref fragmentPorts ); + + string shaderBody = m_currentTemplate.TemplateBody; + + List vertexInstructions = new List(); + List fragmentInstructions = new List(); + + bool validBody = true; + + validBody = CreateInstructionsForList( ref fragmentPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody; + ContainerGraph.ResetNodesLocalVariablesIfNot( MasterNodePortCategory.Vertex ); + validBody = CreateInstructionsForList( ref vertexPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody; + + m_currentTemplate.ResetTemplateUsageData(); + + // Fill vertex interpolators assignment + for( int i = 0; i < m_currentDataCollector.VertexInterpDeclList.Count; i++ ) + { + vertexInstructions.Add( m_currentDataCollector.VertexInterpDeclList[ i ] ); + } + + vertexInstructions.AddRange( m_currentDataCollector.TemplateDataCollectorInstance.GetInterpUnusedChannels() ); + //Fill common local variables and operations + + validBody = m_currentTemplate.FillVertexInstructions( ref shaderBody, vertexInstructions.ToArray() ) && validBody; + validBody = m_currentTemplate.FillFragmentInstructions( ref shaderBody, fragmentInstructions.ToArray() ) && validBody; + + // Add Instanced Properties + if( m_containerGraph.IsInstancedShader ) + { + m_currentDataCollector.TabifyInstancedVars(); + m_currentDataCollector.InstancedPropertiesList.Insert( 0, new PropertyDataCollector( -1, string.Format( IOUtils.InstancedPropertiesBegin, UIUtils.RemoveInvalidCharacters( m_shaderName ) ) ) ); + m_currentDataCollector.InstancedPropertiesList.Add( new PropertyDataCollector( -1, IOUtils.InstancedPropertiesEnd ) ); + m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.InstancedPropertiesList ); + } + + //Add Functions + m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.FunctionsList ); + + // Fill common tags + m_currentDataCollector.IncludesList.AddRange( m_currentDataCollector.PragmasList ); + + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.ShaderNameId, ref shaderBody, string.Format( TemplatesManager.NameFormatter, m_shaderName ) ) && validBody; + validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplatePassTag, ref shaderBody, m_currentDataCollector.GrabPassList ) && validBody; + validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplatePragmaTag, ref shaderBody, m_currentDataCollector.IncludesList ) && validBody; + //validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplateTagsTag, ref shaderBody, m_currentDataCollector.TagsList ) && validBody; + validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplatePropertyTag, ref shaderBody, m_currentDataCollector.BuildUnformatedPropertiesStringArr() ) && validBody; + validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplateGlobalsTag, ref shaderBody, m_currentDataCollector.UniformsList ) && validBody; + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.VertexDataId, ref shaderBody, m_currentDataCollector.VertexInputList.ToArray() ) && validBody; + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.InterpDataId, ref shaderBody, m_currentDataCollector.InterpolatorList.ToArray() ) && validBody; + + if( m_currentTemplate.BlendData.ValidBlendMode ) + { + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.BlendData.BlendModeId, ref shaderBody, m_blendOpHelper.CurrentBlendFactor ) && validBody; + } + + if( m_currentTemplate.BlendData.ValidBlendOp ) + { + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.BlendData.BlendOpId, ref shaderBody, m_blendOpHelper.CurrentBlendOp ) && validBody; + } + + if( m_currentTemplate.AlphaToMaskData.DataCheck == TemplateDataCheck.Valid ) + { + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.AlphaToMaskData.AlphaToMaskId, ref shaderBody, m_alphaToMaskHelper.GenerateShaderData( false ) ) && validBody; + } + + if( m_currentTemplate.DepthData.ValidZWrite ) + { + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.DepthData.ZWriteModeId, ref shaderBody, m_depthOphelper.CurrentZWriteMode ) && validBody; + } + + if( m_currentTemplate.DepthData.ValidZTest ) + { + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.DepthData.ZTestModeId, ref shaderBody, m_depthOphelper.CurrentZTestMode ) && validBody; + } + + if( m_currentTemplate.DepthData.ValidOffset ) + { + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.DepthData.OffsetId, ref shaderBody, m_depthOphelper.CurrentOffset ) && validBody; + } + + if( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid ) + { + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.CullModeData.CullModeId, ref shaderBody, m_cullModeHelper.GenerateShaderData(false) ) && validBody; + } + + if( m_currentTemplate.ColorMaskData.DataCheck == TemplateDataCheck.Valid ) + { + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.ColorMaskData.ColorMaskId, ref shaderBody, m_colorMaskHelper.GenerateShaderData( false ) ) && validBody; + } + + if( m_currentTemplate.StencilData.DataCheck == TemplateDataCheck.Valid ) + { + CullMode cullMode = ( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid ) ? m_cullModeHelper.CurrentCullMode : CullMode.Back; + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.StencilData.StencilBufferId, ref shaderBody, m_stencilBufferHelper.CreateStencilOp( cullMode ) ) && validBody; + } + + if( m_currentTemplate.TagData.DataCheck == TemplateDataCheck.Valid ) + { + validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.TagData.TagsId, ref shaderBody, m_tagsHelper.GenerateTags() ) && validBody; + } + + if( m_currentDataCollector.TemplateDataCollectorInstance.HasVertexInputParams ) + { + validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplateInputsVertParamsTag, ref shaderBody, m_currentDataCollector.TemplateDataCollectorInstance.VertexInputParamsStr ) && validBody; + } + + if( m_currentDataCollector.TemplateDataCollectorInstance.HasFragmentInputParams ) + { + validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplateInputsFragParamsTag, ref shaderBody, m_currentDataCollector.TemplateDataCollectorInstance.FragInputParamsStr ) && validBody; + } + + m_currentTemplate.FillEmptyTags( ref shaderBody ); + + //m_currentTemplate.InsertSnippets( ref shaderBody ); + + vertexInstructions.Clear(); + vertexInstructions = null; + + fragmentInstructions.Clear(); + fragmentInstructions = null; + if( validBody ) + { + UpdateShaderAsset( ref pathname, ref shaderBody, isFullPath ); + } + + return m_currentShader; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + try + { + ShaderName = GetCurrentParam( ref nodeParams ); + if( m_shaderName.Length > 0 ) + ShaderName = UIUtils.RemoveShaderInvalidCharacters( ShaderName ); + + string templateGUID = GetCurrentParam( ref nodeParams ); + string templateShaderName = string.Empty; + if( UIUtils.CurrentShaderVersion() > 13601 ) + { + templateShaderName = GetCurrentParam( ref nodeParams ); + } + + TemplateData template = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( templateGUID ) as TemplateData; + if( template != null ) + { + SetTemplate( template, false, true ); + } + else + { + template = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplateByName( templateShaderName ) as TemplateData; + if( template != null ) + { + SetTemplate( template, false, true ); + } + else + { + m_masterNodeCategory = -1; + } + } + + if( UIUtils.CurrentShaderVersion() > 13902 ) + { + //BLEND MODULE + if( m_currentTemplate.BlendData.ValidBlendMode ) + { + m_blendOpHelper.ReadBlendModeFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( m_currentTemplate.BlendData.ValidBlendOp ) + { + m_blendOpHelper.ReadBlendOpFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + //CULL MODE + if( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid ) + { + m_cullModeHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + //COLOR MASK + if( m_currentTemplate.ColorMaskData.DataCheck == TemplateDataCheck.Valid ) + { + m_colorMaskHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + //STENCIL BUFFER + if( m_currentTemplate.StencilData.DataCheck == TemplateDataCheck.Valid ) + { + m_stencilBufferHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + } + + if( UIUtils.CurrentShaderVersion() > 14202 ) + { + //DEPTH OPTIONS + if( m_currentTemplate.DepthData.ValidZWrite ) + { + m_depthOphelper.ReadZWriteFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( m_currentTemplate.DepthData.ValidZTest ) + { + m_depthOphelper.ReadZTestFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( m_currentTemplate.DepthData.ValidOffset ) + { + m_depthOphelper.ReadOffsetFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + } + + //TAGS + if( UIUtils.CurrentShaderVersion() > 14301 ) + { + if( m_currentTemplate.TagData.DataCheck == TemplateDataCheck.Valid ) + m_tagsHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 18302 ) + SamplingMacros = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + else + SamplingMacros = false; + } + catch( Exception e ) + { + Debug.LogException( e, this ); + } + m_containerGraph.CurrentCanvasMode = NodeAvailability.TemplateShader; + m_containerGraph.CurrentPrecision = m_currentPrecisionType; + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_shaderName ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_currentTemplate != null ) ? m_currentTemplate.GUID : string.Empty ); + IOUtils.AddFieldValueToString( ref nodeInfo, ( m_currentTemplate != null ) ? m_currentTemplate.DefaultShaderName : string.Empty ); + + //BLEND MODULE + if( m_currentTemplate.BlendData.ValidBlendMode ) + { + m_blendOpHelper.WriteBlendModeToString( ref nodeInfo ); + } + + if( m_currentTemplate.BlendData.ValidBlendOp ) + { + m_blendOpHelper.WriteBlendOpToString( ref nodeInfo ); + } + + //CULL MODULE + if( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid ) + { + m_cullModeHelper.WriteToString( ref nodeInfo ); + } + + //COLOR MASK MODULE + if( m_currentTemplate.ColorMaskData.DataCheck == TemplateDataCheck.Valid ) + { + m_colorMaskHelper.WriteToString( ref nodeInfo ); + } + + //STENCIL BUFFER MODULE + if( m_currentTemplate.StencilData.DataCheck == TemplateDataCheck.Valid ) + { + m_stencilBufferHelper.WriteToString( ref nodeInfo ); + } + + //DEPTH MODULE + if( m_currentTemplate.DepthData.ValidZWrite ) + { + m_depthOphelper.WriteZWriteToString( ref nodeInfo ); + } + + if( m_currentTemplate.DepthData.ValidZTest ) + { + m_depthOphelper.WriteZTestToString( ref nodeInfo ); + } + + if( m_currentTemplate.DepthData.ValidOffset ) + { + m_depthOphelper.WriteOffsetToString( ref nodeInfo ); + } + + //TAGS + if( m_currentTemplate.TagData.DataCheck == TemplateDataCheck.Valid ) + { + m_tagsHelper.WriteToString( ref nodeInfo ); + } + + IOUtils.AddFieldValueToString( ref nodeInfo, m_samplingMacros ); + } + + public override void Destroy() + { + base.Destroy(); + m_currentTemplate = null; + m_blendOpHelper = null; + m_alphaToMaskHelper = null; + m_cullModeHelper = null; + m_colorMaskHelper.Destroy(); + m_colorMaskHelper = null; + m_stencilBufferHelper.Destroy(); + m_stencilBufferHelper = null; + m_tagsHelper.Destroy(); + m_tagsHelper = null; + + } + + public TemplateData CurrentTemplate { get { return m_currentTemplate; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs.meta new file mode 100644 index 0000000..b17058f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8bbd856408a816448a2686501df37397 +timeCreated: 1493905112 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs new file mode 100644 index 0000000..ec2cefb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs @@ -0,0 +1,55 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public class TemplateMenuItems + { + [MenuItem( "Assets/Create/Amplify Shader/Legacy/Unlit", false, 85 )] + public static void ApplyTemplateLegacyUnlit() + { + AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "0770190933193b94aaa3065e307002fa" ); + } + [MenuItem( "Assets/Create/Amplify Shader/Legacy/Post Process", false, 85 )] + public static void ApplyTemplateLegacyPostProcess() + { + AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "c71b220b631b6344493ea3cf87110c93" ); + } + [MenuItem( "Assets/Create/Amplify Shader/Deprecated/Legacy/Default Unlit", false, 85 )] + public static void ApplyTemplateDeprecatedLegacyDefaultUnlit() + { + AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "6e114a916ca3e4b4bb51972669d463bf" ); + } + [MenuItem( "Assets/Create/Amplify Shader/Legacy/Default UI", false, 85 )] + public static void ApplyTemplateLegacyDefaultUI() + { + AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "5056123faa0c79b47ab6ad7e8bf059a4" ); + } + [MenuItem( "Assets/Create/Amplify Shader/Legacy/Unlit Lightmap", false, 85 )] + public static void ApplyTemplateLegacyUnlitLightmap() + { + AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "899e609c083c74c4ca567477c39edef0" ); + } + [MenuItem( "Assets/Create/Amplify Shader/Legacy/Default Sprites", false, 85 )] + public static void ApplyTemplateLegacyDefaultSprites() + { + AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "0f8ba0101102bb14ebf021ddadce9b49" ); + } + [MenuItem( "Assets/Create/Amplify Shader/Legacy/Particles Alpha Blended", false, 85 )] + public static void ApplyTemplateLegacyParticlesAlphaBlended() + { + AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "0b6a9f8b4f707c74ca64c0be8e590de0" ); + } + [MenuItem( "Assets/Create/Amplify Shader/Legacy/Multi Pass Unlit", false, 85 )] + public static void ApplyTemplateLegacyMultiPassUnlit() + { + AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "e1de45c0d41f68c41b2cc20c8b9c05ef" ); + } + [MenuItem( "Assets/Create/Amplify Shader/Legacy/Lit", false, 85 )] + public static void ApplyTemplateLegacyLit() + { + AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "ed95fe726fd7b4644bb42f4d1ddd2bcd" ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs.meta new file mode 100644 index 0000000..69a390b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: da0b931bd234a1e43b65f684d4b59bfb +timeCreated: 1496736284 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs new file mode 100644 index 0000000..1d0bd3b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs @@ -0,0 +1,788 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + + [Serializable] + public class TemplateModulesHelper + { + [SerializeField] + internal bool Foldout = false; + + private bool m_isDirty = false; + + [SerializeField] + private TemplatesBlendModule m_blendOpHelper = new TemplatesBlendModule(); + + [SerializeField] + private TemplatesBlendModule m_blendOpHelper1 = new TemplatesBlendModule(); + + [SerializeField] + private TemplatesBlendModule m_blendOpHelper2 = new TemplatesBlendModule(); + + [SerializeField] + private TemplatesBlendModule m_blendOpHelper3 = new TemplatesBlendModule(); + + [SerializeField] + private TemplateAlphaToMaskModule m_alphaToMaskHelper = new TemplateAlphaToMaskModule(); + + [SerializeField] + private TemplateCullModeModule m_cullModeHelper = new TemplateCullModeModule(); + + [SerializeField] + private TemplateColorMaskModule m_colorMaskHelper = new TemplateColorMaskModule(); + + [SerializeField] + private TemplateColorMaskModule m_colorMaskHelper1 = new TemplateColorMaskModule(); + + [SerializeField] + private TemplateColorMaskModule m_colorMaskHelper2 = new TemplateColorMaskModule(); + + [SerializeField] + private TemplateColorMaskModule m_colorMaskHelper3 = new TemplateColorMaskModule(); + + [SerializeField] + private TemplatesStencilBufferModule m_stencilBufferHelper = new TemplatesStencilBufferModule(); + + [SerializeField] + private TemplateDepthModule m_depthOphelper = new TemplateDepthModule(); + + [SerializeField] + private TemplateTagsModule m_tagsHelper = new TemplateTagsModule(); + + [SerializeField] + private TemplateShaderModelModule m_shaderModelHelper = new TemplateShaderModelModule(); + + [SerializeField] + private TemplateAdditionalIncludesHelper m_additionalIncludes = new TemplateAdditionalIncludesHelper(); + + [SerializeField] + private TemplateAdditionalDefinesHelper m_additionalDefines = new TemplateAdditionalDefinesHelper(); + + [SerializeField] + private TemplateAdditionalPragmasHelper m_additionalPragmas = new TemplateAdditionalPragmasHelper(); + + [SerializeField] + private TemplateAdditionalDirectivesHelper m_additionalDirectives = new TemplateAdditionalDirectivesHelper(" Additional Directives"); + + [SerializeField] + private RenderingPlatformOpHelper m_renderingPlatforms = new RenderingPlatformOpHelper(); + + [SerializeField] + private bool m_hasValidData = false; + + [SerializeField] + private bool m_allModulesMode = false; + + public void CopyFrom( TemplateModulesHelper other ) + { + m_allModulesMode = other.AllModulesMode; + + if( other.BlendOpHelper.IsDirty ) + { + m_blendOpHelper.CopyFrom( other.BlendOpHelper, true ); + } + + if( other.BlendOpHelper1.IsDirty ) + { + m_blendOpHelper1.CopyFrom( other.BlendOpHelper1, true ); + } + + if( other.BlendOpHelper2.IsDirty ) + { + m_blendOpHelper2.CopyFrom( other.BlendOpHelper2, true ); + } + + if( other.BlendOpHelper3.IsDirty ) + { + m_blendOpHelper3.CopyFrom( other.BlendOpHelper3, true ); + } + + if( other.AlphaToMaskHelper.IsDirty ) + { + m_alphaToMaskHelper.CopyFrom( other.AlphaToMaskHelper, true ); + } + + if( other.CullModeHelper.IsDirty ) + { + m_cullModeHelper.CopyFrom( other.CullModeHelper , true ); + } + + if( other.ColorMaskHelper.IsDirty ) + { + m_colorMaskHelper.CopyFrom( other.ColorMaskHelper , true); + } + + if( other.ColorMaskHelper1.IsDirty ) + { + m_colorMaskHelper1.CopyFrom( other.ColorMaskHelper1, true ); + } + + if( other.ColorMaskHelper2.IsDirty ) + { + m_colorMaskHelper2.CopyFrom( other.ColorMaskHelper2, true ); + } + + if( other.ColorMaskHelper3.IsDirty ) + { + m_colorMaskHelper3.CopyFrom( other.ColorMaskHelper3, true ); + } + + if( other.StencilBufferHelper.IsDirty ) + { + m_stencilBufferHelper.CopyFrom( other.StencilBufferHelper,true ); + } + + if( other.DepthOphelper.IsDirty ) + { + m_depthOphelper.CopyFrom( other.DepthOphelper,true ); + } + + if( other.TagsHelper.IsDirty ) + { + m_tagsHelper.CopyFrom( other.TagsHelper ); + } + + if( other.ShaderModelHelper.IsDirty ) + { + m_shaderModelHelper.CopyFrom( other.ShaderModelHelper, true ); + } + } + + public void SyncWith( TemplateModulesHelper other ) + { + + if( m_blendOpHelper.ValidData && other.BlendOpHelper.ValidData ) + { + m_blendOpHelper.CopyFrom( other.BlendOpHelper, false ); + } + + if( m_blendOpHelper1.ValidData && other.BlendOpHelper1.ValidData ) + { + m_blendOpHelper1.CopyFrom( other.BlendOpHelper1, false ); + } + + if( m_blendOpHelper2.ValidData && other.BlendOpHelper2.ValidData ) + { + m_blendOpHelper2.CopyFrom( other.BlendOpHelper2, false ); + } + + if( m_blendOpHelper3.ValidData && other.BlendOpHelper3.ValidData ) + { + m_blendOpHelper3.CopyFrom( other.BlendOpHelper3, false ); + } + + if( m_alphaToMaskHelper.ValidData && other.AlphaToMaskHelper.ValidData ) + { + m_alphaToMaskHelper.CopyFrom( other.AlphaToMaskHelper, false ); + } + + if( m_cullModeHelper.ValidData && other.CullModeHelper.ValidData ) + { + m_cullModeHelper.CopyFrom( other.CullModeHelper, false ); + } + + if( m_colorMaskHelper.ValidData && other.ColorMaskHelper.ValidData ) + { + m_colorMaskHelper.CopyFrom( other.ColorMaskHelper , false ); + } + + if( m_colorMaskHelper1.ValidData && other.ColorMaskHelper1.ValidData ) + { + m_colorMaskHelper1.CopyFrom( other.ColorMaskHelper1, false ); + } + + if( m_colorMaskHelper2.ValidData && other.ColorMaskHelper2.ValidData ) + { + m_colorMaskHelper2.CopyFrom( other.ColorMaskHelper2, false ); + } + + if( m_colorMaskHelper3.ValidData && other.ColorMaskHelper3.ValidData ) + { + m_colorMaskHelper3.CopyFrom( other.ColorMaskHelper3, false ); + } + + if( m_stencilBufferHelper.ValidData && other.StencilBufferHelper.ValidData ) + { + m_stencilBufferHelper.CopyFrom( other.StencilBufferHelper, false ); + } + + if( m_depthOphelper.ValidData && other.DepthOphelper.ValidData ) + { + m_depthOphelper.CopyFrom( other.DepthOphelper, false ); + } + + if( m_shaderModelHelper.ValidData && other.ShaderModelHelper.ValidData ) + { + m_shaderModelHelper.CopyFrom( other.ShaderModelHelper , false); + } + } + + public void FetchDataFromTemplate( TemplateModulesData module ) + { + m_allModulesMode = module.AllModulesMode; + + if( module.PragmaTag.IsValid ) + { + m_hasValidData = true; + //m_additionalPragmas.IsValid = true; + //m_additionalPragmas.FillNativeItems( module.IncludePragmaContainer.PragmasList ); + + //m_additionalIncludes.IsValid = true; + //m_additionalIncludes.FillNativeItems( module.IncludePragmaContainer.IncludesList ); + + //m_additionalDefines.IsValid = true; + //m_additionalDefines.FillNativeItems( module.IncludePragmaContainer.DefinesList ); + + m_additionalDirectives.FillNativeItems( module.IncludePragmaContainer.NativeDirectivesList ); + m_additionalDirectives.IsValid = true; + } + else + { + //m_additionalPragmas.IsValid = false; + //m_additionalIncludes.IsValid = false; + //m_additionalDefines.IsValid = false; + m_additionalDirectives.IsValid = false; + } + + m_blendOpHelper.ConfigureFromTemplateData( module.BlendData ); + if( module.BlendData.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_blendOpHelper1.ConfigureFromTemplateData( module.BlendData1 ); + if( module.BlendData1.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_blendOpHelper2.ConfigureFromTemplateData( module.BlendData2 ); + if( module.BlendData2.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_blendOpHelper3.ConfigureFromTemplateData( module.BlendData3 ); + if( module.BlendData3.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_alphaToMaskHelper.ConfigureFromTemplateData( module.AlphaToMaskData ); + if( module.AlphaToMaskData.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_cullModeHelper.ConfigureFromTemplateData( module.CullModeData ); + if( module.CullModeData.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_colorMaskHelper.ConfigureFromTemplateData( module.ColorMaskData ); + if( module.ColorMaskData.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_colorMaskHelper1.ConfigureFromTemplateData( module.ColorMaskData1 ); + if( module.ColorMaskData1.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_colorMaskHelper2.ConfigureFromTemplateData( module.ColorMaskData2 ); + if( module.ColorMaskData2.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_colorMaskHelper3.ConfigureFromTemplateData( module.ColorMaskData3 ); + if( module.ColorMaskData3.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_stencilBufferHelper.ConfigureFromTemplateData( module.StencilData ); + if( module.StencilData.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_depthOphelper.ConfigureFromTemplateData( module.DepthData ); + if( module.DepthData.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_tagsHelper.ConfigureFromTemplateData( module.TagData ); + if( module.TagData.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + m_shaderModelHelper.ConfigureFromTemplateData( module.ShaderModel ); + if( module.ShaderModel.DataCheck == TemplateDataCheck.Valid ) + { + m_hasValidData = true; + } + + + if( module.RenderPlatformHelper.IsValid ) + { + m_renderingPlatforms.SetupFromTemplate( module.RenderPlatformHelper ); + m_hasValidData = true; + } + + } + + public void OnLogicUpdate( TemplateModulesData currentModule ) + { + if( currentModule.TagData.DataCheck == TemplateDataCheck.Valid ) + m_tagsHelper.OnLogicUpdate(); + } + + public void Draw( ParentNode owner, TemplateModulesData currentModule , TemplateModulesHelper parent = null ) + { + if( currentModule.ShaderModel.DataCheck == TemplateDataCheck.Valid ) + m_shaderModelHelper.Draw( owner ); + + m_isDirty = m_shaderModelHelper.IsDirty; + + if( currentModule.CullModeData.DataCheck == TemplateDataCheck.Valid ) + m_cullModeHelper.Draw( owner ); + + m_isDirty = m_isDirty || m_cullModeHelper.IsDirty; + + if( currentModule.ColorMaskData.DataCheck == TemplateDataCheck.Valid ) + m_colorMaskHelper.Draw( owner ); + + m_isDirty = m_isDirty || m_colorMaskHelper.IsDirty; + + if( currentModule.ColorMaskData1.DataCheck == TemplateDataCheck.Valid ) + m_colorMaskHelper1.Draw( owner ); + + m_isDirty = m_isDirty || m_colorMaskHelper1.IsDirty; + + if( currentModule.ColorMaskData2.DataCheck == TemplateDataCheck.Valid ) + m_colorMaskHelper2.Draw( owner ); + + m_isDirty = m_isDirty || m_colorMaskHelper2.IsDirty; + + if( currentModule.ColorMaskData3.DataCheck == TemplateDataCheck.Valid ) + m_colorMaskHelper3.Draw( owner ); + + m_isDirty = m_isDirty || m_colorMaskHelper3.IsDirty; + + if( currentModule.AlphaToMaskData.DataCheck == TemplateDataCheck.Valid ) + m_alphaToMaskHelper.Draw( owner ); + + m_isDirty = m_isDirty || m_alphaToMaskHelper.IsDirty; + + if( currentModule.DepthData.DataCheck == TemplateDataCheck.Valid ) + m_depthOphelper.Draw( owner, false ); + + m_isDirty = m_isDirty || m_depthOphelper.IsDirty; + + if( currentModule.BlendData.DataCheck == TemplateDataCheck.Valid ) + m_blendOpHelper.Draw( owner, false ); + + m_isDirty = m_isDirty || m_blendOpHelper.IsDirty; + + if( currentModule.BlendData1.DataCheck == TemplateDataCheck.Valid ) + m_blendOpHelper1.Draw( owner, false ); + + m_isDirty = m_isDirty || m_blendOpHelper1.IsDirty; + + if( currentModule.BlendData2.DataCheck == TemplateDataCheck.Valid ) + m_blendOpHelper2.Draw( owner, false ); + + m_isDirty = m_isDirty || m_blendOpHelper2.IsDirty; + + if( currentModule.BlendData3.DataCheck == TemplateDataCheck.Valid ) + m_blendOpHelper3.Draw( owner, false ); + + m_isDirty = m_isDirty || m_blendOpHelper3.IsDirty; + + + if( currentModule.StencilData.DataCheck == TemplateDataCheck.Valid ) + { + CullMode cullMode = CullMode.Back; + if( currentModule.CullModeData.DataCheck == TemplateDataCheck.Valid ) + { + cullMode = m_cullModeHelper.CurrentCullMode; + } + else if( parent != null && parent.CullModeHelper.ValidData ) + { + cullMode = parent.CullModeHelper.CurrentCullMode; + } + m_stencilBufferHelper.Draw( owner, cullMode, false ); + } + + m_isDirty = m_isDirty || m_stencilBufferHelper.IsDirty; + + if( currentModule.TagData.DataCheck == TemplateDataCheck.Valid ) + m_tagsHelper.Draw( owner, false ); + + m_isDirty = m_isDirty || m_tagsHelper.IsDirty; + + if( currentModule.PragmaTag.IsValid ) + { + //m_additionalDefines.Draw( owner ); + //m_additionalIncludes.Draw( owner ); + //m_additionalPragmas.Draw( owner ); + m_additionalDirectives.Draw( owner , false); + } + + if( currentModule.RenderPlatformHelper.IsValid ) + { + m_renderingPlatforms.DrawNested( owner ); + } + + m_isDirty = m_isDirty || + //m_additionalDefines.IsDirty || + //m_additionalIncludes.IsDirty || + //m_additionalPragmas.IsDirty || + m_additionalDirectives.IsDirty; + } + + public void Destroy() + { + m_shaderModelHelper = null; + m_blendOpHelper = null; + m_blendOpHelper1 = null; + m_blendOpHelper2 = null; + m_blendOpHelper3 = null; + m_cullModeHelper = null; + m_alphaToMaskHelper = null; + m_colorMaskHelper.Destroy(); + m_colorMaskHelper = null; + m_colorMaskHelper1.Destroy(); + m_colorMaskHelper1 = null; + m_colorMaskHelper2.Destroy(); + m_colorMaskHelper2 = null; + m_colorMaskHelper3.Destroy(); + m_colorMaskHelper3 = null; + m_stencilBufferHelper.Destroy(); + m_stencilBufferHelper = null; + m_tagsHelper.Destroy(); + m_tagsHelper = null; + m_additionalDefines.Destroy(); + m_additionalDefines = null; + m_additionalIncludes.Destroy(); + m_additionalIncludes = null; + m_additionalPragmas.Destroy(); + m_additionalPragmas = null; + m_additionalDirectives.Destroy(); + m_additionalDirectives = null; + m_renderingPlatforms.Destroy(); + m_renderingPlatforms = null; + } + + public string GenerateAllModulesString( bool isSubShader ) + { + string moduleBody = string.Empty; + if( !ShaderModelHelper.IndependentModule ) + { + moduleBody += ShaderModelHelper.GenerateShaderData( isSubShader ) + "\n"; + } + + if( !BlendOpHelper.IndependentModule ) + { + if( BlendOpHelper.BlendModeEnabled ) + moduleBody += BlendOpHelper.CurrentBlendFactor + "\n"; + + if( BlendOpHelper.BlendOpActive ) + moduleBody += BlendOpHelper.CurrentBlendOp + "\n"; + } + + if( !AlphaToMaskHelper.IndependentModule ) + moduleBody += AlphaToMaskHelper.GenerateShaderData( isSubShader ) + "\n"; + + if( !CullModeHelper.IndependentModule ) + moduleBody += CullModeHelper.GenerateShaderData( isSubShader ) + "\n"; + + if( !ColorMaskHelper.IndependentModule ) + moduleBody += ColorMaskHelper.GenerateShaderData( isSubShader ) + "\n"; + + if( !DepthOphelper.IndependentModule ) + { + moduleBody += DepthOphelper.CurrentZWriteMode; + moduleBody += DepthOphelper.CurrentZTestMode; + if( DepthOphelper.OffsetEnabled ) + moduleBody += DepthOphelper.CurrentOffset; + } + + if( !StencilBufferHelper.IndependentModule && StencilBufferHelper.Active ) + { + CullMode cullMode = ( CullModeHelper.ValidData ) ? CullModeHelper.CurrentCullMode : CullMode.Back; + moduleBody += StencilBufferHelper.CreateStencilOp( cullMode ); + } + + return moduleBody; + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + try + { + m_blendOpHelper.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + if( UIUtils.CurrentShaderVersion() > 18103 ) + { + try + { + m_blendOpHelper1.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + try + { + m_blendOpHelper2.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + try + { + m_blendOpHelper3.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + try + { + m_alphaToMaskHelper.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + try + { + m_cullModeHelper.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + try + { + m_colorMaskHelper.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + if( UIUtils.CurrentShaderVersion() > 18103 ) + { + try + { + m_colorMaskHelper1.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + try + { + m_colorMaskHelper2.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + try + { + m_colorMaskHelper3.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + try + { + m_stencilBufferHelper.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + try + { + m_depthOphelper.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + try + { + m_tagsHelper.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + try + { + m_shaderModelHelper.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + if( UIUtils.CurrentShaderVersion() > 18910 ) + { + try + { + m_renderingPlatforms.ReadFromStringTemplate( ref index , ref nodeParams ); + } + catch(Exception e) + { + Debug.Log( e ); + } + } + + if( UIUtils.CurrentShaderVersion() < 15312 ) + { + try + { + m_additionalDefines.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + try + { + m_additionalPragmas.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + try + { + m_additionalIncludes.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + m_additionalDirectives.AddItems( AdditionalLineType.Include, m_additionalIncludes.ItemsList ); + m_additionalDirectives.AddItems( AdditionalLineType.Define, m_additionalDefines.ItemsList ); + m_additionalDirectives.AddItems( AdditionalLineType.Pragma, m_additionalPragmas.ItemsList ); + + } + else + { + try + { + m_additionalDirectives.ReadFromString( ref index, ref nodeParams ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + + } + + public void WriteToString( ref string nodeInfo ) + { + m_blendOpHelper.WriteToString( ref nodeInfo ); + m_blendOpHelper1.WriteToString( ref nodeInfo ); + m_blendOpHelper2.WriteToString( ref nodeInfo ); + m_blendOpHelper3.WriteToString( ref nodeInfo ); + m_alphaToMaskHelper.WriteToString( ref nodeInfo ); + m_cullModeHelper.WriteToString( ref nodeInfo ); + m_colorMaskHelper.WriteToString( ref nodeInfo ); + m_colorMaskHelper1.WriteToString( ref nodeInfo ); + m_colorMaskHelper2.WriteToString( ref nodeInfo ); + m_colorMaskHelper3.WriteToString( ref nodeInfo ); + m_stencilBufferHelper.WriteToString( ref nodeInfo ); + m_depthOphelper.WriteToString( ref nodeInfo ); + m_tagsHelper.WriteToString( ref nodeInfo ); + m_shaderModelHelper.WriteToString( ref nodeInfo ); + m_renderingPlatforms.WriteToStringTemplate( ref nodeInfo ); + + //m_additionalDefines.WriteToString( ref nodeInfo ); + //m_additionalPragmas.WriteToString( ref nodeInfo ); + //m_additionalIncludes.WriteToString( ref nodeInfo ); + + m_additionalDirectives.WriteToString( ref nodeInfo ); + } + + public TemplatesBlendModule BlendOpHelper { get { return m_blendOpHelper; } } + public TemplatesBlendModule BlendOpHelper1 { get { return m_blendOpHelper1; } } + public TemplatesBlendModule BlendOpHelper2 { get { return m_blendOpHelper2; } } + public TemplatesBlendModule BlendOpHelper3 { get { return m_blendOpHelper3; } } + public TemplateAlphaToMaskModule AlphaToMaskHelper { get { return m_alphaToMaskHelper; } } + public TemplateCullModeModule CullModeHelper { get { return m_cullModeHelper; } } + public TemplateColorMaskModule ColorMaskHelper { get { return m_colorMaskHelper; } } + public TemplateColorMaskModule ColorMaskHelper1 { get { return m_colorMaskHelper1; } } + public TemplateColorMaskModule ColorMaskHelper2 { get { return m_colorMaskHelper2; } } + public TemplateColorMaskModule ColorMaskHelper3 { get { return m_colorMaskHelper3; } } + public TemplatesStencilBufferModule StencilBufferHelper { get { return m_stencilBufferHelper; } } + public TemplateDepthModule DepthOphelper { get { return m_depthOphelper; } } + public TemplateTagsModule TagsHelper { get { return m_tagsHelper; } } + public TemplateShaderModelModule ShaderModelHelper { get { return m_shaderModelHelper; } } + //public TemplateAdditionalIncludesHelper AdditionalIncludes { get { return m_additionalIncludes; } } + //public TemplateAdditionalDefinesHelper AdditionalDefines { get { return m_additionalDefines; } } + //public TemplateAdditionalPragmasHelper AdditionalPragmas { get { return m_additionalPragmas; } } + public TemplateAdditionalDirectivesHelper AdditionalDirectives { get { return m_additionalDirectives; } } + public RenderingPlatformOpHelper RenderingPlatforms { get { return m_renderingPlatforms; } } + public bool AllModulesMode { get { return m_allModulesMode; } } + public bool HasValidData { get { return m_hasValidData; } } + public bool IsDirty + { + get { return m_isDirty; } + set + { + m_isDirty = value; + if( !value ) + { + m_blendOpHelper.IsDirty = false; + m_blendOpHelper1.IsDirty = false; + m_blendOpHelper2.IsDirty = false; + m_blendOpHelper3.IsDirty = false; + m_cullModeHelper.IsDirty = false; + m_alphaToMaskHelper.IsDirty = false; + m_colorMaskHelper.IsDirty = false; + m_colorMaskHelper1.IsDirty = false; + m_colorMaskHelper2.IsDirty = false; + m_colorMaskHelper3.IsDirty = false; + m_stencilBufferHelper.IsDirty = false; + m_tagsHelper.IsDirty = false; + m_shaderModelHelper.IsDirty = false; + //m_additionalDefines.IsDirty = false; + //m_additionalPragmas.IsDirty = false; + //m_additionalIncludes.IsDirty = false; + m_additionalDirectives.IsDirty = false; + } + } + } + // public bool Foldout { get { return m_foldout; } set { m_foldout = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs.meta new file mode 100644 index 0000000..95ebce9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 144af5a201bd97542bf3a483976759db +timeCreated: 1518705839 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs new file mode 100644 index 0000000..a8d4e23 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs @@ -0,0 +1,82 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateModuleParent + { + private const string UnreadableDataMessagePrefix = "Unreadable data on Module "; + protected string m_unreadableMessage; + + [SerializeField] + protected bool m_validData = false; + + [SerializeField] + protected bool m_isDirty = false; + + [SerializeField] + protected string m_moduleName = string.Empty; + + //[SerializeField] + //protected bool m_foldoutValue = false; + + [SerializeField] + protected bool m_independentModule = true; + + [SerializeField] + private bool m_customEdited = false; + + public TemplateModuleParent( string moduleName ) { m_moduleName = moduleName; m_unreadableMessage = UnreadableDataMessagePrefix + moduleName; } + public virtual void Draw( UndoParentNode owner , bool style = true) { } + public virtual void ReadFromString( ref uint index, ref string[] nodeParams ) + { + if( UIUtils.CurrentShaderVersion() > 18805 ) + { + CustomEdited = Convert.ToBoolean( nodeParams[ index++ ] ); + } + } + + public virtual void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_customEdited ); + } + + public virtual string GenerateShaderData( bool isSubShader ) { return string.Empty; } + public virtual void Destroy() { } + public bool ValidData { get { return m_validData; } } + public bool ValidAndIndependent { get { return m_validData && m_independentModule; } } + + public virtual void ShowUnreadableDataMessage( ParentNode owner ) + { + ShowUnreadableDataMessage(); + } + + public virtual void ShowUnreadableDataMessage() + { + EditorGUILayout.HelpBox( m_unreadableMessage, MessageType.Info ); + } + + public bool IsDirty + { + get { return m_isDirty; } + set { m_isDirty = value; } + } + + public bool IndependentModule + { + get { return m_independentModule; } + set { m_independentModule = value; } + } + + public bool CustomEdited + { + get { return m_customEdited; } + set { m_customEdited = value; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs.meta new file mode 100644 index 0000000..a0a1d88 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3aaabf1f5cb06414a8be17a89487e10f +timeCreated: 1511185965 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs new file mode 100644 index 0000000..2ee10ff --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs @@ -0,0 +1,819 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Text.RegularExpressions; +using System.Collections.Generic; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public enum TemplateModuleDataType + { + ModuleShaderModel, + ModuleBlendMode, + ModuleBlendMode1, + ModuleBlendMode2, + ModuleBlendMode3, + ModuleBlendOp, + ModuleBlendOp1, + ModuleBlendOp2, + ModuleBlendOp3, + ModuleAlphaToMask, + ModuleCullMode, + ModuleColorMask, + ModuleColorMask1, + ModuleColorMask2, + ModuleColorMask3, + ModuleStencil, + ModuleZwrite, + ModuleZTest, + ModuleZOffset, + ModuleTag, + ModuleGlobals, + ModuleSRPBatcher, + ModuleFunctions, + ModulePragma, + ModulePragmaBefore, + ModulePass, + ModuleInputVert, + ModuleInputFrag, + PassVertexFunction, + PassFragmentFunction, + PassVertexData, + PassInterpolatorData, + PassNameData, + AllModules, + VControl, + ControlData, + DomainData, + ModuleRenderPlatforms + //EndPass + } + + public enum TemplateSRPType + { + BuiltIn, + HD, + Lightweight + } + + [Serializable] + public class TemplateModulesData + { + [SerializeField] + TemplateRenderPlatformHelper m_renderPlatformHelper; + + [SerializeField] + private TemplateBlendData m_blendData = new TemplateBlendData(); + + [SerializeField] + private TemplateBlendData m_blendData1 = new TemplateBlendData(); + + [SerializeField] + private TemplateBlendData m_blendData2 = new TemplateBlendData(); + + [SerializeField] + private TemplateBlendData m_blendData3 = new TemplateBlendData(); + + [SerializeField] + private TemplateAlphaToMaskData m_alphaToMaskData = new TemplateAlphaToMaskData(); + + [SerializeField] + private TemplateCullModeData m_cullModeData = new TemplateCullModeData(); + + [SerializeField] + private TemplateColorMaskData m_colorMaskData = new TemplateColorMaskData(); + + [SerializeField] + private TemplateColorMaskData m_colorMaskData1 = new TemplateColorMaskData(); + + [SerializeField] + private TemplateColorMaskData m_colorMaskData2 = new TemplateColorMaskData(); + + [SerializeField] + private TemplateColorMaskData m_colorMaskData3 = new TemplateColorMaskData(); + + [SerializeField] + private TemplateStencilData m_stencilData = new TemplateStencilData(); + + [SerializeField] + private TemplateDepthData m_depthData = new TemplateDepthData(); + + [SerializeField] + private TemplateTagsModuleData m_tagData = new TemplateTagsModuleData(); + + [SerializeField] + private TemplateTagData m_globalsTag = new TemplateTagData( TemplatesManager.TemplateGlobalsTag, true ); + + [SerializeField] + private TemplateTagData m_srpBatcherTag = new TemplateTagData( TemplatesManager.TemplateSRPBatcherTag, true ); + + [SerializeField] + private TemplateTagData m_allModulesTag = new TemplateTagData( TemplatesManager.TemplateAllModulesTag, true ); + + [SerializeField] + private TemplateTagData m_functionsTag = new TemplateTagData( TemplatesManager.TemplateFunctionsTag, true ); + + [SerializeField] + private TemplateTagData m_pragmaTag = new TemplateTagData( TemplatesManager.TemplatePragmaTag, true ); + + [SerializeField] + private TemplateTagData m_pragmaBeforeTag = new TemplateTagData( TemplatesManager.TemplatePragmaBeforeTag, true ); + + [SerializeField] + private TemplateTagData m_passTag = new TemplateTagData( TemplatesManager.TemplatePassTag, true ); + + [SerializeField] + private TemplateTagData m_inputsVertTag = new TemplateTagData( TemplatesManager.TemplateInputsVertParamsTag, false ); + + [SerializeField] + private TemplateTagData m_inputsFragTag = new TemplateTagData( TemplatesManager.TemplateInputsFragParamsTag, false ); + + [SerializeField] + private TemplateShaderModelData m_shaderModel = new TemplateShaderModelData(); + + [SerializeField] + private TemplateSRPType m_srpType = TemplateSRPType.BuiltIn; + + [SerializeField] + private bool m_srpIsPBR = false; + + [SerializeField] + private string m_uniquePrefix; + + [SerializeField] + private TemplateIncludePragmaContainter m_includePragmaContainer = new TemplateIncludePragmaContainter(); + + [SerializeField] + private bool m_allModulesMode = false; + + [SerializeField] + private string m_passUniqueName = string.Empty; + + public void Destroy() + { + m_renderPlatformHelper.Destroy(); + m_renderPlatformHelper = null; + + m_blendData = null; + m_blendData1 = null; + m_blendData2 = null; + m_blendData3 = null; + m_alphaToMaskData = null; + m_cullModeData = null; + m_colorMaskData = null; + m_colorMaskData1 = null; + m_colorMaskData2 = null; + m_colorMaskData3 = null; + m_stencilData = null; + m_depthData = null; + m_tagData.Destroy(); + m_tagData = null; + m_globalsTag = null; + m_srpBatcherTag = null; + m_allModulesTag = null; + m_functionsTag = null; + m_pragmaTag = null; + m_pragmaBeforeTag = null; + m_passTag = null; + m_inputsVertTag = null; + m_inputsFragTag = null; + m_includePragmaContainer.Destroy(); + m_includePragmaContainer = null; + } + + public void ConfigureCommonTag( TemplateTagData tagData, TemplatePropertyContainer propertyContainer, TemplateIdManager idManager, string uniquePrefix, int offsetIdx, string subBody ) + { + int id = subBody.IndexOf( tagData.Id ); + if ( id >= 0 ) + { + tagData.StartIdx = offsetIdx + id; + idManager.RegisterId( tagData.StartIdx, uniquePrefix + tagData.Id, tagData.Id ); + propertyContainer.AddId( subBody, tagData.Id, tagData.SearchIndentation ); + } + } + + public TemplateModulesData( TemplateOptionsContainer optionsContainer, TemplateIdManager idManager, TemplatePropertyContainer propertyContainer, string uniquePrefix, int offsetIdx, string subBody, bool isSubShader ) + { + if ( string.IsNullOrEmpty( subBody ) ) + return; + + m_uniquePrefix = uniquePrefix; + + //RENDERING PLATFORMS + m_renderPlatformHelper = new TemplateRenderPlatformHelper(); + TemplateHelperFunctions.FillRenderingPlatform( m_renderPlatformHelper , subBody ); + if( m_renderPlatformHelper.IsValid ) + { + m_renderPlatformHelper.Index = offsetIdx + m_renderPlatformHelper.Index; + idManager.RegisterId( m_renderPlatformHelper.Index , uniquePrefix + m_renderPlatformHelper.ID , m_renderPlatformHelper.ID ); + } + + //PRAGMAS AND INCLUDES + TemplateHelperFunctions.CreatePragmaIncludeList( subBody, m_includePragmaContainer ); + + //COMMON TAGS + ConfigureCommonTag( m_globalsTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody ); + ConfigureCommonTag( m_srpBatcherTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody ); + ConfigureCommonTag( m_functionsTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody ); + ConfigureCommonTag( m_pragmaTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody ); + ConfigureCommonTag( m_pragmaBeforeTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody ); + if( !TemplateHelperFunctions.GetPassUniqueId( m_passTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody, ref m_passUniqueName ) ) + { + ConfigureCommonTag( m_passTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody ); + } + ConfigureCommonTag( m_inputsVertTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody ); + ConfigureCommonTag( m_inputsFragTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody ); + + // If Options are enabled then remove them so they won't influence Regex matches + if( optionsContainer.Enabled && optionsContainer.EndIndex > 0 ) + { + offsetIdx += optionsContainer.EndIndex; + subBody = subBody.Substring( optionsContainer.EndIndex ); + } + //BlEND MODE + { + Match blendModeMatch = Regex.Match( subBody, TemplateHelperFunctions.BlendModePattern1 ); + if( blendModeMatch.Success ) + { + int blendModeIdx = blendModeMatch.Index; + int end = blendModeMatch.Length + blendModeIdx; + string blendParams = subBody.Substring( blendModeIdx, end - blendModeIdx ); + m_blendData1.BlendModeId = blendParams; + m_blendData1.BlendModeStartIndex = offsetIdx + blendModeIdx; + idManager.RegisterId( m_blendData1.BlendModeStartIndex, uniquePrefix + m_blendData1.BlendModeId, m_blendData1.BlendModeId ); + + TemplateHelperFunctions.CreateBlendMode( blendParams, ref m_blendData1, TemplateHelperFunctions.BlendModePattern1 ); + if( m_blendData1.ValidBlendMode ) + { + propertyContainer.AddId( subBody, blendParams, false ); + } + } + } + { + Match blendModeMatch = Regex.Match( subBody, TemplateHelperFunctions.BlendModePattern2 ); + if( blendModeMatch.Success ) + { + int blendModeIdx = blendModeMatch.Index; + int end = blendModeMatch.Length + blendModeIdx; + string blendParams = subBody.Substring( blendModeIdx, end - blendModeIdx ); + m_blendData2.BlendModeId = blendParams; + m_blendData2.BlendModeStartIndex = offsetIdx + blendModeIdx; + idManager.RegisterId( m_blendData2.BlendModeStartIndex, uniquePrefix + m_blendData2.BlendModeId, m_blendData2.BlendModeId ); + + TemplateHelperFunctions.CreateBlendMode( blendParams, ref m_blendData2, TemplateHelperFunctions.BlendModePattern2 ); + if( m_blendData2.ValidBlendMode ) + { + propertyContainer.AddId( subBody, blendParams, false ); + } + } + } + { + Match blendModeMatch = Regex.Match( subBody, TemplateHelperFunctions.BlendModePattern3 ); + if( blendModeMatch.Success ) + { + int blendModeIdx = blendModeMatch.Index; + int end = blendModeMatch.Length + blendModeIdx; + string blendParams = subBody.Substring( blendModeIdx, end - blendModeIdx ); + m_blendData3.BlendModeId = blendParams; + m_blendData3.BlendModeStartIndex = offsetIdx + blendModeIdx; + idManager.RegisterId( m_blendData3.BlendModeStartIndex, uniquePrefix + m_blendData3.BlendModeId, m_blendData3.BlendModeId ); + + TemplateHelperFunctions.CreateBlendMode( blendParams, ref m_blendData3, TemplateHelperFunctions.BlendModePattern3 ); + if( m_blendData3.ValidBlendMode ) + { + propertyContainer.AddId( subBody, blendParams, false ); + } + } + } + { + string pattern = TemplateHelperFunctions.BlendModePattern; + Match blendModeMatch = Regex.Match( subBody, pattern ); + if( !blendModeMatch.Success && !m_blendData1.ValidBlendMode && !m_blendData2.ValidBlendMode && !m_blendData3.ValidBlendMode ) + { + pattern = TemplateHelperFunctions.BlendModePatternFirst; + blendModeMatch = Regex.Match( subBody, pattern ); + } + if( blendModeMatch.Success ) + { + int blendModeIdx = blendModeMatch.Index; + int end = blendModeMatch.Length + blendModeIdx; + string blendParams = subBody.Substring( blendModeIdx, end - blendModeIdx ); + m_blendData.BlendModeId = blendParams; + m_blendData.BlendModeStartIndex = offsetIdx + blendModeIdx; + idManager.RegisterId( m_blendData.BlendModeStartIndex, uniquePrefix + m_blendData.BlendModeId, m_blendData.BlendModeId ); + + TemplateHelperFunctions.CreateBlendMode( blendParams, ref m_blendData, pattern ); + if( m_blendData.ValidBlendMode ) + { + propertyContainer.AddId( subBody, blendParams, false ); + } + + } + } + //BLEND OP + { + Match blendOpMatch = Regex.Match( subBody, TemplateHelperFunctions.BlendOpPattern1 ); + if( blendOpMatch.Success ) + { + int blendOpIdx = blendOpMatch.Index; + int end = blendOpMatch.Length + blendOpIdx; + string blendOpParams = subBody.Substring( blendOpIdx, end - blendOpIdx ); + m_blendData1.BlendOpId = blendOpParams; + m_blendData1.BlendOpStartIndex = offsetIdx + blendOpIdx; + idManager.RegisterId( m_blendData1.BlendOpStartIndex, uniquePrefix + m_blendData1.BlendOpId, m_blendData1.BlendOpId ); + TemplateHelperFunctions.CreateBlendOp( blendOpParams, ref m_blendData1, TemplateHelperFunctions.BlendOpPattern1 ); + if( m_blendData1.ValidBlendOp ) + { + propertyContainer.AddId( subBody, blendOpParams, false ); + } + } + + m_blendData1.DataCheck = ( m_blendData1.ValidBlendMode || m_blendData1.ValidBlendOp ) ? TemplateDataCheck.Valid : TemplateDataCheck.Invalid; + } + { + Match blendOpMatch = Regex.Match( subBody, TemplateHelperFunctions.BlendOpPattern2 ); + if( blendOpMatch.Success ) + { + int blendOpIdx = blendOpMatch.Index; + int end = blendOpMatch.Length + blendOpIdx; + string blendOpParams = subBody.Substring( blendOpIdx, end - blendOpIdx ); + m_blendData2.BlendOpId = blendOpParams; + m_blendData2.BlendOpStartIndex = offsetIdx + blendOpIdx; + idManager.RegisterId( m_blendData2.BlendOpStartIndex, uniquePrefix + m_blendData2.BlendOpId, m_blendData2.BlendOpId ); + TemplateHelperFunctions.CreateBlendOp( blendOpParams, ref m_blendData2, TemplateHelperFunctions.BlendOpPattern2 ); + if( m_blendData2.ValidBlendOp ) + { + propertyContainer.AddId( subBody, blendOpParams, false ); + } + } + + m_blendData2.DataCheck = ( m_blendData2.ValidBlendMode || m_blendData2.ValidBlendOp ) ? TemplateDataCheck.Valid : TemplateDataCheck.Invalid; + } + { + Match blendOpMatch = Regex.Match( subBody, TemplateHelperFunctions.BlendOpPattern3 ); + if( blendOpMatch.Success ) + { + int blendOpIdx = blendOpMatch.Index; + int end = blendOpMatch.Length + blendOpIdx; + string blendOpParams = subBody.Substring( blendOpIdx, end - blendOpIdx ); + m_blendData3.BlendOpId = blendOpParams; + m_blendData3.BlendOpStartIndex = offsetIdx + blendOpIdx; + idManager.RegisterId( m_blendData3.BlendOpStartIndex, uniquePrefix + m_blendData3.BlendOpId, m_blendData3.BlendOpId ); + TemplateHelperFunctions.CreateBlendOp( blendOpParams, ref m_blendData3, TemplateHelperFunctions.BlendOpPattern3 ); + if( m_blendData3.ValidBlendOp ) + { + propertyContainer.AddId( subBody, blendOpParams, false ); + } + } + + m_blendData3.DataCheck = ( m_blendData3.ValidBlendMode || m_blendData3.ValidBlendOp ) ? TemplateDataCheck.Valid : TemplateDataCheck.Invalid; + } + { + string pattern = TemplateHelperFunctions.BlendOpPattern; + Match blendOpMatch = Regex.Match( subBody, pattern ); + if( !blendOpMatch.Success && !m_blendData1.ValidBlendOp && !m_blendData2.ValidBlendOp && !m_blendData3.ValidBlendOp ) + { + pattern = TemplateHelperFunctions.BlendOpPatternFirst; + blendOpMatch = Regex.Match( subBody, pattern ); + } + + if( blendOpMatch.Success ) + { + int blendOpIdx = blendOpMatch.Index; + int end = blendOpMatch.Length + blendOpIdx; + string blendOpParams = subBody.Substring( blendOpIdx, end - blendOpIdx ); + m_blendData.BlendOpId = blendOpParams; + m_blendData.BlendOpStartIndex = offsetIdx + blendOpIdx; + idManager.RegisterId( m_blendData.BlendOpStartIndex, uniquePrefix + m_blendData.BlendOpId, m_blendData.BlendOpId ); + TemplateHelperFunctions.CreateBlendOp( blendOpParams, ref m_blendData, pattern ); + if( m_blendData.ValidBlendOp ) + { + propertyContainer.AddId( subBody, blendOpParams, false ); + } + } + + m_blendData.DataCheck = ( m_blendData.ValidBlendMode || m_blendData.ValidBlendOp ) ? TemplateDataCheck.Valid : TemplateDataCheck.Invalid; + } + + //ALPHA TO MASK + { + Match alphaToMaskMatch = Regex.Match( subBody, TemplateHelperFunctions.AlphaToMaskPattern ); + if( alphaToMaskMatch.Success ) + { + int alphaIdx = alphaToMaskMatch.Index; + int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, alphaIdx ); + string alphaParams = subBody.Substring( alphaIdx, end - alphaIdx ); + m_alphaToMaskData.AlphaToMaskId = alphaParams; + m_alphaToMaskData.StartIdx = offsetIdx + alphaIdx; + idManager.RegisterId( m_alphaToMaskData.StartIdx, uniquePrefix + m_alphaToMaskData.AlphaToMaskId, m_alphaToMaskData.AlphaToMaskId ); + TemplateHelperFunctions.CreateAlphaToMask( alphaParams, ref m_alphaToMaskData ); + if( m_alphaToMaskData.DataCheck == TemplateDataCheck.Valid ) + propertyContainer.AddId( subBody, alphaParams, false, string.Empty ); + } + } + + //CULL MODE + { + Match cullMatch = Regex.Match( subBody, TemplateHelperFunctions.CullWholeWordPattern ); + if( cullMatch.Success ) + { + int cullIdx = cullMatch.Index; + int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, cullIdx ); + string cullParams = subBody.Substring( cullIdx, end - cullIdx ); + m_cullModeData.CullModeId = cullParams; + m_cullModeData.StartIdx = offsetIdx + cullIdx; + idManager.RegisterId( m_cullModeData.StartIdx, uniquePrefix + m_cullModeData.CullModeId, m_cullModeData.CullModeId ); + TemplateHelperFunctions.CreateCullMode( cullParams, ref m_cullModeData ); + if( m_cullModeData.DataCheck == TemplateDataCheck.Valid ) + propertyContainer.AddId( subBody, cullParams, false, string.Empty ); + + } + } + //COLOR MASK + { + Match colorMaskMatch = Regex.Match( subBody, TemplateHelperFunctions.ColorMask1Pattern ); + if( colorMaskMatch.Success ) + { + int colorMaskIdx = colorMaskMatch.Index; + int end = colorMaskMatch.Length + colorMaskIdx;// subBody.IndexOf( TemplatesManager.TemplateNewLine, colorMaskIdx ); + string colorMaskParams = subBody.Substring( colorMaskIdx, end - colorMaskIdx ); + m_colorMaskData1.ColorMaskId = colorMaskParams; + m_colorMaskData1.StartIdx = offsetIdx + colorMaskIdx; + idManager.RegisterId( m_colorMaskData1.StartIdx, uniquePrefix + m_colorMaskData1.ColorMaskId, m_colorMaskData1.ColorMaskId ); + TemplateHelperFunctions.CreateColorMask( colorMaskParams, ref m_colorMaskData1, TemplateHelperFunctions.ColorMask1Pattern ); + if( m_colorMaskData1.DataCheck == TemplateDataCheck.Valid ) + propertyContainer.AddId( subBody, colorMaskParams, false ); + + } + } + { + Match colorMaskMatch = Regex.Match( subBody, TemplateHelperFunctions.ColorMask2Pattern ); + if( colorMaskMatch.Success ) + { + int colorMaskIdx = colorMaskMatch.Index; + int end = colorMaskMatch.Length + colorMaskIdx;// subBody.IndexOf( TemplatesManager.TemplateNewLine, colorMaskIdx ); + string colorMaskParams = subBody.Substring( colorMaskIdx, end - colorMaskIdx ); + m_colorMaskData2.ColorMaskId = colorMaskParams; + m_colorMaskData2.StartIdx = offsetIdx + colorMaskIdx; + idManager.RegisterId( m_colorMaskData2.StartIdx, uniquePrefix + m_colorMaskData2.ColorMaskId, m_colorMaskData2.ColorMaskId ); + TemplateHelperFunctions.CreateColorMask( colorMaskParams, ref m_colorMaskData2, TemplateHelperFunctions.ColorMask2Pattern ); + if( m_colorMaskData2.DataCheck == TemplateDataCheck.Valid ) + propertyContainer.AddId( subBody, colorMaskParams, false ); + + } + } + { + Match colorMaskMatch = Regex.Match( subBody, TemplateHelperFunctions.ColorMask3Pattern ); + if( colorMaskMatch.Success ) + { + int colorMaskIdx = colorMaskMatch.Index; + int end = colorMaskMatch.Length + colorMaskIdx;// subBody.IndexOf( TemplatesManager.TemplateNewLine, colorMaskIdx ); + string colorMaskParams = subBody.Substring( colorMaskIdx, end - colorMaskIdx ); + m_colorMaskData3.ColorMaskId = colorMaskParams; + m_colorMaskData3.StartIdx = offsetIdx + colorMaskIdx; + idManager.RegisterId( m_colorMaskData3.StartIdx, uniquePrefix + m_colorMaskData3.ColorMaskId, m_colorMaskData3.ColorMaskId ); + TemplateHelperFunctions.CreateColorMask( colorMaskParams, ref m_colorMaskData3, TemplateHelperFunctions.ColorMask3Pattern ); + if( m_colorMaskData3.DataCheck == TemplateDataCheck.Valid ) + propertyContainer.AddId( subBody, colorMaskParams, false ); + + } + } + { + string pattern = TemplateHelperFunctions.ColorMaskPattern; + Match colorMaskMatch = Regex.Match( subBody, pattern ); + if( !colorMaskMatch.Success && m_colorMaskData1.DataCheck == TemplateDataCheck.Invalid && m_colorMaskData2.DataCheck == TemplateDataCheck.Invalid && m_colorMaskData3.DataCheck == TemplateDataCheck.Invalid ) + { + pattern = TemplateHelperFunctions.ColorMaskPatternFirst; + colorMaskMatch = Regex.Match( subBody, pattern ); + } + + if( colorMaskMatch.Success ) + { + int colorMaskIdx = colorMaskMatch.Index; + int end = colorMaskMatch.Length + colorMaskIdx; //subBody.IndexOf( TemplatesManager.TemplateNewLine, colorMaskIdx ); + string colorMaskParams = subBody.Substring( colorMaskIdx, end - colorMaskIdx ); + m_colorMaskData.ColorMaskId = colorMaskParams; + m_colorMaskData.StartIdx = offsetIdx + colorMaskIdx; + idManager.RegisterId( m_colorMaskData.StartIdx, uniquePrefix + m_colorMaskData.ColorMaskId, m_colorMaskData.ColorMaskId ); + TemplateHelperFunctions.CreateColorMask( colorMaskParams, ref m_colorMaskData, pattern ); + if( m_colorMaskData.DataCheck == TemplateDataCheck.Valid ) + propertyContainer.AddId( subBody, colorMaskParams, false ); + + } + } + //STENCIL + { + Match stencilMatch = Regex.Match( subBody, TemplateHelperFunctions.StencilWholeWordPattern ); + if( stencilMatch.Success ) + { + int stencilIdx = stencilMatch.Index; + int stencilEndIdx = subBody.IndexOf( "}", stencilIdx ); + if( stencilEndIdx > 0 ) + { + string stencilParams = subBody.Substring( stencilIdx, stencilEndIdx + 1 - stencilIdx ); + m_stencilData.StencilBufferId = stencilParams; + m_stencilData.StartIdx = offsetIdx + stencilIdx; + idManager.RegisterId( m_stencilData.StartIdx, uniquePrefix + m_stencilData.StencilBufferId, m_stencilData.StencilBufferId ); + TemplateHelperFunctions.CreateStencilOps( stencilParams, ref m_stencilData ); + if( m_stencilData.DataCheck == TemplateDataCheck.Valid ) + { + propertyContainer.AddId( subBody, stencilParams, true ); + } + } + } + else + { + int stencilTagIdx = subBody.IndexOf( TemplatesManager.TemplateStencilTag ); + if( stencilTagIdx > -1 ) + { + m_stencilData.SetIndependentDefault(); + m_stencilData.StencilBufferId = TemplatesManager.TemplateStencilTag; + m_stencilData.StartIdx = offsetIdx + stencilTagIdx; + idManager.RegisterId( m_stencilData.StartIdx, uniquePrefix + m_stencilData.StencilBufferId, m_stencilData.StencilBufferId ); + propertyContainer.AddId( subBody, m_stencilData.StencilBufferId, true ); + } + } + } + //ZWRITE + { + Match zWriteMatch = Regex.Match( subBody, TemplateHelperFunctions.ZWriteWholeWordPattern ); + if( zWriteMatch.Success ) + { + int zWriteOpIdx = zWriteMatch.Index; + int zWriteEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zWriteOpIdx ); + if( zWriteEndIdx > 0 ) + { + m_depthData.ZWriteModeId = subBody.Substring( zWriteOpIdx, zWriteEndIdx + 1 - zWriteOpIdx ); + m_depthData.ZWriteStartIndex = offsetIdx + zWriteOpIdx; + idManager.RegisterId( m_depthData.ZWriteStartIndex, uniquePrefix + m_depthData.ZWriteModeId, m_depthData.ZWriteModeId ); + TemplateHelperFunctions.CreateZWriteMode( m_depthData.ZWriteModeId, ref m_depthData ); + if( m_depthData.DataCheck == TemplateDataCheck.Valid ) + { + propertyContainer.AddId( subBody, m_depthData.ZWriteModeId, true ); + } + } + } + } + + //ZTEST + { + Match zTestMatch = Regex.Match( subBody, TemplateHelperFunctions.ZTestWholeWordPattern ); + if( zTestMatch.Success ) + { + int zTestOpIdx = zTestMatch.Index; + int zTestEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zTestOpIdx ); + if( zTestEndIdx > 0 ) + { + m_depthData.ZTestModeId = subBody.Substring( zTestOpIdx, zTestEndIdx + 1 - zTestOpIdx ); + m_depthData.ZTestStartIndex = offsetIdx + zTestOpIdx; + idManager.RegisterId( m_depthData.ZTestStartIndex, uniquePrefix + m_depthData.ZTestModeId, m_depthData.ZTestModeId ); + TemplateHelperFunctions.CreateZTestMode( m_depthData.ZTestModeId, ref m_depthData ); + if( m_depthData.DataCheck == TemplateDataCheck.Valid ) + { + propertyContainer.AddId( subBody, m_depthData.ZTestModeId, true ); + } + } + } + } + + //ZOFFSET + { + Match zOffsetMatch = Regex.Match( subBody, TemplateHelperFunctions.ZOffsetWholeWordPattern ); + if( zOffsetMatch.Success ) + { + int zOffsetIdx = zOffsetMatch.Index; + int zOffsetEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zOffsetIdx ); + if( zOffsetEndIdx > 0 ) + { + m_depthData.OffsetId = subBody.Substring( zOffsetIdx, zOffsetEndIdx + 1 - zOffsetIdx ); + m_depthData.OffsetStartIndex = offsetIdx + zOffsetIdx; + idManager.RegisterId( m_depthData.OffsetStartIndex, uniquePrefix + m_depthData.OffsetId, m_depthData.OffsetId ); + TemplateHelperFunctions.CreateZOffsetMode( m_depthData.OffsetId, ref m_depthData ); + if( m_depthData.DataCheck == TemplateDataCheck.Valid ) + { + propertyContainer.AddId( subBody, m_depthData.OffsetId, true ); + } + } + } + m_depthData.SetDataCheck(); + } + //TAGS + { + Match tagsMatch = Regex.Match( subBody, TemplateHelperFunctions.TagsWholeWordPattern ); + if ( tagsMatch.Success ) + { + int tagsIdx = tagsMatch.Index; + int tagsEndIdx = subBody.IndexOf( "}", tagsIdx ); + if ( tagsEndIdx > -1 ) + { + m_tagData.Reset(); + m_tagData.TagsId = subBody.Substring( tagsIdx, tagsEndIdx + 1 - tagsIdx ); + m_tagData.StartIdx = offsetIdx + tagsIdx; + idManager.RegisterId( m_tagData.StartIdx, uniquePrefix + m_tagData.TagsId, m_tagData.TagsId ); + m_srpType = TemplateHelperFunctions.CreateTags( ref m_tagData, isSubShader ); + + propertyContainer.AddId( subBody, m_tagData.TagsId, false ); + m_tagData.DataCheck = TemplateDataCheck.Valid; + } + else + { + m_tagData.DataCheck = TemplateDataCheck.Invalid; + } + } + else + { + m_tagData.DataCheck = TemplateDataCheck.Invalid; + } + } + + //SHADER MODEL + { + Match match = Regex.Match( subBody, TemplateHelperFunctions.ShaderModelPattern ); + if ( match != null && match.Groups.Count > 1 ) + { + if ( TemplateHelperFunctions.AvailableInterpolators.ContainsKey( match.Groups[ 1 ].Value ) ) + { + m_shaderModel.Id = match.Groups[ 0 ].Value; + m_shaderModel.StartIdx = offsetIdx + match.Index; + m_shaderModel.Value = match.Groups[ 1 ].Value; + m_shaderModel.InterpolatorAmount = TemplateHelperFunctions.AvailableInterpolators[ match.Groups[ 1 ].Value ]; + m_shaderModel.DataCheck = TemplateDataCheck.Valid; + idManager.RegisterId( m_shaderModel.StartIdx, uniquePrefix + m_shaderModel.Id, m_shaderModel.Id ); + } + else + { + m_shaderModel.DataCheck = TemplateDataCheck.Invalid; + } + } + } + + // ALL MODULES + int allModulesIndex = subBody.IndexOf( TemplatesManager.TemplateAllModulesTag ); + if( allModulesIndex > 0 ) + { + //ONLY REGISTER MISSING TAGS + ConfigureCommonTag( m_allModulesTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody ); + m_allModulesMode = true; + + m_blendData.SetAllModulesDefault(); + + if( !m_alphaToMaskData.IsValid ) + m_alphaToMaskData.SetAllModulesDefault(); + + if( !m_cullModeData.IsValid ) + m_cullModeData.SetAllModulesDefault(); + + if( !m_colorMaskData.IsValid ) + m_colorMaskData.SetAllModulesDefault(); + + if( !m_stencilData.IsValid ) + m_stencilData.SetAllModulesDefault(); + + if( !m_depthData.IsValid ) + m_depthData.SetAllModulesDefault(); + + if( !m_shaderModel.IsValid ) + m_shaderModel.SetAllModulesDefault(); + } + } + + public void TestPropertyInternalName( string name, ref List availableShaderProperties, ref Dictionary duplicatesHelper ) + { + if( !string.IsNullOrEmpty( name ) && !duplicatesHelper.ContainsKey( name )) + { + TemplateShaderPropertyData newData = new TemplateShaderPropertyData( -1, string.Empty, string.Empty, name, name, WirePortDataType.INT, PropertyType.Property,-1,-1 ); + availableShaderProperties.Add( newData ); + duplicatesHelper.Add( newData.PropertyName , newData ); + } + } + + public void RegisterInternalUnityInlines( ref List availableShaderProperties, ref Dictionary duplicatesHelper ) + { + TestPropertyInternalName( m_depthData.ZWriteInlineValue, ref availableShaderProperties , ref duplicatesHelper); + TestPropertyInternalName( m_depthData.ZTestInlineValue, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_depthData.OffsetFactorInlineValue, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_depthData.OffsetUnitsInlineValue, ref availableShaderProperties, ref duplicatesHelper ); + + TestPropertyInternalName( m_blendData.SourceFactorRGBInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData.DestFactorRGBInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData.SourceFactorAlphaInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData.DestFactorAlphaInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData.BlendOpRGBInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData.BlendOpAlphaInline, ref availableShaderProperties, ref duplicatesHelper ); + + TestPropertyInternalName( m_blendData1.SourceFactorRGBInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData1.DestFactorRGBInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData1.SourceFactorAlphaInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData1.DestFactorAlphaInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData1.BlendOpRGBInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData1.BlendOpAlphaInline, ref availableShaderProperties, ref duplicatesHelper ); + + TestPropertyInternalName( m_blendData2.SourceFactorRGBInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData2.DestFactorRGBInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData2.SourceFactorAlphaInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData2.DestFactorAlphaInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData2.BlendOpRGBInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData2.BlendOpAlphaInline, ref availableShaderProperties, ref duplicatesHelper ); + + TestPropertyInternalName( m_blendData3.SourceFactorRGBInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData3.DestFactorRGBInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData3.SourceFactorAlphaInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData3.DestFactorAlphaInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData3.BlendOpRGBInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_blendData3.BlendOpAlphaInline, ref availableShaderProperties, ref duplicatesHelper ); + + TestPropertyInternalName( m_alphaToMaskData.InlineData, ref availableShaderProperties, ref duplicatesHelper ); + + TestPropertyInternalName( m_stencilData.ReferenceInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_stencilData.ReadMaskInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_stencilData.WriteMaskInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_stencilData.ComparisonFrontInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_stencilData.PassFrontInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_stencilData.FailFrontInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_stencilData.ZFailFrontInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_stencilData.ComparisonBackInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_stencilData.PassBackInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_stencilData.FailBackInline, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_stencilData.ZFailBackInline, ref availableShaderProperties, ref duplicatesHelper ); + + TestPropertyInternalName( m_cullModeData.InlineData, ref availableShaderProperties, ref duplicatesHelper ); + + TestPropertyInternalName( m_colorMaskData.InlineData, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_colorMaskData1.InlineData, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_colorMaskData2.InlineData, ref availableShaderProperties, ref duplicatesHelper ); + TestPropertyInternalName( m_colorMaskData3.InlineData, ref availableShaderProperties, ref duplicatesHelper ); + } + + public void SetPassUniqueNameIfUndefined( string value ) + { + if( string.IsNullOrEmpty( m_passUniqueName ) ) + m_passUniqueName = value; + } + + public bool HasValidData + { + get + { + return m_blendData.DataCheck == TemplateDataCheck.Valid || + m_blendData1.DataCheck == TemplateDataCheck.Valid || + m_blendData2.DataCheck == TemplateDataCheck.Valid || + m_blendData3.DataCheck == TemplateDataCheck.Valid || + m_alphaToMaskData.DataCheck == TemplateDataCheck.Valid || + m_cullModeData.DataCheck == TemplateDataCheck.Valid || + m_colorMaskData.DataCheck == TemplateDataCheck.Valid || + m_colorMaskData1.DataCheck == TemplateDataCheck.Valid || + m_colorMaskData2.DataCheck == TemplateDataCheck.Valid || + m_colorMaskData3.DataCheck == TemplateDataCheck.Valid || + m_stencilData.DataCheck == TemplateDataCheck.Valid || + m_depthData.DataCheck == TemplateDataCheck.Valid || + m_tagData.DataCheck == TemplateDataCheck.Valid || + m_shaderModel.DataCheck == TemplateDataCheck.Valid || + m_globalsTag.IsValid || + m_srpBatcherTag.IsValid || + m_allModulesTag.IsValid || + m_functionsTag.IsValid || + m_pragmaTag.IsValid || + m_pragmaBeforeTag.IsValid || + m_passTag.IsValid || + m_inputsVertTag.IsValid || + m_inputsFragTag.IsValid || + m_renderPlatformHelper.IsValid; + } + } + + public TemplateBlendData BlendData { get { return m_blendData; } } + public TemplateBlendData BlendData1 { get { return m_blendData1; } } + public TemplateBlendData BlendData2 { get { return m_blendData2; } } + public TemplateBlendData BlendData3 { get { return m_blendData3; } } + public TemplateAlphaToMaskData AlphaToMaskData { get { return m_alphaToMaskData; } } + public TemplateCullModeData CullModeData { get { return m_cullModeData; } } + public TemplateColorMaskData ColorMaskData { get { return m_colorMaskData; } } + public TemplateColorMaskData ColorMaskData1 { get { return m_colorMaskData1; } } + public TemplateColorMaskData ColorMaskData2 { get { return m_colorMaskData2; } } + public TemplateColorMaskData ColorMaskData3 { get { return m_colorMaskData3; } } + public TemplateStencilData StencilData { get { return m_stencilData; } } + public TemplateDepthData DepthData { get { return m_depthData; } } + public TemplateTagsModuleData TagData { get { return m_tagData; } } + public TemplateTagData GlobalsTag { get { return m_globalsTag; } } + public TemplateTagData SRPBatcherTag { get { return m_srpBatcherTag; } } + public TemplateTagData AllModulesTag { get { return m_allModulesTag; } } + public TemplateTagData FunctionsTag { get { return m_functionsTag; } } + public TemplateTagData PragmaTag { get { return m_pragmaTag; } } + public TemplateTagData PragmaBeforeTag { get { return m_pragmaBeforeTag; } } + public TemplateTagData PassTag { get { return m_passTag; } } + public TemplateTagData InputsVertTag { get { return m_inputsVertTag; } } + public TemplateTagData InputsFragTag { get { return m_inputsFragTag; } } + public TemplateShaderModelData ShaderModel { get { return m_shaderModel; } } + public TemplateSRPType SRPType { get { return m_srpType; } set { m_srpType = value; } } + public bool SRPIsPBR { get { return m_srpIsPBR; } set { m_srpIsPBR = value; } } + public bool SRPIsPBRHD { get { return m_srpIsPBR && m_srpType == TemplateSRPType.HD; } } + public string UniquePrefix { get { return m_uniquePrefix; } } + public string PassUniqueName { get { return m_passUniqueName; } } + public bool HasPassUniqueName { get { return !string.IsNullOrEmpty( m_passUniqueName ); } } + public TemplateIncludePragmaContainter IncludePragmaContainer { get { return m_includePragmaContainer; } } + public TemplateRenderPlatformHelper RenderPlatformHelper { get { return m_renderPlatformHelper; } } + public bool AllModulesMode { get { return m_allModulesMode; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs.meta new file mode 100644 index 0000000..6471477 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 122447ac2bc376a448a42a0f5373e63b +timeCreated: 1521718529 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs new file mode 100644 index 0000000..bbf891f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs @@ -0,0 +1,1486 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; +using System.Text.RegularExpressions; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateUniquePassData + { + public int SubShaderIdx; + public int PassIdx; + } + + [Serializable] + public sealed class TemplateMultiPass : TemplateDataParent + { + [SerializeField] + private List m_availableShaderProperties = new List(); + + [SerializeField] + private List m_subShaders = new List(); + + [SerializeField] + private TemplateTagData m_propertyTag; + + [SerializeField] + private TemplateIdManager m_templateIdManager; + + [SerializeField] + private string m_shaderNameId = string.Empty; + + [SerializeField] + private string m_shaderBody; + + [SerializeField] + private TemplatePropertyContainer m_templateProperties = new TemplatePropertyContainer(); + + [SerializeField] + private TemplateShaderInfo m_shaderData; + + [SerializeField] + private bool m_isSinglePass = false; + + [SerializeField] + private int m_masterNodesRequired = 0; + + [SerializeField] + TemplateInfoContainer m_customInspectorContainer = new TemplateInfoContainer(); + + [SerializeField] + TemplateInfoContainer m_dependenciesContainer = new TemplateInfoContainer(); + + [SerializeField] + TemplateInfoContainer m_fallbackContainer = new TemplateInfoContainer(); + + [SerializeField] + TemplateInfoContainer m_beforePragmaContainer = new TemplateInfoContainer(); + + [SerializeField] + private CustomTemplatePropertyUIEnum m_customTemplatePropertyUI = CustomTemplatePropertyUIEnum.None; + + [SerializeField] + private int m_lodInjectorId = -1; + + [SerializeField] + TemplateShaderModelData m_globalShaderModel = new TemplateShaderModelData(); + + private Dictionary m_passUniqueIdData = new Dictionary(); + + [NonSerialized] + private List m_allShaderProperties; + + public TemplateMultiPass() + { + m_templateType = TemplateDataType.MultiPass; + } + + public TemplateMultiPass( string name, string guid, bool isCommunity ) + { + m_templateType = TemplateDataType.MultiPass; + Init( name, guid, isCommunity ); + } + + public override void Init( string name, string guid, bool isCommunity ) + { + base.Init( name, guid, isCommunity ); + TemplatesManager.CurrTemplateGUIDLoaded = guid; + LoadTemplateBody( guid ); + Name = string.IsNullOrEmpty( name ) ? m_defaultShaderName : name; + } + + void LoadTemplateBody( string guid ) + { + m_passUniqueIdData.Clear(); + m_guid = guid; + string datapath = AssetDatabase.GUIDToAssetPath( guid ); + string shaderBody = string.Empty; + shaderBody = IOUtils.LoadTextFileFromDisk( datapath ); + shaderBody = UIUtils.ForceLFLineEnding( shaderBody ); + + // Insert Before Tag + MatchCollection col = Regex.Matches( shaderBody, TemplateHelperFunctions.BeforePragmaPattern, RegexOptions.Singleline ); + for( int i = col.Count - 1; i >= 0; i-- ) + { + if( col[ i ].Groups.Count == 3 ) + { + shaderBody = shaderBody.Insert( col[ i ].Groups[ 2 ].Index, TemplatesManager.TemplatePragmaBeforeTag + "\n" + col[ i ].Groups[ 1 ].Value ); + } + } + //Detect SRP Batcher + MatchCollection srpMatch = Regex.Matches( shaderBody, TemplateHelperFunctions.SRPBatcherFindTag ); + for( int i = srpMatch.Count - 1; i >= 0; i-- ) + { + if( srpMatch[ i ].Groups.Count == 2 ) + { + shaderBody = shaderBody.Insert( srpMatch[ i ].Groups[ 0 ].Index + srpMatch[ i ].Groups[ 0 ].Length, TemplatesManager.TemplateSRPBatcherTag + srpMatch[ i ].Groups[ 1 ].Value ); + } + } + + + // Detect if template has LOD tag, if not, insert one + // It will be read and processed over the TemplateSubShader constructor + { + Match match = Regex.Match( shaderBody, TemplateHelperFunctions.SubShaderLODPattern ); + if( match == null || ( match != null && !match.Success ) ) + { + MatchCollection subShaderMatch = Regex.Matches( shaderBody, TemplatesManager.TemplateMPSubShaderTag ); + + int subShaderAmount = subShaderMatch.Count; + + for( int i = subShaderAmount - 1; i > -1; i-- ) + { + if( subShaderMatch[ i ].Success ) + { + shaderBody = shaderBody.Insert( subShaderMatch[ i ].Index + subShaderMatch[ i ].Length, "\n\t\t\tLOD 0\n" ); + } + } + } + } + m_shaderData = TemplateShaderInfoUtil.CreateShaderData( shaderBody ); + if( m_shaderData == null ) + { + m_isValid = false; + return; + } + + m_templateIdManager = new TemplateIdManager( shaderBody ); + + try + { + int nameBegin = shaderBody.IndexOf( TemplatesManager.TemplateShaderNameBeginTag ); + if( nameBegin < 0 ) + { + // Not a template + return; + } + + int nameEnd = shaderBody.IndexOf( TemplatesManager.TemplateFullEndTag, nameBegin ); + if( nameEnd < 0 ) + return; + + + m_shaderBody = shaderBody; + int defaultBegin = nameBegin + TemplatesManager.TemplateShaderNameBeginTag.Length; + int defaultLength = nameEnd - defaultBegin; + m_defaultShaderName = shaderBody.Substring( defaultBegin, defaultLength ); + int[] nameIdx = m_defaultShaderName.AllIndexesOf( "\"" ); + nameIdx[ 0 ] += 1; // Ignore the " character from the string + m_defaultShaderName = m_defaultShaderName.Substring( nameIdx[ 0 ], nameIdx[ 1 ] - nameIdx[ 0 ] ); + m_shaderNameId = shaderBody.Substring( nameBegin, nameEnd + TemplatesManager.TemplateFullEndTag.Length - nameBegin ); + m_templateProperties.AddId( shaderBody, m_shaderNameId, false ); + m_templateIdManager.RegisterId( nameBegin, m_shaderNameId, m_shaderNameId ); + shaderBody = shaderBody.Substring( nameEnd + TemplatesManager.TemplateFullEndTag.Length ); + } + catch( Exception e ) + { + Debug.LogException( e ); + m_isValid = false; + } + + m_customTemplatePropertyUI = TemplateHelperFunctions.FetchCustomUI( shaderBody ); + TemplateHelperFunctions.FetchDependencies( m_dependenciesContainer, ref m_shaderBody ); + if( m_dependenciesContainer.IsValid ) + { + int index = m_dependenciesContainer.Id.IndexOf( TemplatesManager.TemplateDependenciesListTag ); + m_templateProperties.AddId( new TemplateProperty( m_dependenciesContainer.Id, m_dependenciesContainer.Id.Substring( 0, index ), true ) ); + m_templateIdManager.RegisterId( m_dependenciesContainer.Index, m_dependenciesContainer.Id, m_dependenciesContainer.Id ); + } + + TemplateHelperFunctions.FetchCustomInspector( m_customInspectorContainer, ref m_shaderBody ); + if( m_customInspectorContainer.IsValid ) + { + int index = m_customInspectorContainer.Id.IndexOf( "CustomEditor" ); + m_templateProperties.AddId( new TemplateProperty( m_customInspectorContainer.Id, m_customInspectorContainer.Id.Substring( 0, index ), true ) ); + m_templateIdManager.RegisterId( m_customInspectorContainer.Index, m_customInspectorContainer.Id, m_customInspectorContainer.Id ); + } + + TemplateHelperFunctions.FetchFallback( m_fallbackContainer, ref m_shaderBody ); + if( m_fallbackContainer.IsValid ) + { + int index = m_fallbackContainer.Id.IndexOf( "Fallback", StringComparison.InvariantCultureIgnoreCase ); + m_templateProperties.AddId( new TemplateProperty( m_fallbackContainer.Id, m_fallbackContainer.Id.Substring( 0, index ), true ) ); + m_templateIdManager.RegisterId( m_fallbackContainer.Index, m_fallbackContainer.Id, m_fallbackContainer.Id ); + } + + m_lodInjectorId = m_shaderBody.IndexOf( TemplatesManager.TemplateLODsTag ); + + // Shader body may have been changed to inject inexisting tags like fallback + m_templateIdManager.ShaderBody = m_shaderBody; + + m_propertyTag = new TemplateTagData( m_shaderData.PropertyStartIdx, TemplatesManager.TemplatePropertyTag, true ); + m_templateIdManager.RegisterId( m_shaderData.PropertyStartIdx, TemplatesManager.TemplatePropertyTag, TemplatesManager.TemplatePropertyTag ); + m_templateProperties.AddId( shaderBody, TemplatesManager.TemplatePropertyTag, true ); + Dictionary duplicatesHelper = new Dictionary(); + TemplateHelperFunctions.CreateShaderPropertiesList( m_shaderData.Properties, ref m_availableShaderProperties, ref duplicatesHelper,-1,-1 ); + for( int i = 0; i < m_availableShaderProperties.Count; i++ ) + { + m_templateIdManager.RegisterId( m_availableShaderProperties[ i ].Index, m_availableShaderProperties[ i ].FullValue, m_availableShaderProperties[ i ].FullValue ); + } + + int subShaderCount = m_shaderData.SubShaders.Count; + + int mainSubShaderIdx = -1; + int mainPassIdx = -1; + + int firstVisibleSubShaderId = -1; + int firstVisiblePassId = -1; + bool foundMainPass = false; + bool foundFirstVisible = false; + + m_templateIdManager.RegisterTag( TemplatesManager.TemplatePassesEndTag ); + m_templateIdManager.RegisterTag( TemplatesManager.TemplateMainPassTag ); + + //SHADER MODEL + { + Match shaderModelMatch = Regex.Match( m_shaderData.Properties, TemplateHelperFunctions.ShaderModelPattern ); + if( shaderModelMatch != null && shaderModelMatch.Success ) + { + if( TemplateHelperFunctions.AvailableInterpolators.ContainsKey( shaderModelMatch.Groups[ 1 ].Value ) ) + { + m_globalShaderModel.Id = shaderModelMatch.Groups[ 0 ].Value; + m_globalShaderModel.StartIdx = shaderModelMatch.Index; + m_globalShaderModel.Value = shaderModelMatch.Groups[ 1 ].Value; + m_globalShaderModel.InterpolatorAmount = TemplateHelperFunctions.AvailableInterpolators[ shaderModelMatch.Groups[ 1 ].Value ]; + m_globalShaderModel.DataCheck = TemplateDataCheck.Valid; + } + else + { + m_globalShaderModel.DataCheck = TemplateDataCheck.Invalid; + } + } + } + // + + + for( int i = 0; i < subShaderCount; i++ ) + { + TemplateSubShader subShader = new TemplateSubShader(this, i, m_templateIdManager, "SubShader" + i, m_shaderData.SubShaders[ i ], ref duplicatesHelper ); + + if( subShader.FoundMainPass ) + { + if( !foundMainPass ) + { + foundMainPass = true; + mainSubShaderIdx = i; + mainPassIdx = subShader.MainPass; + } + } + else if( subShader.MainPass > -1 ) + { + if( !foundFirstVisible ) + { + foundFirstVisible = true; + firstVisibleSubShaderId = i; + firstVisiblePassId = subShader.MainPass; + } + } + + m_subShaders.Add( subShader ); + m_masterNodesRequired += subShader.Passes.Count; + } + + + if( !foundMainPass && foundFirstVisible ) + { + mainSubShaderIdx = firstVisibleSubShaderId; + mainPassIdx = firstVisiblePassId; + } + + for( int subShaderIdx = 0; subShaderIdx < subShaderCount; subShaderIdx++ ) + { + m_subShaders[ subShaderIdx ].Modules.RegisterInternalUnityInlines( ref m_availableShaderProperties , ref duplicatesHelper ); + int passCount = m_subShaders[ subShaderIdx ].Passes.Count; + for( int passIdx = 0; passIdx < passCount; passIdx++ ) + { + m_subShaders[ subShaderIdx ].Passes[ passIdx ].Modules.RegisterInternalUnityInlines( ref m_availableShaderProperties, ref duplicatesHelper ); + m_subShaders[ subShaderIdx ].Passes[ passIdx ].IsMainPass = ( mainSubShaderIdx == subShaderIdx && mainPassIdx == passIdx ); + } + } + + duplicatesHelper.Clear(); + duplicatesHelper = null; + m_isSinglePass = ( m_subShaders.Count == 1 && m_subShaders[ 0 ].PassAmount == 1 ); + + } + + public void ResetState() + { + m_templateIdManager.ResetRegistersState(); + int subshaderCount = m_subShaders.Count; + for( int subShaderIdx = 0; subShaderIdx < subshaderCount; subShaderIdx++ ) + { + m_subShaders[ subShaderIdx ].TemplateProperties.ResetTemplateUsageData(); + int passCount = m_subShaders[ subShaderIdx ].Passes.Count; + for( int passIdx = 0; passIdx < passCount; passIdx++ ) + { + m_subShaders[ subShaderIdx ].Passes[ passIdx ].TemplateProperties.ResetTemplateUsageData(); + } + } + } + + public override void Destroy() + { + m_templateProperties.Destroy(); + m_templateProperties = null; + + m_availableShaderProperties.Clear(); + m_availableShaderProperties = null; + if( m_allShaderProperties != null ) + { + m_allShaderProperties.Clear(); + m_allShaderProperties = null; + } + + int subShaderCount = m_subShaders.Count; + for( int i = 0; i < subShaderCount; i++ ) + { + m_subShaders[ i ].Destroy(); + } + + m_subShaders.Clear(); + m_subShaders = null; + + m_templateIdManager.Destroy(); + m_templateIdManager = null; + } + + public void SetSubShaderData( TemplateModuleDataType type, int subShaderId, string[] list ) + { + string id = GetSubShaderDataId( type, subShaderId, false ); + string body = string.Empty; + FillTemplateBody( subShaderId, -1, id, ref body, list ); + SetSubShaderData( type, subShaderId, body ); + } + + public void SetSubShaderData( TemplateModuleDataType type, int subShaderId, List list ) + { + string id = GetSubShaderDataId( type, subShaderId, false ); + string body = string.Empty; + FillTemplateBody( subShaderId, -1, id, ref body, list ); + SetSubShaderData( type, subShaderId, body ); + } + + public void SetSubShaderData( TemplateModuleDataType type, int subShaderId, string text ) + { + if( subShaderId >= m_subShaders.Count ) + return; + + string prefix = m_subShaders[ subShaderId ].Modules.UniquePrefix; + switch( type ) + { + case TemplateModuleDataType.AllModules: + { + m_templateIdManager.SetReplacementText( prefix + TemplatesManager.TemplateAllModulesTag, text ); + } + break; + case TemplateModuleDataType.ModuleShaderModel: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.ShaderModel.Id, text ); + } + break; + case TemplateModuleDataType.ModuleBlendMode: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.BlendData.BlendModeId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendMode1: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.BlendData1.BlendModeId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendMode2: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.BlendData2.BlendModeId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendMode3: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.BlendData3.BlendModeId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendOp: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.BlendData.BlendOpId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendOp1: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.BlendData1.BlendOpId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendOp2: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.BlendData2.BlendOpId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendOp3: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.BlendData3.BlendOpId, text ); + } + break; + case TemplateModuleDataType.ModuleAlphaToMask: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.AlphaToMaskData.AlphaToMaskId, text ); + } + break; + case TemplateModuleDataType.ModuleCullMode: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.CullModeData.CullModeId, text ); + } + break; + case TemplateModuleDataType.ModuleColorMask: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.ColorMaskData.ColorMaskId, text ); + } + break; + case TemplateModuleDataType.ModuleColorMask1: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.ColorMaskData1.ColorMaskId, text ); + } + break; + case TemplateModuleDataType.ModuleColorMask2: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.ColorMaskData2.ColorMaskId, text ); + } + break; + case TemplateModuleDataType.ModuleColorMask3: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.ColorMaskData3.ColorMaskId, text ); + } + break; + case TemplateModuleDataType.ModuleStencil: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.StencilData.StencilBufferId, text ); + } + break; + case TemplateModuleDataType.ModuleZwrite: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.DepthData.ZWriteModeId, text ); + } + break; + case TemplateModuleDataType.ModuleZTest: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.DepthData.ZTestModeId, text ); + } + break; + case TemplateModuleDataType.ModuleZOffset: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.DepthData.OffsetId, text ); + } + break; + case TemplateModuleDataType.ModuleTag: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.TagData.TagsId, text ); + } + break; + case TemplateModuleDataType.ModuleGlobals: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.GlobalsTag.Id, text ); + } + break; + case TemplateModuleDataType.ModuleSRPBatcher: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.SRPBatcherTag.Id, text ); + } + break; + case TemplateModuleDataType.ModuleFunctions: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.FunctionsTag.Id, text ); + } + break; + case TemplateModuleDataType.ModulePragma: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.PragmaTag.Id, text ); + } + break; + case TemplateModuleDataType.ModulePragmaBefore: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.PragmaBeforeTag.Id, text ); + } + break; + case TemplateModuleDataType.ModulePass: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.PassTag.Id, text ); + } + break; + case TemplateModuleDataType.ModuleInputVert: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.InputsVertTag.Id, text ); + } + break; + case TemplateModuleDataType.ModuleInputFrag: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.InputsFragTag.Id, text ); + }break; + case TemplateModuleDataType.ModuleRenderPlatforms: + { + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.RenderPlatformHelper.ID , text ); + }break; + } + } + + public void SetPropertyData( string[] properties ) + { + string body = string.Empty; + FillTemplateBody( -1, -1, TemplatesManager.TemplatePropertyTag, ref body, properties ); + SetPropertyData( body ); + } + + + public void SetPropertyData( string text ) + { + m_templateIdManager.SetReplacementText( m_propertyTag.Id, text ); + } + + public string GetSubShaderDataId( TemplateModuleDataType type, int subShaderId, bool addPrefix ) + { + if( subShaderId >= m_subShaders.Count ) + return string.Empty; + + string prefix = string.Empty; + switch( type ) + { + case TemplateModuleDataType.AllModules: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + TemplatesManager.TemplateAllModulesTag; + } + case TemplateModuleDataType.ModuleBlendMode: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.BlendData.BlendModeId; + } + case TemplateModuleDataType.ModuleBlendMode1: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.BlendData1.BlendModeId; + } + case TemplateModuleDataType.ModuleBlendMode2: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.BlendData2.BlendModeId; + } + case TemplateModuleDataType.ModuleBlendMode3: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.BlendData3.BlendModeId; + } + case TemplateModuleDataType.ModuleBlendOp: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.BlendData.BlendOpId; + } + case TemplateModuleDataType.ModuleBlendOp1: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.BlendData1.BlendOpId; + } + case TemplateModuleDataType.ModuleBlendOp2: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.BlendData2.BlendOpId; + } + case TemplateModuleDataType.ModuleBlendOp3: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.BlendData3.BlendOpId; + } + case TemplateModuleDataType.ModuleAlphaToMask: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.AlphaToMaskData.AlphaToMaskId; + } + case TemplateModuleDataType.ModuleCullMode: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.CullModeData.CullModeId; + } + case TemplateModuleDataType.ModuleColorMask: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.ColorMaskData.ColorMaskId; + } + case TemplateModuleDataType.ModuleColorMask1: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.ColorMaskData1.ColorMaskId; + } + case TemplateModuleDataType.ModuleColorMask2: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.ColorMaskData2.ColorMaskId; + } + case TemplateModuleDataType.ModuleColorMask3: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.ColorMaskData3.ColorMaskId; + } + case TemplateModuleDataType.ModuleStencil: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.StencilData.StencilBufferId; + } + case TemplateModuleDataType.ModuleZwrite: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.DepthData.ZWriteModeId; + } + case TemplateModuleDataType.ModuleZTest: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.DepthData.ZTestModeId; + } + case TemplateModuleDataType.ModuleZOffset: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.DepthData.OffsetId; + } + case TemplateModuleDataType.ModuleTag: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.TagData.TagsId; + } + case TemplateModuleDataType.ModuleGlobals: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.GlobalsTag.Id; + } + case TemplateModuleDataType.ModuleSRPBatcher: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.SRPBatcherTag.Id; + } + case TemplateModuleDataType.ModuleFunctions: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.FunctionsTag.Id; + } + case TemplateModuleDataType.ModulePragma: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.PragmaTag.Id; + } + case TemplateModuleDataType.ModulePragmaBefore: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.PragmaBeforeTag.Id; + } + case TemplateModuleDataType.ModulePass: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.PassTag.Id; + } + case TemplateModuleDataType.ModuleInputVert: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.InputsVertTag.Id; + } + case TemplateModuleDataType.ModuleInputFrag: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Modules.InputsFragTag.Id; + } + } + return string.Empty; + + } + public string GetPassDataId( TemplateModuleDataType type, int subShaderId, int passId, bool addPrefix ) + { + if( subShaderId >= m_subShaders.Count || passId >= m_subShaders[ subShaderId ].Passes.Count ) + return string.Empty; + + string prefix = string.Empty; + switch( type ) + { + case TemplateModuleDataType.AllModules: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + TemplatesManager.TemplateAllModulesTag; + } + case TemplateModuleDataType.ModuleBlendMode: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData.BlendModeId; + } + case TemplateModuleDataType.ModuleBlendMode1: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData1.BlendModeId; + } + case TemplateModuleDataType.ModuleBlendMode2: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData2.BlendModeId; + } + case TemplateModuleDataType.ModuleBlendMode3: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData3.BlendModeId; + } + case TemplateModuleDataType.ModuleBlendOp: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData.BlendOpId; + } + case TemplateModuleDataType.ModuleBlendOp1: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData1.BlendOpId; + } + case TemplateModuleDataType.ModuleBlendOp2: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData2.BlendOpId; + } + case TemplateModuleDataType.ModuleBlendOp3: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData3.BlendOpId; + } + case TemplateModuleDataType.ModuleAlphaToMask: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.AlphaToMaskData.AlphaToMaskId; + } + case TemplateModuleDataType.ModuleCullMode: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.CullModeData.CullModeId; + } + case TemplateModuleDataType.ModuleColorMask: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.ColorMaskData.ColorMaskId; + } + case TemplateModuleDataType.ModuleColorMask1: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.ColorMaskData1.ColorMaskId; + } + case TemplateModuleDataType.ModuleColorMask2: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.ColorMaskData2.ColorMaskId; + } + case TemplateModuleDataType.ModuleColorMask3: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.ColorMaskData3.ColorMaskId; + } + case TemplateModuleDataType.ModuleStencil: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.StencilData.StencilBufferId; + } + case TemplateModuleDataType.ModuleZwrite: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.DepthData.ZWriteModeId; + } + case TemplateModuleDataType.ModuleZTest: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.DepthData.ZTestModeId; + } + case TemplateModuleDataType.ModuleZOffset: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.DepthData.OffsetId; + } + case TemplateModuleDataType.ModuleTag: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.TagData.TagsId; + } + case TemplateModuleDataType.ModuleGlobals: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.GlobalsTag.Id; + } + case TemplateModuleDataType.ModuleSRPBatcher: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.SRPBatcherTag.Id; + } + case TemplateModuleDataType.ModuleFunctions: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.FunctionsTag.Id; + } + case TemplateModuleDataType.ModulePragma: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.PragmaTag.Id; + } + case TemplateModuleDataType.ModulePragmaBefore: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.PragmaBeforeTag.Id; + } + case TemplateModuleDataType.ModulePass: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.PassTag.Id; + } + case TemplateModuleDataType.ModuleInputVert: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.InputsVertTag.Id; + } + case TemplateModuleDataType.ModuleInputFrag: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.InputsFragTag.Id; + } + case TemplateModuleDataType.PassVertexFunction: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].VertexFunctionData.Id; + } + case TemplateModuleDataType.PassFragmentFunction: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].FragmentFunctionData.Id; + } + case TemplateModuleDataType.PassVertexData: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].VertexDataContainer.VertexDataId; + } + case TemplateModuleDataType.PassInterpolatorData: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].InterpolatorDataContainer.InterpDataId; + } + case TemplateModuleDataType.VControl: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].TessVControlTag.Id; + } + case TemplateModuleDataType.ControlData: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].TessControlData.Id; + } + case TemplateModuleDataType.DomainData: + { + prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty; + return prefix + m_subShaders[ subShaderId ].Passes[ passId ].TessDomainData.Id; + } + } + return string.Empty; + } + + public void SetPassData( TemplateModuleDataType type, int subShaderId, int passId, string[] list ) + { + //if( list == null || list.Length == 0 ) + // return; + + string id = GetPassDataId( type, subShaderId, passId, false ); + string body = string.Empty; + FillTemplateBody( subShaderId, passId, id, ref body, list ); + SetPassData( type, subShaderId, passId, body ); + } + + public void SetPassData( TemplateModuleDataType type, int subShaderId, int passId, List list ) + { + //if( list == null || list.Count == 0 ) + // return; + + string id = GetPassDataId( type, subShaderId, passId, false ); + string body = string.Empty; + FillTemplateBody( subShaderId, passId, id, ref body, list ); + SetPassData( type, subShaderId, passId, body ); + } + + public void SetPassData( TemplateModuleDataType type, int subShaderId, int passId, string text ) + { + if( subShaderId >= m_subShaders.Count || passId >= m_subShaders[ subShaderId ].Passes.Count ) + return; + + string prefix = string.Empty; + switch( type ) + { + //case TemplateModuleDataType.EndPass: + //{ + // prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix; + // m_templateIdManager.SetReplacementText( prefix + TemplatesManager.TemplateEndPassTag, text ); + //} + //break; + case TemplateModuleDataType.AllModules: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + TemplatesManager.TemplateAllModulesTag, text ); + } + break; + case TemplateModuleDataType.ModuleRenderPlatforms: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.RenderPlatformHelper.ID , text ); + } + break; + case TemplateModuleDataType.ModuleShaderModel: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.ShaderModel.Id, text ); + } + break; + case TemplateModuleDataType.ModuleBlendMode: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData.BlendModeId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendMode1: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData1.BlendModeId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendMode2: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData2.BlendModeId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendMode3: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData3.BlendModeId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendOp: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData.BlendOpId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendOp1: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData1.BlendOpId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendOp2: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData2.BlendOpId, text ); + } + break; + case TemplateModuleDataType.ModuleBlendOp3: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData3.BlendOpId, text ); + } + break; + case TemplateModuleDataType.ModuleAlphaToMask: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.AlphaToMaskData.AlphaToMaskId, text ); + } + break; + case TemplateModuleDataType.ModuleCullMode: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.CullModeData.CullModeId, text ); + } + break; + case TemplateModuleDataType.ModuleColorMask: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.ColorMaskData.ColorMaskId, text ); + } + break; + case TemplateModuleDataType.ModuleColorMask1: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.ColorMaskData1.ColorMaskId, text ); + } + break; + case TemplateModuleDataType.ModuleColorMask2: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.ColorMaskData2.ColorMaskId, text ); + } + break; + case TemplateModuleDataType.ModuleColorMask3: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.ColorMaskData3.ColorMaskId, text ); + } + break; + case TemplateModuleDataType.ModuleStencil: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.StencilData.StencilBufferId, text ); + } + break; + case TemplateModuleDataType.ModuleZwrite: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.DepthData.ZWriteModeId, text ); + } + break; + case TemplateModuleDataType.ModuleZTest: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.DepthData.ZTestModeId, text ); + } + break; + case TemplateModuleDataType.ModuleZOffset: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.DepthData.OffsetId, text ); + } + break; + case TemplateModuleDataType.ModuleTag: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.TagData.TagsId, text ); + } + break; + case TemplateModuleDataType.ModuleGlobals: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.GlobalsTag.Id, text ); + } + break; + case TemplateModuleDataType.ModuleSRPBatcher: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.SRPBatcherTag.Id, text ); + } + break; + case TemplateModuleDataType.ModuleFunctions: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.FunctionsTag.Id, text ); + } + break; + case TemplateModuleDataType.ModulePragma: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.PragmaTag.Id, text ); + } + break; + case TemplateModuleDataType.ModulePragmaBefore: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.PragmaBeforeTag.Id, text ); + } + break; + case TemplateModuleDataType.ModulePass: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.PassTag.Id, text ); + } + break; + case TemplateModuleDataType.ModuleInputVert: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.InputsVertTag.Id, text ); + } + break; + case TemplateModuleDataType.ModuleInputFrag: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.InputsFragTag.Id, text ); + } + break; + case TemplateModuleDataType.PassVertexFunction: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].VertexFunctionData.Id, text ); + } + break; + case TemplateModuleDataType.PassFragmentFunction: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].FragmentFunctionData.Id, text ); + } + break; + case TemplateModuleDataType.PassVertexData: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].VertexDataContainer.VertexDataId, text ); + } + break; + case TemplateModuleDataType.PassInterpolatorData: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].InterpolatorDataContainer.InterpDataId, text ); + } + break; + case TemplateModuleDataType.PassNameData: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].PassNameContainer.Id, text ); + } + break; + case TemplateModuleDataType.VControl: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].TessVControlTag.Id, text ); + } + break; + case TemplateModuleDataType.ControlData: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].TessControlData.Id, text ); + } + break; + case TemplateModuleDataType.DomainData: + { + prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].TessDomainData.Id, text ); + }break; + } + } + + public void SetPassInputData( int subShaderId, int passId, int inputId, string text ) + { + if( subShaderId >= m_subShaders.Count || + passId >= m_subShaders[ subShaderId ].Passes.Count ) + return; + + string prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix; + TemplateInputData inputData = m_subShaders[ subShaderId ].Passes[ passId ].InputDataFromId( inputId ); + if( inputData != null ) + { + m_templateIdManager.SetReplacementText( prefix + inputData.TagId, text ); + } + else + { + Debug.LogErrorFormat( "Unable to find input data for port with id {0} on subshader {1} pass {2}", inputId, subShaderId, passId ); + } + } + + public void SetPassInputDataByArrayIdx( int subShaderId, int passId, int inputId, string text ) + { + if( subShaderId >= m_subShaders.Count || + passId >= m_subShaders[ subShaderId ].Passes.Count || + inputId >= m_subShaders[ subShaderId ].Passes[ passId ].InputDataList.Count ) + return; + + string prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix; + m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].InputDataList[ inputId ].TagId, text ); + } + + public TemplateData CreateTemplateData( string name, string guid, int subShaderId, int passId ) + { + if( subShaderId >= m_subShaders.Count || + passId >= m_subShaders[ subShaderId ].Passes.Count ) + return null; + + if( string.IsNullOrEmpty( name ) ) + name = m_defaultShaderName; + + TemplateData templateData = ScriptableObject.CreateInstance(); + templateData.Name = name; + templateData.GUID = guid; + templateData.TemplateBody = m_shaderBody; + templateData.DefaultShaderName = m_defaultShaderName; + templateData.ShaderNameId = m_shaderNameId; + templateData.OrderId = m_orderId; + + templateData.InputDataList = SubShaders[ subShaderId ].Passes[ passId ].InputDataList; + templateData.VertexDataContainer = SubShaders[ subShaderId ].Passes[ passId ].VertexDataContainer; + templateData.InterpolatorDataContainer = SubShaders[ subShaderId ].Passes[ passId ].InterpolatorDataContainer; + templateData.AvailableShaderProperties = m_availableShaderProperties; + templateData.VertexFunctionData = SubShaders[ subShaderId ].Passes[ passId ].VertexFunctionData; + templateData.FragmentFunctionData = SubShaders[ subShaderId ].Passes[ passId ].FragmentFunctionData; + templateData.BlendData = SubShaders[ subShaderId ].Passes[ passId ].Modules.BlendData; + templateData.CullModeData = SubShaders[ subShaderId ].Passes[ passId ].Modules.CullModeData; + templateData.ColorMaskData = SubShaders[ subShaderId ].Passes[ passId ].Modules.ColorMaskData; + templateData.StencilData = SubShaders[ subShaderId ].Passes[ passId ].Modules.StencilData; + templateData.DepthData = SubShaders[ subShaderId ].Passes[ passId ].Modules.DepthData; + templateData.TagData = SubShaders[ subShaderId ].Passes[ passId ].Modules.TagData; + + //templateData.PropertyList = m_pr; + //private Dictionary m_propertyDict = new Dictionary(); + + return templateData; + } + + public bool FillTemplateBody( int subShaderId, int passId, string id, ref string body, List values ) + { + if( values.Count == 0 ) + { + return true; + } + + string[] array = new string[ values.Count ]; + for( int i = 0; i < values.Count; i++ ) + { + array[ i ] = values[ i ].PropertyName; + } + return FillTemplateBody( subShaderId, passId, id, ref body, array ); + } + + public bool FillTemplateBody( int subShaderId, int passId, string id, ref string body, params string[] values ) + { + if( values.Length == 0 ) + { + if( id[ id.Length - 1 ] == '\n' ) + body = "\n"; + + return true; + } + + TemplatePropertyContainer propertyContainer = null; + if( subShaderId >= 0 ) + { + if( passId >= 0 ) + { + propertyContainer = SubShaders[ subShaderId ].Passes[ passId ].TemplateProperties; + } + else + { + propertyContainer = SubShaders[ subShaderId ].TemplateProperties; + } + } + else + { + propertyContainer = m_templateProperties; + } + + propertyContainer.BuildInfo(); + + if( propertyContainer.PropertyDict.ContainsKey( id ) ) + { + string finalValue = propertyContainer.PropertyDict[ id ].UseIndentationAtStart ? propertyContainer.PropertyDict[ id ].Indentation : string.Empty; + for( int i = 0; i < values.Length; i++ ) + { + + if( propertyContainer.PropertyDict[ id ].AutoLineFeed ) + { + string[] valuesArr = values[ i ].Split( '\n' ); + for( int j = 0; j < valuesArr.Length; j++ ) + { + //first value will be automatically indented by the string replace + finalValue += ( ( i == 0 && j == 0 ) ? string.Empty : propertyContainer.PropertyDict[ id ].Indentation ) + valuesArr[ j ]; + finalValue += TemplatesManager.TemplateNewLine; + } + } + else + { + //first value will be automatically indented by the string replace + finalValue += ( i == 0 ? string.Empty : propertyContainer.PropertyDict[ id ].Indentation ) + values[ i ]; + } + } + + body = finalValue; + propertyContainer.PropertyDict[ id ].Used = true; + return true; + } + + if( values.Length > 1 || !string.IsNullOrEmpty( values[ 0 ] ) ) + { + UIUtils.ShowMessage( string.Format( "Attempting to write data into inexistant tag {0}. Please review the template {1} body and consider adding the missing tag.", id, m_defaultShaderName ), MessageSeverity.Error ); + return false; + } + return true; + } + + public bool FillVertexInstructions( int subShaderId, int passId, params string[] values ) + { + TemplateFunctionData vertexFunctionData = SubShaders[ subShaderId ].Passes[ passId ].VertexFunctionData; + if( vertexFunctionData != null && !string.IsNullOrEmpty( vertexFunctionData.Id ) ) + { + string body = string.Empty; + bool isValid = FillTemplateBody( subShaderId, passId, vertexFunctionData.Id, ref body, values ); + SetPassData( TemplateModuleDataType.PassVertexFunction, subShaderId, passId, body ); + return isValid; + } + + if( values.Length > 0 ) + { + UIUtils.ShowMessage( "Attemping to add vertex instructions on a template with no assigned vertex code area", MessageSeverity.Error ); + return false; + } + return true; + } + + public bool FillFragmentInstructions( int subShaderId, int passId, params string[] values ) + { + TemplateFunctionData fragmentFunctionData = SubShaders[ subShaderId ].Passes[ passId ].FragmentFunctionData; + if( fragmentFunctionData != null && !string.IsNullOrEmpty( fragmentFunctionData.Id ) ) + { + string body = string.Empty; + bool isValid = FillTemplateBody( subShaderId, passId, fragmentFunctionData.Id, ref body, values ); + SetPassData( TemplateModuleDataType.PassFragmentFunction, subShaderId, passId, body ); + return isValid; + } + + if( values.Length > 0 ) + { + UIUtils.ShowMessage( "Attemping to add fragment instructions on a template with no assigned vertex code area", MessageSeverity.Error ); + return false; + } + return true; + } + + public void SetShaderName( string name ) + { + m_templateIdManager.SetReplacementText( m_shaderNameId, name ); + } + + public void SetCustomInspector( string customInspector ) + { + if( m_customInspectorContainer.Index > -1 ) + { + m_templateIdManager.SetReplacementText( m_customInspectorContainer.Id, m_templateProperties.PropertyDict[ m_customInspectorContainer.Id ].Indentation + customInspector ); + } + } + + public void SetFallback( string fallback ) + { + if( m_fallbackContainer.Index > -1 ) + { + m_templateIdManager.SetReplacementText( m_fallbackContainer.Id, m_templateProperties.PropertyDict[ m_fallbackContainer.Id ].Indentation + fallback ); + } + } + + public void SetDependencies( string dependencies ) + { + if( m_dependenciesContainer.Index > -1 ) + { + m_templateIdManager.SetReplacementText( m_dependenciesContainer.Id, dependencies ); + } + } + + private void OnEnable() + { + hideFlags = HideFlags.HideAndDontSave; + } + + public override bool Reload() + { + m_propertyTag = null; + m_shaderNameId = string.Empty; + m_shaderBody = string.Empty; + m_isSinglePass = false; + m_masterNodesRequired = 0; + m_beforePragmaContainer.Reset(); + m_customInspectorContainer.Reset(); + m_fallbackContainer.Reset(); + m_dependenciesContainer.Reset(); + m_availableShaderProperties.Clear(); + int count = m_subShaders.Count; + for( int i = 0; i < count; i++ ) + { + m_subShaders[ i ].Destroy(); + } + m_subShaders.Clear(); + + m_templateIdManager.Reset(); + if( m_shaderData != null ) + m_shaderData.Destroy(); + + m_templateProperties.Reset(); + + string oldName = m_defaultShaderName; + LoadTemplateBody( m_guid ); + + if( m_communityTemplate ) + Name = m_defaultShaderName; + + return !oldName.Equals( m_defaultShaderName ); + } + + public bool GetSubShaderandPassFor( string passUniqueId, ref int subShaderId, ref int passId ) + { + if( string.IsNullOrEmpty( passUniqueId ) ) + return false; + + if( m_passUniqueIdData.Count == 0 ) + { + for( int subShaderIdx = 0; subShaderIdx < m_subShaders.Count; subShaderIdx++ ) + { + for( int passIdx = 0; passIdx < m_subShaders[ subShaderIdx ].Passes.Count; passIdx++ ) + { + if( m_subShaders[ subShaderIdx ].Passes[ passIdx ].Modules.HasPassUniqueName ) + { + if( m_passUniqueIdData.ContainsKey( m_subShaders[ subShaderIdx ].Passes[ passIdx ].Modules.PassUniqueName ) ) + { + Debug.LogErrorFormat( "Found duplicate pass name '{0}' over template. Please fix template as it will result in multiple errors.", m_subShaders[ subShaderIdx ].Passes[ passIdx ].Modules.PassUniqueName ); + return false; + } + m_passUniqueIdData.Add( m_subShaders[ subShaderIdx ].Passes[ passIdx ].Modules.PassUniqueName, new TemplateUniquePassData() { PassIdx = passIdx, SubShaderIdx = subShaderIdx } ); + } + } + } + } + + if( m_passUniqueIdData.ContainsKey( passUniqueId ) ) + { + subShaderId = m_passUniqueIdData[ passUniqueId ].SubShaderIdx; + passId = m_passUniqueIdData[ passUniqueId ].PassIdx; + return true; + } + subShaderId = -1; + passId = -1; + return false; + } + + public TemplateShaderPropertyData GetShaderPropertyData( string propertyName ) + { + return m_availableShaderProperties.Find( ( x ) => ( x.PropertyName.Equals( propertyName ) ) ); + } + + public TemplateSRPType SRPtype { get { return m_subShaders[ 0 ].Modules.SRPType; } } + //public bool SRPIsPBRHD { get { return m_subShaders[0].Modules.SRPIsPBRHD ; } } + public List SubShaders { get { return m_subShaders; } } + public List AvailableShaderProperties { get { return m_availableShaderProperties; } } + public List AllShaderProperties + { + get + { + if( m_allShaderProperties == null ) + { + m_allShaderProperties = new List(); + if( AvailableShaderProperties.Count > 0 ) + { + m_allShaderProperties.AddRange( AvailableShaderProperties ); + } + + for( int subShaderIdx = 0; subShaderIdx < SubShaders.Count; subShaderIdx++ ) + { + if( SubShaders[ subShaderIdx ].AvailableShaderGlobals.Count > 0 ) + { + m_allShaderProperties.AddRange( SubShaders[ subShaderIdx ].AvailableShaderGlobals ); + } + + for( int passIdx = 0; passIdx < SubShaders[ subShaderIdx ].Passes.Count; passIdx++ ) + { + if( SubShaders[ subShaderIdx ].Passes[ passIdx ].AvailableShaderGlobals.Count > 0 ) + { + m_allShaderProperties.AddRange( SubShaders[ subShaderIdx ].Passes[ passIdx ].AvailableShaderGlobals ); + } + } + } + } + + + return m_allShaderProperties; + } + } + + public TemplateTagData PropertyTag { get { return m_propertyTag; } } + public TemplateIdManager IdManager { get { return m_templateIdManager; } } + public TemplatePropertyContainer TemplateProperties { get { return m_templateProperties; } } + public TemplateInfoContainer CustomInspectorContainer { get { return m_customInspectorContainer; } } + public TemplateInfoContainer FallbackContainer { get { return m_fallbackContainer; } } + public TemplateInfoContainer BeforePragmaContainer { get { return m_beforePragmaContainer; } } + public bool IsSinglePass { get { return m_isSinglePass; } } + public int MasterNodesRequired { get { return m_masterNodesRequired; } } + public CustomTemplatePropertyUIEnum CustomTemplatePropertyUI { get { return m_customTemplatePropertyUI; } } + public bool CanAddLODs { get { return m_lodInjectorId > -1; } } + public TemplateShaderModelData GlobalShaderModel { get { return m_globalShaderModel; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs.meta new file mode 100644 index 0000000..00e2dee --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4214390aa7f66364bbab454dc15a04ac +timeCreated: 1516981847 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs new file mode 100644 index 0000000..5616b54 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs @@ -0,0 +1,3647 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +//#define SHOW_TEMPLATE_HELP_BOX + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using System.Linq; + +namespace AmplifyShaderEditor +{ + public enum HDSRPMaterialType + { + SubsurfaceScattering, + Standard, + Specular, + Anisotropy, + Iridescence, + Translucent + } + + public enum InvisibilityStatus + { + LockedInvisible, + Invisible, + Visible + } + + public enum SetTemplateSource + { + NewShader, + ShaderLoad, + HotCodeReload + }; + + [Serializable] + [NodeAttributes( "Template Master Node" , "Master" , "Shader Generated according to template rules" , null , KeyCode.None , false )] + public sealed class TemplateMultiPassMasterNode : MasterNode + { + private const double MaxLODEditTimestamp = 1; + + private static int PASS_SELECTOR_VERSION = 16200; + private static int PASS_UNIQUE_ID_VERSION = 16204; + + private const string LodNameId = "LODName"; + private const string LodValueId = "LODValue"; + + private const string LodSubtitle = "LOD( {0} )"; + private const string AdditionalLODsStr = "LODs"; + + private const string SubTitleFormatterStr = "(SubShader {0} Pass {1})"; + private const string NoSubShaderPropertyStr = "No Sub-Shader properties available"; + private const string NoPassPropertyStr = "No Pass properties available"; + + private const string WarningMessage = "Templates is a feature that is still heavily under development and users may experience some problems.\nPlease email support@amplify.pt if any issue occurs."; + private const string OpenTemplateStr = "Edit Template"; + private const string ReloadTemplateStr = "Reload Template"; + private const string CommonPropertiesStr = "Common Properties "; + private const string SubShaderModuleStr = "SubShader "; + private const string PassModuleStr = "Pass "; + + private const string PassNameStr = "Name"; + private const string PassNameFormateStr = "Name \"{0}\""; + private const string SubShaderLODValueLabel = "LOD Value"; + private const string SubShaderLODNameLabel = "LOD Name"; + + + + private bool m_reRegisterTemplateData = false; + private bool m_fireTemplateChange = false; + private bool m_fetchMasterNodeCategory = false; + + [SerializeField] + private string m_templateGUID = "4e1801f860093ba4f9eb58a4b556825b"; + + [SerializeField] + private int m_passIdx = 0; + + //[SerializeField] + //private string m_passIdxStr = string.Empty; + + [SerializeField] + private bool m_passFoldout = false; + + [SerializeField] + private int m_subShaderIdx = 0; + + //[SerializeField] + //private string m_subShaderIdxStr = string.Empty; + + [SerializeField] + private bool m_subStringFoldout = false; + + [SerializeField] + private bool m_lodFoldout = false; + + + [SerializeField] + private string m_mainLODName = string.Empty; + + //[SerializeField] + //private string m_subShaderLODStr; + + //[SerializeField] + //private bool m_mainMPMasterNode = false; + + [NonSerialized] + private TemplateMultiPass m_templateMultiPass = null; + + [NonSerialized] + private TemplateMultiPassMasterNode m_mainMasterNodeRef = null; + + [SerializeField] + private TemplateModulesHelper m_subShaderModule = new TemplateModulesHelper(); + + [SerializeField] + private TemplateModulesHelper m_passModule = new TemplateModulesHelper(); + + [SerializeField] + private UsePassHelper m_usePass; + + [SerializeField] + private string m_passName = string.Empty; + + [SerializeField] + private string m_passUniqueId = string.Empty; + + [SerializeField] + private string m_originalPassName = string.Empty; + + [SerializeField] + private bool m_hasLinkPorts = false; + + [SerializeField] + private InvisibilityStatus m_isInvisible = InvisibilityStatus.Visible; + + [SerializeField] + private int m_invisibleOptions = 0; + + [SerializeField] + private bool m_invalidNode = false; + + [SerializeField] + private FallbackPickerHelper m_fallbackHelper = null; + + [SerializeField] + private DependenciesHelper m_dependenciesHelper = new DependenciesHelper(); + + [SerializeField] + private TemplateOptionsUIHelper m_subShaderOptions = new TemplateOptionsUIHelper( true ); + + [SerializeField] + private TemplateOptionsUIHelper m_passOptions = new TemplateOptionsUIHelper( false ); + + [SerializeField] + private TemplatePassSelectorHelper m_passSelector = new TemplatePassSelectorHelper(); + + [SerializeField] + private TemplateOptionsDefinesContainer m_optionsDefineContainer = new TemplateOptionsDefinesContainer(); + + [SerializeField] + private TerrainDrawInstancedHelper m_drawInstancedHelper = new TerrainDrawInstancedHelper(); + + // HATE THIS BELOW, MUST REMOVE HD SPECIFIC CODE FROM GENERIC MASTER NODE + private const string HDSRPMaterialTypeStr = "Material Type"; + private const string SRPMaterialSubsurfaceScatteringKeyword = "_MATERIAL_FEATURE_SUBSURFACE_SCATTERING 1"; + private const string SRPMaterialTransmissionKeyword = "_MATERIAL_FEATURE_TRANSMISSION 1"; + private const string SRPHDMaterialSpecularKeyword = "_MATERIAL_FEATURE_SPECULAR_COLOR 1"; + //private const string SRPLWMaterialSpecularKeyword = "_SPECULAR_SETUP 1"; + private const string SRPMaterialAnisotropyKeyword = "_MATERIAL_FEATURE_ANISOTROPY 1"; + private const string SRPMaterialIridiscenceKeyword = "_MATERIAL_FEATURE_IRIDESCENCE 1"; + //private const string SRPMaterialNormalMapKeyword = "_NORMALMAP 1"; + //private const string SRPMaterialAlphaTestKeyword = "_ALPHATEST_ON 1"; + //private const string SRPMaterialBlendModeAlphaClipThresholdKeyword = "_AlphaClip 1"; + private const string SRPMaterialTransparentKeyword = "_SURFACE_TYPE_TRANSPARENT 1"; + private const string SRPMaterialBlendModeAddKeyword = "_BLENDMODE_ADD 1"; + private const string SRPMaterialBlendModeAlphaKeyword = "_BLENDMODE_ALPHA 1"; + private const string SRPMaterialClearCoatKeyword = "_MATERIAL_FEATURE_CLEAR_COAT"; + + [NonSerialized] + private bool m_fetchPorts = true; + [NonSerialized] + private InputPort m_specularPort; + [NonSerialized] + private InputPort m_metallicPort; + [NonSerialized] + private InputPort m_coatMaskPort; + [NonSerialized] + private InputPort m_diffusionProfilePort; + [NonSerialized] + private InputPort m_subsurfaceMaskPort; + [NonSerialized] + private InputPort m_thicknessPort; + [NonSerialized] + private InputPort m_anisotropyPort; + [NonSerialized] + private InputPort m_iridescenceThicknessPort; + [NonSerialized] + private InputPort m_iridescenceMaskPort; + [NonSerialized] + private InputPort m_indexOfRefractionPort; + [NonSerialized] + private InputPort m_transmittanceColorPort; + [NonSerialized] + private InputPort m_transmittanceAbsorptionDistancePort; + [NonSerialized] + private InputPort m_transmittanceMaskPort; + + [SerializeField] + private HDSRPMaterialType m_hdSrpMaterialType = HDSRPMaterialType.Standard; + + [NonSerialized] + private bool m_refreshLODValueMasterNodes = false; + [NonSerialized] + private bool m_refocusLODValueMasterNodes = false; + [NonSerialized] + private double m_refreshLODValueMasterNodesTimestamp; + + ////////////////////////////////////////////////////////////////////////// + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_masterNodeCategory = 1;// First Template + m_marginPreviewLeft = 20; + m_shaderNameIsTitle = true; + m_customInspectorName = string.Empty; + m_customPrecision = true; + } + + public override void ReleaseResources() + { + // Internal template resources ( for inline properties) are released by first node on the list + // As it's also registered that way + if( IsLODMainFirstPass ) + m_containerGraph.ClearInternalTemplateNodes(); + + if( !IsLODMainMasterNode ) + return; + TemplateMultiPass template = ( m_templateMultiPass == null ) ? m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( m_templateGUID ) as TemplateMultiPass : m_templateMultiPass; + //Maintained the logic of being the main master node to unregister since this method is being called + //over the main master node in multiple places + //but it will unregister with unique of the first master node (pass 0) since it was the one + //to register it + int passUniqueId = ( m_passIdx == 0 ) ? UniqueId : ContainerGraph.MultiPassMasterNodes.NodesList[ 0 ].UniqueId; + + if( template != null && template.AvailableShaderProperties != null ) + { + // Unregister old template properties + int oldPropertyCount = template.AvailableShaderProperties.Count; + for( int i = 0 ; i < oldPropertyCount ; i++ ) + { + ContainerGraph.ParentWindow.DuplicatePrevBufferInstance.ReleaseUniformName( passUniqueId , template.AvailableShaderProperties[ i ].PropertyName ); + } + } + } + + public void CopyOptionsFrom( TemplateMultiPassMasterNode origin ) + { + //Copy options + SubShaderOptions.CopyOptionsValuesFrom( origin.SubShaderOptions ); + PassOptions.CopyOptionsValuesFrom( origin.PassOptions ); + + //Copy selected passes + if( IsMainOutputNode ) + m_passSelector.CopyFrom( origin.PassSelector ); + } + + void RegisterProperties() + { + //First pass must be the one to always register properties so all modules + //can extract a valid negative Id when reading inline properties + if( /*!IsLODMainMasterNode*/!IsLODMainFirstPass ) + { + m_reRegisterTemplateData = false; + return; + } + + if( m_templateMultiPass != null ) + { + m_reRegisterTemplateData = false; + // Register old template properties + int newPropertyCount = m_templateMultiPass.AvailableShaderProperties.Count; + for( int i = 0 ; i < newPropertyCount ; i++ ) + { + m_containerGraph.AddInternalTemplateNode( m_templateMultiPass.AvailableShaderProperties[ i ] ); + int nodeId = ContainerGraph.ParentWindow.DuplicatePrevBufferInstance.CheckUniformNameOwner( m_templateMultiPass.AvailableShaderProperties[ i ].PropertyName ); + if( nodeId > -1 ) + { + if( UniqueId != nodeId ) + { + ParentNode node = m_containerGraph.GetNode( nodeId ); + if( node != null ) + { + UIUtils.ShowMessage( string.Format( "Template requires property name {0} which is currently being used by {1}. Please rename it and reload template." , m_templateMultiPass.AvailableShaderProperties[ i ].PropertyName , node.Attributes.Name ) ); + } + else + { + UIUtils.ShowMessage( string.Format( "Template requires property name {0} which is currently being on your graph. Please rename it and reload template." , m_templateMultiPass.AvailableShaderProperties[ i ].PropertyName ) ); + } + } + } + else + { + UIUtils.RegisterUniformName( UniqueId , m_templateMultiPass.AvailableShaderProperties[ i ].PropertyName ); + } + } + } + } + + public override void OnEnable() + { + base.OnEnable(); + m_reRegisterTemplateData = true; + + if( m_usePass == null ) + { + m_usePass = ScriptableObject.CreateInstance(); + m_usePass.Init( " Additional Use Passes" ); + } + + if( m_fallbackHelper == null ) + { + m_fallbackHelper = ScriptableObject.CreateInstance(); + m_fallbackHelper.Init(); + } + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + if( UniqueId >= 0 ) + { + if( m_lodIndex == -1 ) + { + m_containerGraph.MultiPassMasterNodes.AddNode( this ); + } + else + { + m_containerGraph.LodMultiPassMasternodes[ m_lodIndex ].AddNode( this ); + } + } + } + + public override void OnInputPortConnected( int portId , int otherNodeId , int otherPortId , bool activateNode = true ) + { + base.OnInputPortConnected( portId , otherNodeId , otherPortId , activateNode ); + m_passOptions.CheckImediateActionsForPort( this , portId ); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + m_passOptions.CheckImediateActionsForPort( this , portId ); + } + + public void ForceTemplateRefresh() + { + SetTemplate( null , false , true , m_subShaderIdx , m_passIdx , SetTemplateSource.HotCodeReload ); + } + + public void SetTemplate( TemplateMultiPass template , bool writeDefaultData , bool fetchMasterNodeCategory , int subShaderIdx , int passIdx , SetTemplateSource source ) + { + if( subShaderIdx > -1 ) + m_subShaderIdx = subShaderIdx; + + if( passIdx > -1 ) + m_passIdx = passIdx; + + ReleaseResources(); + bool hotCodeOrRead = ( template == null ); + m_templateMultiPass = ( hotCodeOrRead ) ? m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( m_templateGUID ) as TemplateMultiPass : template; + if( m_templateMultiPass != null ) + { + + string passName = string.IsNullOrEmpty( m_passUniqueId ) ? ( m_isInvisible == InvisibilityStatus.LockedInvisible ? m_passName : m_originalPassName ) : m_passUniqueId; + int newPassIdx = m_passIdx; + int newSubShaderIdx = m_subShaderIdx; + m_templateMultiPass.GetSubShaderandPassFor( passName , ref newSubShaderIdx , ref newPassIdx ); + if( newPassIdx == -1 || newSubShaderIdx == -1 ) + { + //m_containerGraph.MarkToDelete( this ); + ContainerGraph.ParentWindow.SetOutdatedShaderFromTemplate(); + m_invalidNode = true; + UIUtils.ShowMessage( "Template changed drastically. Removing invalid passes." ); + return; + } + else + { + if( m_passIdx != newPassIdx ) + m_passIdx = newPassIdx; + + if( m_subShaderIdx != newSubShaderIdx ) + m_subShaderIdx = newSubShaderIdx; + } + + m_containerGraph.CurrentSRPType = m_templateMultiPass.SRPtype; + if( m_templateMultiPass.IsSinglePass ) + { + SetAdditonalTitleText( string.Empty ); + } + else if( m_templateMultiPass.SubShaders[ 0 ].MainPass != m_passIdx ) + { + SetAdditonalTitleText( string.Format( SubTitleFormatterStr , m_subShaderIdx , m_passIdx ) ); + } + m_invalidNode = false; + if( m_subShaderIdx >= m_templateMultiPass.SubShaders.Count || + m_passIdx >= m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes.Count ) + { + if( DebugConsoleWindow.DeveloperMode ) + Debug.LogFormat( "Inexisting pass {0}. Cancelling template fetch" , m_originalPassName ); + + return; + } + + m_isMainOutputNode = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].IsMainPass; + if( m_isMainOutputNode ) + { + // We cannot use UIUtils.MasterNodeOnTexture.height since this method can be + // called before UIUtils is initialized + m_insideSize.y = 55; + } + else + { + m_insideSize.y = 0; + } + + //IsMainOutputNode = m_mainMPMasterNode; + if( source != SetTemplateSource.HotCodeReload ) + { + //Only set this if no hotcode reload happens ( via new shader or load ) + m_isInvisible = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].IsInvisible ? InvisibilityStatus.LockedInvisible : InvisibilityStatus.Visible; + } + else + { + // On hot code reload we only need to verify if template pass visibility data changes + // and change accordingly + if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].IsInvisible ) + { + if( m_isInvisible != InvisibilityStatus.LockedInvisible ) + m_isInvisible = InvisibilityStatus.LockedInvisible; + } + else + { + if( m_isInvisible == InvisibilityStatus.LockedInvisible ) + { + m_isInvisible = InvisibilityStatus.Visible; + } + } + } + + m_invisibleOptions = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].InvisibleOptions; + + m_originalPassName = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].PassNameContainer.Data; + + if( !hotCodeOrRead ) + { + if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].LODContainer.Index > -1 ) + { + //m_subShaderLODStr = m_templateMultiPass.SubShaders[ m_subShaderIdx ].LODContainer.Id; + ShaderLOD = Convert.ToInt32( m_templateMultiPass.SubShaders[ m_subShaderIdx ].LODContainer.Data ); + } + else + { + ShaderLOD = 0; + } + } + + m_shaderNameIsTitle = IsMainOutputNode; + m_fetchMasterNodeCategory = fetchMasterNodeCategory; + m_templateGUID = m_templateMultiPass.GUID; + UpdatePortInfo(); + + RegisterProperties(); + + // template is null when hot code reloading or loading from file so inspector name shouldn't be changed + if( !hotCodeOrRead ) + { + m_customInspectorName = m_templateMultiPass.CustomInspectorContainer.Data; + CheckLegacyCustomInspectors(); + if( m_isMainOutputNode ) + { + m_passSelector.Clear(); + m_passSelector.Setup( m_templateMultiPass.SubShaders[ m_subShaderIdx ] ); + } + } + else + { + //Hotcode reload or ReadFromString + // Setup is only made if internal pass array is null + if( m_isMainOutputNode ) + { + m_passSelector.Setup( m_templateMultiPass.SubShaders[ m_subShaderIdx ] ); + } + } + + SetupCustomOptionsFromTemplate( template != null ); + + if( string.IsNullOrEmpty( m_fallbackHelper.RawFallbackShader ) ) + m_fallbackHelper.RawFallbackShader = m_templateMultiPass.FallbackContainer.Data; + + //bool updateInfofromTemplate = UpdatePortInfo(); + //if( updateInfofromTemplate ) + //{ + m_subShaderModule.FetchDataFromTemplate( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules ); + m_passModule.FetchDataFromTemplate( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules ); + //} + + //RegisterProperties(); + if( writeDefaultData ) + { + //ShaderName = m_templateMultiPass.DefaultShaderName; + ShaderName = m_shaderName; + m_passName = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].PassNameContainer.Data; + if( !m_templateMultiPass.IsSinglePass /*&& !m_shaderNameIsTitle*/ ) + { + if( m_templateMultiPass.SubShaders[ 0 ].MainPass != m_passIdx ) + SetClippedTitle( m_passName ); + } + } + + UpdateSubShaderPassStr(); + + if( m_isMainOutputNode ) + m_fireTemplateChange = true; + } + else + { + m_invalidNode = true; + } + } + + public override void OnRefreshLinkedPortsComplete() + { + if( m_invalidNode ) + return; + + if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBRHD ) + ConfigHDPorts(); + + SetReadOptions(); + } + + public void SetReadOptions() + { + m_passOptions.SetReadOptions(); + if( m_isMainOutputNode ) + m_subShaderOptions.SetReadOptions(); + } + + bool UpdatePortInfo() + { + List inputDataList = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].InputDataList; + int count = inputDataList.Count; + if( count != m_inputPorts.Count ) + { + DeleteAllInputConnections( true ); + + for( int i = 0 ; i < count ; i++ ) + { + InputPort port = AddInputPort( inputDataList[ i ].DataType , false , inputDataList[ i ].PortName , inputDataList[ i ].OrderId , inputDataList[ i ].PortCategory , inputDataList[ i ].PortUniqueId ); + port.ExternalLinkId = inputDataList[ i ].LinkId; + m_hasLinkPorts = m_hasLinkPorts || !string.IsNullOrEmpty( inputDataList[ i ].LinkId ); + } + return true; + } + else + { + for( int i = 0 ; i < count ; i++ ) + { + m_inputPorts[ i ].ChangeProperties( inputDataList[ i ].PortName , inputDataList[ i ].DataType , false ); + m_inputPorts[ i ].ExternalLinkId = inputDataList[ i ].LinkId; + } + return false; + } + } + + public void SetPropertyActionFromItem( bool actionFromUser , TemplateModulesHelper module , TemplateActionItem item ) + { + // this was added because when switching templates the m_mainMasterNodeRef was not properly set yet and was causing issues, there's probably a better place for this + if( !m_isMainOutputNode && m_mainMasterNodeRef == null ) + { + m_mainMasterNodeRef = m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode; + } + + TemplateModulesHelper subShaderModule = m_isMainOutputNode ? m_subShaderModule : m_mainMasterNodeRef.SubShaderModule; + switch( item.PropertyAction ) + { + case PropertyActionsEnum.CullMode: + { + if( item.CopyFromSubShader ) + { + module.CullModeHelper.CurrentCullMode = subShaderModule.CullModeHelper.CurrentCullMode; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.CullModeHelper.CustomEdited; + if( performAction ) + { + module.CullModeHelper.CustomEdited = false; + module.CullModeHelper.CurrentCullMode = item.ActionCullMode; + } + } + + } + break; + case PropertyActionsEnum.ColorMask: + { + if( item.CopyFromSubShader ) + module.ColorMaskHelper.ColorMask = subShaderModule.ColorMaskHelper.ColorMask; + else + { + bool performAction = !ContainerGraph.IsLoading || !module.ColorMaskHelper.CustomEdited; + if( performAction ) + { + module.ColorMaskHelper.CustomEdited = false; + module.ColorMaskHelper.ColorMask = item.ColorMask.GetColorMask( module.ColorMaskHelper.ColorMask ); + } + } + } + break; + case PropertyActionsEnum.ColorMask1: + { + if( item.CopyFromSubShader ) + module.ColorMaskHelper1.ColorMask = subShaderModule.ColorMaskHelper1.ColorMask; + else + { + bool performAction = !ContainerGraph.IsLoading || !module.ColorMaskHelper1.CustomEdited; + if( performAction ) + { + module.ColorMaskHelper1.CustomEdited = false; + module.ColorMaskHelper1.ColorMask = item.ColorMask1.GetColorMask( module.ColorMaskHelper1.ColorMask ); + } + } + } + break; + case PropertyActionsEnum.ColorMask2: + { + if( item.CopyFromSubShader ) + module.ColorMaskHelper2.ColorMask = subShaderModule.ColorMaskHelper2.ColorMask; + else + { + bool performAction = !ContainerGraph.IsLoading || !module.ColorMaskHelper2.CustomEdited; + if( performAction ) + { + module.ColorMaskHelper2.CustomEdited = false; + module.ColorMaskHelper2.ColorMask = item.ColorMask2.GetColorMask( module.ColorMaskHelper2.ColorMask ); + } + } + } + break; + case PropertyActionsEnum.ColorMask3: + { + if( item.CopyFromSubShader ) + module.ColorMaskHelper3.ColorMask = subShaderModule.ColorMaskHelper3.ColorMask; + else + { + bool performAction = !ContainerGraph.IsLoading || !module.ColorMaskHelper3.CustomEdited; + if( performAction ) + { + module.ColorMaskHelper3.CustomEdited = false; + module.ColorMaskHelper3.ColorMask = item.ColorMask3.GetColorMask( module.ColorMaskHelper3.ColorMask ); + } + } + } + break; + case PropertyActionsEnum.ZWrite: + { + if( item.CopyFromSubShader ) + { + module.DepthOphelper.ZWriteModeValue = subShaderModule.DepthOphelper.ZWriteModeValue; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.DepthOphelper.CustomEdited; + if( performAction ) + { + module.DepthOphelper.CustomEdited = false; + module.DepthOphelper.ZWriteModeValue = item.ActionZWrite; + } + } + } + break; + case PropertyActionsEnum.ZTest: + { + if( item.CopyFromSubShader ) + { + module.DepthOphelper.ZTestModeValue = subShaderModule.DepthOphelper.ZTestModeValue; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.DepthOphelper.CustomEdited; + if( performAction ) + { + module.DepthOphelper.CustomEdited = false; + module.DepthOphelper.ZTestModeValue = item.ActionZTest; + } + } + } + break; + case PropertyActionsEnum.ZOffsetFactor: + { + if( item.CopyFromSubShader ) + { + module.DepthOphelper.OffsetFactorValue = subShaderModule.DepthOphelper.OffsetFactorValue; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.DepthOphelper.CustomEdited; + if( performAction ) + { + module.DepthOphelper.CustomEdited = false; + module.DepthOphelper.OffsetFactorValue = item.ActionZOffsetFactor; + } + } + } + break; + case PropertyActionsEnum.ZOffsetUnits: + { + if( item.CopyFromSubShader ) + { + module.DepthOphelper.OffsetUnitsValue = subShaderModule.DepthOphelper.OffsetUnitsValue; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.DepthOphelper.CustomEdited; + if( performAction ) + { + module.DepthOphelper.CustomEdited = false; + module.DepthOphelper.OffsetUnitsValue = item.ActionZOffsetUnits; + } + } + } + break; + case PropertyActionsEnum.BlendRGB: + { + if( item.CopyFromSubShader ) + { + module.BlendOpHelper.SourceFactorRGB = subShaderModule.BlendOpHelper.SourceFactorRGB; + module.BlendOpHelper.DestFactorRGB = subShaderModule.BlendOpHelper.DestFactorRGB; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.BlendOpHelper.CustomEdited; + if( performAction ) + { + module.BlendOpHelper.CustomEdited = false; + module.BlendOpHelper.SourceFactorRGB = item.ActionBlendRGBSource; + module.BlendOpHelper.DestFactorRGB = item.ActionBlendRGBDest; + } + } + } + break; + case PropertyActionsEnum.BlendRGB1: + { + if( item.CopyFromSubShader ) + { + module.BlendOpHelper1.SourceFactorRGB = subShaderModule.BlendOpHelper1.SourceFactorRGB; + module.BlendOpHelper1.DestFactorRGB = subShaderModule.BlendOpHelper1.DestFactorRGB; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.BlendOpHelper1.CustomEdited; + if( performAction ) + { + module.BlendOpHelper1.CustomEdited = false; + module.BlendOpHelper1.SourceFactorRGB = item.ActionBlendRGBSource1; + module.BlendOpHelper1.DestFactorRGB = item.ActionBlendRGBDest1; + } + } + } + break; + case PropertyActionsEnum.BlendRGB2: + { + if( item.CopyFromSubShader ) + { + module.BlendOpHelper2.SourceFactorRGB = subShaderModule.BlendOpHelper2.SourceFactorRGB; + module.BlendOpHelper2.DestFactorRGB = subShaderModule.BlendOpHelper2.DestFactorRGB; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.BlendOpHelper2.CustomEdited; + if( performAction ) + { + module.BlendOpHelper2.CustomEdited = false; + module.BlendOpHelper2.SourceFactorRGB = item.ActionBlendRGBSource2; + module.BlendOpHelper2.DestFactorRGB = item.ActionBlendRGBDest2; + } + } + } + break; + case PropertyActionsEnum.BlendRGB3: + { + if( item.CopyFromSubShader ) + { + module.BlendOpHelper3.SourceFactorRGB = subShaderModule.BlendOpHelper3.SourceFactorRGB; + module.BlendOpHelper3.DestFactorRGB = subShaderModule.BlendOpHelper3.DestFactorRGB; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.BlendOpHelper3.CustomEdited; + if( performAction ) + { + module.BlendOpHelper3.CustomEdited = false; + module.BlendOpHelper3.SourceFactorRGB = item.ActionBlendRGBSource3; + module.BlendOpHelper3.DestFactorRGB = item.ActionBlendRGBDest3; + } + } + } + break; + case PropertyActionsEnum.BlendAlpha: + { + if( item.CopyFromSubShader ) + { + module.BlendOpHelper.SourceFactorAlpha = subShaderModule.BlendOpHelper.SourceFactorAlpha; + module.BlendOpHelper.DestFactorAlpha = subShaderModule.BlendOpHelper.DestFactorAlpha; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.BlendOpHelper.CustomEdited; + if( performAction ) + { + module.BlendOpHelper.CustomEdited = false; + module.BlendOpHelper.CurrentAlphaIndex = 1; + module.BlendOpHelper.SourceFactorAlpha = item.ActionBlendAlphaSource; + module.BlendOpHelper.DestFactorAlpha = item.ActionBlendAlphaDest; + } + } + } + break; + case PropertyActionsEnum.BlendAlpha1: + { + if( item.CopyFromSubShader ) + { + module.BlendOpHelper1.SourceFactorAlpha = subShaderModule.BlendOpHelper1.SourceFactorAlpha; + module.BlendOpHelper1.DestFactorAlpha = subShaderModule.BlendOpHelper1.DestFactorAlpha; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.BlendOpHelper1.CustomEdited; + if( performAction ) + { + module.BlendOpHelper1.CustomEdited = false; + module.BlendOpHelper1.CurrentAlphaIndex = 1; + module.BlendOpHelper1.SourceFactorAlpha = item.ActionBlendAlphaSource1; + module.BlendOpHelper1.DestFactorAlpha = item.ActionBlendAlphaDest1; + } + } + } + break; + case PropertyActionsEnum.BlendAlpha2: + { + if( item.CopyFromSubShader ) + { + module.BlendOpHelper2.SourceFactorAlpha = subShaderModule.BlendOpHelper2.SourceFactorAlpha; + module.BlendOpHelper2.DestFactorAlpha = subShaderModule.BlendOpHelper2.DestFactorAlpha; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.BlendOpHelper2.CustomEdited; + if( performAction ) + { + module.BlendOpHelper2.CustomEdited = false; + module.BlendOpHelper2.CurrentAlphaIndex = 1; + module.BlendOpHelper2.SourceFactorAlpha = item.ActionBlendAlphaSource2; + module.BlendOpHelper2.DestFactorAlpha = item.ActionBlendAlphaDest2; + } + } + } + break; + case PropertyActionsEnum.BlendAlpha3: + { + if( item.CopyFromSubShader ) + { + module.BlendOpHelper3.SourceFactorAlpha = subShaderModule.BlendOpHelper3.SourceFactorAlpha; + module.BlendOpHelper3.DestFactorAlpha = subShaderModule.BlendOpHelper3.DestFactorAlpha; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.BlendOpHelper3.CustomEdited; + if( performAction ) + { + module.BlendOpHelper3.CustomEdited = false; + module.BlendOpHelper3.CurrentAlphaIndex = 1; + module.BlendOpHelper3.SourceFactorAlpha = item.ActionBlendAlphaSource3; + module.BlendOpHelper3.DestFactorAlpha = item.ActionBlendAlphaDest3; + } + } + } + break; + case PropertyActionsEnum.BlendOpRGB: + { + if( item.CopyFromSubShader ) + { + module.BlendOpHelper.BlendOpRGB = subShaderModule.BlendOpHelper.BlendOpRGB; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.BlendOpHelper.CustomEdited; + if( performAction ) + { + module.BlendOpHelper.CustomEdited = false; + module.BlendOpHelper.BlendOpRGB = item.ActionBlendOpRGB; + } + } + } + break; + case PropertyActionsEnum.BlendOpAlpha: + { + if( item.CopyFromSubShader ) + { + module.BlendOpHelper.BlendOpAlpha = subShaderModule.BlendOpHelper.BlendOpAlpha; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.BlendOpHelper.CustomEdited; + if( performAction ) + { + module.BlendOpHelper.CustomEdited = false; + module.BlendOpHelper.BlendOpAlpha = item.ActionBlendOpAlpha; + } + } + } + break; + case PropertyActionsEnum.StencilReference: + { + if( item.CopyFromSubShader ) + { + module.StencilBufferHelper.ReferenceValue = subShaderModule.StencilBufferHelper.ReferenceValue; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.StencilBufferHelper.CustomEdited; + if( performAction ) + { + module.StencilBufferHelper.CustomEdited = false; + module.StencilBufferHelper.ReferenceValue = item.ActionStencilReference; + } + } + } + break; + case PropertyActionsEnum.StencilReadMask: + { + if( item.CopyFromSubShader ) + { + module.StencilBufferHelper.ReadMaskValue = subShaderModule.StencilBufferHelper.ReadMaskValue; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.StencilBufferHelper.CustomEdited; + if( performAction ) + { + module.StencilBufferHelper.CustomEdited = false; + module.StencilBufferHelper.ReadMaskValue = item.ActionStencilReadMask; + } + } + } + break; + case PropertyActionsEnum.StencilWriteMask: + { + if( item.CopyFromSubShader ) + { + module.StencilBufferHelper.WriteMaskValue = subShaderModule.StencilBufferHelper.WriteMaskValue; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.StencilBufferHelper.CustomEdited; + if( performAction ) + { + module.StencilBufferHelper.CustomEdited = false; + module.StencilBufferHelper.WriteMaskValue = item.ActionStencilWriteMask; + } + } + } + break; + case PropertyActionsEnum.StencilComparison: + { + if( item.CopyFromSubShader ) + { + module.StencilBufferHelper.ComparisonFunctionIdxValue = subShaderModule.StencilBufferHelper.ComparisonFunctionIdxValue; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.StencilBufferHelper.CustomEdited; + if( performAction ) + { + module.StencilBufferHelper.CustomEdited = false; + module.StencilBufferHelper.ComparisonFunctionIdxValue = item.ActionStencilComparison; + } + } + } + break; + case PropertyActionsEnum.StencilPass: + { + if( item.CopyFromSubShader ) + { + module.StencilBufferHelper.PassStencilOpIdxValue = subShaderModule.StencilBufferHelper.PassStencilOpIdxValue; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.StencilBufferHelper.CustomEdited; + if( performAction ) + { + module.StencilBufferHelper.CustomEdited = false; + module.StencilBufferHelper.PassStencilOpIdxValue = item.ActionStencilPass; + } + } + } + break; + case PropertyActionsEnum.StencilFail: + { + if( item.CopyFromSubShader ) + { + module.StencilBufferHelper.FailStencilOpIdxValue = subShaderModule.StencilBufferHelper.FailStencilOpIdxValue; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.StencilBufferHelper.CustomEdited; + if( performAction ) + { + module.StencilBufferHelper.CustomEdited = false; + module.StencilBufferHelper.FailStencilOpIdxValue = item.ActionStencilFail; + } + } + } + break; + case PropertyActionsEnum.StencilZFail: + { + if( item.CopyFromSubShader ) + { + module.StencilBufferHelper.ZFailStencilOpIdxValue = subShaderModule.StencilBufferHelper.ZFailStencilOpIdxValue; + } + else + { + bool performAction = !ContainerGraph.IsLoading || !module.StencilBufferHelper.CustomEdited; + if( performAction ) + { + module.StencilBufferHelper.CustomEdited = false; + module.StencilBufferHelper.ZFailStencilOpIdxValue = item.ActionStencilZFail; + } + } + } + break; + case PropertyActionsEnum.RenderType: + { + module.TagsHelper.AddSpecialTag( TemplateSpecialTags.RenderType , item ); + } + break; + case PropertyActionsEnum.RenderQueue: + { + module.TagsHelper.AddSpecialTag( TemplateSpecialTags.Queue , item ); + } + break; + case PropertyActionsEnum.DisableBatching: + { + module.TagsHelper.AddSpecialTag( TemplateSpecialTags.DisableBatching , item ); + } + break; + } + } + + public void OnCustomPassOptionSelected( bool actionFromUser , bool isRefreshing , bool invertAction , TemplateOptionUIItem uiItem , params TemplateActionItem[] validActions ) + { + m_passOptions.OnCustomOptionSelected( actionFromUser , isRefreshing , invertAction , this , uiItem , validActions ); + } + + public void OnCustomSubShaderOptionSelected( bool actionFromUser , bool isRefreshing , bool invertAction , TemplateOptionUIItem uiItem , params TemplateActionItem[] validActions ) + { + if( m_isMainOutputNode ) + m_subShaderOptions.OnCustomOptionSelected( actionFromUser , isRefreshing , invertAction , this , uiItem , validActions ); + } + + void SetupCustomOptionsFromTemplate( bool newTemplate ) + { + m_passOptions.SetupCustomOptionsFromTemplate( this , newTemplate ); + if( m_isMainOutputNode ) + m_subShaderOptions.SetupCustomOptionsFromTemplate( this , newTemplate ); + } + + void SetPassCustomOptionsInfo( TemplateMultiPassMasterNode masterNode ) + { + TemplateMultiPassMasterNode mainMasterNode = masterNode.IsMainOutputNode ? masterNode : ( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ); + mainMasterNode.SubShaderOptions.SetSubShaderCustomOptionsPortsInfo( masterNode , ref m_currentDataCollector ); + masterNode.PassOptions.SetCustomOptionsInfo( masterNode , ref m_currentDataCollector ); + } + + void RefreshCustomOptionsDict() + { + m_passOptions.RefreshCustomOptionsDict(); + if( m_isMainOutputNode ) + m_subShaderOptions.RefreshCustomOptionsDict(); + } + + void SetCategoryIdxFromTemplate() + { + int templateCount = m_containerGraph.ParentWindow.TemplatesManagerInstance.TemplateCount; + for( int i = 0 ; i < templateCount ; i++ ) + { + int idx = i + 1; + TemplateMultiPass templateData = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( i ) as TemplateMultiPass; + if( templateData != null && m_templateMultiPass != null && m_templateMultiPass.GUID.Equals( templateData.GUID ) ) + m_masterNodeCategory = idx; + } + } + + public void CheckTemplateChanges() + { + if( m_invalidNode ) + return; + + if( IsLODMainMasterNode ) + { + if( m_containerGraph.MultiPassMasterNodes.Count != m_templateMultiPass.MasterNodesRequired ) + { + if( m_availableCategories == null ) + RefreshAvailableCategories(); + + if( DebugConsoleWindow.DeveloperMode ) + Debug.Log( "Template Pass amount was changed. Rebuiling master nodes" ); + + m_containerGraph.ParentWindow.ReplaceMasterNode( m_availableCategories[ m_masterNodeCategory ] , true ); + } + } + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + if( m_invalidNode ) + { + return; + } + base.OnNodeLogicUpdate( drawInfo ); + + if( m_templateMultiPass == null ) + { + // Hotcode reload has happened + SetTemplate( null , false , true , m_subShaderIdx , m_passIdx , SetTemplateSource.HotCodeReload ); + CheckTemplateChanges(); + } + + if( m_reRegisterTemplateData ) + { + RegisterProperties(); + } + + if( m_fetchMasterNodeCategory ) + { + if( m_availableCategories != null ) + { + m_fetchMasterNodeCategory = false; + SetCategoryIdxFromTemplate(); + } + } + + if( m_fireTemplateChange ) + { + m_fireTemplateChange = false; + m_containerGraph.FireMasterNodeReplacedEvent(); + } + + if( m_subShaderModule.HasValidData ) + { + m_subShaderModule.OnLogicUpdate( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules ); + } + + if( m_passModule.HasValidData ) + { + m_passModule.OnLogicUpdate( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules ); + } + + if( !m_isMainOutputNode && m_mainMasterNodeRef == null ) + { + m_mainMasterNodeRef = m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode; + } + + if( m_refreshLODValueMasterNodes && ( EditorApplication.timeSinceStartup - m_refreshLODValueMasterNodesTimestamp ) > MaxLODEditTimestamp ) + { + m_refreshLODValueMasterNodes = false; + m_refocusLODValueMasterNodes = true; + m_containerGraph.SortLODMasterNodes(); + } + } + + public override void Draw( DrawInfo drawInfo ) + { + if( m_isInvisible == InvisibilityStatus.Visible ) + { + base.Draw( drawInfo ); + } + } + + public override void OnNodeLayout( DrawInfo drawInfo ) + { + if( m_invalidNode ) + { + if( m_isMainOutputNode ) + { + string newGUID = string.Empty; + if( m_containerGraph.ParentWindow.TemplatesManagerInstance.CheckIfDeprecated( m_templateGUID , out newGUID ) ) + { + m_shaderModelIdx = 0; + SetMasterNodeCategoryFromGUID( newGUID ); + m_containerGraph.ParentWindow.ReplaceMasterNode( m_availableCategories[ m_masterNodeCategory ] , false ); + } + else + { + UIUtils.ShowMessage( "Invalid current template. Switching to Standard Surface" , MessageSeverity.Error ); + m_shaderModelIdx = 0; + m_masterNodeCategory = 0; + m_containerGraph.ParentWindow.ReplaceMasterNode( new MasterNodeCategoriesData( AvailableShaderTypes.SurfaceShader , m_shaderName ) , false ); + } + } + return; + } + + if( m_isInvisible != InvisibilityStatus.Visible ) + { + return; + } + + if( !IsMainOutputNode ) + { + if( !IsInvisible && Docking ) + { + m_useSquareNodeTitle = true; + TemplateMultiPassMasterNode master = ContainerGraph.CurrentMasterNode as TemplateMultiPassMasterNode; + m_position = master.TruePosition; + m_position.height = 32; + int masterIndex = ContainerGraph.MultiPassMasterNodes.NodesList.IndexOf( master ); + int index = ContainerGraph.MultiPassMasterNodes.GetNodeRegisterIdx( UniqueId ); + if( index > masterIndex ) + { + int backTracking = 0; + for( int i = index - 1 ; i > masterIndex ; i-- ) + { + if( !ContainerGraph.MultiPassMasterNodes.NodesList[ i ].IsInvisible && ContainerGraph.MultiPassMasterNodes.NodesList[ i ].Docking ) + backTracking++; + } + m_position.y = master.TruePosition.yMax + 1 + 33 * ( backTracking );// ContainerGraph.MultiPassMasterNodes.NodesList[ index - 1 ].TruePosition.yMax; + base.OnNodeLayout( drawInfo ); + } + else + { + int forwardTracking = 1; + for( int i = index + 1 ; i < masterIndex ; i++ ) + { + if( !ContainerGraph.MultiPassMasterNodes.NodesList[ i ].IsInvisible && ContainerGraph.MultiPassMasterNodes.NodesList[ i ].Docking ) + forwardTracking++; + } + m_position.y = master.TruePosition.y - 33 * ( forwardTracking );// ContainerGraph.MultiPassMasterNodes.NodesList[ index - 1 ].TruePosition.yMax; + base.OnNodeLayout( drawInfo ); + } + } + else + { + m_useSquareNodeTitle = false; + base.OnNodeLayout( drawInfo ); + } + } + else + { + base.OnNodeLayout( drawInfo ); + } + } + + public override void OnNodeRepaint( DrawInfo drawInfo ) + { + base.OnNodeRepaint( drawInfo ); + if( m_invalidNode ) + return; + + if( m_isInvisible == InvisibilityStatus.Visible ) + { + if( m_containerGraph.IsInstancedShader ) + { + DrawInstancedIcon( drawInfo ); + } + } + } + + public override void UpdateFromShader( Shader newShader ) + { + if( m_currentMaterial != null && m_currentMaterial.shader != newShader ) + { + m_currentMaterial.shader = newShader; + } + CurrentShader = newShader; + } + + public override void UpdateMasterNodeMaterial( Material material ) + { + m_currentMaterial = material; + FireMaterialChangedEvt(); + } + + void DrawReloadButton() + { + if( GUILayout.Button( ReloadTemplateStr ) && m_templateMultiPass != null ) + { + m_templateMultiPass.Reload(); + } + } + + void DrawOpenTemplateButton() + { + GUILayout.BeginHorizontal(); + { + if( GUILayout.Button( OpenTemplateStr ) && m_templateMultiPass != null ) + { + try + { + string pathname = AssetDatabase.GUIDToAssetPath( m_templateMultiPass.GUID ); + if( !string.IsNullOrEmpty( pathname ) ) + { + Shader selectedTemplate = AssetDatabase.LoadAssetAtPath( pathname ); + if( selectedTemplate != null ) + { + AssetDatabase.OpenAsset( selectedTemplate , 1 ); + } + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + + if( GUILayout.Button( "\u25C4" , GUILayout.Width( 18 ) , GUILayout.Height( 18 ) ) && m_templateMultiPass != null ) + { + try + { + string pathname = AssetDatabase.GUIDToAssetPath( m_templateMultiPass.GUID ); + if( !string.IsNullOrEmpty( pathname ) ) + { + Shader selectedTemplate = AssetDatabase.LoadAssetAtPath( pathname ); + if( selectedTemplate != null ) + { + Event.current.Use(); + Selection.activeObject = selectedTemplate; + EditorGUIUtility.PingObject( Selection.activeObject ); + } + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + } + GUILayout.EndHorizontal(); + } + + public override void DrawProperties() + { + base.DrawProperties(); + if( m_invalidNode ) + return; + + NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout , CommonPropertiesStr , DrawCommonProperties ); + NodeUtils.DrawPropertyGroup( ref m_subStringFoldout , SubShaderModuleStr , DrawSubShaderProperties ); + NodeUtils.DrawPropertyGroup( ref m_passFoldout , PassModuleStr , DrawPassProperties ); + + DrawMaterialInputs( UIUtils.MenuItemToolbarStyle , false ); + + if( m_propertyOrderChanged ) + { + List mpNodes = ContainerGraph.MultiPassMasterNodes.NodesList; + int count = mpNodes.Count; + for( int i = 0 ; i < count ; i++ ) + { + if( mpNodes[ i ].UniqueId != UniqueId ) + { + mpNodes[ i ].CopyPropertyListFrom( this ); + } + } + } + +#if SHOW_TEMPLATE_HELP_BOX + EditorGUILayout.HelpBox( WarningMessage, MessageType.Warning ); +#endif + } + + // this will be removed later when PBR options are created + void SetExtraDefine( string define ) + { + List nodes = this.ContainerGraph.MultiPassMasterNodes.NodesList; + int count = nodes.Count; + for( int nodeIdx = 0 ; nodeIdx < count ; nodeIdx++ ) + { + nodes[ nodeIdx ].OptionsDefineContainer.AddDirective( "#define " + define , false ); + } + } + + void AddHDKeywords() + { + if( m_templateMultiPass.CustomTemplatePropertyUI == CustomTemplatePropertyUIEnum.None ) + return; + + if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType != TemplateSRPType.HD || + !m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBR ) + return; + + switch( m_hdSrpMaterialType ) + { + case HDSRPMaterialType.SubsurfaceScattering: + { + SetExtraDefine( SRPMaterialSubsurfaceScatteringKeyword ); + //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialSubsurfaceScatteringKeyword ); + if( m_thicknessPort != null && m_thicknessPort.HasOwnOrLinkConnection ) + { + SetExtraDefine( SRPMaterialTransmissionKeyword ); + //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialTransmissionKeyword ); + } + } + break; + case HDSRPMaterialType.Standard: + break; + case HDSRPMaterialType.Specular: + { + SetExtraDefine( SRPHDMaterialSpecularKeyword ); + //m_currentDataCollector.AddToDefines( UniqueId, SRPHDMaterialSpecularKeyword ); + } + break; + case HDSRPMaterialType.Anisotropy: + { + SetExtraDefine( SRPMaterialAnisotropyKeyword ); + //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialAnisotropyKeyword ); + } + break; + case HDSRPMaterialType.Iridescence: + { + SetExtraDefine( SRPMaterialIridiscenceKeyword ); + //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialIridiscenceKeyword ); + } + break; + case HDSRPMaterialType.Translucent: + { + SetExtraDefine( SRPMaterialTransmissionKeyword ); + //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialTransmissionKeyword ); + } + break; + } + + if( m_coatMaskPort != null && m_coatMaskPort.HasOwnOrLinkConnection ) + { + SetExtraDefine( SRPMaterialClearCoatKeyword ); + //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialClearCoatKeyword ); + } + } + + void FetchHDPorts() + { + if( m_fetchPorts ) + { + m_fetchPorts = false; + if( m_inputPorts.Count > 4 ) + { + m_specularPort = GetInputPortByUniqueId( 3 ); + m_metallicPort = GetInputPortByUniqueId( 4 ); + m_coatMaskPort = GetInputPortByUniqueId( 11 ); + m_diffusionProfilePort = GetInputPortByUniqueId( 12 ); + m_subsurfaceMaskPort = GetInputPortByUniqueId( 13 ); + m_thicknessPort = GetInputPortByUniqueId( 14 ); + m_anisotropyPort = GetInputPortByUniqueId( 15 ); + m_iridescenceThicknessPort = GetInputPortByUniqueId( 16 ); + m_iridescenceMaskPort = GetInputPortByUniqueId( 17 ); + m_indexOfRefractionPort = GetInputPortByUniqueId( 18 ); + m_transmittanceColorPort = GetInputPortByUniqueId( 19 ); + m_transmittanceAbsorptionDistancePort = GetInputPortByUniqueId( 20 ); + m_transmittanceMaskPort = GetInputPortByUniqueId( 21 ); + } + } + } + + void ConfigHDPorts() + { + if( m_templateMultiPass.CustomTemplatePropertyUI == CustomTemplatePropertyUIEnum.None ) + return; + + if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType != TemplateSRPType.HD || + !m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBR ) + return; + + FetchHDPorts(); + if( m_inputPorts.Count > 4 ) + { + switch( m_hdSrpMaterialType ) + { + case HDSRPMaterialType.SubsurfaceScattering: + { + m_specularPort.Visible = false; + m_metallicPort.Visible = false; + m_coatMaskPort.Visible = true; + m_diffusionProfilePort.Visible = true; + m_subsurfaceMaskPort.Visible = true; + m_thicknessPort.Visible = true; + m_anisotropyPort.Visible = false; + m_iridescenceThicknessPort.Visible = false; + m_iridescenceMaskPort.Visible = false; + m_indexOfRefractionPort.Visible = false; + m_transmittanceColorPort.Visible = false; + m_transmittanceAbsorptionDistancePort.Visible = false; + m_transmittanceMaskPort.Visible = false; + } + break; + case HDSRPMaterialType.Standard: + { + m_specularPort.Visible = false; + m_metallicPort.Visible = true; + m_coatMaskPort.Visible = true; + m_diffusionProfilePort.Visible = false; + m_subsurfaceMaskPort.Visible = false; + m_thicknessPort.Visible = false; + m_anisotropyPort.Visible = false; + m_iridescenceThicknessPort.Visible = false; + m_iridescenceMaskPort.Visible = false; + m_indexOfRefractionPort.Visible = false; + m_transmittanceColorPort.Visible = false; + m_transmittanceAbsorptionDistancePort.Visible = false; + m_transmittanceMaskPort.Visible = false; + } + break; + case HDSRPMaterialType.Specular: + { + m_specularPort.Visible = true; + m_metallicPort.Visible = false; + m_coatMaskPort.Visible = true; + m_diffusionProfilePort.Visible = false; + m_subsurfaceMaskPort.Visible = false; + m_thicknessPort.Visible = false; + m_anisotropyPort.Visible = false; + m_iridescenceThicknessPort.Visible = false; + m_iridescenceMaskPort.Visible = false; + m_indexOfRefractionPort.Visible = false; + m_transmittanceColorPort.Visible = false; + m_transmittanceAbsorptionDistancePort.Visible = false; + m_transmittanceMaskPort.Visible = false; + } + break; + case HDSRPMaterialType.Anisotropy: + { + m_specularPort.Visible = false; + m_metallicPort.Visible = true; + m_coatMaskPort.Visible = true; + m_diffusionProfilePort.Visible = false; + m_subsurfaceMaskPort.Visible = false; + m_thicknessPort.Visible = false; + m_anisotropyPort.Visible = true; + m_iridescenceThicknessPort.Visible = false; + m_iridescenceMaskPort.Visible = false; + m_indexOfRefractionPort.Visible = false; + m_transmittanceColorPort.Visible = false; + m_transmittanceAbsorptionDistancePort.Visible = false; + m_transmittanceMaskPort.Visible = false; + } + break; + case HDSRPMaterialType.Iridescence: + { + m_specularPort.Visible = false; + m_metallicPort.Visible = true; + m_coatMaskPort.Visible = true; + m_diffusionProfilePort.Visible = false; + m_subsurfaceMaskPort.Visible = false; + m_thicknessPort.Visible = false; + m_anisotropyPort.Visible = false; + m_iridescenceThicknessPort.Visible = true; + m_iridescenceMaskPort.Visible = true; + m_indexOfRefractionPort.Visible = false; + m_transmittanceColorPort.Visible = false; + m_transmittanceAbsorptionDistancePort.Visible = false; + m_transmittanceMaskPort.Visible = false; + } + break; + case HDSRPMaterialType.Translucent: + { + m_specularPort.Visible = false; + m_metallicPort.Visible = false; + m_coatMaskPort.Visible = false; + m_diffusionProfilePort.Visible = true; + m_subsurfaceMaskPort.Visible = false; + m_thicknessPort.Visible = true; + m_anisotropyPort.Visible = false; + m_iridescenceThicknessPort.Visible = false; + m_iridescenceMaskPort.Visible = false; + m_indexOfRefractionPort.Visible = false; + m_transmittanceColorPort.Visible = false; + m_transmittanceAbsorptionDistancePort.Visible = false; + m_transmittanceMaskPort.Visible = false; + } + break; + } + } + m_sizeIsDirty = ( m_isInvisible == InvisibilityStatus.Visible ); + } + + + public void SetShaderLODValueAndLabel( int value ) + { + if( ShaderLOD != value ) + ShaderLOD = value; + + if( ContainerGraph.HasLODs ) + { + SetClippedAdditionalTitle( string.Format( LodSubtitle , ShaderLOD ) ); + } + else + { + SetAdditonalTitleText( string.Empty ); + } + } + + void DrawLODAddRemoveButtons() + { + DrawLODAddRemoveButtons( -2 , true ); + } + + void DrawLODAddRemoveButtons( int index , bool showRemove ) + { + if( GUILayoutButton( string.Empty , UIUtils.PlusStyle , GUILayout.Width( 15 ) ) ) + { + Vector2 minPos = Vec2Position; + //bool newNodePositionMode = false; + //if( newNodePositionMode ) + //{ + // for( int lod = 0; lod < ContainerGraph.LodMultiPassMasternodes.Count; lod++ ) + // { + // if( ContainerGraph.LodMultiPassMasternodes[ lod ].Count != 0 ) + // { + // Vector2 currPos = ContainerGraph.LodMultiPassMasternodes[ lod ].NodesList[ m_passIdx ].Vec2Position; + // if( currPos.y > minPos.y ) + // { + // minPos = currPos; + // } + // } + // else + // { + // if( index < 0 ) + // { + // index = lod; + // } + // break; + // } + // } + //} + //else + //{ + for( int lod = ContainerGraph.LodMultiPassMasternodes.Count - 1 ; lod >= 0 ; lod-- ) + { + if( ContainerGraph.LodMultiPassMasternodes[ lod ].Count != 0 ) + { + minPos = ContainerGraph.LodMultiPassMasternodes[ lod ].NodesList[ m_passIdx ].Vec2Position; + break; + } + } + //} + + minPos.y += HeightEstimate + 10; + ContainerGraph.CreateLodMasterNodes( m_templateMultiPass , index , minPos ); + } + + if( showRemove && GUILayoutButton( string.Empty , UIUtils.MinusStyle , GUILayout.Width( 15 ) ) ) + { + ContainerGraph.DestroyLodMasterNodes( index ); + } + } + + void SetupLODNodeName() + { + if( IsMainOutputNode ) + { + if( string.IsNullOrEmpty( m_mainLODName ) ) + { + m_shaderNameIsTitle = true; + m_content.text = GenerateClippedTitle( m_croppedShaderName ); + } + else + { + m_shaderNameIsTitle = false; + m_content.text = GenerateClippedTitle( m_mainLODName ); + } + } + else + { + m_shaderNameIsTitle = false; + m_content.text = GenerateClippedTitle( m_passName ); + } + } + + public void DrawLodRowItem( bool listMode ) + { + float labelWidthBuffer = EditorGUIUtility.labelWidth; + EditorGUILayout.BeginHorizontal(); + if( listMode ) + { + if( GUILayout.Button( "\u25b6" , GUILayout.Width( 18 ) , GUILayout.Height( 18 ) ) ) + { + m_containerGraph.ParentWindow.FocusOnNode( this , 1 , false , true ); + } + EditorGUI.BeginChangeCheck(); + GUI.SetNextControlName( LodValueId + m_lodIndex ); + m_shaderLOD = EditorGUILayoutIntField( string.Empty , m_shaderLOD , GUILayout.Width( 50 ) ); + } + else + { + EditorGUI.BeginChangeCheck(); + EditorGUIUtility.labelWidth = 45; + GUI.SetNextControlName( LodValueId + m_lodIndex ); + m_shaderLOD = EditorGUILayoutIntField( "LOD" , ShaderLOD , GUILayout.Width( 100 ) ); + EditorGUIUtility.labelWidth = labelWidthBuffer; + } + + if( EditorGUI.EndChangeCheck() ) + { + m_refreshLODValueMasterNodes = true; + m_refreshLODValueMasterNodesTimestamp = EditorApplication.timeSinceStartup; + + if( ContainerGraph.HasLODs ) + SetClippedAdditionalTitle( string.Format( LodSubtitle , ShaderLOD ) ); + } + + EditorGUI.BeginChangeCheck(); + GUI.SetNextControlName( LodNameId + ShaderLOD ); + if( listMode ) + { + m_mainLODName = EditorGUILayoutTextField( string.Empty , m_mainLODName , GUILayout.Width( 100 ) ); + } + else + { + GUILayout.Space( -15 ); + EditorGUIUtility.labelWidth = 45; + m_mainLODName = EditorGUILayoutTextField( string.Empty , m_mainLODName ); + EditorGUIUtility.labelWidth = labelWidthBuffer; + } + if( EditorGUI.EndChangeCheck() ) + { + // If reorder is scheduled make sure it doesn't happen when editing LOD name + if( m_refreshLODValueMasterNodes ) + m_refreshLODValueMasterNodesTimestamp = EditorApplication.timeSinceStartup; + + SetupLODNodeName(); + } + + if( listMode ) + DrawLODAddRemoveButtons( m_lodIndex , ( m_lodIndex >= 0 ) ); + + EditorGUILayout.EndHorizontal(); + + if( m_refocusLODValueMasterNodes ) + { + m_refocusLODValueMasterNodes = false; + string focusedControl = GUI.GetNameOfFocusedControl(); + if( focusedControl.Contains( LodValueId ) ) + { + GUI.FocusControl( LodValueId + m_lodIndex ); + TextEditor te = (TextEditor)GUIUtility.GetStateObject( typeof( TextEditor ) , GUIUtility.keyboardControl ); + if( te != null ) + { + te.SelectTextEnd(); + } + } + else if( focusedControl.Contains( LodNameId ) ) + { + GUI.FocusControl( LodNameId + m_lodIndex ); + TextEditor te = (TextEditor)GUIUtility.GetStateObject( typeof( TextEditor ) , GUIUtility.keyboardControl ); + if( te != null ) + { + te.SelectTextEnd(); + } + } + } + } + + void DrawLOD() + { + if( m_templateMultiPass.CanAddLODs && m_lodIndex == -1 ) + { + EditorGUILayout.Space(); + + DrawLodRowItem( true ); + EditorGUILayout.Space(); + + for( int i = 0 ; i < ContainerGraph.LodMultiPassMasternodes.Count ; i++ ) + { + if( ContainerGraph.LodMultiPassMasternodes[ i ].NodesList.Count > 0 ) + { + TemplateMultiPassMasterNode masterNode = m_containerGraph.LodMultiPassMasternodes[ i ].NodesList[ m_passIdx ]; + masterNode.DrawLodRowItem( true ); + EditorGUILayout.Space(); + } + } + EditorGUILayout.Space(); + } + } + + void DrawCommonProperties() + { + if( m_isMainOutputNode ) + { + //if( m_templateMultiPass.CanAddLODs && m_lodIndex == -1 ) + //{ + // if( GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( 15 ) ) ) + // { + // ContainerGraph.CreateLodMasterNodes( m_templateMultiPass, Vec2Position ); + // } + + + // if( GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( 15 ) ) ) + // { + // ContainerGraph.DestroyLodMasterNodes(); + // } + + //} + + //EditorGUILayout.LabelField( "LOD: " + m_lodIndex ); + DrawShaderName(); + DrawCurrentShaderType(); + + if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBRHD ) + { + if( m_templateMultiPass.CustomTemplatePropertyUI == CustomTemplatePropertyUIEnum.HDPBR ) + { + EditorGUI.BeginChangeCheck(); + CurrentHDMaterialType = (HDSRPMaterialType)EditorGUILayoutEnumPopup( HDSRPMaterialTypeStr , m_hdSrpMaterialType ); + if( EditorGUI.EndChangeCheck() ) + ConfigHDPorts(); + } + } + + EditorGUI.BeginChangeCheck(); + DrawPrecisionProperty( false ); + if( EditorGUI.EndChangeCheck() ) + ContainerGraph.CurrentPrecision = m_currentPrecisionType; + + DrawSamplingMacros(); + + m_drawInstancedHelper.Draw( this ); + m_fallbackHelper.Draw( this ); + DrawCustomInspector( m_templateMultiPass.SRPtype != TemplateSRPType.BuiltIn ); + m_subShaderOptions.DrawCustomOptions( this ); + m_dependenciesHelper.Draw( this , true ); + } + //EditorGUILayout.LabelField( m_subShaderIdxStr ); + //EditorGUILayout.LabelField( m_passIdxStr ); + + if( IsLODMainMasterNode && m_templateMultiPass.CanAddLODs ) + { + NodeUtils.DrawNestedPropertyGroup( ref m_lodFoldout , AdditionalLODsStr , DrawLOD , DrawLODAddRemoveButtons ); + } + + DrawOpenTemplateButton(); + if( DebugConsoleWindow.DeveloperMode ) + DrawReloadButton(); + + } + + public void DrawSubShaderProperties() + { + if( !m_isMainOutputNode ) + { + m_mainMasterNodeRef.DrawSubShaderProperties(); + return; + } + + bool noValidData = true; + if( ShaderLOD > 0 ) + { + noValidData = false; + if( m_templateMultiPass.CanAddLODs && m_containerGraph.LodMultiPassMasternodes[ 0 ].Count > 0 ) + { + DrawLodRowItem( false ); + } + else + { + ShaderLOD = EditorGUILayoutIntField( SubShaderLODValueLabel , ShaderLOD ); + } + } + + if( m_subShaderModule.HasValidData ) + { + noValidData = false; + m_subShaderModule.Draw( this , m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules ); + //if( m_subShaderModule.IsDirty ) + //{ + // List mpNodes = UIUtils.CurrentWindow.CurrentGraph.MultiPassMasterNodes.NodesList; + // int count = mpNodes.Count; + // for( int i = 0; i < count; i++ ) + // { + // if( mpNodes[ i ].SubShaderIdx == m_subShaderIdx && mpNodes[ i ].UniqueId != UniqueId ) + // { + // mpNodes[ i ].SubShaderModule.CopyFrom( m_subShaderModule ); + // } + // } + // m_subShaderModule.IsDirty = false; + //} + } + + m_passSelector.Draw( this ); + + if( noValidData ) + { + EditorGUILayout.HelpBox( NoSubShaderPropertyStr , MessageType.Info ); + } + } + + void DrawPassProperties() + { + EditorGUI.BeginChangeCheck(); + m_passName = EditorGUILayoutTextField( PassNameStr , m_passName ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_passName.Length > 0 ) + { + m_passName = UIUtils.RemoveShaderInvalidCharacters( m_passName ); + } + else + { + m_passName = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].PassNameContainer.Data; + } + //if( !m_templateMultiPass.IsSinglePass ) + // SetClippedTitle( m_passName ); + } + EditorGUILayout.LabelField( Pass.Modules.PassUniqueName ); + if( m_passModule.HasValidData ) + { + m_passModule.Draw( this , m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules , m_subShaderModule ); + } + + m_usePass.Draw( this , false ); + m_passOptions.DrawCustomOptions( this ); + } + + bool CreateInstructionsForList( TemplateData templateData , ref List ports , ref string shaderBody , ref List vertexInstructions , ref List fragmentInstructions ) + { + if( ports.Count == 0 ) + return true; + AddHDKeywords(); + bool isValid = true; + //UIUtils.CurrentWindow.CurrentGraph.ResetNodesLocalVariables(); + for( int i = 0 ; i < ports.Count ; i++ ) + { + TemplateInputData inputData = templateData.InputDataFromId( ports[ i ].PortId ); + if( ports[ i ].HasOwnOrLinkConnection ) + { + //if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType == TemplateSRPType.Lightweight ) + //{ + // if( ports[ i ].Name.Contains( "Normal" ) ) + // { + // m_currentDataCollector.AddToDirectives( SRPMaterialNormalMapKeyword, -1, AdditionalLineType.Define ); + // } + + // if( ports[ i ].Name.Contains( "Alpha Clip Threshold" ) ) + // { + // m_currentDataCollector.AddToDirectives( SRPMaterialBlendModeAlphaClipThresholdKeyword, -1, AdditionalLineType.Define ); + // } + + // if( ports[ i ].Name.Contains( "Specular" ) ) + // { + // m_currentDataCollector.AddToDirectives( SRPLWMaterialSpecularKeyword, -1, AdditionalLineType.Define ); + // } + //} + //else if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType == TemplateSRPType.HD ) + //{ + // if( ports[ i ].Name.Contains( "Normal" ) ) + // { + // //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialNormalMapKeyword ); + // } + + // if( ports[ i ].Name.Contains( "Alpha Clip Threshold" ) ) + // { + // //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialAlphaTestKeyword ); + // } + + //} + + m_currentDataCollector.ResetInstructions(); + m_currentDataCollector.ResetVertexInstructions(); + + m_currentDataCollector.PortCategory = ports[ i ].Category; + string newPortInstruction = ports[ i ].GeneratePortInstructions( ref m_currentDataCollector ); + + if( m_currentDataCollector.DirtySpecialLocalVariables ) + { + string cleanVariables = m_currentDataCollector.SpecialLocalVariables.Replace( "\t" , string.Empty ); + m_currentDataCollector.AddInstructions( cleanVariables , false ); + m_currentDataCollector.ClearSpecialLocalVariables(); + } + + if( m_currentDataCollector.DirtyVertexVariables ) + { + string cleanVariables = m_currentDataCollector.VertexLocalVariables.Replace( "\t" , string.Empty ); + m_currentDataCollector.AddVertexInstruction( cleanVariables , UniqueId , false ); + m_currentDataCollector.ClearVertexLocalVariables(); + } + + // fill functions + for( int j = 0 ; j < m_currentDataCollector.InstructionsList.Count ; j++ ) + { + fragmentInstructions.Add( m_currentDataCollector.InstructionsList[ j ].PropertyName ); + } + + for( int j = 0 ; j < m_currentDataCollector.VertexDataList.Count ; j++ ) + { + vertexInstructions.Add( m_currentDataCollector.VertexDataList[ j ].PropertyName ); + } + + m_templateMultiPass.SetPassInputData( m_subShaderIdx , m_passIdx , ports[ i ].PortId , newPortInstruction ); + isValid = m_templateMultiPass.FillTemplateBody( m_subShaderIdx , m_passIdx , inputData.TagId , ref shaderBody , newPortInstruction ) && isValid; + } + else + { + m_templateMultiPass.SetPassInputData( m_subShaderIdx , m_passIdx , ports[ i ].PortId , inputData.DefaultValue ); + isValid = m_templateMultiPass.FillTemplateBody( m_subShaderIdx , m_passIdx , inputData.TagId , ref shaderBody , inputData.DefaultValue ) && isValid; + } + } + return isValid; + } + + public string BuildShaderBody( MasterNodeDataCollector inDataCollector , ref MasterNodeDataCollector outDataCollector ) + { + List list = ContainerGraph.MultiPassMasterNodes.NodesList; + int currentSubshader = list[ 0 ].SubShaderIdx; + m_templateMultiPass.SetShaderName( string.Format( TemplatesManager.NameFormatter , m_shaderName ) ); + if( string.IsNullOrEmpty( m_customInspectorName ) ) + { + m_templateMultiPass.SetCustomInspector( string.Empty ); + } + else + { + m_templateMultiPass.SetCustomInspector( CustomInspectorFormatted ); + } + + m_templateMultiPass.SetFallback( m_fallbackHelper.FallbackShader ); + m_templateMultiPass.SetDependencies( m_dependenciesHelper.GenerateDependencies() ); + + if( inDataCollector != null ) + outDataCollector.CopyPropertiesFromDataCollector( inDataCollector ); + + outDataCollector.TemplateDataCollectorInstance.CurrentSRPType = m_templateMultiPass.SRPtype; + + int lastActivePass = m_passSelector.LastActivePass; + int count = list.Count; + bool filledSubshaderData = false; + + bool foundExcludePassName = false; + string excludePassName = string.Empty; + + foundExcludePassName = CheckExcludeAllPassOptions( m_subShaderOptions , out excludePassName ); + for( int i = 0 ; i < count ; i++ ) + { + bool removePass = !m_passSelector.IsVisible( i ) || ( foundExcludePassName && !list[ i ].OriginalPassName.Equals( excludePassName ) ); + + list[ 0 ].CurrentTemplate.IdManager.SetPassIdUsage( i , removePass ); + if( removePass ) + { + if( m_isMainOutputNode ) + { + //Make sure that property change options are set even if the main master node is invisible + CheckPropertyChangesOnOptions( m_subShaderOptions ); + } + continue; + } + + list[ i ].CollectData(); + list[ i ].FillPassData( this , outDataCollector.TemplateDataCollectorInstance ); + + if( list[ i ].SubShaderIdx == currentSubshader ) + { + outDataCollector.CopyPropertiesFromDataCollector( list[ i ].CurrentDataCollector ); + } + else + { + list[ i - 1 ].FillPropertyData( outDataCollector ); + list[ i - 1 ].FillSubShaderData(); + outDataCollector.Destroy(); + outDataCollector = new MasterNodeDataCollector(); + outDataCollector.CopyPropertiesFromDataCollector( list[ i ].CurrentDataCollector ); + + currentSubshader = list[ i ].SubShaderIdx; + } + + // Last element must the one filling subshader data + // as only there all properties are caught + //if( i == ( count - 1 ) ) + if( i == lastActivePass ) + { + list[ i ].FillPropertyData( outDataCollector ); + } + + if( list[ i ].IsMainOutputNode ) + { + filledSubshaderData = true; + list[ i ].FillSubShaderData(); + } + } + + if( !filledSubshaderData ) + { + FillSubShaderData(); + } + outDataCollector.TemplateDataCollectorInstance.BuildCBuffer( -1 ); + + //Fill uniforms is set on last since we need to collect all srp batcher data ( if needed ) + //To set it into each pass + for( int i = 0 ; i < count ; i++ ) + { + bool removePass = !m_passSelector.IsVisible( i ) || ( foundExcludePassName && !list[ i ].OriginalPassName.Equals( excludePassName ) ); + if( removePass ) + continue; + + list[ i ].FillUniforms( outDataCollector.TemplateDataCollectorInstance ); + } + + return list[ 0 ].CurrentTemplate.IdManager.BuildShader(); + } + + public string BuildLOD( MasterNodeDataCollector inDataCollector , ref MasterNodeDataCollector outDataCollector ) + { + UsageListTemplateMultiPassMasterNodes bufferNodesList = ContainerGraph.MultiPassMasterNodes; + int bufferMasterNodeId = ContainerGraph.CurrentMasterNodeId; + + ContainerGraph.MultiPassMasterNodes = ContainerGraph.LodMultiPassMasternodes[ m_lodIndex ]; + ContainerGraph.CurrentMasterNodeId = UniqueId; + + m_templateMultiPass.ResetState(); + base.Execute( string.Empty , false ); + string shaderBody = BuildShaderBody( inDataCollector , ref outDataCollector ); + + + ContainerGraph.MultiPassMasterNodes = bufferNodesList; + ContainerGraph.CurrentMasterNodeId = bufferMasterNodeId; + return shaderBody; + } + + public override Shader Execute( string pathname , bool isFullPath ) + { + ForceReordering(); + MasterNodeDataCollector overallDataCollector = new MasterNodeDataCollector(); + + //BUILD LOD + string allLodSubShaders = string.Empty; + if( ContainerGraph.HasLODs ) + { + for( int lod = 0 ; lod < ContainerGraph.LodMultiPassMasternodes.Count ; lod++ ) + { + if( ContainerGraph.LodMultiPassMasternodes[ lod ].Count == 0 ) + break; + + TemplateMultiPassMasterNode newMasterNode = ContainerGraph.LodMultiPassMasternodes[ lod ].NodesList.Find( ( x ) => x.IsMainOutputNode ); + string lodSubShaders = newMasterNode.BuildLOD( null , ref overallDataCollector ); + lodSubShaders = TemplateHelperFunctions.GetSubShaderFrom( lodSubShaders ) + "\n"; + allLodSubShaders += lodSubShaders; + } + } + + //BUILD MAIN + m_templateMultiPass.ResetState(); + base.Execute( pathname , isFullPath ); + MasterNodeDataCollector dummy = new MasterNodeDataCollector(); + string shaderBody = BuildShaderBody( overallDataCollector , ref dummy ); + + //COMBINE LOD WITH MAIN + if( !string.IsNullOrEmpty( allLodSubShaders ) ) + shaderBody = shaderBody.Replace( TemplatesManager.TemplateLODsTag , allLodSubShaders ); + + UpdateShaderAsset( ref pathname , ref shaderBody , isFullPath ); + return m_currentShader; + } + + public void CollectData() + { + if( m_inputPorts.Count == 0 ) + return; + + ContainerGraph.ResetNodesLocalVariables(); + m_optionsDefineContainer.RemoveTemporaries(); + m_currentDataCollector = new MasterNodeDataCollector( this ); + m_currentDataCollector.TemplateDataCollectorInstance.SetMultipassInfo( m_templateMultiPass , m_subShaderIdx , m_passIdx , m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType ); + m_currentDataCollector.TemplateDataCollectorInstance.FillSpecialVariables( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ] ); + SetupNodeCategories(); + if( m_containerGraph.IsInstancedShader ) + { + string blockName = UIUtils.RemoveInvalidCharacters( ContainerGraph.GetMainMasterNodeOfLOD( -1 ).ShaderName ); + m_currentDataCollector.SetupInstancePropertiesBlock( blockName ); + } + TemplateData templateData = m_templateMultiPass.CreateTemplateData( m_shaderName , string.Empty , m_subShaderIdx , m_passIdx ); + m_currentDataCollector.TemplateDataCollectorInstance.BuildFromTemplateData( m_currentDataCollector , templateData ); + + if( m_currentDataCollector.TemplateDataCollectorInstance.InterpData.DynamicMax ) + { + int interpolatorAmount = -1; + if( m_passModule.ShaderModelHelper.ValidData ) + { + interpolatorAmount = m_passModule.ShaderModelHelper.InterpolatorAmount; + } + else + { + TemplateModulesHelper subShaderModule = IsMainOutputNode ? m_subShaderModule : ( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ).SubShaderModule; + if( subShaderModule.ShaderModelHelper.ValidData ) + { + interpolatorAmount = subShaderModule.ShaderModelHelper.InterpolatorAmount; + } + } + + if( interpolatorAmount > -1 ) + { + m_currentDataCollector.TemplateDataCollectorInstance.InterpData.RecalculateAvailableInterpolators( interpolatorAmount ); + } + } + + //Copy Properties + { + int shaderPropertiesAmount = m_templateMultiPass.AvailableShaderProperties.Count; + for( int i = 0 ; i < shaderPropertiesAmount ; i++ ) + { + m_currentDataCollector.SoftRegisterUniform( m_templateMultiPass.AvailableShaderProperties[ i ] ); + } + } + //Copy Globals from SubShader level + { + int subShaderGlobalAmount = m_templateMultiPass.SubShaders[ m_subShaderIdx ].AvailableShaderGlobals.Count; + for( int i = 0 ; i < subShaderGlobalAmount ; i++ ) + { + m_currentDataCollector.SoftRegisterUniform( m_templateMultiPass.SubShaders[ m_subShaderIdx ].AvailableShaderGlobals[ i ] ); + } + } + //Copy Globals from Pass Level + { + int passGlobalAmount = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].AvailableShaderGlobals.Count; + for( int i = 0 ; i < passGlobalAmount ; i++ ) + { + m_currentDataCollector.SoftRegisterUniform( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].AvailableShaderGlobals[ i ] ); + } + } + // Check Current Options for property changes on subshader + if( m_isMainOutputNode ) + { + CheckPropertyChangesOnOptions( m_subShaderOptions ); + } + + // Check Current Options for property changes on pass + CheckPropertyChangesOnOptions( m_passOptions ); + + + //Set SRP info +#if UNITY_2018_3_OR_NEWER + if( m_templateMultiPass.SRPtype != TemplateSRPType.BuiltIn ) + ASEPackageManagerHelper.SetSRPInfoOnDataCollector( ref m_currentDataCollector ); +#endif + RegisterStandaloneFuntions(); + m_containerGraph.CheckPropertiesAutoRegister( ref m_currentDataCollector ); + + //Sort ports by both + List fragmentPorts = new List(); + List vertexPorts = new List(); + + SortInputPorts( ref vertexPorts , ref fragmentPorts ); + + + string shaderBody = templateData.TemplateBody; + + List vertexInstructions = new List(); + List fragmentInstructions = new List(); + + bool validBody = true; + + //validBody = CreateInstructionsForList( templateData, ref fragmentPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody; + //ContainerGraph.ResetNodesLocalVariablesIfNot( MasterNodePortCategory.Vertex ); + //validBody = CreateInstructionsForList( templateData, ref vertexPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody; + validBody = CreateInstructionsForList( templateData , ref vertexPorts , ref shaderBody , ref vertexInstructions , ref fragmentInstructions ) && validBody; + validBody = CreateInstructionsForList( templateData , ref fragmentPorts , ref shaderBody , ref vertexInstructions , ref fragmentInstructions ) && validBody; + + if( !m_isMainOutputNode && m_mainMasterNodeRef == null ) + { + m_mainMasterNodeRef = m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode; + } + + TerrainDrawInstancedHelper drawInstanced = m_isMainOutputNode ? m_drawInstancedHelper : m_mainMasterNodeRef.DrawInstancedHelperInstance; + drawInstanced.UpdateDataCollectorForTemplates( ref m_currentDataCollector , ref vertexInstructions ); + + templateData.ResetTemplateUsageData(); + + // Fill vertex interpolators assignment + for( int i = 0 ; i < m_currentDataCollector.VertexInterpDeclList.Count ; i++ ) + { + vertexInstructions.Add( m_currentDataCollector.VertexInterpDeclList[ i ] ); + } + + vertexInstructions.AddRange( m_currentDataCollector.TemplateDataCollectorInstance.GetInterpUnusedChannels() ); + + //Fill common local variables and operations + validBody = m_templateMultiPass.FillVertexInstructions( m_subShaderIdx , m_passIdx , vertexInstructions.ToArray() ) && validBody; + validBody = m_templateMultiPass.FillFragmentInstructions( m_subShaderIdx , m_passIdx , fragmentInstructions.ToArray() ) && validBody; + + vertexInstructions.Clear(); + vertexInstructions = null; + + fragmentInstructions.Clear(); + fragmentInstructions = null; + + // Add Instanced Properties + if( m_containerGraph.IsInstancedShader ) + { + m_currentDataCollector.OptimizeInstancedProperties(); + m_currentDataCollector.TabifyInstancedVars(); + + //string cbufferBegin = m_currentDataCollector.IsSRP ? + // string.Format( IOUtils.SRPInstancedPropertiesBegin, "UnityPerMaterial" ) : + // string.Format( IOUtils.InstancedPropertiesBegin, m_currentDataCollector.InstanceBlockName ); + //string cBufferEnd = m_currentDataCollector.IsSRP ? ( string.Format( IOUtils.SRPInstancedPropertiesEnd, m_currentDataCollector.InstanceBlockName ) ) : IOUtils.InstancedPropertiesEnd; + string cbufferBegin = m_currentDataCollector.IsSRP ? + string.Format( IOUtils.LWSRPInstancedPropertiesBegin , m_currentDataCollector.InstanceBlockName ) : + string.Format( IOUtils.InstancedPropertiesBegin , m_currentDataCollector.InstanceBlockName ); + string cBufferEnd = m_currentDataCollector.IsSRP ? ( string.Format( IOUtils.LWSRPInstancedPropertiesEnd , m_currentDataCollector.InstanceBlockName ) ) : IOUtils.InstancedPropertiesEnd; + + m_currentDataCollector.InstancedPropertiesList.Insert( 0 , new PropertyDataCollector( -1 , cbufferBegin ) ); + m_currentDataCollector.InstancedPropertiesList.Add( new PropertyDataCollector( -1 , cBufferEnd ) ); + m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.InstancedPropertiesList ); + } + + if( m_currentDataCollector.DotsPropertiesList.Count > 0 ) + { + m_currentDataCollector.DotsPropertiesList.Insert( 0 , new PropertyDataCollector( -1 , "UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)" ) ); + m_currentDataCollector.DotsPropertiesList.Insert( 0 , new PropertyDataCollector( -1 , "#ifdef UNITY_DOTS_INSTANCING_ENABLED" ) ); + m_currentDataCollector.DotsPropertiesList.Insert( 0 , new PropertyDataCollector( -1 , "" ) ); + m_currentDataCollector.DotsPropertiesList.Add( new PropertyDataCollector( -1 , "UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)" ) ); + m_currentDataCollector.DotsDefinesList.Add( new PropertyDataCollector( -1 , "#endif" ) ); + m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.DotsPropertiesList ); + m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.DotsDefinesList ); + } + + TemplateShaderModelModule shaderModelModule = m_isMainOutputNode ? m_subShaderModule.ShaderModelHelper : m_mainMasterNodeRef.SubShaderModule.ShaderModelHelper; + string shaderModel = string.Empty; + if( m_passModule.ShaderModelHelper.ValidData ) + { + shaderModel = m_passModule.ShaderModelHelper.CurrentShaderModel; + } + else if( shaderModelModule.ValidData ) + { + shaderModel = shaderModelModule.CurrentShaderModel; + } + else if( m_templateMultiPass.GlobalShaderModel.IsValid ) + { + shaderModel = m_templateMultiPass.GlobalShaderModel.Value; + } + else + { + shaderModel = ( m_templateMultiPass.SRPtype == TemplateSRPType.HD ) ? "4.5" : "3.0"; + } + + m_currentDataCollector.TemplateDataCollectorInstance.CheckInterpolatorOverflow( shaderModel , m_passName ); + } + + public bool CheckExcludeAllPassOptions( TemplateOptionsUIHelper optionsUI , out string passName ) + { + List options = optionsUI.PassCustomOptionsUI; + for( int optionIdx = 0 ; optionIdx < options.Count ; optionIdx++ ) + { + if( options[ optionIdx ].IsVisible ) + { + TemplateActionItem[] actionItems = options[ optionIdx ].CurrentOptionActions.Columns; + for( int actionIdx = 0 ; actionIdx < actionItems.Length ; actionIdx++ ) + { + if( actionItems[ actionIdx ].ActionType == AseOptionsActionType.ExcludeAllPassesBut ) + { + passName = actionItems[ actionIdx ].ActionData; + return true; + } + } + } + } + + passName = string.Empty; + return false; + } + + public void CheckPropertyChangesOnOptions( TemplateOptionsUIHelper optionsUI ) + { + //Only Main LOD master node can change shader properties + if( !IsLODMainMasterNode ) + return; + + List options = optionsUI.PassCustomOptionsUI; + for( int optionIdx = 0 ; optionIdx < options.Count ; optionIdx++ ) + { + if( options[ optionIdx ].IsVisible ) + { + TemplateActionItem[] actionItems = options[ optionIdx ].CurrentOptionActions.Columns; + for( int actionIdx = 0 ; actionIdx < actionItems.Length ; actionIdx++ ) + { + if( actionItems[ actionIdx ].ActionType == AseOptionsActionType.SetShaderProperty && !string.IsNullOrEmpty( actionItems[ actionIdx ].ActionBuffer ) ) + { + TemplateShaderPropertyData data = m_templateMultiPass.GetShaderPropertyData( actionItems[ actionIdx ].ActionData ); + if( data != null ) + { + string newPropertyValue = data.CreatePropertyForValue( actionItems[ actionIdx ].ActionBuffer ); + CurrentTemplate.IdManager.SetReplacementText( data.FullValue , newPropertyValue ); + if( CurrentMaterial != null ) + { + switch( data.PropertyDataType ) + { + case WirePortDataType.FLOAT: + { + float value = 0; + if( actionItems[ actionIdx ].GetFloatValueFromActionBuffer( out value ) ) + { + CurrentMaterial.SetFloat( data.PropertyName , value ); + } + } + break; + case WirePortDataType.INT: + { + int value = 0; + if( actionItems[ actionIdx ].GetIntValueFromActionBuffer( out value ) ) + { + CurrentMaterial.SetInt( data.PropertyName , value ); + } + } + break; + case WirePortDataType.UINT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + break; + } + + } + } + } + } + + if( options[ optionIdx ].Options.Type == AseOptionsType.Field ) + { + foreach( var item in CurrentTemplate.IdManager.RegisteredTags ) + { + if( item.Output.Equals( options[ optionIdx ].Options.FieldInlineName ) ) + { + var node = options[ optionIdx ].Options.FieldValue.GetPropertyNode(); + if( node != null && ( node.IsConnected || node.AutoRegister || node.UniqueId < -1 ) && options[ optionIdx ].Options.FieldValue.Active ) + { + item.Replacement = node.PropertyName; + } + } + } + } + } + } + } + + public void FillPropertyData( MasterNodeDataCollector dataCollector = null ) + { + MasterNodeDataCollector currDataCollector = ( dataCollector == null ) ? m_currentDataCollector : dataCollector; + +#if UNITY_2019_2_OR_NEWER + // Temporary hack + if( m_templateMultiPass.SRPtype != TemplateSRPType.BuiltIn && ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_6_9_0 ) + { + if( m_templateMultiPass.AvailableShaderProperties.Find( x => x.PropertyName.Equals( "_AlphaCutoff" ) ) == null ) + { + if( !currDataCollector.ContainsProperty("_AlphaCutoff") ) + { + currDataCollector.AddToProperties( UniqueId, "[HideInInspector] _AlphaCutoff(\"Alpha Cutoff \", Range(0, 1)) = 0.5", -1 ); + } + } + + if( m_templateMultiPass.AvailableShaderProperties.Find( x => x.PropertyName.Equals( "_EmissionColor" ) ) == null ) + { + if( !currDataCollector.ContainsProperty( "_EmissionColor" ) ) + { + currDataCollector.AddToProperties( UniqueId, "[HideInInspector] _EmissionColor(\"Emission Color\", Color) = (1,1,1,1)", -1 ); + } + } + } +#endif + + // here we add ASE attributes to the material properties that allows materials to communicate with ASE + //if( m_templateMultiPass.SRPtype != TemplateSRPType.BuiltIn ) + { + string currentInspector = IsLODMainMasterNode ? m_customInspectorName : ContainerGraph.GetMainMasterNodeOfLOD( -1 ).CurrentInspector; + bool isASENativeInspector = Constants.DefaultCustomInspector.Equals( currentInspector ); + bool isUnityNativeInspector = Constants.UnityNativeInspectors.FindIndex( x => x.Equals( currentInspector ) ) > 0; + + List list = new List( currDataCollector.PropertiesDict.Values ); + list.Sort( ( x , y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + if( isUnityNativeInspector ) + { + for( int i = 0 ; i < list.Count ; i++ ) + { + if( !( list[ i ].PropertyName.Contains( "[HideInInspector]" ) || list[ i ].PropertyName.Contains( "//" ) ) ) + { + list[ i ].PropertyName = "[ASEBegin]" + list[ i ].PropertyName; + break; + } + } + } + + if( !isASENativeInspector ) + { + for( int i = list.Count - 1 ; i >= 0 ; i-- ) + { + if( !( list[ i ].PropertyName.Contains( "[HideInInspector]" ) || list[ i ].PropertyName.Contains( "//" ) ) ) + { + list[ i ].PropertyName = "[ASEEnd]" + list[ i ].PropertyName; + break; + } + } + } + } + + m_templateMultiPass.SetPropertyData( currDataCollector.BuildUnformatedPropertiesStringArr() ); + } + + public void FillSubShaderData( /*MasterNodeDataCollector dataCollector = null */) + { + //MasterNodeDataCollector currDataCollector = ( dataCollector == null ) ? m_currentDataCollector : dataCollector; + //// SubShader Data + + //m_templateMultiPass.SetPropertyData( currDataCollector.BuildUnformatedPropertiesStringArr() ); + //templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModulePass, m_subShaderIdx, currDataCollector.GrabPassList ); + if( ShaderLOD > -1 ) + { + string lodUniqueId = m_templateMultiPass.SubShaders[ m_subShaderIdx ].UniquePrefix + "Module" + m_templateMultiPass.SubShaders[ m_subShaderIdx ].LODContainer.Id; + m_templateMultiPass.IdManager.SetReplacementText( lodUniqueId , "LOD " + ShaderLOD ); + } + + SetModuleData( m_subShaderModule , true ); + } + + public bool CheckDefineListItem( PropertyDataCollector item ) + { + //The IsDirective flag in this context is used to determine if its #pragma + if( item.IsDirective ) + { + return !m_currentDataCollector.ContainsPragma( item.PropertyName ); + } + else + { + return !m_currentDataCollector.ContainsDefine( item.PropertyName ); + } + + } + + public void FillPassData( TemplateMultiPassMasterNode masterNode , TemplateDataCollector mainTemplateDataCollector ) + { + if( m_isInvisible != InvisibilityStatus.Visible ) + { + if( masterNode.UniqueId != UniqueId ) + { + if( ( m_invisibleOptions & (int)InvisibleOptionsEnum.SyncProperties ) > 0 ) + { + PassModule.SyncWith( masterNode.PassModule ); + } + } + + int inputCount = m_inputPorts.Count; + for( int i = 0 ; i < inputCount ; i++ ) + { + if( m_inputPorts[ i ].HasExternalLink ) + { + TemplateMultiPassMasterNode linkedNode = m_inputPorts[ i ].ExternalLinkNode as TemplateMultiPassMasterNode; + if( linkedNode != null ) + { + SetLinkedModuleData( linkedNode.PassModule ); + } + } + } + } + + SetModuleData( m_passModule , false ); + if( m_currentDataCollector != null ) + { + if( Pass.CustomOptionsContainer.CopyOptionsFromMainPass ) + { + SetPassCustomOptionsInfo( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ); + } + else + { + SetPassCustomOptionsInfo( this ); + } + + var inputArray = m_currentDataCollector.VertexInputList.ToArray(); + + m_templateMultiPass.SetPassData( TemplateModuleDataType.PassVertexData , m_subShaderIdx , m_passIdx , inputArray ); + m_templateMultiPass.SetPassData( TemplateModuleDataType.PassInterpolatorData , m_subShaderIdx , m_passIdx , m_currentDataCollector.InterpolatorList.ToArray() ); + SetHDInfoOnPass(); + List afterNativesIncludePragmaDefineList = new List(); + afterNativesIncludePragmaDefineList.AddRange( m_currentDataCollector.IncludesList ); + afterNativesIncludePragmaDefineList.AddRange( m_currentDataCollector.DefinesList ); + //includePragmaDefineList.AddRange( m_optionsDefineContainer.DefinesList ); + afterNativesIncludePragmaDefineList.AddRange( m_currentDataCollector.PragmasList ); + CheckSamplingMacrosFlag(); + m_currentDataCollector.AddASEMacros(); + afterNativesIncludePragmaDefineList.AddRange( m_currentDataCollector.AfterNativeDirectivesList ); + + //includePragmaDefineList.AddRange( m_currentDataCollector.MiscList ); + + List beforeNatives = new List(); + int defineListCount = m_optionsDefineContainer.DefinesList.Count; + for( int i = 0 ; i < defineListCount ; i++ ) + { + if( CheckDefineListItem( m_optionsDefineContainer.DefinesList[ i ] ) ) + { + beforeNatives.Add( m_optionsDefineContainer.DefinesList[ i ] ); + } + } + + beforeNatives.AddRange( m_currentDataCollector.BeforeNativeDirectivesList ); + + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModulePragmaBefore , m_subShaderIdx , m_passIdx , beforeNatives ); + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModulePragma , m_subShaderIdx , m_passIdx , afterNativesIncludePragmaDefineList ); + + m_currentDataCollector.TemplateDataCollectorInstance.CloseLateDirectives(); + + //Add Functions + if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.FunctionsTag.IsValid ) + { + m_currentDataCollector.FunctionsList.InsertRange( 0 , m_currentDataCollector.TemplateDataCollectorInstance.LateDirectivesList ); + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleFunctions , m_subShaderIdx , m_passIdx , m_currentDataCollector.FunctionsList ); + } + else + { + m_currentDataCollector.UniformsList.InsertRange( 0 , m_currentDataCollector.TemplateDataCollectorInstance.LateDirectivesList ); + m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.FunctionsList ); + } + + //copy srp batch if present + //if( m_currentDataCollector.IsSRP ) + //{ + // m_currentDataCollector.UniformsList.AddRange( mainTemplateDataCollector.SrpBatcherPropertiesList ); + //} + //m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleGlobals, m_subShaderIdx, m_passIdx, m_currentDataCollector.UniformsList ); + + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleInputVert , m_subShaderIdx , m_passIdx , m_currentDataCollector.TemplateDataCollectorInstance.VertexInputParamsStr ); + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleInputFrag , m_subShaderIdx , m_passIdx , m_currentDataCollector.TemplateDataCollectorInstance.FragInputParamsStr ); + + if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessVControlTag != null && m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessVControlTag.IsValid ) + m_templateMultiPass.SetPassData( TemplateModuleDataType.VControl , m_subShaderIdx , m_passIdx , inputArray ); + + if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessControlData != null && m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessControlData.IsValid ) + m_templateMultiPass.SetPassData( TemplateModuleDataType.ControlData , m_subShaderIdx , m_passIdx , m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessControlData.GenerateControl( m_currentDataCollector.TemplateDataCollectorInstance.VertexDataDict , m_currentDataCollector.VertexInputList ) ); + + if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessDomainData != null && m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessDomainData.IsValid ) + m_templateMultiPass.SetPassData( TemplateModuleDataType.DomainData , m_subShaderIdx , m_passIdx , m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessDomainData.GenerateDomain( m_currentDataCollector.TemplateDataCollectorInstance.VertexDataDict , m_currentDataCollector.VertexInputList ) ); + + afterNativesIncludePragmaDefineList.Clear(); + afterNativesIncludePragmaDefineList = null; + + beforeNatives.Clear(); + beforeNatives = null; + } + + m_templateMultiPass.SetPassData( TemplateModuleDataType.PassNameData , m_subShaderIdx , m_passIdx , string.Format( PassNameFormateStr , m_passName ) ); + } + + public List CrossCheckSoftRegisteredUniformList( List uniformList ) + { + List newItems = new List(); + for( int i = 0 ; i < uniformList.Count ; i++ ) + { + if( !m_currentDataCollector.CheckIfSoftRegistered( uniformList[ i ].PropertyName ) ) + { + newItems.Add( uniformList[ i ] ); + } + } + return newItems; + } + + public void FillUniforms( TemplateDataCollector mainTemplateDataCollector ) + { + if( m_currentDataCollector.IsSRP ) + { + + if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPBatcherTag.IsValid ) + { + List finalList = CrossCheckSoftRegisteredUniformList( mainTemplateDataCollector.SrpBatcherPropertiesList ); + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleSRPBatcher , m_subShaderIdx , m_passIdx , finalList ); + finalList.Clear(); + finalList = null; + } + else + { + List finalList = CrossCheckSoftRegisteredUniformList( mainTemplateDataCollector.FullSrpBatcherPropertiesList ); + m_currentDataCollector.UniformsList.AddRange( finalList ); + finalList.Clear(); + finalList = null; + } + } + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleGlobals , m_subShaderIdx , m_passIdx , m_currentDataCollector.UniformsList ); + } + + void SetHDInfoOnPass() + { +#if UNITY_2019_3_OR_NEWER + if( ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_6_9_1 ) + return; +#endif + + if( m_currentDataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) + { + TemplateModulesHelper subShaderHelper = null; + TemplateModulesHelper passHelper = null; + + if( m_isMainOutputNode ) + { + subShaderHelper = m_subShaderModule; + passHelper = m_passModule; + } + else + { + TemplateMultiPassMasterNode masterNode = m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode; + if( masterNode != null ) + { + subShaderHelper = masterNode.SubShaderModule; + passHelper = masterNode.PassModule; + } + else + { + subShaderHelper = m_subShaderModule; + passHelper = m_passModule; + } + } + + RenderQueue renderQueue = RenderQueue.Geometry; + RenderType renderType = RenderType.Opaque; + if( passHelper.TagsHelper.HasRenderInfo( ref renderType , ref renderQueue ) || + subShaderHelper.TagsHelper.HasRenderInfo( ref renderType , ref renderQueue ) ) + { + if( renderType == RenderType.Transparent && renderQueue == RenderQueue.Transparent ) + { + SetExtraDefine( SRPMaterialTransparentKeyword ); + //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialTransparentKeyword ); + TemplatesBlendModule blendOpHelper = passHelper.BlendOpHelper.ValidBlendMode ? passHelper.BlendOpHelper : subShaderHelper.BlendOpHelper; + if( blendOpHelper.IsAdditiveRGB ) + { + SetExtraDefine( SRPMaterialBlendModeAddKeyword ); + //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialBlendModeAddKeyword ); + } + else if( blendOpHelper.IsAlphaBlendRGB ) + { + SetExtraDefine( SRPMaterialBlendModeAlphaKeyword ); + //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialBlendModeAlphaKeyword ); + } + } + } + } + } + + void SetLinkedModuleData( TemplateModulesHelper linkedModule ) + { + //if( linkedModule.AdditionalPragmas.ValidData ) + //{ + // linkedModule.AdditionalPragmas.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); + //} + + //if( linkedModule.AdditionalIncludes.ValidData ) + //{ + // linkedModule.AdditionalIncludes.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); + //} + + //if( linkedModule.AdditionalDefines.ValidData ) + //{ + // linkedModule.AdditionalDefines.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); + //} + + if( linkedModule.AdditionalDirectives.ValidData ) + { + linkedModule.AdditionalDirectives.AddAllToDataCollector( ref m_currentDataCollector , m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); + } + } + + void SetModuleData( TemplateModulesHelper module , bool isSubShader ) + { + if( isSubShader ) + { + + //if ( module.AdditionalPragmas.ValidData ) + //{ + // module.AdditionalPragmas.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.IncludePragmaContainer ); + //} + + //if ( module.AdditionalIncludes.ValidData ) + //{ + // module.AdditionalIncludes.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.IncludePragmaContainer ); + //} + + //if ( module.AdditionalDefines.ValidData ) + //{ + // module.AdditionalDefines.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.IncludePragmaContainer ); + //} + + if( module.AdditionalDirectives.ValidData ) + { + module.AdditionalDirectives.AddAllToDataCollector( ref m_currentDataCollector , m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.IncludePragmaContainer ); + } + + if( module.TagsHelper.ValidData ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleTag , m_subShaderIdx , module.TagsHelper.GenerateTags() ); + } + + if( module.AllModulesMode ) + { + string body = module.GenerateAllModulesString( isSubShader ); + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.AllModules , m_subShaderIdx , body.Split( '\n' ) ); + } + + if( module.ShaderModelHelper.ValidAndIndependent ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleShaderModel , m_subShaderIdx , module.ShaderModelHelper.GenerateShaderData( isSubShader ) ); + } + + if( module.BlendOpHelper.IndependentModule && module.BlendOpHelper.ValidBlendMode ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendMode , m_subShaderIdx , module.BlendOpHelper.CurrentBlendFactor ); + } + + if( module.BlendOpHelper1.IndependentModule && module.BlendOpHelper1.ValidBlendMode ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendMode1 , m_subShaderIdx , module.BlendOpHelper1.CurrentBlendFactor ); + } + + if( module.BlendOpHelper2.IndependentModule && module.BlendOpHelper2.ValidBlendMode ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendMode2 , m_subShaderIdx , module.BlendOpHelper2.CurrentBlendFactor ); + } + + if( module.BlendOpHelper3.IndependentModule && module.BlendOpHelper3.ValidBlendMode ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendMode3 , m_subShaderIdx , module.BlendOpHelper3.CurrentBlendFactor ); + } + + if( module.BlendOpHelper.IndependentModule && module.BlendOpHelper.ValidBlendOp ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendOp , m_subShaderIdx , module.BlendOpHelper.CurrentBlendOp ); + } + + if( module.BlendOpHelper1.IndependentModule && module.BlendOpHelper1.ValidBlendOp ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendOp1 , m_subShaderIdx , module.BlendOpHelper1.CurrentBlendOp ); + } + + if( module.BlendOpHelper2.IndependentModule && module.BlendOpHelper2.ValidBlendOp ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendOp2 , m_subShaderIdx , module.BlendOpHelper2.CurrentBlendOp ); + } + + if( module.BlendOpHelper3.IndependentModule && module.BlendOpHelper3.ValidBlendOp ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendOp3 , m_subShaderIdx , module.BlendOpHelper3.CurrentBlendOp ); + } + + if( module.AlphaToMaskHelper.ValidAndIndependent ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleAlphaToMask , m_subShaderIdx , module.AlphaToMaskHelper.GenerateShaderData( isSubShader ) ); + } + + if( module.CullModeHelper.ValidAndIndependent ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleCullMode , m_subShaderIdx , module.CullModeHelper.GenerateShaderData( isSubShader ) ); + } + + if( module.ColorMaskHelper.ValidAndIndependent ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleColorMask , m_subShaderIdx , module.ColorMaskHelper.GenerateShaderData( isSubShader ) ); + } + + if( module.ColorMaskHelper1.ValidAndIndependent ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleColorMask1 , m_subShaderIdx , module.ColorMaskHelper1.GenerateShaderData( isSubShader ) ); + } + + if( module.ColorMaskHelper2.ValidAndIndependent ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleColorMask2 , m_subShaderIdx , module.ColorMaskHelper2.GenerateShaderData( isSubShader ) ); + } + + if( module.ColorMaskHelper3.ValidAndIndependent ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleColorMask3 , m_subShaderIdx , module.ColorMaskHelper3.GenerateShaderData( isSubShader ) ); + } + + if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidZTest ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleZTest , m_subShaderIdx , module.DepthOphelper.CurrentZTestMode ); + } + + if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidZWrite ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleZwrite , m_subShaderIdx , module.DepthOphelper.CurrentZWriteMode ); + } + + if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidOffset ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleZOffset , m_subShaderIdx , module.DepthOphelper.CurrentOffset ); + } + + if( module.StencilBufferHelper.ValidAndIndependent ) + { + CullMode cullMode = ( module.CullModeHelper.ValidData ) ? module.CullModeHelper.CurrentCullMode : CullMode.Back; + string value = module.StencilBufferHelper.CreateStencilOp( cullMode ); + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleStencil , m_subShaderIdx , value.Split( '\n' ) ); + } + + if( module.RenderingPlatforms.LoadedFromTemplate ) + { + m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleRenderPlatforms , m_subShaderIdx , module.RenderingPlatforms.CreateResult(true) ); + } + + } + else + { + //if ( module.AdditionalPragmas.ValidData ) + //{ + // module.AdditionalPragmas.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); + //} + + //if ( module.AdditionalIncludes.ValidData ) + //{ + // module.AdditionalIncludes.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); + //} + + //if ( module.AdditionalDefines.ValidData ) + //{ + // module.AdditionalDefines.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); + //} + List aboveUsePass = new List(); + List belowUsePass = new List(); + m_usePass.BuildUsePassInfo( m_currentDataCollector , ref aboveUsePass , ref belowUsePass ); + //TODO Must place this on the correct place + aboveUsePass.AddRange( belowUsePass ); + + //adding grab pass after use pass on purpose, so it wont be caught by them + aboveUsePass.AddRange( m_currentDataCollector.GrabPassList ); + + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModulePass , m_subShaderIdx , m_passIdx , aboveUsePass ); + //m_templateMultiPass.SetPassData( TemplateModuleDataType.EndPass, m_subShaderIdx, m_passIdx, bellowUsePass); + + if( module.AdditionalDirectives.ValidData ) + { + module.AdditionalDirectives.AddAllToDataCollector( ref m_currentDataCollector , m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); + } + + if( module.TagsHelper.ValidData ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleTag , m_subShaderIdx , m_passIdx , module.TagsHelper.GenerateTags() ); + } + + if( module.AllModulesMode ) + { + string body = module.GenerateAllModulesString( isSubShader ); + m_templateMultiPass.SetPassData( TemplateModuleDataType.AllModules , m_subShaderIdx , m_passIdx , body.Split( '\n' ) ); + } + + if( module.ShaderModelHelper.ValidAndIndependent ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleShaderModel , m_subShaderIdx , m_passIdx , module.ShaderModelHelper.GenerateShaderData( isSubShader ) ); + } + + if( module.BlendOpHelper.IndependentModule && module.BlendOpHelper.ValidBlendMode ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendMode , m_subShaderIdx , m_passIdx , module.BlendOpHelper.CurrentBlendFactor ); + } + + if( module.BlendOpHelper1.IndependentModule && module.BlendOpHelper1.ValidBlendMode ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendMode1 , m_subShaderIdx , m_passIdx , module.BlendOpHelper1.CurrentBlendFactor ); + } + + if( module.BlendOpHelper2.IndependentModule && module.BlendOpHelper2.ValidBlendMode ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendMode2 , m_subShaderIdx , m_passIdx , module.BlendOpHelper2.CurrentBlendFactor ); + } + + if( module.BlendOpHelper3.IndependentModule && module.BlendOpHelper3.ValidBlendMode ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendMode3 , m_subShaderIdx , m_passIdx , module.BlendOpHelper3.CurrentBlendFactor ); + } + + if( module.BlendOpHelper.IndependentModule && module.BlendOpHelper.ValidBlendOp ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendOp , m_subShaderIdx , m_passIdx , module.BlendOpHelper.CurrentBlendOp ); + } + + if( module.BlendOpHelper1.IndependentModule && module.BlendOpHelper1.ValidBlendOp ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendOp1 , m_subShaderIdx , m_passIdx , module.BlendOpHelper1.CurrentBlendOp ); + } + + if( module.BlendOpHelper2.IndependentModule && module.BlendOpHelper2.ValidBlendOp ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendOp2 , m_subShaderIdx , m_passIdx , module.BlendOpHelper2.CurrentBlendOp ); + } + + if( module.BlendOpHelper3.IndependentModule && module.BlendOpHelper3.ValidBlendOp ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendOp3 , m_subShaderIdx , m_passIdx , module.BlendOpHelper3.CurrentBlendOp ); + } + + if( module.AlphaToMaskHelper.ValidAndIndependent ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleAlphaToMask , m_subShaderIdx , m_passIdx , module.AlphaToMaskHelper.GenerateShaderData( isSubShader ) ); + } + + if( module.CullModeHelper.ValidAndIndependent ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleCullMode , m_subShaderIdx , m_passIdx , module.CullModeHelper.GenerateShaderData( isSubShader ) ); + } + + if( module.ColorMaskHelper.ValidAndIndependent ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleColorMask , m_subShaderIdx , m_passIdx , module.ColorMaskHelper.GenerateShaderData( isSubShader ) ); + } + + if( module.ColorMaskHelper1.ValidAndIndependent ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleColorMask1 , m_subShaderIdx , m_passIdx , module.ColorMaskHelper1.GenerateShaderData( isSubShader ) ); + } + + if( module.ColorMaskHelper2.ValidAndIndependent ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleColorMask2 , m_subShaderIdx , m_passIdx , module.ColorMaskHelper2.GenerateShaderData( isSubShader ) ); + } + + if( module.ColorMaskHelper3.ValidAndIndependent ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleColorMask3 , m_subShaderIdx , m_passIdx , module.ColorMaskHelper3.GenerateShaderData( isSubShader ) ); + } + + if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidZTest ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleZTest , m_subShaderIdx , m_passIdx , module.DepthOphelper.CurrentZTestMode ); + } + + if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidZWrite ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleZwrite , m_subShaderIdx , m_passIdx , module.DepthOphelper.CurrentZWriteMode ); + } + + if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidOffset ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleZOffset , m_subShaderIdx , m_passIdx , module.DepthOphelper.CurrentOffset ); + } + + if( module.StencilBufferHelper.ValidAndIndependent ) + { + CullMode cullMode = ( module.CullModeHelper.ValidData ) ? module.CullModeHelper.CurrentCullMode : CullMode.Back; + string value = module.StencilBufferHelper.CreateStencilOp( cullMode ); + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleStencil , m_subShaderIdx , m_passIdx , value.Split( '\n' ) ); + } + + if( module.RenderingPlatforms.LoadedFromTemplate ) + { + m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleRenderPlatforms , m_subShaderIdx , m_passIdx , module.RenderingPlatforms.CreateResult( true ) ); + } + } + } + + public override string GenerateShaderForOutput( int outputId , ref MasterNodeDataCollector dataCollector , bool ignoreLocalvar ) + { + return "0"; + } + + public override void Destroy() + { + base.Destroy(); + + m_drawInstancedHelper = null; + + m_optionsDefineContainer.Destroy(); + m_optionsDefineContainer = null; + + m_passSelector.Destroy(); + m_passSelector = null; + + m_subShaderOptions.Destroy(); + m_passOptions.Destroy(); + + m_fallbackHelper.Destroy(); + GameObject.DestroyImmediate( m_fallbackHelper ); + m_fallbackHelper = null; + + m_usePass.Destroy(); + GameObject.DestroyImmediate( m_usePass ); + m_usePass = null; + + m_dependenciesHelper.Destroy(); + m_dependenciesHelper = null; + + m_subShaderModule.Destroy(); + m_subShaderModule = null; + m_passModule.Destroy(); + m_passModule = null; + if( m_lodIndex == -1 ) + { + ContainerGraph.MultiPassMasterNodes.RemoveNode( this ); + } + else + { + ContainerGraph.LodMultiPassMasternodes[ m_lodIndex ].RemoveNode( this ); + } + } + + void UpdateSubShaderPassStr() + { + //m_subShaderIdxStr = SubShaderModuleStr + m_templateMultiPass.SubShaders[ m_subShaderIdx ].Idx; + //m_passIdxStr = PassModuleStr + m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Idx; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + + base.ReadFromString( ref nodeParams ); + try + { + string currShaderName = GetCurrentParam( ref nodeParams ); + if( currShaderName.Length > 0 ) + currShaderName = UIUtils.RemoveShaderInvalidCharacters( currShaderName ); + + m_templateGUID = GetCurrentParam( ref nodeParams ); + + bool hasUniqueName = false; + if( UIUtils.CurrentShaderVersion() > PASS_UNIQUE_ID_VERSION ) + { + hasUniqueName = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + + if( hasUniqueName ) + m_passUniqueId = GetCurrentParam( ref nodeParams ); + + m_subShaderIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_passIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + if( UIUtils.CurrentShaderVersion() > LOD_SUBSHADER_VERSION ) + { + + if( m_lodIndex != -1 ) + { + m_containerGraph.MultiPassMasterNodes.RemoveNode( this ); + m_containerGraph.LodMultiPassMasternodes[ m_lodIndex ].AddNode( this ); + } + } + + m_passName = GetCurrentParam( ref nodeParams ); + SetTemplate( null , false , true , m_subShaderIdx , m_passIdx , SetTemplateSource.ShaderLoad ); + ////If value gotten from template is > -1 then it contains the LOD field + ////and we can properly write the value + //if( m_subShaderLOD > -1 ) + //{ + // m_subShaderLOD = subShaderLOD; + //} + + // only in here, after SetTemplate, we know if shader name is to be used as title or not + ShaderName = currShaderName; + m_visiblePorts = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_subShaderModule.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + m_passModule.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > 15308 ) + { + m_fallbackHelper.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + m_dependenciesHelper.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 15402 ) + { + m_usePass.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + if( UIUtils.CurrentShaderVersion() > 15409 ) + { + m_hdSrpMaterialType = (HDSRPMaterialType)Enum.Parse( typeof( HDSRPMaterialType ) , GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 15501 ) + { + if( m_isMainOutputNode && UIUtils.CurrentShaderVersion() > PASS_SELECTOR_VERSION ) + m_subShaderOptions.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + + m_passOptions.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + if( m_isMainOutputNode && UIUtils.CurrentShaderVersion() > PASS_SELECTOR_VERSION ) + { + m_passSelector.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + if( m_isMainOutputNode && UIUtils.CurrentShaderVersion() > 16203 ) + { + m_drawInstancedHelper.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + if( m_isMainOutputNode && UIUtils.CurrentShaderVersion() > LOD_SUBSHADER_VERSION ) + { + m_mainLODName = GetCurrentParam( ref nodeParams ); + SetupLODNodeName(); + } + else + { + m_content.text = GenerateClippedTitle( m_passName ); + } + + if( UIUtils.CurrentShaderVersion() > 18302 ) + SamplingMacros = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + else + SamplingMacros = false; + + //if( m_templateMultiPass != null && !m_templateMultiPass.IsSinglePass ) + //{ + // SetClippedTitle( m_passName ); + //} + } + catch( Exception e ) + { + Debug.LogException( e , this ); + } + + m_containerGraph.CurrentCanvasMode = NodeAvailability.TemplateShader; + m_containerGraph.CurrentPrecision = m_currentPrecisionType; + CheckLegacyCustomInspectors(); + } + + void CheckLegacyCustomInspectors() + { +#if UNITY_2021_1_OR_NEWER + if( m_templateMultiPass.SubShaders[ 0 ].Modules.SRPType == TemplateSRPType.HD && ASEPackageManagerHelper.CurrentHDVersion >= ASESRPVersions.ASE_SRP_11_0_0 ) + { + if( Constants.CustomInspectorHDLegacyTo11.ContainsKey( m_customInspectorName ) ) + { + UIUtils.ShowMessage( string.Format( "Detected obsolete custom inspector \"{0}\" in shader meta. Converting to new one \"{1}\"" , m_customInspectorName , Constants.CustomInspectorHDLegacyTo11[ m_customInspectorName ] ) , MessageSeverity.Warning ); + m_customInspectorName = Constants.CustomInspectorHDLegacyTo11[ m_customInspectorName ]; + } + } +#elif UNITY_2020_2_OR_NEWER + if( m_templateMultiPass.SubShaders[0].Modules.SRPType == TemplateSRPType.HD && ASEPackageManagerHelper.CurrentHDVersion >= ASESRPVersions.ASE_SRP_10_0_0 ) + { + if( Constants.CustomInspectorHD7To10.ContainsKey( m_customInspectorName ) ) + { + UIUtils.ShowMessage( string.Format("Detected obsolete custom inspector \"{0}\" in shader meta. Converting to new one \"{1}\"", m_customInspectorName , Constants.CustomInspectorHD7To10[ m_customInspectorName ] ), MessageSeverity.Warning ); + m_customInspectorName = Constants.CustomInspectorHD7To10[ m_customInspectorName ]; + } + } +#endif + } + public override void WriteToString( ref string nodeInfo , ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo , ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo , ShaderName ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_templateGUID ); + + bool hasUniquePassName = Pass.Modules.HasPassUniqueName; + IOUtils.AddFieldValueToString( ref nodeInfo , hasUniquePassName ); + if( hasUniquePassName ) + { + IOUtils.AddFieldValueToString( ref nodeInfo , Pass.Modules.PassUniqueName ); + } + + IOUtils.AddFieldValueToString( ref nodeInfo , m_subShaderIdx ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_passIdx ); + + IOUtils.AddFieldValueToString( ref nodeInfo , m_passName ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_visiblePorts ); + m_subShaderModule.WriteToString( ref nodeInfo ); + m_passModule.WriteToString( ref nodeInfo ); + m_fallbackHelper.WriteToString( ref nodeInfo ); + m_dependenciesHelper.WriteToString( ref nodeInfo ); + m_usePass.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo , m_hdSrpMaterialType ); + if( m_isMainOutputNode ) + m_subShaderOptions.WriteToString( ref nodeInfo ); + + m_passOptions.WriteToString( ref nodeInfo ); + + if( m_isMainOutputNode ) + { + m_passSelector.WriteToString( ref nodeInfo ); + m_drawInstancedHelper.WriteToString( ref nodeInfo ); + } + + if( m_isMainOutputNode ) + IOUtils.AddFieldValueToString( ref nodeInfo , m_mainLODName ); + + IOUtils.AddFieldValueToString( ref nodeInfo , m_samplingMacros ); + } + + public override void ReadFromDeprecated( ref string[] nodeParams , Type oldType = null ) + { + base.ReadFromString( ref nodeParams ); + try + { + string currShaderName = GetCurrentParam( ref nodeParams ); + if( currShaderName.Length > 0 ) + currShaderName = UIUtils.RemoveShaderInvalidCharacters( currShaderName ); + + string templateGUID = GetCurrentParam( ref nodeParams ); + string templateShaderName = string.Empty; + if( UIUtils.CurrentShaderVersion() > 13601 ) + { + templateShaderName = GetCurrentParam( ref nodeParams ); + } + + TemplateMultiPass template = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( templateGUID ) as TemplateMultiPass; + if( template != null ) + { + m_templateGUID = templateGUID; + SetTemplate( null , false , true , 0 , 0 , SetTemplateSource.ShaderLoad ); + } + else + { + template = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplateByName( templateShaderName ) as TemplateMultiPass; + if( template != null ) + { + m_templateGUID = template.GUID; + SetTemplate( null , false , true , 0 , 0 , SetTemplateSource.ShaderLoad ); + } + else + { + m_masterNodeCategory = -1; + } + } + + if( m_invalidNode ) + return; + + // only in here, after SetTemplate, we know if shader name is to be used as title or not + ShaderName = currShaderName; + if( UIUtils.CurrentShaderVersion() > 13902 ) + { + + //BLEND MODULE + if( m_templateMultiPass.SubShaders[ 0 ].Modules.BlendData.ValidBlendMode ) + { + m_subShaderModule.BlendOpHelper.ReadBlendModeFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.BlendData.ValidBlendMode ) + { + m_passModule.BlendOpHelper.ReadBlendModeFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + if( m_templateMultiPass.SubShaders[ 0 ].Modules.BlendData.ValidBlendOp ) + { + m_subShaderModule.BlendOpHelper.ReadBlendOpFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.BlendData.ValidBlendOp ) + { + m_passModule.BlendOpHelper.ReadBlendOpFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + + //CULL MODE + if( m_templateMultiPass.SubShaders[ 0 ].Modules.CullModeData.DataCheck == TemplateDataCheck.Valid ) + { + m_subShaderModule.CullModeHelper.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.CullModeData.DataCheck == TemplateDataCheck.Valid ) + { + m_passModule.CullModeHelper.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + //COLOR MASK + if( m_templateMultiPass.SubShaders[ 0 ].Modules.ColorMaskData.DataCheck == TemplateDataCheck.Valid ) + { + m_subShaderModule.ColorMaskHelper.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.ColorMaskData.DataCheck == TemplateDataCheck.Valid ) + { + m_passModule.ColorMaskHelper.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + //STENCIL BUFFER + if( m_templateMultiPass.SubShaders[ 0 ].Modules.StencilData.DataCheck == TemplateDataCheck.Valid ) + { + m_subShaderModule.StencilBufferHelper.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.StencilData.DataCheck == TemplateDataCheck.Valid ) + { + m_passModule.StencilBufferHelper.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + } + + if( UIUtils.CurrentShaderVersion() > 14202 ) + { + //DEPTH OPTIONS + if( m_templateMultiPass.SubShaders[ 0 ].Modules.DepthData.ValidZWrite ) + { + m_subShaderModule.DepthOphelper.ReadZWriteFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.DepthData.ValidZWrite ) + { + m_passModule.DepthOphelper.ReadZWriteFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + if( m_templateMultiPass.SubShaders[ 0 ].Modules.DepthData.ValidZTest ) + { + m_subShaderModule.DepthOphelper.ReadZTestFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.DepthData.ValidZTest ) + { + m_subShaderModule.DepthOphelper.ReadZTestFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + if( m_templateMultiPass.SubShaders[ 0 ].Modules.DepthData.ValidOffset ) + { + m_subShaderModule.DepthOphelper.ReadOffsetFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.DepthData.ValidOffset ) + { + m_passModule.DepthOphelper.ReadOffsetFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + + } + + //TAGS + if( UIUtils.CurrentShaderVersion() > 14301 ) + { + if( m_templateMultiPass.SubShaders[ 0 ].Modules.TagData.DataCheck == TemplateDataCheck.Valid ) + { + m_subShaderModule.TagsHelper.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.TagData.DataCheck == TemplateDataCheck.Valid ) + { + m_passModule.TagsHelper.ReadFromString( ref m_currentReadParamIdx , ref nodeParams ); + } + } + + SamplingMacros = false; + } + catch( Exception e ) + { + Debug.LogException( e , this ); + } + m_containerGraph.CurrentCanvasMode = NodeAvailability.TemplateShader; + } + + public void ForceOptionsRefresh() + { + m_passOptions.Refresh(); + if( m_isMainOutputNode ) + m_subShaderOptions.Refresh(); + } + + public void SetPassVisible( string passName , bool visible ) + { + TemplateMultiPassMasterNode node = m_containerGraph.GetMasterNodeOfPass( passName , m_lodIndex ); + if( node != null ) + { + m_passSelector.SetPassVisible( passName , visible ); + node.IsInvisible = !visible; + } + + } + + public override void RefreshExternalReferences() + { + if( m_invalidNode ) + return; + + base.RefreshExternalReferences(); + if( IsLODMainMasterNode ) + { + SetMasterNodeCategoryFromGUID( m_templateGUID ); + } + + CheckTemplateChanges(); + if( m_templateMultiPass != null && m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBRHD && UIUtils.CurrentShaderVersion() < 15410 ) + { + FetchHDPorts(); + m_hdSrpMaterialType = ( m_specularPort != null && m_specularPort.HasOwnOrLinkConnection ) ? HDSRPMaterialType.Specular : HDSRPMaterialType.Standard; + ConfigHDPorts(); + } + + if( ContainerGraph.HasLODs ) + { + SetClippedAdditionalTitle( string.Format( LodSubtitle , ShaderLOD ) ); + } + + if( m_isMainOutputNode ) + { + List masterNodes = ( m_lodIndex == -1 ) ? m_containerGraph.MultiPassMasterNodes.NodesList : m_containerGraph.LodMultiPassMasternodes[ m_lodIndex ].NodesList; + masterNodes.Sort( ( x , y ) => ( x.PassIdx.CompareTo( y.PassIdx ) ) ); + int passAmount = m_templateMultiPass.SubShaders[ m_subShaderIdx ].PassAmount; + if( passAmount != masterNodes.Count ) + { + UIUtils.ShowMessage( "Template master nodes amount was modified. Could not set correctly its visibility options." ); + } + else + { + for( int i = 0 ; i < passAmount ; i++ ) + { + if( i != m_passIdx ) + { + masterNodes[ i ].IsInvisible = !m_passSelector.IsVisible( i ); + } + } + } + } + } + + public override void ReadInputDataFromString( ref string[] nodeParams ) + { + //For a Template Master Node an input port data must be set by its template and not meta data + if( UIUtils.CurrentShaderVersion() > 17007 ) + return; + + int count = 0; + if( UIUtils.CurrentShaderVersion() > 7003 ) + { + try + { + count = Convert.ToInt32( nodeParams[ m_currentReadParamIdx++ ] ); + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + else + { + count = ( m_oldInputCount < 0 ) ? m_inputPorts.Count : m_oldInputCount; + } + + for( int i = 0 ; i < count && i < nodeParams.Length && m_currentReadParamIdx < nodeParams.Length ; i++ ) + { + if( UIUtils.CurrentShaderVersion() < 5003 ) + { + int newId = VersionConvertInputPortId( i ); + if( UIUtils.CurrentShaderVersion() > 23 ) + { + m_currentReadParamIdx++; + } + + m_currentReadParamIdx++; + if( m_inputPorts[ newId ].IsEditable && UIUtils.CurrentShaderVersion() >= 3100 && m_currentReadParamIdx < nodeParams.Length ) + { + m_currentReadParamIdx++; + } + } + else + { + m_currentReadParamIdx++; + m_currentReadParamIdx++; + m_currentReadParamIdx++; + bool isEditable = Convert.ToBoolean( nodeParams[ m_currentReadParamIdx++ ] ); + if( isEditable && m_currentReadParamIdx < nodeParams.Length ) + { + m_currentReadParamIdx++; + } + } + } + } + + //For a Template Master Node an input port data must be set by its template and not meta data + public override void WriteInputDataToString( ref string nodeInfo ) { } + + public override float HeightEstimate + { + get + { + float heightEstimate = 0; + heightEstimate = 32 + Constants.INPUT_PORT_DELTA_Y; + if( m_templateMultiPass != null && !m_templateMultiPass.IsSinglePass ) + { + heightEstimate += 22; + } + float internalPortSize = 0; + for( int i = 0 ; i < InputPorts.Count ; i++ ) + { + if( InputPorts[ i ].Visible ) + internalPortSize += 18 + Constants.INPUT_PORT_DELTA_Y; + } + + return heightEstimate + Mathf.Max( internalPortSize , m_insideSize.y ); + } + } + + public HDSRPMaterialType CurrentHDMaterialType + { + get { return m_hdSrpMaterialType; } + set + { + m_hdSrpMaterialType = value; + if( m_isMainOutputNode ) + { + List mpNodes = ContainerGraph.MultiPassMasterNodes.NodesList; + int count = mpNodes.Count; + for( int i = 0 ; i < count ; i++ ) + { + if( mpNodes[ i ].UniqueId != UniqueId ) + { + mpNodes[ i ].CurrentHDMaterialType = value; + } + } + } + } + } + public TemplateSubShader SubShader { get { return m_templateMultiPass.SubShaders[ m_subShaderIdx ]; } } + public TemplatePass Pass { get { return m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ]; } } + public int SubShaderIdx { get { return m_subShaderIdx; } } + public int PassIdx { get { return m_passIdx; } } + public TemplateMultiPass CurrentTemplate { get { return m_templateMultiPass; } } + public TemplateModulesHelper SubShaderModule { get { return m_subShaderModule; } } + public TemplateModulesHelper PassModule { get { return m_passModule; } } + public string PassName { get { return m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].PassNameContainer.Data; } } + public string PassUniqueName + { + get + { + return string.IsNullOrEmpty( m_passUniqueId ) ? m_originalPassName : m_passUniqueId; + } + } + + public string OriginalPassName { get { return m_originalPassName; } } + public bool HasLinkPorts { get { return m_hasLinkPorts; } } + public bool IsInvisible + { + get + { + return m_isInvisible != InvisibilityStatus.Visible; + } + set + { + if( m_isInvisible != InvisibilityStatus.LockedInvisible && !m_isMainOutputNode ) + { + m_isInvisible = value ? InvisibilityStatus.Invisible : InvisibilityStatus.Visible; + if( value ) + { + for( int i = 0 ; i < m_inputPorts.Count ; i++ ) + { + m_inputPorts[ i ].FullDeleteConnections(); + } + } + } + } + } + + public TemplatePassSelectorHelper PassSelector { get { return m_passSelector; } } + public TemplateOptionsUIHelper PassOptions { get { return m_passOptions; } } + public TemplateOptionsUIHelper SubShaderOptions { get { return m_subShaderOptions; } } + public TemplateOptionsDefinesContainer OptionsDefineContainer { get { return m_optionsDefineContainer; } } + public TerrainDrawInstancedHelper DrawInstancedHelperInstance { get { return m_drawInstancedHelper; } } + public bool InvalidNode { get { return m_invalidNode; } } + public override void SetName( string name ) + { + ShaderName = name; + } + public bool IsLODMainFirstPass { get { return m_passIdx == 0 && m_lodIndex == -1; } } + public override AvailableShaderTypes CurrentMasterNodeCategory { get { return AvailableShaderTypes.Template; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs.meta new file mode 100644 index 0000000..a96d88d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: fce684c26c654d14e927860863cd99dd +timeCreated: 1517406883 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs new file mode 100644 index 0000000..e8aeadf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs @@ -0,0 +1,328 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + + [Serializable] + public class InputSwitchMPHelper + { + public int SubShaderIdx; + public int PassIdx; + public InputSwitchMPHelper( int subShaderIdx, int passIdx ) + { + SubShaderIdx = subShaderIdx; + PassIdx = passIdx; + } + } + + [Serializable] + [NodeAttributes( "Template Multi-Pass Switch", "Logical Operators", "Relays, in compile time, the correct input port according to current analyzed sub-shader/pass." )] + public sealed class TemplateMultiPassSwitchNode : TemplateNodeParent + { + private const string InputLabelStr = "SubShader {0} Pass {1}"; + + [SerializeField] + private List m_inputHelper = new List(); + + [SerializeField] + private int m_inputCountHelper = -1; + + protected override void CommonInit( int uniqueId ) + { + m_createAllOutputs = false; + base.CommonInit( uniqueId ); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + UpdateConnections(); + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + UpdateConnections(); + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + UpdateConnections(); + } + + private void UpdateConnections() + { + WirePortDataType mainType = WirePortDataType.FLOAT; + + int highest = UIUtils.GetPriority( mainType ); + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + WirePortDataType portType = m_inputPorts[ i ].GetOutputConnection().DataType; + if( UIUtils.GetPriority( portType ) > highest ) + { + mainType = portType; + highest = UIUtils.GetPriority( portType ); + } + } + } + + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + m_inputPorts[ i ].ChangeType( mainType, false ); + } + + m_outputPorts[ 0 ].ChangeType( mainType, false ); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + + if( m_templateMPData == null ) + { + FetchMultiPassTemplate(); + if( m_inputPorts.Count != m_inputCountHelper ) + { + CreateInputPorts(); + } + else + { + RefreshInputPorts(); + } + } + } + + + public void RefreshInputPorts() + { + if( m_multiPassMode ) + { + m_inputHelper.Clear(); + if( m_templateMPData != null ) + { + int index = 0; + int subShaderCount = m_templateMPData.SubShaders.Count; + for( int subShaderIdx = 0; subShaderIdx < subShaderCount; subShaderIdx++ ) + { + int passCount = m_templateMPData.SubShaders[ subShaderIdx ].Passes.Count; + for( int passIdx = 0; passIdx < passCount; passIdx++ ) + { + if( m_templateMPData.SubShaders[ subShaderIdx ].Passes[ passIdx ].HasValidFunctionBody ) + { + m_inputPorts[ index ].Name = string.Format( InputLabelStr, subShaderIdx, passIdx ); + m_inputHelper.Add( new InputSwitchMPHelper( subShaderIdx, passIdx ) ); + index += 1; + } + } + } + } + } + else + { + m_inputPorts[0].Name = "In"; + } + } + + public int RefreshInputCountHelper() + { + int inputCountHelper = 0; + if( m_multiPassMode ) + { + if( m_templateMPData != null ) + { + int subShaderCount = m_templateMPData.SubShaders.Count; + for( int subShaderIdx = 0; subShaderIdx < subShaderCount; subShaderIdx++ ) + { + int passCount = m_templateMPData.SubShaders[ subShaderIdx ].Passes.Count; + for( int passIdx = 0; passIdx < passCount; passIdx++ ) + { + if( m_templateMPData.SubShaders[ subShaderIdx ].Passes[passIdx].HasValidFunctionBody ) + inputCountHelper += 1; + } + } + } + } + else + { + inputCountHelper += 1; + } + return inputCountHelper; + } + + public void CreateInputPorts() + { + m_inputCountHelper = 0; + DeleteAllInputConnections( true ); + if( m_multiPassMode ) + { + m_inputHelper.Clear(); + if( m_templateMPData != null ) + { + int subShaderCount = m_templateMPData.SubShaders.Count; + for( int subShaderIdx = 0; subShaderIdx < subShaderCount; subShaderIdx++ ) + { + int passCount = m_templateMPData.SubShaders[ subShaderIdx ].Passes.Count; + for( int passIdx = 0; passIdx < passCount; passIdx++ ) + { + if( m_templateMPData.SubShaders[ subShaderIdx ].Passes[ passIdx ].HasValidFunctionBody ) + { + AddInputPort( WirePortDataType.FLOAT, false, string.Format( InputLabelStr, subShaderIdx, passIdx ) ); + m_inputHelper.Add( new InputSwitchMPHelper( subShaderIdx, passIdx ) ); + m_inputCountHelper += 1; + } + } + } + } + } + else + { + AddInputPort( WirePortDataType.FLOAT, false, "In" ); + m_inputCountHelper += 1; + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.MasterNodeCategory != AvailableShaderTypes.Template ) + { + UIUtils.ShowMessage( "Template Multi-Pass Switch Data node is only intended for templates use only" ); + return m_outputPorts[ 0 ].ErrorValue; + } + + int currSubShaderIdx = dataCollector.TemplateDataCollectorInstance.MultipassSubshaderIdx; + int currPassIdx = dataCollector.TemplateDataCollectorInstance.MultipassPassIdx; + + int inputHelperCount = m_inputHelper.Count; + for( int i = 0; i< inputHelperCount; i++ ) + { + if(m_inputHelper[i].SubShaderIdx == currSubShaderIdx && m_inputHelper[ i ].PassIdx == currPassIdx ) + return m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ); + } + + UIUtils.ShowMessage( "Invalid subshader or pass on Template Multi-Pass Switch Data" ); + return m_outputPorts[ 0 ].ErrorValue; + } + + public override void OnMasterNodeReplaced( MasterNode newMasterNode ) + { + base.OnMasterNodeReplaced( newMasterNode ); + if( newMasterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template ) + { + FetchMultiPassTemplate( newMasterNode ); + m_inputCountHelper = RefreshInputCountHelper(); + if( m_inputPorts.Count != m_inputCountHelper ) + { + CreateInputPorts(); + } + else + { + RefreshInputPorts(); + } + } + else + { + DeleteAllInputConnections( true ); + } + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_inputCountHelper = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + // Need to add ports here so read internal data is correct + for( int i = 0; i < m_inputCountHelper; i++ ) + { + AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_inputCountHelper ); + } + + public override void Destroy() + { + base.Destroy(); + m_inputHelper.Clear(); + m_inputHelper = null; + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + FetchMultiPassTemplate(); + + bool create = false; + if( m_inputCountHelper == -1 ) + { + create = true; + } + else + { + int newInputCount = RefreshInputCountHelper(); + if( newInputCount != m_inputCountHelper ) + { + create = true; + } + } + + + if( m_multiPassMode ) + { + if( m_templateMPData != null ) + { + if( create ) + { + CreateInputPorts(); + } + else + { + m_inputHelper.Clear(); + int index = 0; + int subShaderCount = m_templateMPData.SubShaders.Count; + for( int subShaderIdx = 0; subShaderIdx < subShaderCount; subShaderIdx++ ) + { + int passCount = m_templateMPData.SubShaders[ subShaderIdx ].Passes.Count; + for( int passIdx = 0; passIdx < passCount; passIdx++ ) + { + if( m_templateMPData.SubShaders[ subShaderIdx ].Passes[ passIdx ].HasValidFunctionBody ) + { + m_inputPorts[ index ].Name = string.Format( InputLabelStr, subShaderIdx, passIdx ); + m_inputHelper.Add( new InputSwitchMPHelper( subShaderIdx, passIdx )); + index += 1; + } + } + } + + if( index != m_inputCountHelper ) + { + Debug.LogWarning( "Something wrong occured in reading MultiPass Switch node" ); + } + } + } + } + else + { + if( create ) + { + AddInputPort( WirePortDataType.FLOAT, false, "In" ); + } + else + { + m_inputPorts[ 0 ].Name = "In"; + } + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs.meta new file mode 100644 index 0000000..4aafb59 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 58e4eb5fc3fed124384eef956c6c3ee1 +timeCreated: 1519319737 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs new file mode 100644 index 0000000..272e002 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs @@ -0,0 +1,272 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateNodeParent : ParentNode + { + + + protected const string ErrorMessageStr = "This node can only be used inside a Template category!"; + protected const string DataLabelStr = "Data"; + protected const string SubShaderStr = "SubShader"; + protected const string PassStr = "Pass"; + + [SerializeField] + private int m_subShaderIdx = 0; + + [SerializeField] + private int m_passIdx = 0; + + [SerializeField] + private int m_passLocalArrayIdx = 0; + + [SerializeField] + protected bool m_multiPassMode = false; + + [SerializeField] + protected string[] m_availableSubshaders; + + [SerializeField] + protected string[] m_availablePassesLabels; + + [SerializeField] + protected int[] m_availablePassesValues; + + [NonSerialized] + protected TemplateMultiPass m_templateMPData = null; + protected bool m_createAllOutputs = true; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + AddOutputPort( WirePortDataType.FLOAT, "Out" ); + if( m_createAllOutputs ) + { + AddOutputPort( WirePortDataType.FLOAT, "X" ); + AddOutputPort( WirePortDataType.FLOAT, "Y" ); + AddOutputPort( WirePortDataType.FLOAT, "Z" ); + AddOutputPort( WirePortDataType.FLOAT, "W" ); + } + m_textLabelWidth = 67; + m_hasLeftDropdown = true; + } + + public override void AfterCommonInit() + { + base.AfterCommonInit(); + + if( PaddingTitleLeft == 0 ) + { + PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + if( PaddingTitleRight == 0 ) + PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + } + } + + protected void ConfigurePorts() + { + switch( m_outputPorts[ 0 ].DataType ) + { + default: + { + for( int i = 1; i < 5; i++ ) + { + m_outputPorts[ i ].Visible = false; + } + } + break; + case WirePortDataType.FLOAT2: + { + for( int i = 1; i < 5; i++ ) + { + m_outputPorts[ i ].Visible = ( i < 3 ); + if( m_outputPorts[ i ].Visible ) + { + m_outputPorts[ i ].Name = Constants.ChannelNamesVector[ i - 1 ]; + } + } + } + break; + case WirePortDataType.FLOAT3: + { + for( int i = 1; i < 5; i++ ) + { + m_outputPorts[ i ].Visible = ( i < 4 ); + if( m_outputPorts[ i ].Visible ) + { + m_outputPorts[ i ].Name = Constants.ChannelNamesVector[ i - 1 ]; + } + } + } + break; + case WirePortDataType.FLOAT4: + { + for( int i = 1; i < 5; i++ ) + { + m_outputPorts[ i ].Visible = true; + m_outputPorts[ i ].Name = Constants.ChannelNamesVector[ i - 1 ]; + } + } + break; + case WirePortDataType.COLOR: + { + for( int i = 1; i < 5; i++ ) + { + m_outputPorts[ i ].Visible = true; + m_outputPorts[ i ].Name = Constants.ChannelNamesColor[ i - 1 ]; + } + } + break; + } + m_sizeIsDirty = true; + } + + protected virtual void OnSubShaderChange() { } + protected virtual void OnPassChange() { } + + protected void DrawSubShaderUI() + { + EditorGUI.BeginChangeCheck(); + m_subShaderIdx = EditorGUILayoutPopup( SubShaderStr, m_subShaderIdx, m_availableSubshaders ); + if( EditorGUI.EndChangeCheck() ) + { + //UpdateSubShaderAmount(); + UpdatePassAmount(); + OnSubShaderChange(); + } + } + + protected void DrawPassUI() + { + EditorGUI.BeginChangeCheck(); + m_passLocalArrayIdx = EditorGUILayoutPopup( PassStr, m_passLocalArrayIdx, m_availablePassesLabels ); + if( EditorGUI.EndChangeCheck() ) + { + m_passIdx = m_availablePassesValues[ m_passLocalArrayIdx ]; + //UpdatePassAmount(); + OnPassChange(); + } + } + + virtual protected void CheckWarningState() + { + if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader ) + { + ShowTab( NodeMessageType.Error, ErrorMessageStr ); + } + else + { + m_showErrorMessage = false; + } + } + + protected void FetchMultiPassTemplate( MasterNode masterNode = null ) + { + m_multiPassMode = m_containerGraph.MultiPassMasterNodes.NodesList.Count > 0; + if( m_multiPassMode ) + { + m_templateMPData = ( ( ( masterNode == null ) ? m_containerGraph.CurrentMasterNode : masterNode ) as TemplateMultiPassMasterNode ).CurrentTemplate; + if( m_templateMPData != null ) + { + UpdateSubShaderAmount(); + } + } + } + + protected void UpdateSubShaderAmount() + { + if( m_templateMPData == null ) + m_templateMPData = ( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ).CurrentTemplate; + + if( m_templateMPData != null ) + { + int subShaderCount = m_templateMPData.SubShaders.Count; + if( m_availableSubshaders == null || subShaderCount != m_availableSubshaders.Length ) + { + m_availableSubshaders = new string[ subShaderCount ]; + for( int i = 0; i < subShaderCount; i++ ) + { + m_availableSubshaders[ i ] = i.ToString(); + } + } + m_subShaderIdx = Mathf.Min( m_subShaderIdx, subShaderCount - 1 ); + UpdatePassAmount(); + } + } + protected virtual bool ValidatePass( int passIdx ) { return true; } + protected void UpdatePassAmount() + { + if( !m_multiPassMode ) + return; + + if( m_templateMPData == null ) + m_templateMPData = ( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ).CurrentTemplate; + + List passLabels = new List(); + List passValues = new List(); + int minPassIdx = int.MaxValue; + int passCount = m_templateMPData.SubShaders[ m_subShaderIdx ].Passes.Count; + bool resetPassIdx = true; + for( int i = 0; i < passCount; i++ ) + { + if( ValidatePass( i ) ) + { + passLabels.Add( i.ToString() ); + passValues.Add( i ); + minPassIdx = Mathf.Min( minPassIdx, i ); + if( m_passIdx == i ) + resetPassIdx = false; + } + } + m_availablePassesLabels = passLabels.ToArray(); + m_availablePassesValues = passValues.ToArray(); + if( resetPassIdx ) + m_passIdx = minPassIdx; + + RefreshPassLocalArrayIdx(); + } + + void RefreshPassLocalArrayIdx( ) + { + for( int i = 0; i < m_availablePassesValues.Length; i++ ) + { + if( m_availablePassesValues[ i ] == m_passIdx ) + { + m_passLocalArrayIdx = i; + } + } + } + + public override void Destroy() + { + base.Destroy(); + m_templateMPData = null; + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + m_subShaderIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_passIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_subShaderIdx ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_passIdx ); + } + public int SubShaderIdx { get { return m_subShaderIdx; } set { m_subShaderIdx = value; } } + public int PassIdx { get { return m_passIdx; } set { m_passIdx = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs.meta new file mode 100644 index 0000000..134dcd6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b21cb297a12ef0a4281213619e3e76bf +timeCreated: 1519235586 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs new file mode 100644 index 0000000..8482ba9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs @@ -0,0 +1,1162 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Text.RegularExpressions; +using System.Collections.Generic; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + /*ase_pass_options OLDEST + DefineOnConnected:portId:definevalue + DefineOnUnconnected:portId:definevalue + Options:name:defaultOption:opt0:opt1:opt2 + SetVisible:PortId:OptionName:OptionValue + */ + + /*ase_pass_options OLD + Option:Option Name:UI Type:Default:Item0,Item1,Item3...ItemN + Action:Action Type:Action Data:ConditionA && ConditionB || ConditionC: + */ + + /*ase_pass_options:UniqueId:PropagateDataToHiddenPasses + Option:Color Offset:A,B,C:A + A:ShowPort:My Port Name + B,C:HidePort:My Port Name + B:SetDefine:MY_DEFINE + C:SetDefine:MY_COLOR_DEFINE + Option:My Other Option:True,False + True:ShowOption:Color Offset + False:HideOption:Color Offset + Port:My Port Name + On:SetDefine:MY_COLOR_DEFINE + Off:UnsetDefine:MY_COLOR_DEFINE + */ + public enum AseOptionsUIWidget + { + Dropdown, + Toggle, + Float, + FloatRange, + Int, + IntRange + } + + public enum AseOptionsType + { + Option, + Port, + Field + } + + + public enum AseOptionItemSetup + { + None, + InvertActionOnDeselection + } + + public enum AseOptionsActionType + { + ShowOption, + HideOption, + SetOption, + HidePort, + ShowPort, + SetPortName, + SetDefine, + RemoveDefine, + SetUndefine, + RemoveUndefine, + ExcludePass, + IncludePass, + SetPropertyOnPass, + SetPropertyOnSubShader, + SetShaderProperty, + SetMaterialProperty, + ExcludeAllPassesBut + } + + public enum PropertyActionsEnum + { + CullMode, + ColorMask, + ColorMask1, + ColorMask2, + ColorMask3, + ZWrite, + ZTest, + ZOffsetFactor, + ZOffsetUnits, + BlendRGB, + BlendAlpha, + BlendOpRGB, + BlendOpAlpha, + BlendRGB1, + BlendAlpha1, + BlendOpRGB1, + BlendOpAlpha1, + BlendRGB2, + BlendAlpha2, + BlendOpRGB2, + BlendOpAlpha2, + BlendRGB3, + BlendAlpha3, + BlendOpRGB3, + BlendOpAlpha3, + StencilReference, + StencilReadMask, + StencilWriteMask, + StencilComparison, + StencilPass, + StencilFail, + StencilZFail, + RenderType, + RenderQueue, + DisableBatching + } + + public enum AseOptionsSetup + { + CopyOptionsFromMainPass, + Id, + Name + } + + [Serializable] + public class ItemColorMask + { + public bool ValueR = true; + public bool ValueG = true; + public bool ValueB = true; + public bool ValueA = true; + + public bool MaskR = false; + public bool MaskG = false; + public bool MaskB = false; + public bool MaskA = false; + + public bool[] GetColorMask( bool[] input ) + { + bool[] result = { ValueR, ValueG, ValueB, ValueA }; + result[ 0 ] = MaskR ? ValueR : input[ 0 ]; + result[ 1 ] = MaskG ? ValueG : input[ 1 ]; + result[ 2 ] = MaskB ? ValueB : input[ 2 ]; + result[ 3 ] = MaskA ? ValueA : input[ 3 ]; + return result; + } + + public void SetColorMask( int index, string value ) + { + switch( index ) + { + default: + case 0: + { + MaskR = !string.IsNullOrEmpty( value ); + if(MaskR) + ValueR = Convert.ToBoolean( value ); + } + break; + case 1: + { + MaskG = !string.IsNullOrEmpty( value ); + if( MaskG ) + ValueG = Convert.ToBoolean( value ); + } + break; + case 2: + { + MaskB = !string.IsNullOrEmpty( value ); + if( MaskB ) + ValueB = Convert.ToBoolean( value ); + } + break; + case 3: + { + MaskA = !string.IsNullOrEmpty( value ); + if( MaskA ) + ValueA = Convert.ToBoolean( value ); + } + break; + } + } + } + + [Serializable] + public class TemplateActionItem + { + public AseOptionsActionType ActionType; + public string ActionData = string.Empty; + public int ActionDataIdx = -1; + + public string PassName; + public bool AllPasses = false; + + public PropertyActionsEnum PropertyAction; + //CULL + public CullMode ActionCullMode; + //COLOR MASK + public ItemColorMask ColorMask = new ItemColorMask(); + public ItemColorMask ColorMask1 = new ItemColorMask(); + public ItemColorMask ColorMask2 = new ItemColorMask(); + public ItemColorMask ColorMask3 = new ItemColorMask(); + + //DEPTH + public ZWriteMode ActionZWrite; + public ZTestMode ActionZTest; + public float ActionZOffsetFactor; + public float ActionZOffsetUnits; + + //BLEND OPS + public AvailableBlendFactor ActionBlendRGBSource; + public AvailableBlendFactor ActionBlendRGBDest; + public AvailableBlendFactor ActionBlendAlphaSource; + public AvailableBlendFactor ActionBlendAlphaDest; + public AvailableBlendOps ActionBlendOpRGB; + public AvailableBlendOps ActionBlendOpAlpha; + + public AvailableBlendFactor ActionBlendRGBSource1; + public AvailableBlendFactor ActionBlendRGBDest1; + public AvailableBlendFactor ActionBlendAlphaSource1; + public AvailableBlendFactor ActionBlendAlphaDest1; + public AvailableBlendOps ActionBlendOpRGB1; + public AvailableBlendOps ActionBlendOpAlpha1; + + public AvailableBlendFactor ActionBlendRGBSource2; + public AvailableBlendFactor ActionBlendRGBDest2; + public AvailableBlendFactor ActionBlendAlphaSource2; + public AvailableBlendFactor ActionBlendAlphaDest2; + public AvailableBlendOps ActionBlendOpRGB2; + public AvailableBlendOps ActionBlendOpAlpha2; + + public AvailableBlendFactor ActionBlendRGBSource3; + public AvailableBlendFactor ActionBlendRGBDest3; + public AvailableBlendFactor ActionBlendAlphaSource3; + public AvailableBlendFactor ActionBlendAlphaDest3; + public AvailableBlendOps ActionBlendOpRGB3; + public AvailableBlendOps ActionBlendOpAlpha3; + + //STENCIL + public int ActionStencilReference; + public int ActionStencilReadMask; + public int ActionStencilWriteMask; + public int ActionStencilComparison; + public int ActionStencilPass; + public int ActionStencilFail; + public int ActionStencilZFail; + + public bool CopyFromSubShader = false; + + public string ActionBuffer; + public override string ToString() + { + return ActionType + " " + ActionData + " " + ActionDataIdx; + } + + public bool GetIntValueFromActionBuffer( out int result ) + { + return int.TryParse( ActionBuffer, out result ); + } + + public bool GetFloatValueFromActionBuffer( out float result ) + { + return float.TryParse( ActionBuffer, out result ); + } + } + + [Serializable] + public class TemplateActionItemGrid + { + [Serializable] + public class TemplateActionItemRow + { + public TemplateActionItem[] Columns; + } + + public TemplateActionItemRow[] Rows; + + public TemplateActionItemGrid( int rowsCount ) + { + Rows = new TemplateActionItemRow[ rowsCount ]; + } + + public TemplateActionItem this[ int row, int column ] + { + get { return Rows[ row ].Columns[ column ]; } + set { Rows[ row ].Columns[ column ] = value; } + } + + public TemplateActionItem[] this[ int row ] + { + get { return Rows[ row ].Columns; } + + set + { + if( Rows[ row ] == null ) + Rows[ row ] = new TemplateActionItemRow(); + + Rows[ row ].Columns = value; + } + } + } + + [Serializable] + public class TemplateOptionsItem + { + public AseOptionsType Type; + public AseOptionsUIWidget UIWidget; + public AseOptionItemSetup Setup = AseOptionItemSetup.None; + + public string Id = string.Empty; + public string Name = string.Empty; + public string DefaultOption = string.Empty; + public string[] Options = null; + public string[] DisplayOptions = null; + public int DisableIdx = -1; + + [SerializeField] + private float m_defaultFieldValue; + + public float FieldMin; + public float FieldMax; + + public bool FieldInline; + public string FieldInlineName; + public string FieldInlineOutput = string.Empty; + + [SerializeField] + public InlineProperty FieldValue = new InlineProperty(); + + public TemplateActionItemGrid ActionsPerOption = null; + + public int Count = 0; + + [SerializeField] + private int m_defaultOptionIndex = -1; + + ~TemplateOptionsItem() + { + Options = null; + } + + public int OptionIndexFor( string option ) + { + for( int i = 0; i < Options.Length; i++ ) + { + if( Options[ i ].Equals( option ) ) + { + return i; + } + } + Debug.LogWarning( "Couldn't find index for option: " + option ); + return 0; + } + + public int DefaultOptionIndex + { + get + { + if( m_defaultOptionIndex > -1 ) + return m_defaultOptionIndex; + + for( int i = 0; i < Options.Length; i++ ) + { + if( Options[ i ].Equals( DefaultOption ) ) + { + m_defaultOptionIndex = i; + return i; + } + } + Debug.LogWarning( "Couldn't find index for default option: " + DefaultOption ); + return 0; + } + } + + public float DefaultFieldValue + { + get + { + return m_defaultFieldValue; + } + set + { + m_defaultFieldValue = value; + } + } + } + + [Serializable] + public class TemplateOptionsContainer + { + public bool Enabled = false; + public string Body = string.Empty; + public int Index = -1; + public int Id = -1; + public string Name = string.Empty; + public bool CopyOptionsFromMainPass = false; + public TemplateOptionsItem[] Options = null; + ~TemplateOptionsContainer() + { + Options = null; + } + + public void CopyPortOptionsFrom( TemplateOptionsContainer container, string passName ) + { + if( container == null || container.Options == null ) + return; + + List newItems = new List(); + for( int i = 0; i < container.Options.Length; i++ ) + { + if( container.Options[ i ].Type == AseOptionsType.Port && + container.Options[ i ].Id.Equals( passName ) ) + { + newItems.Add( container.Options[ i ] ); + } + } + + if( newItems.Count > 0 ) + { + Enabled = true; + if( Options == null ) + { + Options = newItems.ToArray(); + } + else + { + Array.Resize( ref Options, Options.Length + newItems.Count ); + Array.Copy( newItems.ToArray(), Options, newItems.Count ); + } + } + newItems.Clear(); + newItems = null; + } + + public int EndIndex { get { return Index + Body.Length; } } + } + + public class TemplateOptionsToolsHelper + { + //public const string PassOptionsMainPattern = @"\/\*ase_pass_options:([\w:= ]*)[\n]([\w: \t;\n&|,_\+-]*)\*\/"; + //public const string SubShaderOptionsMainPattern = @"\/\*ase_subshader_options:([\w:= ]*)[\n]([\w: \t;\n&|,_\+-]*)\*\/"; + public const string PassOptionsMainPattern = "\\/\\*ase_pass_options:([\\w:= ]*)[\n]([\\w: \t;\n&|,_\\+\\-\\(\\)\\[\\]\\\"\\=\\/\\.]*)\\*\\/"; + public const string SubShaderOptionsMainPattern = "\\/\\*ase_subshader_options:([\\w:= ]*)[\n]([\\w: \t;\n&|,_\\+\\-\\(\\)\\[\\]\\\"\\=\\/\\.]*)\\*\\/"; + public static readonly char OptionsDataSeparator = ','; + public static Dictionary AseOptionsSetupDict = new Dictionary() + { + { "CopyOptionsFromMainPass",AseOptionsSetup.CopyOptionsFromMainPass}, + { "Id",AseOptionsSetup.Id}, + { "Name",AseOptionsSetup.Name}, + }; + + public static Dictionary AseOptionsUITypeDict = new Dictionary() + { + { "Dropdown",AseOptionsUIWidget.Dropdown }, + { "Toggle", AseOptionsUIWidget.Toggle } + }; + + public static Dictionary AseOptionsActionTypeDict = new Dictionary() + { + {"ShowOption", AseOptionsActionType.ShowOption }, + {"HideOption", AseOptionsActionType.HideOption }, + {"SetOption", AseOptionsActionType.SetOption }, + {"HidePort", AseOptionsActionType.HidePort }, + {"ShowPort", AseOptionsActionType.ShowPort }, + {"SetPortName", AseOptionsActionType.SetPortName }, + {"SetDefine", AseOptionsActionType.SetDefine }, + {"RemoveDefine", AseOptionsActionType.RemoveDefine }, + {"SetUndefine", AseOptionsActionType.SetUndefine }, + {"RemoveUndefine", AseOptionsActionType.RemoveUndefine }, + {"ExcludePass", AseOptionsActionType.ExcludePass }, + {"IncludePass", AseOptionsActionType.IncludePass }, + {"SetPropertyOnPass", AseOptionsActionType.SetPropertyOnPass }, + {"SetPropertyOnSubShader", AseOptionsActionType.SetPropertyOnSubShader }, + {"SetShaderProperty", AseOptionsActionType.SetShaderProperty }, + {"SetMaterialProperty", AseOptionsActionType.SetMaterialProperty }, + {"ExcludeAllPassesBut",AseOptionsActionType.ExcludeAllPassesBut} + }; + + public static Dictionary AseOptionItemSetupDict = new Dictionary + { + {"None", AseOptionItemSetup.None }, + { "InvertActionOnDeselection", AseOptionItemSetup.InvertActionOnDeselection} + }; + + public static bool InvertAction( AseOptionsActionType original, ref AseOptionsActionType inverted ) + { + bool success = true; + switch( original ) + { + case AseOptionsActionType.ShowOption: + inverted = AseOptionsActionType.HideOption; + break; + case AseOptionsActionType.HideOption: + inverted = AseOptionsActionType.ShowOption; + break; + case AseOptionsActionType.HidePort: + inverted = AseOptionsActionType.ShowPort; + break; + case AseOptionsActionType.ShowPort: + inverted = AseOptionsActionType.HidePort; + break; + case AseOptionsActionType.SetDefine: + inverted = AseOptionsActionType.RemoveDefine; + break; + case AseOptionsActionType.RemoveDefine: + inverted = AseOptionsActionType.SetDefine; + break; + case AseOptionsActionType.SetUndefine: + inverted = AseOptionsActionType.RemoveUndefine; + break; + case AseOptionsActionType.RemoveUndefine: + inverted = AseOptionsActionType.SetUndefine; + break; + case AseOptionsActionType.ExcludePass: + inverted = AseOptionsActionType.IncludePass; + break; + case AseOptionsActionType.IncludePass: + inverted = AseOptionsActionType.ExcludePass; + break; + case AseOptionsActionType.SetPortName: + case AseOptionsActionType.SetOption: + case AseOptionsActionType.SetPropertyOnPass: + case AseOptionsActionType.SetPropertyOnSubShader: + success = false; + break; + } + return success; + } + + + public static TemplateOptionsContainer GenerateOptionsContainer( bool isSubShader, string data ) + { + TemplateOptionsContainer optionsContainer = new TemplateOptionsContainer(); + + Match match = Regex.Match( data, isSubShader ? SubShaderOptionsMainPattern : PassOptionsMainPattern ); + optionsContainer.Enabled = match.Success; + if( match.Success ) + { + try + { + optionsContainer.Body = match.Value; + optionsContainer.Index = match.Index; + + List optionItemsList = new List(); + List> actionItemsList = new List>(); + Dictionary optionItemToIndex = new Dictionary(); + TemplateOptionsItem currentOption = null; + + //OPTIONS OVERALL SETUP + string[] setupLines = match.Groups[ 1 ].Value.Split( ':' ); + for( int i = 0; i < setupLines.Length; i++ ) + { + if( AseOptionsSetupDict.ContainsKey( setupLines[ i ] ) ) + { + AseOptionsSetup setup = AseOptionsSetupDict[ setupLines[ i ] ]; + switch( setup ) + { + case AseOptionsSetup.CopyOptionsFromMainPass: optionsContainer.CopyOptionsFromMainPass = true; break; + } + } + else + { + string[] args = setupLines[ i ].Split( '=' ); + if( args.Length > 1 && AseOptionsSetupDict.ContainsKey( args[ 0 ] ) ) + { + AseOptionsSetup setup = AseOptionsSetupDict[ args[ 0 ] ]; + switch( setup ) + { + case AseOptionsSetup.Id: if( !int.TryParse( args[ 1 ], out optionsContainer.Id ) ) optionsContainer.Id = -1; break; + case AseOptionsSetup.Name: optionsContainer.Name = args[ 1 ]; break; + } + } + } + } + + //AVAILABLE OPTIONS + string body = match.Groups[ 2 ].Value.Replace( "\t", string.Empty ); + string[] optionLines = body.Split( '\n' ); + for( int oL = 0; oL < optionLines.Length; oL++ ) + { + string[] optionItems = optionLines[ oL ].Split( ':' ); + if( optionItems.Length > 0 ) + { + string[] itemIds = optionItems[ 0 ].Split( OptionsDataSeparator ); + switch( itemIds[ 0 ] ) + { + case "Option": + { + //Fills previous option with its actions + //actionItemsList is cleared over here + FillOptionAction( currentOption, ref actionItemsList ); + + optionItemToIndex.Clear(); + currentOption = new TemplateOptionsItem(); + currentOption.Type = AseOptionsType.Option; + string[] optionItemSetup = optionItems[ 1 ].Split( OptionsDataSeparator ); + currentOption.Name = optionItemSetup[ 0 ]; + if( optionItemSetup.Length > 1 ) + { + if( AseOptionItemSetupDict.ContainsKey( optionItemSetup[ 1 ] ) ) + currentOption.Setup = AseOptionItemSetupDict[ optionItemSetup[ 1 ] ]; + } + + currentOption.Id = itemIds.Length > 1 ? itemIds[ 1 ] : optionItems[ 1 ]; + currentOption.DisplayOptions = optionItems[ 2 ].Split( OptionsDataSeparator ); + currentOption.DisableIdx = currentOption.DisplayOptions.Length; + optionItems[ 2 ] += ",disable"; + currentOption.Options = optionItems[ 2 ].Split( OptionsDataSeparator ); + currentOption.Count = currentOption.Options.Length; + + for( int opIdx = 0; opIdx < currentOption.Options.Length; opIdx++ ) + { + optionItemToIndex.Add( currentOption.Options[ opIdx ], opIdx ); + actionItemsList.Add( new List() ); + } + + if( optionItems.Length > 3 ) + { + currentOption.DefaultOption = optionItems[ 3 ]; + } + else + { + currentOption.DefaultOption = currentOption.Options[ 0 ]; + } + + if( currentOption.Options.Length == 2 || ( currentOption.Options.Length == 3 && currentOption.Options[ 2 ].Equals( "disable" ) ) ) + { + if( ( currentOption.Options[ 0 ].Equals( "true" ) && currentOption.Options[ 1 ].Equals( "false" ) ) || + ( currentOption.Options[ 0 ].Equals( "false" ) && currentOption.Options[ 1 ].Equals( "true" ) ) ) + { + // Toggle 0 is false and 1 is true + currentOption.Options[ 0 ] = "false"; + currentOption.Options[ 1 ] = "true"; + currentOption.UIWidget = AseOptionsUIWidget.Toggle; + } + } + else if( currentOption.Options.Length > 2 ) + { + currentOption.UIWidget = AseOptionsUIWidget.Dropdown; + } + else + { + Debug.LogWarning( "Detected an option with less than two items:" + optionItems[ 1 ] ); + } + optionItemsList.Add( currentOption ); + } + break; + case "Port": + { + //Fills previous option with its actions + //actionItemsList is cleared over here + FillOptionAction( currentOption, ref actionItemsList ); + + optionItemToIndex.Clear(); + + currentOption = new TemplateOptionsItem(); + currentOption.Type = AseOptionsType.Port; + if( isSubShader && optionItems.Length > 2 ) + { + currentOption.Id = optionItems[ 1 ]; + currentOption.Name = optionItems[ 2 ]; + } + else + { + currentOption.Name = optionItems[ 1 ]; + } + + currentOption.Options = new string[] { "On", "Off" }; + optionItemToIndex.Add( currentOption.Options[ 0 ], 0 ); + optionItemToIndex.Add( currentOption.Options[ 1 ], 1 ); + + actionItemsList.Add( new List() ); + actionItemsList.Add( new List() ); + + optionItemsList.Add( currentOption ); + } + break; + case "Field": + { + //Fills previous option with its actions + //actionItemsList is cleared over here + FillOptionAction( currentOption, ref actionItemsList ); + + optionItemToIndex.Clear(); + currentOption = new TemplateOptionsItem(); + currentOption.Type = AseOptionsType.Field; + + currentOption.Id = optionItems[ 1 ]; + currentOption.Name = optionItems[ 1 ]; + + currentOption.UIWidget = AseOptionsUIWidget.Float; + if( optionItems[ 2 ].Equals( "Int" ) ) + currentOption.UIWidget = AseOptionsUIWidget.Int; + + if( optionItems.Length >= 3 ) + { + currentOption.DefaultFieldValue = Convert.ToSingle( optionItems[ 3 ], System.Globalization.CultureInfo.InvariantCulture ); + } + + if( optionItems.Length >= 6 ) + { + if( currentOption.UIWidget == AseOptionsUIWidget.Int ) + currentOption.UIWidget = AseOptionsUIWidget.Int; + else + currentOption.UIWidget = AseOptionsUIWidget.FloatRange; + + currentOption.FieldMin = Convert.ToSingle( optionItems[ 4 ], System.Globalization.CultureInfo.InvariantCulture ); + currentOption.FieldMax = Convert.ToSingle( optionItems[ 5 ], System.Globalization.CultureInfo.InvariantCulture ); + } + + if( optionItems.Length == 5 || optionItems.Length == 7 ) + { + currentOption.FieldInline = true; + currentOption.FieldInlineName = optionItems[ optionItems.Length - 1 ]; + } + + currentOption.Options = new string[] { "Change", "Inline", "disable" }; + + optionItemToIndex.Add( currentOption.Options[ 0 ], 0 ); + optionItemToIndex.Add( currentOption.Options[ 1 ], 1 ); + optionItemToIndex.Add( currentOption.Options[ 2 ], 2 ); + currentOption.DisableIdx = 2; + + actionItemsList.Add( new List() ); + actionItemsList.Add( new List() ); + actionItemsList.Add( new List() ); + + optionItemsList.Add( currentOption ); + } + break; + default: + { + if( optionItemToIndex.ContainsKey( optionItems[ 0 ] ) ) + { + int idx = 0; + if( currentOption != null && currentOption.UIWidget == AseOptionsUIWidget.Toggle ) + { + idx = ( optionItems[ 0 ].Equals( "true" ) ) ? 1 : 0; + if( optionItems[ 0 ].Equals( "disable" ) ) + idx = 2; + } + else + { + idx = optionItemToIndex[ optionItems[ 0 ] ]; + } + actionItemsList[ idx ].Add( CreateActionItem( isSubShader, optionItems ) ); + } + else + { + //string[] ids = optionItems[ 0 ].Split( ',' ); + if( itemIds.Length > 1 ) + { + for( int i = 0; i < itemIds.Length; i++ ) + { + if( optionItemToIndex.ContainsKey( itemIds[ i ] ) ) + { + int idx = optionItemToIndex[ itemIds[ i ] ]; + actionItemsList[ idx ].Add( CreateActionItem( isSubShader, optionItems ) ); + } + } + } + } + + } + break; + } + } + } + + //Fills last option with its actions + FillOptionAction( currentOption, ref actionItemsList ); + + actionItemsList.Clear(); + actionItemsList = null; + + optionsContainer.Options = optionItemsList.ToArray(); + optionItemsList.Clear(); + optionItemsList = null; + + optionItemToIndex.Clear(); + optionItemToIndex = null; + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + return optionsContainer; + } + + static void FillOptionAction( TemplateOptionsItem currentOption, ref List> actionItemsList ) + { + if( currentOption != null ) + { + int count = actionItemsList.Count; + currentOption.ActionsPerOption = new TemplateActionItemGrid( count ); + for( int i = 0; i < count; i++ ) + { + currentOption.ActionsPerOption[ i ] = actionItemsList[ i ].ToArray(); + actionItemsList[ i ].Clear(); + } + actionItemsList.Clear(); + } + } + + static TemplateActionItem CreateActionItem( bool isSubshader, string[] optionItems ) + { + TemplateActionItem actionItem = new TemplateActionItem(); + try + { + actionItem.ActionType = AseOptionsActionTypeDict[ optionItems[ 1 ] ]; + int optionsIdx = 2; + if( optionItems.Length > 3 ) + { + optionsIdx = 3; + actionItem.PassName = optionItems[ 2 ]; + } + else + { + actionItem.AllPasses = isSubshader; + } + + actionItem.ActionData = optionItems[ optionsIdx ]; + + switch( actionItem.ActionType ) + { + case AseOptionsActionType.ShowOption: + case AseOptionsActionType.HideOption: + { + string[] arr = optionItems[ optionsIdx ].Split( OptionsDataSeparator ); + if( arr.Length > 1 ) + { + actionItem.ActionData = arr[ 0 ]; + if( !int.TryParse( arr[ 1 ], out actionItem.ActionDataIdx ) ) + { + actionItem.ActionDataIdx = -1; + } + } + } + break; + case AseOptionsActionType.SetOption: + { + string[] arr = optionItems[ optionsIdx ].Split( OptionsDataSeparator ); + if( arr.Length > 1 ) + { + actionItem.ActionData = arr[ 0 ]; + if( !int.TryParse( arr[ 1 ], out actionItem.ActionDataIdx ) ) + { + Debug.LogWarning( "SetOption value must be a the selection index" ); + } + } + } + break; + case AseOptionsActionType.HidePort: + case AseOptionsActionType.ShowPort: + { + if( !int.TryParse( actionItem.ActionData, out actionItem.ActionDataIdx ) ) + actionItem.ActionDataIdx = -1; + } + break; + case AseOptionsActionType.SetPortName: + { + string[] arr = optionItems[ optionsIdx ].Split( OptionsDataSeparator ); + if( arr.Length > 1 ) + { + int.TryParse( arr[ 0 ], out actionItem.ActionDataIdx ); + actionItem.ActionData = arr[ 1 ]; + } + } + break; + case AseOptionsActionType.SetDefine: + case AseOptionsActionType.RemoveDefine: + case AseOptionsActionType.SetUndefine: + case AseOptionsActionType.RemoveUndefine: + case AseOptionsActionType.ExcludePass: + case AseOptionsActionType.IncludePass: + case AseOptionsActionType.ExcludeAllPassesBut: + break; + case AseOptionsActionType.SetShaderProperty: + { + int optIndex = optionItems[ optionsIdx ].IndexOf( OptionsDataSeparator ); + if( optIndex > -1 ) + { + actionItem.ActionData = optionItems[ optionsIdx ].Substring( 0, optIndex ); + actionItem.ActionBuffer = optionItems[ optionsIdx ].Substring( optIndex + 1, optionItems[ optionsIdx ].Length - optIndex - 1); + } + }break; + case AseOptionsActionType.SetMaterialProperty: + { + int optIndex = optionItems[ optionsIdx ].IndexOf( OptionsDataSeparator ); + if( optIndex > -1 ) + { + actionItem.ActionData = optionItems[ optionsIdx ].Substring( 0, optIndex ); + } + } + break; + case AseOptionsActionType.SetPropertyOnPass: + case AseOptionsActionType.SetPropertyOnSubShader: + { + string[] arr = optionItems[ optionsIdx ].Split( OptionsDataSeparator ); + actionItem.PropertyAction = (PropertyActionsEnum)Enum.Parse( typeof( PropertyActionsEnum ), arr[ 0 ] ); + if( arr.Length == 1 && actionItem.ActionType == AseOptionsActionType.SetPropertyOnPass ) + { + actionItem.CopyFromSubShader = true; + } + else + { + switch( actionItem.PropertyAction ) + { + case PropertyActionsEnum.CullMode: + { + if( arr.Length > 1 ) + actionItem.ActionCullMode = (CullMode)Enum.Parse( typeof( CullMode ), arr[ 1 ] ); + } + break; + case PropertyActionsEnum.ColorMask: + { + if( arr.Length > 4 ) + { + actionItem.ColorMask.SetColorMask( 0, arr[ 1 ] ); + actionItem.ColorMask.SetColorMask( 1, arr[ 2 ] ); + actionItem.ColorMask.SetColorMask( 2, arr[ 3 ] ); + actionItem.ColorMask.SetColorMask( 3, arr[ 4 ] ); + } + } + break; + case PropertyActionsEnum.ColorMask1: + { + if( arr.Length > 4 ) + { + actionItem.ColorMask1.SetColorMask( 0, arr[ 1 ] ); + actionItem.ColorMask1.SetColorMask( 1, arr[ 2 ] ); + actionItem.ColorMask1.SetColorMask( 2, arr[ 3 ] ); + actionItem.ColorMask1.SetColorMask( 3, arr[ 4 ] ); + } + } + break; + case PropertyActionsEnum.ColorMask2: + { + if( arr.Length > 4 ) + { + actionItem.ColorMask2.SetColorMask( 0, arr[ 1 ] ); + actionItem.ColorMask2.SetColorMask( 1, arr[ 2 ] ); + actionItem.ColorMask2.SetColorMask( 2, arr[ 3 ] ); + actionItem.ColorMask2.SetColorMask( 3, arr[ 4 ] ); + } + } + break; + case PropertyActionsEnum.ColorMask3: + { + if( arr.Length > 4 ) + { + actionItem.ColorMask3.SetColorMask( 0, arr[ 1 ] ); + actionItem.ColorMask3.SetColorMask( 1, arr[ 2 ] ); + actionItem.ColorMask3.SetColorMask( 2, arr[ 3 ] ); + actionItem.ColorMask3.SetColorMask( 3, arr[ 4 ] ); + } + } + break; + case PropertyActionsEnum.ZWrite: + { + if( arr.Length > 1 ) + actionItem.ActionZWrite = (ZWriteMode)Enum.Parse( typeof( ZWriteMode ), arr[ 1 ] ); + } + break; + case PropertyActionsEnum.ZTest: + { + if( arr.Length > 1 ) + actionItem.ActionZTest = (ZTestMode)Enum.Parse( typeof( ZTestMode ), arr[ 1 ] ); + } + break; + case PropertyActionsEnum.ZOffsetFactor: + { + if( arr.Length > 1 ) + actionItem.ActionZOffsetFactor = Convert.ToSingle( arr[ 1 ] ); + } + break; + case PropertyActionsEnum.ZOffsetUnits: + { + if( arr.Length > 1 ) + actionItem.ActionZOffsetUnits = Convert.ToSingle( arr[ 1 ] ); + } + break; + case PropertyActionsEnum.BlendRGB: + { + if( arr.Length > 2 ) + { + actionItem.ActionBlendRGBSource = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 1 ] ); + actionItem.ActionBlendRGBDest = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 2 ] ); + } + } + break; + case PropertyActionsEnum.BlendRGB1: + { + if( arr.Length > 2 ) + { + actionItem.ActionBlendRGBSource1 = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 1 ] ); + actionItem.ActionBlendRGBDest1 = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 2 ] ); + } + } + break; + case PropertyActionsEnum.BlendRGB2: + { + if( arr.Length > 2 ) + { + actionItem.ActionBlendRGBSource2 = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 1 ] ); + actionItem.ActionBlendRGBDest2 = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 2 ] ); + } + } + break; + case PropertyActionsEnum.BlendRGB3: + { + if( arr.Length > 2 ) + { + actionItem.ActionBlendRGBSource3 = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 1 ] ); + actionItem.ActionBlendRGBDest3 = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 2 ] ); + } + } + break; + case PropertyActionsEnum.BlendAlpha: + { + if( arr.Length > 2 ) + { + actionItem.ActionBlendAlphaSource = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 1 ] ); + actionItem.ActionBlendAlphaDest = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 2 ] ); + } + } + break; + case PropertyActionsEnum.BlendAlpha1: + { + if( arr.Length > 2 ) + { + actionItem.ActionBlendAlphaSource1 = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 1 ] ); + actionItem.ActionBlendAlphaDest1 = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 2 ] ); + } + } + break; + case PropertyActionsEnum.BlendAlpha2: + { + if( arr.Length > 2 ) + { + actionItem.ActionBlendAlphaSource2 = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 1 ] ); + actionItem.ActionBlendAlphaDest2 = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 2 ] ); + } + } + break; + case PropertyActionsEnum.BlendAlpha3: + { + if( arr.Length > 2 ) + { + actionItem.ActionBlendAlphaSource3 = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 1 ] ); + actionItem.ActionBlendAlphaDest3 = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 2 ] ); + } + } + break; + case PropertyActionsEnum.BlendOpRGB: + { + if( arr.Length > 1 ) + { + actionItem.ActionBlendOpRGB = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), arr[ 1 ] ); + + } + } + break; + case PropertyActionsEnum.BlendOpAlpha: + { + if( arr.Length > 1 ) + { + actionItem.ActionBlendOpAlpha = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), arr[ 1 ] ); + } + } + break; + case PropertyActionsEnum.StencilReference: + { + if( arr.Length > 1 ) + { + int.TryParse( arr[ 1 ], out actionItem.ActionStencilReference ); + } + } + break; + case PropertyActionsEnum.StencilReadMask: + { + if( arr.Length > 1 ) + { + int.TryParse( arr[ 1 ], out actionItem.ActionStencilReadMask ); + } + } + break; + case PropertyActionsEnum.StencilWriteMask: + { + if( arr.Length > 1 ) + { + int.TryParse( arr[ 1 ], out actionItem.ActionStencilWriteMask ); + } + } + break; + case PropertyActionsEnum.StencilComparison: + { + if( arr.Length > 1 ) + actionItem.ActionStencilComparison = StencilBufferOpHelper.StencilComparisonValuesDict[ arr[ 1 ] ]; + } + break; + case PropertyActionsEnum.StencilPass: + { + if( arr.Length > 1 ) + actionItem.ActionStencilPass = StencilBufferOpHelper.StencilOpsValuesDict[ arr[ 1 ] ]; + } + break; + case PropertyActionsEnum.StencilFail: + { + if( arr.Length > 1 ) + actionItem.ActionStencilFail = StencilBufferOpHelper.StencilOpsValuesDict[ arr[ 1 ] ]; + } + break; + case PropertyActionsEnum.StencilZFail: + { + if( arr.Length > 1 ) + actionItem.ActionStencilZFail = StencilBufferOpHelper.StencilOpsValuesDict[ arr[ 1 ] ]; + } + break; + case PropertyActionsEnum.RenderType: + { + if( arr.Length > 1 ) + actionItem.ActionData = arr[ 1 ]; + } + break; + case PropertyActionsEnum.RenderQueue: + { + if( arr.Length > 1 ) + actionItem.ActionData = arr[ 1 ]; + if( arr.Length > 2 ) + { + int.TryParse( arr[ 2 ], out actionItem.ActionDataIdx ); + } + else + { + actionItem.ActionDataIdx = 0; + } + } + break; + case PropertyActionsEnum.DisableBatching: + { + if( arr.Length > 1 ) + actionItem.ActionData = arr[ 1 ]; + } + break; + } + } + } + break; + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + return actionItem; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs.meta new file mode 100644 index 0000000..55c0596 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 019dfacde4ed75a41851c7f15f69963f +timeCreated: 1533143812 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs new file mode 100644 index 0000000..d8c7b66 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs @@ -0,0 +1,69 @@ +using UnityEngine; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateOptionsDefinesContainer + { + [SerializeField] + private List m_directivesList = new List(); + + [NonSerialized] + private Dictionary m_directivesDict = new Dictionary(); + + void Refresh() + { + if( m_directivesDict.Count != m_directivesList.Count ) + { + m_directivesDict.Clear(); + for( int i = 0; i < m_directivesList.Count; i++ ) + { + m_directivesDict.Add( m_directivesList[ i ].PropertyName, m_directivesList[ i ] ); + } + } + } + + public void RemoveTemporaries() + { + List temporaries = m_directivesList.FindAll( ( x ) => ( x.NodeId == 1 ) ); + for( int i = 0; i < temporaries.Count; i++ ) + { + m_directivesList.Remove( temporaries[ i ] ); + m_directivesDict.Remove( temporaries[ i ].PropertyName ); + } + } + + public void AddDirective( string directive , bool temporary , bool isPragma = false ) + { + Refresh(); + if( !m_directivesDict.ContainsKey( directive ) ) + { + int nodeId = temporary ? 1 : 0; + PropertyDataCollector data = new PropertyDataCollector( nodeId, directive,-1, isPragma ); + m_directivesDict.Add( directive, data ); + m_directivesList.Add( data ); + } + } + + public void RemoveDirective( string directive ) + { + Refresh(); + if( m_directivesDict.ContainsKey( directive ) ) + { + m_directivesList.Remove( m_directivesDict[directive] ); + m_directivesDict.Remove( directive ); + } + } + + public void Destroy() + { + m_directivesDict.Clear(); + m_directivesDict = null; + m_directivesList.Clear(); + m_directivesList = null; + } + public List DefinesList { get { return m_directivesList; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs.meta new file mode 100644 index 0000000..151a9ab --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0f32755ee64bb1542ad9598810d9faf9 +timeCreated: 1543339825 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs new file mode 100644 index 0000000..007a238 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs @@ -0,0 +1,174 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + // PORT CONTROLLERS + [Serializable] + public class TemplateOptionPortItem + { + [SerializeField] + private int m_portId = -1; + + [SerializeField] + private TemplateOptionsItem m_options; + + public TemplateOptionPortItem( TemplateMultiPassMasterNode owner, TemplateOptionsItem options ) + { + m_options = options; + InputPort port = owner.InputPorts.Find( x => x.Name.Equals( options.Name ) ); + if( port != null ) + { + m_portId = port.PortId; + } + } + + public void FillDataCollector( TemplateMultiPassMasterNode owner, ref MasterNodeDataCollector dataCollector ) + { + InputPort port = null; + if( m_portId > -1 ) + { + port = owner.GetInputPortByUniqueId( m_portId ); + } + else + { + port = owner.InputPorts.Find( x => x.Name.Equals( m_options.Name ) ); + } + + if( port != null ) + { + int optionId = port.HasOwnOrLinkConnection ? 0 : 1; + for( int i = 0; i < m_options.ActionsPerOption[ optionId ].Length; i++ ) + { + switch( m_options.ActionsPerOption[ optionId ][ i ].ActionType ) + { + case AseOptionsActionType.SetDefine: + { + List nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex ); + int count = nodes.Count; + for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ ) + { + nodes[ nodeIdx ].OptionsDefineContainer.AddDirective( "#define "+m_options.ActionsPerOption[ optionId ][ i ].ActionData, false ); + } + //dataCollector.AddToDefines( -1, m_options.ActionsPerOption[ optionId ][ i ].ActionData ); + } + break; + case AseOptionsActionType.SetUndefine: + { + List nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex ); + int count = nodes.Count; + for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ ) + { + nodes[ nodeIdx ].OptionsDefineContainer.AddDirective( "#undef " + m_options.ActionsPerOption[ optionId ][ i ].ActionData, false ); + } + //dataCollector.AddToDefines( -1, m_options.ActionsPerOption[ optionId ][ i ].ActionData, false ); + } + break; + case AseOptionsActionType.SetShaderProperty: + { + TemplateShaderPropertyData data = owner.CurrentTemplate.GetShaderPropertyData( m_options.ActionsPerOption[ optionId ][ i ].ActionData ); + if( data != null ) + { + string newPropertyValue = data.CreatePropertyForValue( m_options.ActionsPerOption[ optionId ][ i ].ActionBuffer ); + owner.CurrentTemplate.IdManager.SetReplacementText( data.FullValue, newPropertyValue ); + } + } + break; + } + } + } + } + + public void SubShaderFillDataCollector( TemplateMultiPassMasterNode owner, ref MasterNodeDataCollector dataCollector ) + { + + //TemplateMultiPassMasterNode targetNode = string.IsNullOrEmpty(m_options.Id) ? owner:owner.ContainerGraph.GetMasterNodeOfPass( m_options.Id , owner.LODIndex ); + TemplateMultiPassMasterNode targetNode = string.IsNullOrEmpty( m_options.Id ) ? + owner.ContainerGraph.GetMainMasterNodeOfLOD( owner.LODIndex ) : + owner.ContainerGraph.GetMasterNodeOfPass( m_options.Id , owner.LODIndex ); + + InputPort port = null; + if( m_portId > -1 ) + { + port = targetNode.GetInputPortByUniqueId( m_portId ); + } + else + { + port = targetNode.InputPorts.Find( x => x.Name.Equals( m_options.Name ) ); + } + + if( port != null ) + { + int optionId = port.HasOwnOrLinkConnection ? 0 : 1; + for( int i = 0; i < m_options.ActionsPerOption[ optionId ].Length; i++ ) + { + if( string.IsNullOrEmpty( m_options.ActionsPerOption[ optionId ][ i ].PassName ) || + m_options.ActionsPerOption[ optionId ][ i ].PassName.Equals( owner.PassName ) ) + { + switch( m_options.ActionsPerOption[ optionId ][ i ].ActionType ) + { + case AseOptionsActionType.SetDefine: + { + owner.OptionsDefineContainer.AddDirective( "#define " + m_options.ActionsPerOption[ optionId ][ i ].ActionData, true ); + } + break; + case AseOptionsActionType.SetUndefine: + { + owner.OptionsDefineContainer.AddDirective( "#undef " + m_options.ActionsPerOption[ optionId ][ i ].ActionData, true ); + } + break; + case AseOptionsActionType.SetShaderProperty: + { + TemplateShaderPropertyData data = owner.CurrentTemplate.GetShaderPropertyData( m_options.ActionsPerOption[ optionId ][ i ].ActionData ); + if( data != null ) + { + string newPropertyValue = data.CreatePropertyForValue( m_options.ActionsPerOption[ optionId ][ i ].ActionBuffer ); + owner.CurrentTemplate.IdManager.SetReplacementText( data.FullValue, newPropertyValue ); + } + } + break; + } + } + } + } + } + + public void CheckImediateActionsForPort( TemplateMultiPassMasterNode owner, int portId ) + { + if( portId != m_portId ) + return; + + InputPort port = null; + if( m_portId > -1 ) + { + port = owner.GetInputPortByUniqueId( m_portId ); + } + else + { + port = owner.InputPorts.Find( x => x.Name.Equals( m_options.Name ) ); + } + + if( port != null ) + { + int optionId = port.HasOwnOrLinkConnection ? 0 : 1; + for( int i = 0; i < m_options.ActionsPerOption[ optionId ].Length; i++ ) + { + switch( m_options.ActionsPerOption[ optionId ][ i ].ActionType ) + { + case AseOptionsActionType.SetPortName: + { + port.Name = m_options.ActionsPerOption[ optionId ][ i ].ActionData; + owner.SizeIsDirty = true; + } + break; + } + } + } + } + public TemplateOptionsItem Options { get { return m_options; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs.meta new file mode 100644 index 0000000..a9c15d2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: fa2d25bd070cde046876bd1fa77bf116 +timeCreated: 1535044953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs new file mode 100644 index 0000000..cb3e40b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs @@ -0,0 +1,323 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + // UI STRUCTURES + [Serializable] + public class TemplateOptionUIItem + { + public delegate void OnActionPerformed( bool actionFromUser, bool isRefreshing, bool invertAction, TemplateOptionUIItem uiItem, params TemplateActionItem[] validActions ); + public event OnActionPerformed OnActionPerformedEvt; + + [SerializeField] + private bool m_isVisible = true; + + [SerializeField] + private bool m_wasVisible = true; + + [SerializeField] + private int m_currentOption = 0; + + [SerializeField] + private TemplateOptionsItem m_options; + + [SerializeField] + private bool m_checkOnExecute = false; + + [SerializeField] + private bool m_invertActionOnDeselection = false; + + public TemplateOptionUIItem( TemplateOptionsItem options ) + { + m_options = options; + if( m_options.Type == AseOptionsType.Field ) + { + m_options.FieldValue.FloatValue = m_options.DefaultFieldValue; + } + else + { + m_currentOption = m_options.DefaultOptionIndex; + } + m_invertActionOnDeselection = options.Setup == AseOptionItemSetup.InvertActionOnDeselection; + } + + public void CopyValuesFrom( TemplateOptionUIItem origin ) + { + m_isVisible = origin.IsVisible; + m_wasVisible = origin.WasVisible; + m_currentOption = origin.CurrentOption; + m_options.FieldValue.FloatValue = origin.CurrentFieldValue; + m_checkOnExecute = origin.CheckOnExecute; + m_invertActionOnDeselection = origin.InvertActionOnDeselection; + } + + public void Draw( UndoParentNode owner ) + { + if( m_isVisible ) + { + int lastOption = m_currentOption; + EditorGUI.BeginChangeCheck(); + switch( m_options.UIWidget ) + { + case AseOptionsUIWidget.Dropdown: + { + m_currentOption = owner.EditorGUILayoutPopup( m_options.Name, m_currentOption, m_options.DisplayOptions ); + } + break; + case AseOptionsUIWidget.Toggle: + { + m_currentOption = owner.EditorGUILayoutToggle( m_options.Name, m_currentOption == 1 ) ? 1 : 0; + } + break; + case AseOptionsUIWidget.Float: + { + if( m_options.FieldInline ) + { + m_options.FieldValue.FloatField( ref owner, m_options.Name ); + if( m_options.FieldValue.Active ) + m_currentOption = 1; + else + m_currentOption = 0; + } + else + { + m_options.FieldValue.FloatValue = owner.EditorGUILayoutFloatField( m_options.Name, m_options.FieldValue.FloatValue ); + } + } + break; + case AseOptionsUIWidget.Int: + { + if( m_options.FieldInline ) + { + m_options.FieldValue.IntField( ref owner, m_options.Name ); + if( m_options.FieldValue.Active ) + m_currentOption = 1; + else + m_currentOption = 0; + } + else + m_options.FieldValue.FloatValue = owner.EditorGUILayoutIntField( m_options.Name, (int)m_options.FieldValue.FloatValue ); + } + break; + case AseOptionsUIWidget.FloatRange: + { + if( m_options.FieldInline ) + { + m_options.FieldValue.SliderField( ref owner, m_options.Name, m_options.FieldMin, m_options.FieldMax ); + if( m_options.FieldValue.Active ) + m_currentOption = 1; + else + m_currentOption = 0; + } + else + m_options.FieldValue.FloatValue = owner.EditorGUILayoutSlider( m_options.Name, m_options.FieldValue.FloatValue, m_options.FieldMin, m_options.FieldMax ); + } + break; + case AseOptionsUIWidget.IntRange: + { + if( m_options.FieldInline ) + { + m_options.FieldValue.IntSlider( ref owner, m_options.Name, (int)m_options.FieldMin, (int)m_options.FieldMax ); + if( m_options.FieldValue.Active ) + m_currentOption = 1; + else + m_currentOption = 0; + } + else + m_options.FieldValue.FloatValue = owner.EditorGUILayoutIntSlider( m_options.Name, (int)m_options.FieldValue.FloatValue, (int)m_options.FieldMin, (int)m_options.FieldMax ); + } + break; + } + if( EditorGUI.EndChangeCheck() ) + { + if( OnActionPerformedEvt != null ) + { + if( m_invertActionOnDeselection ) + OnActionPerformedEvt( true, false, lastOption != m_options.DisableIdx, this, m_options.ActionsPerOption[ lastOption ] ); + + OnActionPerformedEvt( true, false, false, this, m_options.ActionsPerOption[ m_currentOption ] ); + } + } + } + } + + public void CheckEnDisable( bool actionFromUser ) + { + //string deb = string.Empty;// "-- Checked --" + m_options.Name+" "+ m_isVisible + " "+ m_wasVisible; + if( m_isVisible ) + { + if( !m_wasVisible ) + { + //deb = "-- Enable --" + m_options.Name; + //Debug.Log( deb ); + if( OnActionPerformedEvt != null ) + { + if( m_invertActionOnDeselection ) + { + for( int i = 0; i < m_options.Count; i++ ) + { + if( i != m_currentOption && i != m_options.DisableIdx ) + { + OnActionPerformedEvt( actionFromUser, false, true, this, m_options.ActionsPerOption[ i ] ); + } + } + } + + OnActionPerformedEvt( actionFromUser, false, false, this, m_options.ActionsPerOption[ m_currentOption ] ); + //if( !m_isVisible ) + //OnActionPerformedEvt( isRefreshing, false, this, m_options.ActionsPerOption[ m_options.DisableIdx ] ); + } + } + + m_wasVisible = true; + } + else if( m_wasVisible ) + { + //deb = "-- Disable --" + m_options.Name; + //Debug.Log( deb ); + m_wasVisible = false; + + if( OnActionPerformedEvt != null ) + { + OnActionPerformedEvt( actionFromUser, false, false, this, m_options.ActionsPerOption[ m_options.DisableIdx ] ); + } + } + } + + public void FillDataCollector( ref MasterNodeDataCollector dataCollector ) + { + if( m_isVisible && m_checkOnExecute ) + { + for( int i = 0; i < m_options.ActionsPerOption[ m_currentOption ].Length; i++ ) + { + switch( m_options.ActionsPerOption[ m_currentOption ][ i ].ActionType ) + { + case AseOptionsActionType.SetDefine: + { + dataCollector.AddToDefines( -1, m_options.ActionsPerOption[ m_currentOption ][ i ].ActionData ); + } + break; + case AseOptionsActionType.SetUndefine: + { + dataCollector.AddToDefines( -1, m_options.ActionsPerOption[ m_currentOption ][ i ].ActionData, false ); + } + break; + } + } + } + } + + public void Refresh() + { + if( OnActionPerformedEvt != null ) + { + if( m_invertActionOnDeselection ) + { + for( int i = 0; i < m_options.Count; i++ ) + { + if( i != m_currentOption && i != m_options.DisableIdx ) + { + OnActionPerformedEvt( false, true, true, this, m_options.ActionsPerOption[ i ] ); + } + } + } + + OnActionPerformedEvt( false, true, false, this, m_options.ActionsPerOption[ m_currentOption ] ); + } + } + + public TemplateOptionsItem Options { get { return m_options; } } + + public void Destroy() + { + OnActionPerformedEvt = null; + } + + public bool IsVisible + { + get { return m_isVisible; } + set { m_isVisible = value; } + } + + public bool WasVisible + { + get { return m_wasVisible; } + set { m_wasVisible = value; } + } + + public bool CheckOnExecute + { + get { return m_checkOnExecute; } + set { m_checkOnExecute = value; } + } + + public InlineProperty FieldValue + { + get { return m_options.FieldValue; } + set { m_options.FieldValue = value; } + } + + public float CurrentFieldValue + { + get { return m_options.FieldValue.FloatValue; } + set { m_options.FieldValue.FloatValue = value; } + } + + public int CurrentOption + { + get { return m_currentOption; } + set + { + m_currentOption = Mathf.Clamp( value, 0, m_options.Options.Length - 1 ); + // why refreshing here? + //Refresh(); + } + } + + public int CurrentOptionIdx + { + set + { + m_currentOption = Mathf.Clamp( value, 0, m_options.Options.Length - 1 ); + } + } + public bool EmptyEvent { get { return OnActionPerformedEvt == null; } } + public TemplateActionItemGrid.TemplateActionItemRow CurrentOptionActions + { + get + { + if( m_options.Type == AseOptionsType.Field && + m_currentOption == 1 ) + { + if( m_options.FieldValue.NodeId < -1 ) + { + //This is quite the hack. The bug is related to if a user chooses an inline property on the field option, then the behavior is to comment the original property set on the template + // The problem is that, if the user sets an inline property and select its own internal property from there, then the behavior that will prevail without this hack is to call the actions associated with setting a new inline property + // Which is on all templates to comment the original template internal property leaving the property commented on the final code (This was detected on URP PBR) + PropertyNode node = UIUtils.CurrentWindow.OutsideGraph.GetInternalTemplateNode( m_options.FieldValue.NodeId ) as PropertyNode; + if( node != null ) + { + if( node.PropertyName.Equals( m_options.FieldInlineName ) ) + { + return m_options.ActionsPerOption.Rows[ 0 ]; + } + } + } + else if( m_options.FieldValue.NodeId == -1 ) + { + // If node id is -1 then no node is selected on the inline dropdown then we should also fallback to using its internal property + return m_options.ActionsPerOption.Rows[ 0 ]; + } + } + return m_options.ActionsPerOption.Rows[m_currentOption]; + } + } + public bool InvertActionOnDeselection { get { return m_invertActionOnDeselection; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs.meta new file mode 100644 index 0000000..b3f1764 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 081c72eb35d61c84e9a5c34522c3ff33 +timeCreated: 1534775306 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs new file mode 100644 index 0000000..e24433b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs @@ -0,0 +1,873 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateOptionsUIHelper + { + private const string CustomOptionsLabel = " Custom Options"; + + private bool m_isSubShader = false; + + [SerializeField] + private bool m_passCustomOptionsFoldout = true; + + [SerializeField] + private string m_passCustomOptionsLabel = CustomOptionsLabel; + + [SerializeField] + private int m_passCustomOptionsSizeCheck = 0; + + [SerializeField] + private List m_passCustomOptionsUI = new List(); + + [NonSerialized] + private Dictionary m_passCustomOptionsUIDict = new Dictionary(); + + [NonSerialized] + private TemplateMultiPassMasterNode m_owner; + + [NonSerialized] + private string[] m_readOptionNames; + + [NonSerialized] + private string[] m_readOptionSelections; + + [SerializeField] + private List m_passCustomOptionsPorts = new List(); + + public TemplateOptionsUIHelper( bool isSubShader ) + { + m_isSubShader = isSubShader; + } + + public void CopyOptionsValuesFrom( TemplateOptionsUIHelper origin ) + { + for( int i = 0; i < origin.PassCustomOptionsUI.Count; i++ ) + { + m_passCustomOptionsUI[ i ].CopyValuesFrom( origin.PassCustomOptionsUI[ i ] ); + } + } + + public void Destroy() + { + for( int i = 0; i < m_passCustomOptionsUI.Count; i++ ) + { + m_passCustomOptionsUI[ i ].Destroy(); + } + + m_passCustomOptionsUI.Clear(); + m_passCustomOptionsUI = null; + + m_passCustomOptionsUIDict.Clear(); + m_passCustomOptionsUIDict = null; + + m_passCustomOptionsPorts.Clear(); + m_passCustomOptionsPorts = null; + } + + public void DrawCustomOptions( TemplateMultiPassMasterNode owner ) + { + m_owner = owner; + + if( m_passCustomOptionsUI.Count > 0 ) + { + NodeUtils.DrawNestedPropertyGroup( ref m_passCustomOptionsFoldout, m_passCustomOptionsLabel, DrawCustomOptionsBlock ); + } + } + + public void DrawCustomOptionsBlock() + { + float currWidth = EditorGUIUtility.labelWidth; +#if UNITY_2019_3_OR_NEWER + float size = Mathf.Max( UIUtils.CurrentWindow.ParametersWindow.TransformedArea.width * 0.385f, 0 ); +#else + float size = Mathf.Max( UIUtils.CurrentWindow.ParametersWindow.TransformedArea.width * 0.34f, 0 ); +#endif + EditorGUIUtility.labelWidth = size; + for( int i = 0; i < m_passCustomOptionsUI.Count; i++ ) + { + m_passCustomOptionsUI[ i ].Draw( m_owner ); + } + EditorGUILayout.Space(); + EditorGUIUtility.labelWidth = currWidth; + } + + public void OnCustomOptionSelected( bool actionFromUser, bool isRefreshing, bool invertAction, TemplateMultiPassMasterNode owner, TemplateOptionUIItem uiItem, params TemplateActionItem[] validActions ) + { + uiItem.CheckOnExecute = false; + for( int i = 0; i < validActions.Length; i++ ) + { + AseOptionsActionType actionType = validActions[ i ].ActionType; + if( invertAction ) + { + if( !TemplateOptionsToolsHelper.InvertAction( validActions[ i ].ActionType, ref actionType ) ) + { + continue; + } + } + + + switch( actionType ) + { + case AseOptionsActionType.ShowOption: + { + TemplateOptionUIItem item = m_passCustomOptionsUI.Find( x => ( x.Options.Name.Equals( validActions[ i ].ActionData ) ) ); + if( item != null ) + { + if( isRefreshing ) + { + string optionId = validActions[ i ].PassName + validActions[ i ].ActionData + "Option"; + owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, true ); + } + + // this prevents options from showing up when loading by checking if they were hidden by another option + // it works on the assumption that an option that may possible hide this one is checked first + if( !isRefreshing ) + item.IsVisible = true; + else if( item.WasVisible ) + item.IsVisible = true; + + if( !invertAction && validActions[ i ].ActionDataIdx > -1 ) + item.CurrentOption = validActions[ i ].ActionDataIdx; + + item.CheckEnDisable( actionFromUser ); + } + else + { + Debug.LogFormat( "Could not find Option {0} for action {1}", validActions[ i ].ActionData, validActions[ i ].ActionType ); + } + } + break; + case AseOptionsActionType.HideOption: + { + TemplateOptionUIItem item = m_passCustomOptionsUI.Find( x => ( x.Options.Name.Equals( validActions[ i ].ActionData ) ) ); + if( item != null ) + { + bool flag = false; + if( isRefreshing ) + { + string optionId = validActions[ i ].PassName + validActions[ i ].ActionData + "Option"; + flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, false ); + } + + item.IsVisible = false || flag; + if( !invertAction && validActions[ i ].ActionDataIdx > -1 ) + item.CurrentOption = validActions[ i ].ActionDataIdx; + + item.CheckEnDisable( actionFromUser ); + } + else + { + Debug.LogFormat( "Could not find Option {0} for action {1}", validActions[ i ].ActionData, validActions[ i ].ActionType ); + } + } + break; + case AseOptionsActionType.SetOption: + { + if( !uiItem.IsVisible ) + break; + + TemplateOptionUIItem item = m_passCustomOptionsUI.Find( x => ( x.Options.Name.Equals( validActions[ i ].ActionData ) ) ); + if( item != null ) + { + item.CurrentOption = validActions[ i ].ActionDataIdx; + item.Refresh(); + } + else + { + Debug.LogFormat( "Could not find Option {0} for action {1}", validActions[ i ].ActionData, validActions[ i ].ActionType ); + } + } + break; + case AseOptionsActionType.HidePort: + { + TemplateMultiPassMasterNode passMasterNode = owner; + if( !string.IsNullOrEmpty( validActions[ i ].PassName ) ) + { + passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName,owner.LODIndex ); + } + + if( passMasterNode != null ) + { + InputPort port = validActions[ i ].ActionDataIdx > -1 ? + passMasterNode.GetInputPortByUniqueId( validActions[ i ].ActionDataIdx ) : + passMasterNode.InputPorts.Find( x => x.Name.Equals( validActions[ i ].ActionData ) ); + if( port != null ) + { + if( isRefreshing ) + { + string optionId = validActions[ i ].PassName + port.Name; + owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, port.IsConnected ); + port.Visible = port.IsConnected; + } + else + { + port.Visible = false; + } + passMasterNode.SizeIsDirty = true; + } + else + { + Debug.LogFormat( "Could not find port {0},{1} for action {2}", validActions[ i ].ActionDataIdx, validActions[ i ].ActionData, validActions[ i ].ActionType ); + } + } + else + { + Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData ); + } + } + break; + case AseOptionsActionType.ShowPort: + { + if( !uiItem.IsVisible ) + break; + + TemplateMultiPassMasterNode passMasterNode = owner; + if( !string.IsNullOrEmpty( validActions[ i ].PassName ) ) + { + passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex ); + } + + if( passMasterNode != null ) + { + InputPort port = validActions[ i ].ActionDataIdx > -1 ? + passMasterNode.GetInputPortByUniqueId( validActions[ i ].ActionDataIdx ) : + passMasterNode.InputPorts.Find( x => x.Name.Equals( validActions[ i ].ActionData ) ); + if( port != null ) + { + if( isRefreshing ) + { + string optionId = validActions[ i ].PassName + port.Name; + owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, true ); + } + + port.Visible = true; + passMasterNode.SizeIsDirty = true; + } + else + { + Debug.LogFormat( "Could not find port {0},{1} for action {2}", validActions[ i ].ActionDataIdx, validActions[ i ].ActionData, validActions[ i ].ActionType ); + } + } + else + { + Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData ); + } + } + break; + case AseOptionsActionType.SetPortName: + { + if( !uiItem.IsVisible ) + break; + + TemplateMultiPassMasterNode passMasterNode = owner; + if( !string.IsNullOrEmpty( validActions[ i ].PassName ) ) + { + passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex ); + } + + if( passMasterNode != null ) + { + InputPort port = passMasterNode.GetInputPortByUniqueId( validActions[ i ].ActionDataIdx ); + if( port != null ) + { + port.Name = validActions[ i ].ActionData; + passMasterNode.SizeIsDirty = true; + } + else + { + Debug.LogFormat( "Could not find port {0},{1} for action {2}", validActions[ i ].ActionDataIdx, validActions[ i ].ActionData, validActions[ i ].ActionType ); + } + } + else + { + Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData ); + } + } + break; + case AseOptionsActionType.SetDefine: + { + if( !uiItem.IsVisible ) + { + uiItem.CheckOnExecute = true; + break; + } + + //Debug.Log( "DEFINE " + validActions[ i ].ActionData ); + if( validActions[ i ].AllPasses ) + { + string actionData = validActions[ i ].ActionData; + string defineValue = string.Empty; + bool isPragma = false; + if( actionData.StartsWith( "pragma" ) ) + { + defineValue = "#" + actionData; + isPragma = true; + } + else + { + defineValue = "#define " + validActions[ i ].ActionData; + } + if( isRefreshing ) + { + owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( defineValue, true ); + } + List nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex ); + int count = nodes.Count; + for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ ) + { + nodes[ nodeIdx ].OptionsDefineContainer.AddDirective( defineValue, false, isPragma ); + } + } + else if( !string.IsNullOrEmpty( validActions[ i ].PassName ) ) + { + TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex ); + if( passMasterNode != null ) + { + string actionData = validActions[ i ].ActionData; + string defineValue = string.Empty; + bool isPragma = false; + if( actionData.StartsWith( "pragma" ) ) + { + defineValue = "#" + actionData; + isPragma = true; + } + else + { + defineValue = "#define " + validActions[ i ].ActionData; + } + if( isRefreshing ) + { + string optionsId = validActions[ i ].PassName + defineValue; + owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionsId, true ); + } + passMasterNode.OptionsDefineContainer.AddDirective( defineValue, false, isPragma ); + } + else + { + Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData ); + } + } + else + { + uiItem.CheckOnExecute = true; + } + } + break; + case AseOptionsActionType.RemoveDefine: + { + //Debug.Log( "UNDEFINE " + validActions[ i ].ActionData ); + if( validActions[ i ].AllPasses ) + { + string actionData = validActions[ i ].ActionData; + string defineValue = string.Empty; + if( actionData.StartsWith( "pragma" ) ) + { + defineValue = "#" + actionData; + } + else + { + defineValue = "#define " + validActions[ i ].ActionData; + } + + bool flag = false; + if( isRefreshing ) + { + flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( defineValue, false ); + } + + if( !flag ) + { + List nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex ); + int count = nodes.Count; + for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ ) + { + nodes[ nodeIdx ].OptionsDefineContainer.RemoveDirective( defineValue ); + } + } + } + else if( !string.IsNullOrEmpty( validActions[ i ].PassName ) ) + { + TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex ); + if( passMasterNode != null ) + { + string actionData = validActions[ i ].ActionData; + string defineValue = string.Empty; + if( actionData.StartsWith( "pragma" ) ) + { + defineValue = "#" + actionData; + } + else + { + defineValue = "#define " + validActions[ i ].ActionData; + } + bool flag = false; + if( isRefreshing ) + { + string optionId = validActions[ i ].PassName + defineValue; + flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, false ); + } + if( !flag ) + { + passMasterNode.OptionsDefineContainer.RemoveDirective( defineValue ); + } + } + else + { + Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData ); + } + } + else + { + uiItem.CheckOnExecute = false; + } + } + break; + case AseOptionsActionType.SetUndefine: + { + if( !uiItem.IsVisible ) + { + uiItem.CheckOnExecute = true; + break; + } + + if( validActions[ i ].AllPasses ) + { + string defineValue = "#undef " + validActions[ i ].ActionData; + if( isRefreshing ) + { + owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( defineValue, true ); + } + List nodes = owner.ContainerGraph.GetMultiPassMasterNodes(owner.LODIndex); + int count = nodes.Count; + for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ ) + { + nodes[ nodeIdx ].OptionsDefineContainer.AddDirective( defineValue, false ); + } + } + else if( !string.IsNullOrEmpty( validActions[ i ].PassName ) ) + { + TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex ); + if( passMasterNode != null ) + { + string defineValue = "#undef " + validActions[ i ].ActionData; + if( isRefreshing ) + { + string optionsId = validActions[ i ].PassName + defineValue; + owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionsId, true ); + } + passMasterNode.OptionsDefineContainer.AddDirective( defineValue, false ); + } + else + { + Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData ); + } + } + else + { + uiItem.CheckOnExecute = true; + } + } + break; + case AseOptionsActionType.RemoveUndefine: + { + if( validActions[ i ].AllPasses ) + { + string defineValue = "#undef " + validActions[ i ].ActionData; + bool flag = false; + if( isRefreshing ) + { + flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( defineValue, false ); + } + + if( !flag ) + { + List nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex ); + int count = nodes.Count; + for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ ) + { + nodes[ nodeIdx ].OptionsDefineContainer.RemoveDirective( defineValue ); + } + } + } + else if( !string.IsNullOrEmpty( validActions[ i ].PassName ) ) + { + TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex ); + if( passMasterNode != null ) + { + bool flag = false; + string defineValue = "#undef " + validActions[ i ].ActionData; + if( isRefreshing ) + { + string optionId = validActions[ i ].PassName + defineValue; + flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, false ); + } + + if( !flag ) + { + passMasterNode.OptionsDefineContainer.RemoveDirective( defineValue ); + } + } + else + { + Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData ); + } + } + else + { + uiItem.CheckOnExecute = false; + } + } + break; + case AseOptionsActionType.ExcludePass: + { + string optionId = validActions[ i ].ActionData + "Pass"; + bool flag = isRefreshing ? owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, false ) : false; + if( !flag ) + owner.SetPassVisible( validActions[ i ].ActionData, false ); + } + break; + case AseOptionsActionType.IncludePass: + { + if( !uiItem.IsVisible ) + break; + + string optionId = validActions[ i ].ActionData + "Pass"; + owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, true ); + owner.SetPassVisible( validActions[ i ].ActionData, true ); + } + break; + case AseOptionsActionType.SetPropertyOnPass: + { + //Debug.Log( "PASSPROP " + validActions[ i ].ActionData ); + //Refresh happens on hotcode reload and shader load and in those situation + // The property own serialization handles its setup + if( isRefreshing ) + continue; + + if( !string.IsNullOrEmpty( validActions[ i ].PassName ) ) + { + TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex ); + if( passMasterNode != null ) + { + passMasterNode.SetPropertyActionFromItem( actionFromUser, passMasterNode.PassModule, validActions[ i ] ); + } + else + { + Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData ); + } + } + else + { + owner.SetPropertyActionFromItem( actionFromUser, owner.PassModule, validActions[ i ] ); + } + } + break; + case AseOptionsActionType.SetPropertyOnSubShader: + { + //Refresh happens on hotcode reload and shader load and in those situation + // The property own serialization handles its setup + if( isRefreshing ) + continue; + + owner.SetPropertyActionFromItem( actionFromUser, owner.SubShaderModule, validActions[ i ] ); + } + break; + case AseOptionsActionType.SetShaderProperty: + { + //This action is only check when shader is compiled over + //the TemplateMultiPassMasterNode via the on CheckPropertyChangesOnOptions() method + } + break; + case AseOptionsActionType.ExcludeAllPassesBut: + { + //This action is only check when shader is compiled over + //the TemplateMultiPassMasterNode via the on CheckExcludeAllPassOptions() method + } + break; + case AseOptionsActionType.SetMaterialProperty: + { + if( isRefreshing ) + continue; + + if( !uiItem.IsVisible ) + break; + + if( owner.ContainerGraph.CurrentMaterial != null ) + { + string prop = validActions[ i ].ActionData; + if( owner.ContainerGraph.CurrentMaterial.HasProperty( prop ) ) + { + if( uiItem.Options.UIWidget == AseOptionsUIWidget.Float || uiItem.Options.UIWidget == AseOptionsUIWidget.FloatRange ) + owner.ContainerGraph.CurrentMaterial.SetFloat( prop, uiItem.CurrentFieldValue ); + else + owner.ContainerGraph.CurrentMaterial.SetInt( prop, (int)uiItem.CurrentFieldValue ); + + if( ASEMaterialInspector.Instance != null ) + ASEMaterialInspector.Instance.Repaint(); + } + } + } + break; + } + } + } + + public void SetupCustomOptionsFromTemplate( TemplateMultiPassMasterNode owner, bool newTemplate ) + { + TemplateOptionsContainer customOptionsContainer = m_isSubShader ? owner.SubShader.CustomOptionsContainer : owner.Pass.CustomOptionsContainer; + + if( !newTemplate && customOptionsContainer.Body.Length == m_passCustomOptionsSizeCheck ) + { + for( int i = 0; i < m_passCustomOptionsUI.Count; i++ ) + { + if( m_passCustomOptionsUI[ i ].EmptyEvent ) + { + if( m_isSubShader ) + { + m_passCustomOptionsUI[ i ].OnActionPerformedEvt += owner.OnCustomSubShaderOptionSelected; + } + else + { + m_passCustomOptionsUI[ i ].OnActionPerformedEvt += owner.OnCustomPassOptionSelected; + } + } + } + return; + } + + m_passCustomOptionsLabel = string.IsNullOrEmpty( customOptionsContainer.Name ) ? CustomOptionsLabel : " " + customOptionsContainer.Name; + + for( int i = 0; i < m_passCustomOptionsUI.Count; i++ ) + { + m_passCustomOptionsUI[ i ].Destroy(); + } + + m_passCustomOptionsUI.Clear(); + m_passCustomOptionsUIDict.Clear(); + m_passCustomOptionsPorts.Clear(); + + if( customOptionsContainer.Enabled ) + { + m_passCustomOptionsSizeCheck = customOptionsContainer.Body.Length; + for( int i = 0; i < customOptionsContainer.Options.Length; i++ ) + { + switch( customOptionsContainer.Options[ i ].Type ) + { + case AseOptionsType.Option: + { + TemplateOptionUIItem item = new TemplateOptionUIItem( customOptionsContainer.Options[ i ] ); + if( m_isSubShader ) + { + item.OnActionPerformedEvt += owner.OnCustomSubShaderOptionSelected; + } + else + { + item.OnActionPerformedEvt += owner.OnCustomPassOptionSelected; + } + + m_passCustomOptionsUI.Add( item ); + m_passCustomOptionsUIDict.Add( customOptionsContainer.Options[ i ].Id, item ); + } + break; + case AseOptionsType.Port: + { + TemplateOptionPortItem item = new TemplateOptionPortItem( owner, customOptionsContainer.Options[ i ] ); + m_passCustomOptionsPorts.Add( item ); + //if( m_isSubShader ) + //{ + // if( string.IsNullOrEmpty( customOptionsContainer.Options[ i ].Id ) ) + // { + // //No pass name selected. inject on all passes + // TemplateOptionPortItem item = new TemplateOptionPortItem( owner, customOptionsContainer.Options[ i ] ); + // m_passCustomOptionsPorts.Add( item ); + // } + // else if( customOptionsContainer.Options[ i ].Id.Equals( owner.PassName ) ) + // { + // TemplateOptionPortItem item = new TemplateOptionPortItem( owner, customOptionsContainer.Options[ i ] ); + // m_passCustomOptionsPorts.Add( item ); + // } + //} + //else + //{ + // TemplateOptionPortItem item = new TemplateOptionPortItem( owner, customOptionsContainer.Options[ i ] ); + // m_passCustomOptionsPorts.Add( item ); + //} + } + break; + case AseOptionsType.Field: + { + TemplateOptionUIItem item = new TemplateOptionUIItem( customOptionsContainer.Options[ i ] ); + if( m_isSubShader ) + { + item.OnActionPerformedEvt += owner.OnCustomSubShaderOptionSelected; + } + else + { + item.OnActionPerformedEvt += owner.OnCustomPassOptionSelected; + } + + m_passCustomOptionsUI.Add( item ); + m_passCustomOptionsUIDict.Add( customOptionsContainer.Options[ i ].Id, item ); + } + break; + } + } + } + else + { + m_passCustomOptionsSizeCheck = 0; + } + } + + public void SetCustomOptionsInfo( TemplateMultiPassMasterNode masterNode, ref MasterNodeDataCollector dataCollector ) + { + if( masterNode == null ) + return; + + for( int i = 0; i < m_passCustomOptionsUI.Count; i++ ) + { + m_passCustomOptionsUI[ i ].FillDataCollector( ref dataCollector ); + } + + for( int i = 0; i < m_passCustomOptionsPorts.Count; i++ ) + { + m_passCustomOptionsPorts[ i ].FillDataCollector( masterNode, ref dataCollector ); + } + } + + public void CheckImediateActionsForPort( TemplateMultiPassMasterNode masterNode , int portId ) + { + for( int i = 0; i < m_passCustomOptionsPorts.Count; i++ ) + { + m_passCustomOptionsPorts[ i ].CheckImediateActionsForPort( masterNode, portId ); + } + } + + public void SetSubShaderCustomOptionsPortsInfo( TemplateMultiPassMasterNode masterNode, ref MasterNodeDataCollector dataCollector ) + { + if( masterNode == null ) + return; + + + //for( int i = 0; i < m_passCustomOptionsPorts.Count; i++ ) + //{ + // if( string.IsNullOrEmpty( m_passCustomOptionsPorts[ i ].Options.Id ) || + // masterNode.PassUniqueName.Equals( m_passCustomOptionsPorts[ i ].Options.Id ) ) + // { + // m_passCustomOptionsPorts[ i ].FillDataCollector( masterNode, ref dataCollector ); + // } + //} + + for( int i = 0; i < m_passCustomOptionsPorts.Count; i++ ) + { + m_passCustomOptionsPorts[ i ].SubShaderFillDataCollector( masterNode, ref dataCollector ); + } + } + + public void RefreshCustomOptionsDict() + { + if( m_passCustomOptionsUIDict.Count != m_passCustomOptionsUI.Count ) + { + m_passCustomOptionsUIDict.Clear(); + int count = m_passCustomOptionsUI.Count; + for( int i = 0; i < count; i++ ) + { + m_passCustomOptionsUIDict.Add( m_passCustomOptionsUI[ i ].Options.Id, m_passCustomOptionsUI[ i ] ); + } + } + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + RefreshCustomOptionsDict(); + int savedOptions = Convert.ToInt32( nodeParams[ index++ ] ); + + m_readOptionNames = new string[ savedOptions ]; + m_readOptionSelections = new string[ savedOptions ]; + + for( int i = 0; i < savedOptions; i++ ) + { + string optionName = nodeParams[ index++ ]; + string optionSelection = nodeParams[ index++ ]; + m_readOptionNames[ i ] = optionName; + m_readOptionSelections[ i ] = optionSelection; + + } + } + + public void SetReadOptions() + { + if( m_readOptionNames != null && m_readOptionSelections != null ) + { + for( int i = 0; i < m_readOptionNames.Length; i++ ) + { + if( m_passCustomOptionsUIDict.ContainsKey( m_readOptionNames[ i ] ) ) + { + if( m_passCustomOptionsUIDict[ m_readOptionNames[ i ] ].Options.Type == AseOptionsType.Field ) + { + m_passCustomOptionsUIDict[ m_readOptionNames[ i ] ].FieldValue.ReadFromSingle( m_readOptionSelections[ i ] ); + foreach( var item in m_passCustomOptionsUIDict[ m_readOptionNames[ i ] ].Options.ActionsPerOption.Rows ) + { + if( item.Columns.Length>0 && item.Columns[ 0 ].ActionType == AseOptionsActionType.SetMaterialProperty ) + { + if( UIUtils.CurrentWindow.CurrentGraph.CurrentMaterial != null ) + { + if( UIUtils.CurrentWindow.CurrentGraph.CurrentMaterial.HasProperty( item.Columns[ 0 ].ActionData ) ) + { + m_passCustomOptionsUIDict[ m_readOptionNames[ i ] ].CurrentFieldValue = UIUtils.CurrentWindow.CurrentGraph.CurrentMaterial.GetFloat( item.Columns[ 0 ].ActionData ); + } + } + } + } + } + else + m_passCustomOptionsUIDict[ m_readOptionNames[ i ] ].CurrentOptionIdx = Convert.ToInt32( m_readOptionSelections[ i ] ); + } + } + } + } + + public void Refresh() + { + int count = m_passCustomOptionsUI.Count; + for( int i = 0; i < count; i++ ) + { + m_passCustomOptionsUI[ i ].Refresh(); + } + } + + public void CheckDisable() + { + int count = m_passCustomOptionsUI.Count; + for( int i = 0; i < count; i++ ) + { + m_passCustomOptionsUI[ i ].CheckEnDisable(false); + } + } + + public void WriteToString( ref string nodeInfo ) + { + int optionsCount = m_passCustomOptionsUI.Count; + IOUtils.AddFieldValueToString( ref nodeInfo, optionsCount ); + for( int i = 0; i < optionsCount; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_passCustomOptionsUI[ i ].Options.Id ); + if( m_passCustomOptionsUI[ i ].Options.Type == AseOptionsType.Field ) + IOUtils.AddFieldValueToString( ref nodeInfo, m_passCustomOptionsUI[ i ].FieldValue.WriteToSingle() ); + else + IOUtils.AddFieldValueToString( ref nodeInfo, m_passCustomOptionsUI[ i ].CurrentOption ); + } + } + + public List PassCustomOptionsUI { get { return m_passCustomOptionsUI; } } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs.meta new file mode 100644 index 0000000..077260b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 389dcf32e61ce9d47b9a92ab691365d3 +timeCreated: 1544089703 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs new file mode 100644 index 0000000..833482f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs @@ -0,0 +1,637 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +#define CUSTOM_OPTIONS_AVAILABLE +using UnityEngine; +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace AmplifyShaderEditor +{ + + [Serializable] + public class TemplatePass + { + private const string DefaultPassNameStr = "SubShader {0} Pass {1}"; + + [SerializeField] + private int m_idx = -1; + + [SerializeField] + private bool m_isInvisible = false; + + [SerializeField] + private int m_invisibleOptions = 0; + + [SerializeField] + private bool m_isMainPass = false; + + [SerializeField] + private TemplateModulesData m_modules; + + [SerializeField] + private List m_inputDataList = new List(); + private Dictionary m_inputDataDict = new Dictionary(); + + [SerializeField] + private TemplateFunctionData m_vertexFunctionData; + + [SerializeField] + private TemplateFunctionData m_fragmentFunctionData; + + [SerializeField] + private VertexDataContainer m_vertexDataContainer; + + [SerializeField] + private TemplateInterpData m_interpolatorDataContainer; + + [SerializeField] + private TemplateTessVControlTag m_tessVControlTag; + + [SerializeField] + private TemplateTessControlData m_tessControlData; + + [SerializeField] + private TemplateTessDomainData m_tessDomainData; + + [SerializeField] + private List m_localVarsList = new List(); + + [SerializeField] + private string m_uniquePrefix; + + [SerializeField] + private TemplatePropertyContainer m_templateProperties = new TemplatePropertyContainer(); + + [SerializeField] + private List m_availableShaderGlobals = new List(); + + [SerializeField] + TemplateInfoContainer m_passNameContainer = new TemplateInfoContainer(); +#if CUSTOM_OPTIONS_AVAILABLE + [SerializeField] + TemplateOptionsContainer m_customOptionsContainer = new TemplateOptionsContainer(); +#endif + public TemplatePass( TemplateMultiPass template, TemplateSubShader subShader, int subshaderIdx, int passIdx, TemplateIdManager idManager, string uniquePrefix, int offsetIdx, TemplatePassInfo passInfo, ref Dictionary duplicatesHelper ) + { + m_idx = passIdx; + + m_uniquePrefix = uniquePrefix; + idManager.RegisterPassId( passInfo.Data ); + m_isMainPass = passInfo.Data.Contains( TemplatesManager.TemplateMainPassTag ); + if( !m_isMainPass ) + { + string id = string.Empty; + int idIndex = 0; + m_isInvisible = TemplateHelperFunctions.FetchInvisibleInfo( passInfo.Data, ref m_invisibleOptions, ref id, ref idIndex ); + if( m_isInvisible ) + { + idManager.RegisterId( idIndex, uniquePrefix + id, id, true ); + } + } + + FetchPassName( offsetIdx, passInfo.Data ); + if( m_passNameContainer.Index > -1 ) + { + idManager.RegisterId( m_passNameContainer.Index, uniquePrefix + m_passNameContainer.Id, m_passNameContainer.Id ); + } + else + { + m_passNameContainer.Data = string.Format( DefaultPassNameStr, subshaderIdx, passIdx ); + } + +#if CUSTOM_OPTIONS_AVAILABLE + m_customOptionsContainer = TemplateOptionsToolsHelper.GenerateOptionsContainer( false, passInfo.Data ); + if( m_customOptionsContainer.Enabled ) + { + idManager.RegisterId( m_customOptionsContainer.Index, uniquePrefix + m_customOptionsContainer.Body, m_customOptionsContainer.Body, true ); + } + //m_customOptionsContainer.CopyPortOptionsFrom( subShader.CustomOptionsContainer, m_passNameContainer.Data ); +#endif + m_modules = new TemplateModulesData( m_customOptionsContainer,idManager, m_templateProperties, uniquePrefix + "Module", offsetIdx, passInfo.Data, false ); + + if( !m_modules.PassTag.IsValid ) + { + m_modules.PassTag.StartIdx = passInfo.GlobalStartIdx; + m_templateProperties.AddId( passInfo.Data, m_modules.PassTag.Id, passInfo.LocalStartIdx, false ); + //m_modules.PassTag.StartIdx -= m_templateProperties.PropertyDict[ m_modules.PassTag.Id ].Indentation.Length; + //m_templateProperties.PropertyDict[ m_modules.PassTag.Id ].UseIndentationAtStart = false; + idManager.RegisterId( m_modules.PassTag.StartIdx, m_modules.UniquePrefix + m_modules.PassTag.Id, string.Empty ); + } + m_modules.SetPassUniqueNameIfUndefined( m_passNameContainer.Data ); + + m_modules.SRPType = subShader.Modules.SRPType; + if( m_modules.SRPType == TemplateSRPType.HD ) + { + m_modules.SRPIsPBR = passInfo.Data.Contains( TemplateHelperFunctions.HDPBRTag ); + + } + + Dictionary ownDuplicatesDict = new Dictionary( duplicatesHelper ); + TemplateHelperFunctions.CreateShaderGlobalsList( passInfo.Data, ref m_availableShaderGlobals, ref ownDuplicatesDict,subshaderIdx,passIdx ); + if( m_modules.SRPType == TemplateSRPType.BuiltIn ) + { + TemplateHelperFunctions.CheckUnityBuiltinGlobalMacros( passInfo.Data, ref m_availableShaderGlobals, ref ownDuplicatesDict, subshaderIdx, passIdx ); + } + + // Vertex and Interpolator data + FetchVertexAndInterpData( template, subShader.Modules, offsetIdx, passInfo.Data ); + if( m_vertexDataContainer != null ) + idManager.RegisterId( m_vertexDataContainer.VertexDataStartIdx, uniquePrefix + m_vertexDataContainer.VertexDataId, m_vertexDataContainer.VertexDataId ); + + if( m_interpolatorDataContainer != null ) + idManager.RegisterId( m_interpolatorDataContainer.InterpDataStartIdx, uniquePrefix + m_interpolatorDataContainer.InterpDataId, m_interpolatorDataContainer.InterpDataId ); + + //Fetch function code areas + FetchCodeAreas( offsetIdx, TemplatesManager.TemplateVertexCodeBeginArea, MasterNodePortCategory.Vertex, passInfo.Data ); + if( m_vertexFunctionData != null ) + idManager.RegisterId( m_vertexFunctionData.Position, uniquePrefix + m_vertexFunctionData.Id, m_vertexFunctionData.Id ); + + FetchCodeAreas( offsetIdx, TemplatesManager.TemplateFragmentCodeBeginArea, MasterNodePortCategory.Fragment, passInfo.Data ); + if( m_fragmentFunctionData != null ) + idManager.RegisterId( m_fragmentFunctionData.Position, uniquePrefix + m_fragmentFunctionData.Id, m_fragmentFunctionData.Id ); + + //Fetching inputs, must be do + if( m_fragmentFunctionData != null ) + FetchInputs( offsetIdx, MasterNodePortCategory.Fragment, passInfo.Data ); + + if( m_vertexFunctionData != null ) + FetchInputs( offsetIdx, MasterNodePortCategory.Vertex, passInfo.Data ); + + FetchTessellationData( template, subShader.Modules, offsetIdx, passInfo.Data ); + if( m_tessVControlTag != null ) + idManager.RegisterId( m_tessVControlTag.StartIdx, uniquePrefix + m_tessVControlTag.Id, m_tessVControlTag.Id ); + + if( m_tessControlData != null ) + idManager.RegisterId( m_tessControlData.StartIdx, uniquePrefix + m_tessControlData.Id, m_tessControlData.Id ); + + if( m_tessDomainData != null ) + idManager.RegisterId( m_tessDomainData.StartIdx, uniquePrefix + m_tessDomainData.Id, m_tessDomainData.Id ); + + TemplateHelperFunctions.FetchInlineVars( passInfo.Data, ref idManager ); + + //Fetch local variables must be done after fetching code areas as it needs them to see is variable is on vertex or fragment + TemplateHelperFunctions.FetchLocalVars( passInfo.Data, ref m_localVarsList, m_vertexFunctionData, m_fragmentFunctionData ); + + int localVarCount = m_localVarsList.Count; + if( localVarCount > 0 ) + { + idManager.RegisterTag( TemplatesManager.TemplateLocalVarTag ); + for( int i = 0; i < localVarCount; i++ ) + { + if( m_localVarsList[ i ].IsSpecialVar ) + { + idManager.RegisterTag( m_localVarsList[ i ].Id ); + } + } + } + + int inputsCount = m_inputDataList.Count; + for( int i = 0; i < inputsCount; i++ ) + { + if( m_inputDataList[ i ] != null ) + idManager.RegisterId( m_inputDataList[ i ].TagGlobalStartIdx, uniquePrefix + m_inputDataList[ i ].TagId, m_inputDataList[ i ].TagId ); + } + + //int passEndIndex = passInfo.Data.LastIndexOf( "}" ); + //if( passEndIndex > 0 ) + //{ + // int identationIndex = -1; + // for( int i = passEndIndex; i >= 0; i-- ) + // { + // if( passInfo.Data[ i ] == TemplatesManager.TemplateNewLine ) + // { + // identationIndex = i + 1; + // break; + // } + + // if( i == 0 ) + // { + // identationIndex = 0; + // } + // } + + // if( identationIndex > -1 ) + // { + // int length = passEndIndex - identationIndex; + // string indentation = ( length > 0 ) ? passInfo.Data.Substring( identationIndex, length ) : string.Empty; + // TemplateProperty templateProperty = new TemplateProperty( TemplatesManager.TemplateEndPassTag, indentation, false ); + // m_templateProperties.AddId( templateProperty ); + // idManager.RegisterId( offsetIdx + passEndIndex, uniquePrefix + TemplatesManager.TemplateEndPassTag, string.Empty ); + // } + //} + + ownDuplicatesDict.Clear(); + ownDuplicatesDict = null; + } + + public void Destroy() + { + m_passNameContainer = null; +#if CUSTOM_OPTIONS_AVAILABLE + m_customOptionsContainer = null; +#endif + if( m_templateProperties != null ) + m_templateProperties.Destroy(); + + m_templateProperties = null; + + if( m_modules != null ) + m_modules.Destroy(); + + m_modules = null; + + if( m_inputDataList != null ) + m_inputDataList.Clear(); + + m_inputDataList = null; + + if( m_inputDataDict != null ) + m_inputDataDict.Clear(); + + m_inputDataDict = null; + + m_vertexFunctionData = null; + m_fragmentFunctionData = null; + + if( m_vertexDataContainer != null ) + m_vertexDataContainer.Destroy(); + + m_vertexDataContainer = null; + + m_tessVControlTag = null; + + m_tessControlData = null; + + m_tessDomainData = null; + + if( m_interpolatorDataContainer != null ) + m_interpolatorDataContainer.Destroy(); + + if( m_localVarsList != null ) + { + m_localVarsList.Clear(); + m_localVarsList = null; + } + + m_interpolatorDataContainer = null; + + if( m_availableShaderGlobals != null ) + m_availableShaderGlobals.Clear(); + + m_availableShaderGlobals = null; + } + + public TemplateInputData InputDataFromId( int id ) + { + if( m_inputDataDict == null ) + m_inputDataDict = new Dictionary(); + + if( m_inputDataDict.Count != m_inputDataList.Count ) + { + m_inputDataDict.Clear(); + for( int i = 0; i < m_inputDataList.Count; i++ ) + { + m_inputDataDict.Add( m_inputDataList[ i ].PortUniqueId, m_inputDataList[ i ] ); + } + } + + if( m_inputDataDict.ContainsKey( id ) ) + return m_inputDataDict[ id ]; + + return null; + } + + void FetchPassName( int offsetIdx, string body ) + { + Match match = Regex.Match( body, TemplateHelperFunctions.PassNamePattern ); + if( match != null && match.Groups.Count > 1 ) + { + m_passNameContainer.Id = match.Groups[ 0 ].Value; + m_passNameContainer.Data = match.Groups[ 1 ].Value; + m_passNameContainer.Index = offsetIdx + match.Index; + } + } + + void FetchTessellationData( TemplateMultiPass template, TemplateModulesData subShaderModule, int offsetIdx, string body ) + { + // Tessellation VControl Tag + try + { + int vcontrolcodeBegin = body.IndexOf( TemplatesManager.TemplateTessVControlTag ); + if( vcontrolcodeBegin > -1 ) + { + m_tessVControlTag = new TemplateTessVControlTag(); + m_tessVControlTag.Id = TemplatesManager.TemplateTessVControlTag; + m_tessVControlTag.StartIdx = offsetIdx + vcontrolcodeBegin; + + m_templateProperties.AddId( body, m_tessVControlTag.Id ); + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + // Tessellation Control Data + try + { + int controlCodeBegin = body.IndexOf( TemplatesManager.TemplateTessControlCodeArea ); + if( controlCodeBegin > -1 ) + { + int beginIdx = controlCodeBegin + TemplatesManager.TemplateTessControlCodeArea.Length; + int endIdx = body.IndexOf( TemplatesManager.TemplateEndOfLine, beginIdx ); + int length = endIdx - beginIdx; + + string parameters = body.Substring( beginIdx, length ); + + string[] parametersArr = parameters.Split( IOUtils.FIELD_SEPARATOR ); + + string id = body.Substring( controlCodeBegin, endIdx + TemplatesManager.TemplateEndOfLine.Length - controlCodeBegin ); + string inParameters = parametersArr[ 0 ]; + string outParameters = ( parametersArr.Length > 1 ) ? parametersArr[ 1 ] : string.Empty; + + m_tessControlData = new TemplateTessControlData( offsetIdx + controlCodeBegin, id, inParameters, outParameters ); + + m_templateProperties.AddId( body, id ); + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + // Tessellation Domain Data + try + { + int domainCodeBegin = body.IndexOf( TemplatesManager.TemplateTessDomainCodeArea ); + if( domainCodeBegin > -1 ) + { + int beginIdx = domainCodeBegin + TemplatesManager.TemplateTessDomainCodeArea.Length; + int endIdx = body.IndexOf( TemplatesManager.TemplateEndOfLine, beginIdx ); + int length = endIdx - beginIdx; + + string parameters = body.Substring( beginIdx, length ); + + string[] parametersArr = parameters.Split( IOUtils.FIELD_SEPARATOR ); + + string id = body.Substring( domainCodeBegin, endIdx + TemplatesManager.TemplateEndOfLine.Length - domainCodeBegin ); + string inParameters = ( parametersArr.Length > 0 ) ? parametersArr[ 0 ] : string.Empty; + string outParameters = ( parametersArr.Length > 1 ) ? parametersArr[ 1 ] : string.Empty; + string baryParameters = ( parametersArr.Length > 2 ) ? parametersArr[ 2 ] : string.Empty; + + m_tessDomainData = new TemplateTessDomainData( offsetIdx + domainCodeBegin, id, inParameters, outParameters, baryParameters ); + + m_templateProperties.AddId( body, id ); + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + + void FetchVertexAndInterpData(TemplateMultiPass template, TemplateModulesData subShaderModule, int offsetIdx, string body ) + { + // Vertex Data + try + { + int vertexDataTagBegin = body.IndexOf( TemplatesManager.TemplateVertexDataTag ); + if( vertexDataTagBegin > -1 ) + { + m_vertexDataContainer = new VertexDataContainer(); + m_vertexDataContainer.VertexDataStartIdx = offsetIdx + vertexDataTagBegin; + int vertexDataTagEnd = body.IndexOf( TemplatesManager.TemplateEndOfLine, vertexDataTagBegin ); + m_vertexDataContainer.VertexDataId = body.Substring( vertexDataTagBegin, vertexDataTagEnd + TemplatesManager.TemplateEndOfLine.Length - vertexDataTagBegin ); + int dataBeginIdx = body.LastIndexOf( '{', vertexDataTagBegin, vertexDataTagBegin ); + int dataEndIdx = body.IndexOf( '}', vertexDataTagEnd ); + string vertexData = body.Substring( dataBeginIdx + 1, dataEndIdx - dataBeginIdx ); + + int parametersBegin = vertexDataTagBegin + TemplatesManager.TemplateVertexDataTag.Length; + string parameters = body.Substring( parametersBegin, vertexDataTagEnd - parametersBegin ); + m_vertexDataContainer.VertexData = TemplateHelperFunctions.CreateVertexDataList( vertexData, parameters ); + m_templateProperties.AddId( body, m_vertexDataContainer.VertexDataId ); + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + + // Available interpolators + try + { + int interpDataBegin = body.IndexOf( TemplatesManager.TemplateInterpolatorBeginTag ); + if( interpDataBegin > -1 ) + { + int interpDataEnd = body.IndexOf( TemplatesManager.TemplateEndOfLine, interpDataBegin ); + string interpDataId = body.Substring( interpDataBegin, interpDataEnd + TemplatesManager.TemplateEndOfLine.Length - interpDataBegin ); + + int dataBeginIdx = body.LastIndexOf( '{', interpDataBegin, interpDataBegin ); + int dataEndIdx = body.IndexOf( '}', interpDataEnd ); + string interpData = body.Substring( dataBeginIdx + 1, dataEndIdx - dataBeginIdx ); + + int interpolatorAmount = TemplateHelperFunctions.AvailableInterpolators[ "2.5" ]; + + if( m_modules.ShaderModel.IsValid ) + { + interpolatorAmount = m_modules.ShaderModel.InterpolatorAmount; + } + else if( subShaderModule.ShaderModel.IsValid ) + { + interpolatorAmount = subShaderModule.ShaderModel.InterpolatorAmount; + } + else if( template.GlobalShaderModel.IsValid ) + { + interpolatorAmount = template.GlobalShaderModel.InterpolatorAmount; + } + + m_interpolatorDataContainer = TemplateHelperFunctions.CreateInterpDataList( interpData, interpDataId, interpolatorAmount ); + m_interpolatorDataContainer.InterpDataId = interpDataId; + m_interpolatorDataContainer.InterpDataStartIdx = offsetIdx + interpDataBegin; + m_templateProperties.AddId( body, interpDataId ); + + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + + void FetchCodeAreas( int offsetIdx, string begin, MasterNodePortCategory category, string body ) + { + int areaBeginIndexes = body.IndexOf( begin ); + if( areaBeginIndexes > -1 ) + { + int beginIdx = areaBeginIndexes + begin.Length; + int endIdx = body.IndexOf( TemplatesManager.TemplateEndOfLine, beginIdx ); + int length = endIdx - beginIdx; + + string parameters = body.Substring( beginIdx, length ); + + string[] parametersArr = parameters.Split( IOUtils.FIELD_SEPARATOR ); + + string id = body.Substring( areaBeginIndexes, endIdx + TemplatesManager.TemplateEndOfLine.Length - areaBeginIndexes ); + string inParameters = parametersArr[ 0 ]; + string outParameters = ( parametersArr.Length > 1 ) ? parametersArr[ 1 ] : string.Empty; + if( category == MasterNodePortCategory.Fragment ) + { + string mainBodyName = string.Empty; + int mainBodyLocalIndex = -1; + + Match mainBodyNameMatch = Regex.Match( body, TemplateHelperFunctions.FragmentPragmaPattern ); + if( mainBodyNameMatch != null && mainBodyNameMatch.Groups.Count == 2 ) + { + mainBodyName = mainBodyNameMatch.Groups[ 1 ].Value; + string pattern = string.Format( TemplateHelperFunctions.FunctionBodyStartPattern, mainBodyName ); + Match mainBodyIdMatch = Regex.Match( body, pattern ); + if( mainBodyIdMatch != null && mainBodyIdMatch.Groups.Count > 0 ) + { + mainBodyLocalIndex = mainBodyIdMatch.Index; + } + + } + + m_fragmentFunctionData = new TemplateFunctionData( mainBodyLocalIndex, mainBodyName, id, offsetIdx + areaBeginIndexes, inParameters, outParameters, category ); + } + else + { + string mainBodyName = string.Empty; + int mainBodyLocalIndex = -1; + + Match mainBodyNameMatch = Regex.Match( body, TemplateHelperFunctions.VertexPragmaPattern ); + if( mainBodyNameMatch != null && mainBodyNameMatch.Groups.Count == 2 ) + { + mainBodyName = mainBodyNameMatch.Groups[ 1 ].Value; + string pattern = string.Format( TemplateHelperFunctions.FunctionBodyStartPattern, mainBodyName ); + Match mainBodyIdMatch = Regex.Match( body, pattern ); + if( mainBodyIdMatch != null && mainBodyIdMatch.Groups.Count > 0 ) + { + mainBodyLocalIndex = mainBodyIdMatch.Index; + } + } + + m_vertexFunctionData = new TemplateFunctionData( mainBodyLocalIndex, mainBodyName, id, offsetIdx + areaBeginIndexes, inParameters, outParameters, category ); + } + m_templateProperties.AddId( body, id, true ); + } + } + + void FetchInputs( int offset, MasterNodePortCategory portCategory, string body ) + { + string beginTag = ( portCategory == MasterNodePortCategory.Fragment ) ? TemplatesManager.TemplateInputsFragBeginTag : TemplatesManager.TemplateInputsVertBeginTag; + int[] inputBeginIndexes = body.AllIndexesOf( beginTag ); + if( inputBeginIndexes != null && inputBeginIndexes.Length > 0 ) + { + for( int i = 0; i < inputBeginIndexes.Length; i++ ) + { + int inputEndIdx = body.IndexOf( TemplatesManager.TemplateEndSectionTag, inputBeginIndexes[ i ] ); + int defaultValueBeginIdx = inputEndIdx + TemplatesManager.TemplateEndSectionTag.Length; + int endLineIdx = body.IndexOf( TemplatesManager.TemplateFullEndTag, defaultValueBeginIdx ); + + string defaultValue = body.Substring( defaultValueBeginIdx, endLineIdx - defaultValueBeginIdx ); + string tagId = body.Substring( inputBeginIndexes[ i ], endLineIdx + TemplatesManager.TemplateFullEndTag.Length - inputBeginIndexes[ i ] ); + + int beginIndex = inputBeginIndexes[ i ] + beginTag.Length; + int length = inputEndIdx - beginIndex; + string inputData = body.Substring( beginIndex, length ); + string[] inputDataArray = inputData.Split( IOUtils.FIELD_SEPARATOR ); + + if( inputDataArray != null && inputDataArray.Length > 0 ) + { + try + { + string portName = inputDataArray[ (int)TemplatePortIds.Name ]; + WirePortDataType dataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), inputDataArray[ (int)TemplatePortIds.DataType ].ToUpper() ); + if( inputDataArray.Length == 3 ) + { + int portOrderId = m_inputDataList.Count; + int portUniqueId = -1; + bool isInt = int.TryParse( inputDataArray[ 2 ], out portUniqueId ); + if( isInt ) + { + if( portUniqueId < 0 ) + portUniqueId = m_inputDataList.Count; + + m_inputDataList.Add( new TemplateInputData( inputBeginIndexes[ i ], offset + inputBeginIndexes[ i ], tagId, portName, defaultValue, dataType, portCategory, portUniqueId, portOrderId, string.Empty ) ); + m_templateProperties.AddId( body, tagId, false ); + } + else + { + portUniqueId = m_inputDataList.Count; + m_inputDataList.Add( new TemplateInputData( inputBeginIndexes[ i ], offset + inputBeginIndexes[ i ], tagId, portName, defaultValue, dataType, portCategory, portUniqueId, portOrderId, inputDataArray[ 2 ] ) ); + m_templateProperties.AddId( body, tagId, false ); + } + } + else + { + int portUniqueIDArrIdx = (int)TemplatePortIds.UniqueId; + int portUniqueId = ( portUniqueIDArrIdx < inputDataArray.Length ) ? Convert.ToInt32( inputDataArray[ portUniqueIDArrIdx ] ) : -1; + if( portUniqueId < 0 ) + portUniqueId = m_inputDataList.Count; + + int portOrderArrayIdx = (int)TemplatePortIds.OrderId; + int portOrderId = ( portOrderArrayIdx < inputDataArray.Length ) ? Convert.ToInt32( inputDataArray[ portOrderArrayIdx ] ) : -1; + if( portOrderId < 0 ) + portOrderId = m_inputDataList.Count; + + int portLinkIdx = (int)TemplatePortIds.Link; + string linkId = ( portLinkIdx < inputDataArray.Length ) ? inputDataArray[ portLinkIdx ] : string.Empty; + m_inputDataList.Add( new TemplateInputData( inputBeginIndexes[ i ], offset + inputBeginIndexes[ i ], tagId, portName, defaultValue, dataType, portCategory, portUniqueId, portOrderId, linkId ) ); + m_templateProperties.AddId( body, tagId, false ); + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + } + } + } + +#if CUSTOM_OPTIONS_AVAILABLE + public TemplateOptionsContainer CustomOptionsContainer { get { return m_customOptionsContainer; } } +#endif + public TemplateModulesData Modules { get { return m_modules; } } + public List InputDataList { get { return m_inputDataList; } } + public TemplateFunctionData VertexFunctionData { get { return m_vertexFunctionData; } } + public TemplateFunctionData FragmentFunctionData { get { return m_fragmentFunctionData; } } + public VertexDataContainer VertexDataContainer { get { return m_vertexDataContainer; } } + public TemplateInterpData InterpolatorDataContainer { get { return m_interpolatorDataContainer; } } + public TemplateTessVControlTag TessVControlTag { get { return m_tessVControlTag; } } + public TemplateTessControlData TessControlData { get { return m_tessControlData; } } + public TemplateTessDomainData TessDomainData { get { return m_tessDomainData; } } + public string UniquePrefix { get { return m_uniquePrefix; } } + public TemplatePropertyContainer TemplateProperties { get { return m_templateProperties; } } + public List AvailableShaderGlobals { get { return m_availableShaderGlobals; } } + public List LocalVarsList { get { return m_localVarsList; } } + public TemplateInfoContainer PassNameContainer { get { return m_passNameContainer; } } + public bool IsMainPass { get { return m_isMainPass; } set { m_isMainPass = value; } } + public bool IsInvisible { get { return m_isInvisible; } } + public int InvisibleOptions { get { return m_invisibleOptions; } } + public int Idx { get { return m_idx; } } + public bool AddToList + { + get + { + if( m_isInvisible ) + { + return ( m_inputDataList.Count > 0 ); + } + + return true; + } + } + public bool HasValidFunctionBody + { + get + { + if( m_fragmentFunctionData != null || m_vertexFunctionData != null ) + return true; + return false; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs.meta new file mode 100644 index 0000000..e36dee4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1e6749bf88e2d0f4ab5812f084973f4c +timeCreated: 1517831575 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs new file mode 100644 index 0000000..e85a92d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs @@ -0,0 +1,167 @@ +using UnityEditor; +using UnityEngine; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class PassVisibleOptionsItems + { + public bool Visible; + public string Name; + public int Idx = -1; + } + + [Serializable] + public class TemplatePassSelectorHelper + { + private const string Label = " Available Passes"; + + [SerializeField] + private bool m_foldout; + + [SerializeField] + private PassVisibleOptionsItems[] m_currentPasses; + + [NonSerialized] + private Dictionary m_currentPassesDict; + + [SerializeField] + private int m_mainPassId; + + public void CopyFrom( TemplatePassSelectorHelper from ) + { + for( int i = 0; i < from.AvailablePasses.Length; i++ ) + { + SetPassVisible( from.AvailablePasses[ i ].Name, from.AvailablePasses[ i ].Visible ); + } + } + + public void Setup( TemplateSubShader subShader ) + { + if( m_currentPasses == null ) + { + m_currentPassesDict = new Dictionary(); + m_currentPasses = new PassVisibleOptionsItems[ subShader.Passes.Count ]; + for( int i = 0; i < m_currentPasses.Length; i++ ) + { + if( subShader.Passes[ i ].IsMainPass ) + m_mainPassId = i; + + m_currentPasses[ i ] = new PassVisibleOptionsItems() { Name = subShader.Passes[ i ].PassNameContainer.Data, Visible = true, Idx = i }; + m_currentPassesDict.Add( m_currentPasses[ i ].Name, m_currentPasses[ i ] ); + } + } + } + + public void Clear() + { + m_currentPasses = null; + + if( m_currentPassesDict != null ) + m_currentPassesDict.Clear(); + + m_currentPassesDict = null; + } + + public void Destroy() + { + m_currentPasses = null; + + if( m_currentPassesDict != null ) + m_currentPassesDict.Clear(); + + m_currentPassesDict = null; + } + + public void Draw( TemplateMultiPassMasterNode owner ) + { + if( m_currentPasses.Length < 2 ) + return; + + NodeUtils.DrawNestedPropertyGroup( ref m_foldout, Label, () => + { + for( int i = 0; i < m_currentPasses.Length; i++ ) + { + EditorGUI.BeginChangeCheck(); + m_currentPasses[ i ].Visible = owner.EditorGUILayoutToggleLeft( m_currentPasses[ i ].Name, m_currentPasses[ i ].Visible ); + if( EditorGUI.EndChangeCheck() ) + { + owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex)[ m_currentPasses[ i ].Idx ].IsInvisible = !m_currentPasses[ i ].Visible; + } + + } + EditorGUILayout.Space(); + } ); + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { + int passAmount = Convert.ToInt32( nodeParams[ index++ ] ); + for( int i = 0; i < passAmount; i++ ) + { + bool value = Convert.ToBoolean( nodeParams[ index++ ] ); + if( i < m_currentPasses.Length ) + { + m_currentPasses[ i ].Visible = value; + } + } + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentPasses.Length ); + for( int i = 0; i < m_currentPasses.Length; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentPasses[ i ].Visible ); + } + } + + public void SetPassVisible( string passName, bool visible ) + { + bool refresh = false; + if( m_currentPassesDict == null ) + { + m_currentPassesDict = new Dictionary(); + refresh = true; + } + else if( m_currentPassesDict.Count != m_currentPasses.Length ) + { + refresh = true; + } + + if( refresh ) + { + for( int i = 0; i < m_currentPasses.Length; i++ ) + { + m_currentPassesDict.Add( m_currentPasses[ i ].Name, m_currentPasses[ i ] ); + } + } + + if( m_currentPassesDict.ContainsKey( passName ) ) + { + m_currentPassesDict[ passName ].Visible = visible; + } + } + + public int LastActivePass + { + get + { + if( m_currentPasses != null ) + { + for( int i = m_currentPasses.Length - 1; i > -1; i-- ) + { + if( m_currentPasses[ i ].Visible ) + return i; + } + } + m_currentPasses[ m_mainPassId ].Visible = true; + return m_mainPassId; + } + } + public bool IsVisible( int passId ) { return m_currentPasses[ passId ].Visible; } + private PassVisibleOptionsItems[] AvailablePasses { get { return m_currentPasses; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs.meta new file mode 100644 index 0000000..2f45a9d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1340693b71fe44846bb72eb1035f138d +timeCreated: 1542731803 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs new file mode 100644 index 0000000..8f6245e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs @@ -0,0 +1,177 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEditor; +using UnityEngine; +using System.IO; +using System.Security.AccessControl; +using System.Security.Principal; +using System.Text.RegularExpressions; +using Debug = UnityEngine.Debug; + +namespace AmplifyShaderEditor +{ + public sealed class TemplatePostProcessor : AssetPostprocessor + { + public static TemplatesManager DummyManager; + public static void Destroy() + { + if( DummyManager != null ) + { + DummyManager.Destroy(); + ScriptableObject.DestroyImmediate( DummyManager ); + DummyManager = null; + } + } + + static void OnPostprocessAllAssets( string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths ) + { + bool containsShaders = false; + for( int i = 0; i < importedAssets.Length; i++ ) + { + if( importedAssets[ i ].EndsWith( ".shader" ) ) + { + containsShaders = true; + break; + } + } + + // leave early if there's no shaders among the imports + if( !containsShaders ) + return; + + TemplatesManager templatesManager; + bool firstTimeDummyFlag = false; + if( UIUtils.CurrentWindow == null ) + { + if( DummyManager == null ) + { + DummyManager = ScriptableObject.CreateInstance(); + DummyManager.hideFlags = HideFlags.HideAndDontSave; + firstTimeDummyFlag = true; + } + templatesManager = DummyManager; + } + else + { + Destroy(); + templatesManager = UIUtils.CurrentWindow.TemplatesManagerInstance; + } + + if( templatesManager == null ) + { + return; + } + + if( !templatesManager.Initialized ) + { + templatesManager.Init(); + } + + bool refreshMenuItems = false; + for( int i = 0; i < importedAssets.Length; i++ ) + { + if( TemplateHelperFunctions.CheckIfTemplate( importedAssets[ i ] ) ) + { + string guid = AssetDatabase.AssetPathToGUID( importedAssets[ i ] ); + TemplateDataParent templateData = templatesManager.GetTemplate( guid ); + if( templateData != null ) + { + refreshMenuItems = templateData.Reload() || refreshMenuItems || firstTimeDummyFlag; + int windowCount = IOUtils.AllOpenedWindows.Count; + AmplifyShaderEditorWindow currWindow = UIUtils.CurrentWindow; + for( int windowIdx = 0; windowIdx < windowCount; windowIdx++ ) + { + if( IOUtils.AllOpenedWindows[ windowIdx ].OutsideGraph.CurrentCanvasMode == NodeAvailability.TemplateShader ) + { + if( IOUtils.AllOpenedWindows[ windowIdx ].OutsideGraph.MultiPassMasterNodes.NodesList[ 0 ].CurrentTemplate == templateData ) + { + UIUtils.CurrentWindow = IOUtils.AllOpenedWindows[ windowIdx ]; + IOUtils.AllOpenedWindows[ windowIdx ].OutsideGraph.ForceMultiPassMasterNodesRefresh(); + } + } + } + UIUtils.CurrentWindow = currWindow; + } + else + { + refreshMenuItems = true; + string name = TemplatesManager.OfficialTemplates.ContainsKey( guid ) ? TemplatesManager.OfficialTemplates[ guid ] : string.Empty; + TemplateMultiPass mp = TemplateMultiPass.CreateInstance(); + mp.Init( name, guid, true ); + templatesManager.AddTemplate( mp ); + } + } + } + + if( deletedAssets.Length > 0 ) + { + if( deletedAssets[ 0 ].IndexOf( Constants.InvalidPostProcessDatapath ) < 0 ) + { + for( int i = 0; i < deletedAssets.Length; i++ ) + { + string guid = AssetDatabase.AssetPathToGUID( deletedAssets[ i ] ); + TemplateDataParent templateData = templatesManager.GetTemplate( guid ); + if( templateData != null ) + { + // Close any window using that template + int windowCount = IOUtils.AllOpenedWindows.Count; + for( int windowIdx = 0; windowIdx < windowCount; windowIdx++ ) + { + TemplateMasterNode masterNode = IOUtils.AllOpenedWindows[ windowIdx ].CurrentGraph.CurrentMasterNode as TemplateMasterNode; + if( masterNode != null && masterNode.CurrentTemplate.GUID.Equals( templateData.GUID ) ) + { + IOUtils.AllOpenedWindows[ windowIdx ].Close(); + } + } + + templatesManager.RemoveTemplate( templateData ); + refreshMenuItems = true; + } + } + } + } + + //for ( int i = 0; i < movedAssets.Length; i++ ) + //{ + // if ( TemplateHelperFunctions.CheckIfTemplate( movedAssets[ i ] ) ) + // { + // refreshMenuItems = true; + // break; + // } + //} + + //for ( int i = 0; i < movedFromAssetPaths.Length; i++ ) + //{ + // if ( TemplateHelperFunctions.CheckIfTemplate( movedFromAssetPaths[ i ] ) ) + // { + // refreshMenuItems = true; + // break; + // } + //} + + if( refreshMenuItems ) + { + //UnityEngine.Debug.Log( "Refresh Menu Items" ); + refreshMenuItems = false; + templatesManager.CreateTemplateMenuItems(); + + AmplifyShaderEditorWindow currWindow = UIUtils.CurrentWindow; + + int windowCount = IOUtils.AllOpenedWindows.Count; + for( int windowIdx = 0; windowIdx < windowCount; windowIdx++ ) + { + UIUtils.CurrentWindow = IOUtils.AllOpenedWindows[ windowIdx ]; + IOUtils.AllOpenedWindows[ windowIdx ].CurrentGraph.ForceCategoryRefresh(); + } + UIUtils.CurrentWindow = currWindow; + } + + // reimport menu items at the end of everything, hopefully preventing import loops + templatesManager.ReimportMenuItems(); + + // destroying the DummyManager, not doing so will create leaks over time + Destroy(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs.meta new file mode 100644 index 0000000..3598b89 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d5f63490d6402e9488add7cbdfdd6872 +timeCreated: 1496739732 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateRenderPlatformHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateRenderPlatformHelper.cs new file mode 100644 index 0000000..063366a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateRenderPlatformHelper.cs @@ -0,0 +1,80 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateRenderPlatformHelper : TemplateModuleData + { + [SerializeField] + private string m_id; + + [SerializeField] + private int m_index; + + [SerializeField] + private bool[] m_renderingPlatforms = null; + + private void CommonInit( bool initialValue ) + { + DataCheck = TemplateDataCheck.Valid; + int renderPlatformLength = RenderingPlatformOpHelper.RenderingPlatformsInfo.Length; + m_renderingPlatforms = new bool[ renderPlatformLength ]; + for( int i = 0 ; i < m_renderingPlatforms.Length ; i++ ) + { + m_renderingPlatforms[ i ] = initialValue; + } + } + + public void InitByTag(int index) + { + m_id = TemplatesManager.TemplateRenderPlatformsTag; + m_index = index; + CommonInit( true ); + + } + + public void InitByExcludeRenders( int index, string id ) + { + m_id = id; + m_index = index; + CommonInit( true ); + } + + public void InitByOnlyRenders( int index , string id ) + { + m_id = id; + m_index = index; + CommonInit( false ); + } + + public void SetupPlatform( string platformStr , bool value ) + { + try + { + RenderPlatforms platform = (RenderPlatforms)Enum.Parse( typeof( RenderPlatforms ) , platformStr ); + int index = -1; + if( RenderingPlatformOpHelper.PlatformToIndex.TryGetValue( platform , out index ) ) + { + m_renderingPlatforms[ index ] = value; + } + } + catch( Exception e ) + { + Debug.LogException( e ); + } + } + + public void Destroy() + { + m_renderingPlatforms = null; + } + + public bool[] RenderingPlatforms { get { return m_renderingPlatforms; } } + public string ID { get { return m_id; } } + public int Index { get { return m_index; } set{ m_index = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateRenderPlatformHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateRenderPlatformHelper.cs.meta new file mode 100644 index 0000000..a37765b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateRenderPlatformHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3324f7aa07eb04d42bea8791af66cc15 +timeCreated: 1625564235 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs new file mode 100644 index 0000000..6f42c6f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs @@ -0,0 +1,121 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplatePassInfo + { + public string Modules; + public string Data; + public int GlobalStartIdx = -1; + public int LocalStartIdx = -1; + } + + [Serializable] + public class TemplateSubShaderInfo + { + public string Data; + public string Modules; + public int StartIdx = -1; + public List Passes = new List(); + public void Destroy() + { + Passes.Clear(); + Passes = null; + } + } + + [Serializable] + public class TemplateShaderInfo + { + public string Body; + public string Properties; + public int PropertyStartIdx = -1; + public List SubShaders = new List(); + public void Destroy() + { + int count = SubShaders.Count; + for( int i = 0; i < count; i++ ) + { + SubShaders[ i ].Destroy(); + } + SubShaders.Clear(); + SubShaders = null; + } + } + + public class TemplateShaderInfoUtil + { + public static TemplateShaderInfo CreateShaderData( string body ) + { + int nameBegin = body.IndexOf( TemplatesManager.TemplateShaderNameBeginTag ); + if( nameBegin < 0 ) + { + // Not a template + return null; + } + + TemplateShaderInfo shaderData = null; + //SHADER + MatchCollection shaderMatch = Regex.Matches( body, "\\bShader\\b" ); + if( shaderMatch.Count > 0 ) + { + //SUBSHADER + MatchCollection subShaderMatch = Regex.Matches( body, TemplatesManager.TemplateMPSubShaderTag ); + int subShaderAmount = subShaderMatch.Count; + if( subShaderAmount > 0 ) + { + shaderData = new TemplateShaderInfo(); + shaderData.Body = body; + int length = subShaderMatch[ 0 ].Index - shaderMatch[ 0 ].Groups[ 0 ].Index; + shaderData.Properties = body.Substring( shaderMatch[ 0 ].Index, length ); + shaderData.PropertyStartIdx = body.IndexOf( TemplatesManager.TemplatePropertyTag ); + + for( int subShaderIdx = 0; subShaderIdx < subShaderAmount; subShaderIdx++ ) + { + TemplateSubShaderInfo subShaderData = new TemplateSubShaderInfo(); + int subshaderBeginIndex = subShaderMatch[ subShaderIdx ].Index; + int subShaderEndIndex = ( subShaderIdx == ( subShaderAmount - 1 ) ) ? body.Length - 1 : subShaderMatch[ subShaderIdx + 1 ].Index; + subShaderData.Data = body.Substring( subshaderBeginIndex, subShaderEndIndex - subshaderBeginIndex ); + subShaderData.StartIdx = subshaderBeginIndex; + + //PASS + MatchCollection passMatch = Regex.Matches( subShaderData.Data, TemplatesManager.TemplatePassTagPattern ); + if( passMatch.Count == 0 ) + { + passMatch = Regex.Matches( subShaderData.Data, TemplatesManager.TemplateMPPassTag ); + } + + int passCount = passMatch.Count; + if( passCount > 0 ) + { + int lastPassIndex = subShaderData.Data.LastIndexOf( TemplatesManager.TemplatePassesEndTag ); + if( lastPassIndex < 0 ) + { + lastPassIndex = subShaderData.Data.Length - 1; + } + + subShaderData.Modules = subShaderData.Data.Substring( 0, passMatch[ 0 ].Index ); + for( int passIdx = 0; passIdx < passCount; passIdx++ ) + { + int passBeginIndex = passMatch[ passIdx ].Index; + int passEndIdx = ( passIdx == ( passCount - 1 ) ) ? lastPassIndex : passMatch[ passIdx + 1 ].Index; + TemplatePassInfo passData = new TemplatePassInfo(); + passData.Data = subShaderData.Data.Substring( passBeginIndex, passEndIdx - passBeginIndex ); + passData.GlobalStartIdx = subshaderBeginIndex + passBeginIndex; + passData.LocalStartIdx = passBeginIndex; + subShaderData.Passes.Add( passData ); + } + shaderData.SubShaders.Add( subShaderData ); + } + } + } + } + return shaderData; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs.meta new file mode 100644 index 0000000..8ae726e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 33fdd6a5fbc437a489acf58f5d82885c +timeCreated: 1516879445 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs new file mode 100644 index 0000000..e1de14b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs @@ -0,0 +1,107 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public sealed class TemplateShaderModelModule : TemplateModuleParent + { + private const string ShaderModelStr = "Shader Model"; + private const string ShaderModelFormatStr = "#pragma target "; + private const string ShaderModelEncapsulateFormatStr = "CGINCLUDE\n#pragma target {0}\nENDCG"; + + [SerializeField] + private int m_shaderModelIdx = 2; + + [SerializeField] + private bool m_encapsulateOnCGInlude = false; + + public TemplateShaderModelModule() : base("Shader Model"){ } + + public override void Draw( UndoParentNode owner, bool style = true ) + { + EditorGUI.BeginChangeCheck(); + m_shaderModelIdx = owner.EditorGUILayoutPopup( ShaderModelStr, m_shaderModelIdx, TemplateHelperFunctions.AvailableShaderModels ); + if( EditorGUI.EndChangeCheck() ) + { + m_isDirty = true; + } + } + + public void CopyFrom( TemplateShaderModelModule other , bool allData ) + { + if( allData ) + { + m_independentModule = other.IndependentModule; + m_encapsulateOnCGInlude = other.EncapsulateOnCGInlude; + } + + m_shaderModelIdx = other.CurrentShaderModelIdx; + } + + public override void ReadFromString( ref uint index, ref string[] nodeParams ) + { + bool validDataOnMeta = m_validData; + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( validDataOnMeta ) + m_shaderModelIdx = Convert.ToInt32( nodeParams[ index++ ] ); + } + + public override void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_validData ); + if( m_validData ) + IOUtils.AddFieldValueToString( ref nodeInfo, m_shaderModelIdx ); + } + + public override string GenerateShaderData( bool isSubShader ) + { + if( m_encapsulateOnCGInlude ) + { + return string.Format( ShaderModelEncapsulateFormatStr, TemplateHelperFunctions.AvailableShaderModels[ m_shaderModelIdx ] ); + } + else + { + return ShaderModelFormatStr + TemplateHelperFunctions.AvailableShaderModels[ m_shaderModelIdx ]; + } + } + + public void ConfigureFromTemplateData( TemplateShaderModelData data ) + { + bool newValidData = ( data.DataCheck == TemplateDataCheck.Valid ); + + if( newValidData && m_validData != newValidData ) + { + m_independentModule = data.IndependentModule; + + if( TemplateHelperFunctions.ShaderModelToArrayIdx.ContainsKey( data.Value ) ) + { + m_shaderModelIdx = TemplateHelperFunctions.ShaderModelToArrayIdx[ data.Value ]; + } + m_encapsulateOnCGInlude = data.Encapsulate; + } + + m_validData = newValidData; + } + + public int CurrentShaderModelIdx { get { return m_shaderModelIdx; } } + public string CurrentShaderModel { get { return TemplateHelperFunctions.AvailableShaderModels[ m_shaderModelIdx ]; } } + public bool EncapsulateOnCGInlude { get { return m_encapsulateOnCGInlude; } } + public int InterpolatorAmount + { + get + { + return TemplateHelperFunctions.AvailableInterpolators[ TemplateHelperFunctions.AvailableShaderModels[ m_shaderModelIdx ] ]; + } + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs.meta new file mode 100644 index 0000000..9afc9c9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 33c15b597b8db18499c1b4a76035a552 +timeCreated: 1519899350 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs new file mode 100644 index 0000000..bb38283 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs @@ -0,0 +1,52 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateShaderPropertyData + { + public string PropertyInspectorName; + public string PropertyName; + public WirePortDataType PropertyDataType; + public PropertyType PropertyType; + + public int Index; + public string FullValue; + public string ReplacementValueHelper; + public string Identation; + + public bool IsMacro; + + public int SubShaderId; + public int PassId; + + public TemplateShaderPropertyData( int index, string fullValue, string identation, string propertyInspectorName, string propertyName, WirePortDataType propertyDataType, PropertyType propertyType,int subShaderId, int passId, bool isMacro = false ) + { + Index = index; + FullValue = fullValue; + Identation = identation; + PropertyInspectorName = string.IsNullOrEmpty( propertyInspectorName )?propertyName: propertyInspectorName; + PropertyName = propertyName; + PropertyDataType = propertyDataType; + PropertyType = propertyType; + int idx = FullValue.LastIndexOf( "=" ); + ReplacementValueHelper = ( idx >= 0 ) ? FullValue.Substring( 0, idx + 1 ) +" ": FullValue + " = "; + IsMacro = isMacro; + SubShaderId = subShaderId; + PassId = passId; + } + + public string CreatePropertyForValue( string value ) + { + return value.Contains( PropertyName ) ? Identation + value : ReplacementValueHelper + value; + } + + public override string ToString() + { + return string.Format( "{0}(\"{1}\", {2})", PropertyName, PropertyInspectorName,UIUtils.WirePortToCgType( PropertyDataType ) ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs.meta new file mode 100644 index 0000000..411f053 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7d16f1d82f69ac945ac524dd877ce7fe +timeCreated: 1496341538 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs new file mode 100644 index 0000000..96185d4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs @@ -0,0 +1,715 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public enum ShaderPropertyScope + { + Shader, + SubShader, + Pass + } + + [Serializable] + [NodeAttributes( "Template Parameter", "Constants And Properties", "Select and use one of the pre-existing properties given by the template" )] + public sealed class TemplateShaderPropertyNode : TemplateNodeParent + { + private const string CurrentScopeStr = "Scope"; + private const string WarningStr = "Preview doesn't work with global variables"; + private const string PropertyLabelStr = "Parameter"; + private const string TypeLabelStr = "Type: "; + private const string PropertyNameStr = "Property Name: "; + + private int IntPropertyId; + private int FloatPropertyId; + private int VectorPropertyId; + private int Sampler2DPropertyId; + private int Sampler3DPropertyId; + private int SamplerCubePropertyId; + + [SerializeField] + private int m_currentPropertyIdx = -1; + + [SerializeField] + private string m_propertyName = string.Empty; + + [SerializeField] + private int m_propertyNameId = 0; + + [SerializeField] + private string m_typeName = string.Empty; + + [SerializeField] + private string m_propertyNameLabel = string.Empty; + + private bool m_fetchPropertyId = false; + private bool m_fetchScopeFromProperty = false; + + private List m_shaderProperties = null; + private string[] m_propertyLabels = null; + + private UpperLeftWidgetHelper m_upperLeftWidgetHelper = new UpperLeftWidgetHelper(); + + //Multi-Pass only properties + [SerializeField] + private ShaderPropertyScope m_currentScope = ShaderPropertyScope.Shader; + + [SerializeField] + private bool m_advancedView = false; + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_previewShaderGUID = "4feb2016be0ece148b8bf234508f6aa4"; + m_autoWrapProperties = true; + } + + void FetchScope() + { + int shaderScopeCount = m_templateMPData.AvailableShaderProperties.Count; + for( int i = 0; i < shaderScopeCount; i++ ) + { + if( m_templateMPData.AvailableShaderProperties[ i ].PropertyName.Equals( m_propertyName ) ) + { + m_currentScope = ShaderPropertyScope.Shader; + } + } + + int subShaderScopeCount = m_templateMPData.SubShaders[ SubShaderIdx ].AvailableShaderGlobals.Count; + for( int i = 0; i < subShaderScopeCount; i++ ) + { + if( m_templateMPData.SubShaders[ SubShaderIdx ].AvailableShaderGlobals[ i ].PropertyName.Equals( m_propertyName ) ) + { + m_currentScope = ShaderPropertyScope.SubShader; + } + } + + int passScopeCount = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].AvailableShaderGlobals.Count; + for( int i = 0; i < passScopeCount; i++ ) + { + if( m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].AvailableShaderGlobals[ i ].PropertyName.Equals( m_propertyName ) ) + { + m_currentScope = ShaderPropertyScope.Pass; + } + } + } + + void FetchShaderProperties() + { + if( m_templateMPData == null ) + m_templateMPData = ( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ).CurrentTemplate; + + if( m_templateMPData != null ) + { + if( m_advancedView ) + { + switch( m_currentScope ) + { + case ShaderPropertyScope.Shader: + m_shaderProperties = m_templateMPData.AvailableShaderProperties; + break; + case ShaderPropertyScope.SubShader: + m_shaderProperties = m_templateMPData.SubShaders[ SubShaderIdx ].AvailableShaderGlobals; + break; + case ShaderPropertyScope.Pass: + m_shaderProperties = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].AvailableShaderGlobals; + break; + } + } + else + { + m_shaderProperties = m_templateMPData.AllShaderProperties; + + if( m_currentPropertyIdx < 0 && m_shaderProperties.Count > 0 ) + { + m_currentPropertyIdx = 0; + } + } + } + } + + public override void OnEnable() + { + base.OnEnable(); + IntPropertyId = Shader.PropertyToID( "_IntData" ); + FloatPropertyId = Shader.PropertyToID( "_FloatData" ); + VectorPropertyId = Shader.PropertyToID( "_VectorData" ); + Sampler2DPropertyId = Shader.PropertyToID( "_Sampler2DData" ); + Sampler3DPropertyId = Shader.PropertyToID( "_Sampler3DData" ); + SamplerCubePropertyId = Shader.PropertyToID( "_SamplerCubeData" ); + } + + public override void DrawProperties() + { + base.DrawProperties(); + EditorGUI.BeginChangeCheck(); + m_advancedView = EditorGUILayoutToggle( "Advanced View", m_advancedView ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_advancedView ) + { + if( m_shaderProperties[ m_currentPropertyIdx ].PassId >= 0 ) + { + m_currentScope = ShaderPropertyScope.Pass; + PassIdx = m_shaderProperties[ m_currentPropertyIdx ].PassId; + SubShaderIdx = m_shaderProperties[ m_currentPropertyIdx ].SubShaderId; + } + else if( m_shaderProperties[ m_currentPropertyIdx ].SubShaderId >= 0 ) + { + m_currentScope = ShaderPropertyScope.SubShader; + SubShaderIdx = m_shaderProperties[ m_currentPropertyIdx ].SubShaderId; + PassIdx = 0; + } + else + { + m_currentScope = ShaderPropertyScope.Shader; + SubShaderIdx = 0; + PassIdx = 0; + } + } + + FetchShaderProperties(); + FetchPropertyId(); + } + + if( m_advancedView && m_multiPassMode ) + { + DrawMultipassProperties(); + } + + if( m_currentPropertyIdx > -1 ) + { + + bool hasProperties = ( m_shaderProperties != null && m_shaderProperties.Count > 0 ); + if( hasProperties ) + { + EditorGUI.BeginChangeCheck(); + m_currentPropertyIdx = EditorGUILayoutPopup( PropertyLabelStr, m_currentPropertyIdx, m_propertyLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromId(); + } + EditorGUILayout.LabelField( m_typeName ); + if( m_shaderProperties[ m_currentPropertyIdx ].PropertyType != PropertyType.Global ) + { + EditorGUILayout.LabelField( m_propertyNameLabel ); + } + } + } + + } + + void DrawMultipassProperties() + { + EditorGUI.BeginChangeCheck(); + m_currentScope = (ShaderPropertyScope)EditorGUILayoutEnumPopup( CurrentScopeStr, m_currentScope ); + if( EditorGUI.EndChangeCheck() ) + { + FetchShaderProperties(); + FetchPropertyId(); + } + + bool showSubShader = false; + bool showPass = false; + switch( m_currentScope ) + { + case ShaderPropertyScope.SubShader: + { + showSubShader = true; + } + break; + case ShaderPropertyScope.Pass: + { + showSubShader = true; + showPass = true; + } + break; + } + + if( showSubShader ) + { + DrawSubShaderUI(); + } + + if( showPass ) + { + DrawPassUI(); + } + } + + protected override void OnSubShaderChange() + { + FetchShaderProperties(); + FetchPropertyId(); + } + + protected override void OnPassChange() + { + FetchShaderProperties(); + FetchPropertyId(); + } + + override protected void CheckWarningState() + { + if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader ) + { + ShowTab( NodeMessageType.Error, ErrorMessageStr ); + } + else + { + if( m_shaderProperties != null && + m_shaderProperties.Count > 0 && + m_shaderProperties.Count > m_currentPropertyIdx && + m_shaderProperties[ m_currentPropertyIdx ].PropertyType == PropertyType.Global && + m_showPreview ) + { + ShowTab( NodeMessageType.Info, WarningStr ); + } + else + { + m_showErrorMessage = false; + } + } + } + + public override void SetPreviewInputs() + { + if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader ) + return; + + if( m_shaderProperties == null || m_currentPropertyIdx >= m_shaderProperties.Count || m_currentPropertyIdx < 0 ) + return; + + if( m_shaderProperties[ m_currentPropertyIdx ].PropertyType == PropertyType.Global ) + { + m_additionalContent.text = string.Empty; + PreviewMaterial.SetInt( IntPropertyId, 0 ); + return; + } + + Material currMat = m_containerGraph.CurrentMaterial; + if( currMat != null && currMat.HasProperty( m_propertyNameId ) ) + { + switch( m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType ) + { + case WirePortDataType.INT: + { + int value = currMat.GetInt( m_propertyNameId ); + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, GenerateTitle( value ) ) ); + PreviewMaterial.SetInt( IntPropertyId, value ); + } + break; + case WirePortDataType.FLOAT: + { + float value = currMat.GetFloat( m_propertyNameId ); + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, GenerateTitle( value ) ) ); + PreviewMaterial.SetFloat( FloatPropertyId, value ); + } + break; + case WirePortDataType.FLOAT4: + { + Vector4 value = currMat.GetVector( m_propertyNameId ); + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, GenerateTitle( value.x, value.y, value.z, value.w ) ) ); + PreviewMaterial.SetVector( VectorPropertyId, value ); + } + break; + case WirePortDataType.COLOR: + { + Color value = currMat.GetColor( m_propertyNameId ); + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, GenerateTitle( value.r, value.g, value.b, value.a ) ) ); + PreviewMaterial.SetColor( VectorPropertyId, value ); + } + break; + case WirePortDataType.SAMPLER2D: + { + Texture value = currMat.GetTexture( m_propertyNameId ); + if( value ) + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, value.name ) ); + else + SetAdditonalTitleText( string.Empty ); + PreviewMaterial.SetTexture( Sampler2DPropertyId, value ); + } + break; + case WirePortDataType.SAMPLER3D: + { + Texture value = currMat.GetTexture( m_propertyNameId ); + if( value ) + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, value.name ) ); + else + SetAdditonalTitleText( string.Empty ); + PreviewMaterial.SetTexture( Sampler3DPropertyId, value ); + } + break; + case WirePortDataType.SAMPLERCUBE: + { + Texture value = currMat.GetTexture( m_propertyNameId ); + if( value ) + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, value.name ) ); + else + SetAdditonalTitleText( string.Empty ); + PreviewMaterial.SetTexture( SamplerCubePropertyId, value ); + } + break; + case WirePortDataType.SAMPLER2DARRAY: + { + Texture value = currMat.GetTexture( m_propertyNameId ); + if( value ) + SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, value.name ) ); + else + SetAdditonalTitleText( string.Empty ); + PreviewMaterial.SetTexture( SamplerCubePropertyId, value ); + } + break; + } + } + else + { + SetAdditonalTitleText( string.Empty ); + } + } + + public override void Draw( DrawInfo drawInfo ) + { + if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader ) + { + if( !m_showErrorMessage || m_errorMessageTypeIsError == NodeMessageType.Info ) + { + ShowTab( NodeMessageType.Error, ErrorMessageStr ); + } + } + else if( m_showErrorMessage ) + { + if( m_errorMessageTypeIsError == NodeMessageType.Error ) + HideTab(); + } + + base.Draw( drawInfo ); + if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader ) + return; + + if( m_shaderProperties == null ) + { + MasterNode masterNode = m_containerGraph.CurrentMasterNode; + if( masterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template ) + { + if( SetTemplate( masterNode ) ) + { + m_fetchPropertyId = true; + } + } + } + + if( m_fetchScopeFromProperty ) + { + m_fetchScopeFromProperty = false; + FetchScope(); + FetchShaderProperties(); + } + + if( m_fetchPropertyId ) + { + m_fetchPropertyId = false; + FetchPropertyId(); + } + + if( m_currentPropertyIdx > -1 ) + { + EditorGUI.BeginChangeCheck(); + m_currentPropertyIdx = m_upperLeftWidgetHelper.DrawWidget( this, m_currentPropertyIdx, m_propertyLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromId(); + } + } + } + + void FetchPropertyId() + { + if( m_shaderProperties != null ) + { + m_currentPropertyIdx = 0; + m_propertyLabels = new string[ m_shaderProperties.Count ]; + for( int i = 0; i < m_shaderProperties.Count; i++ ) + { + if( m_shaderProperties[ i ].PropertyName.Equals( m_propertyName ) ) + { + m_currentPropertyIdx = i; + } + m_propertyLabels[ i ] = m_shaderProperties[ i ].PropertyInspectorName; + } + UpdateFromId(); + } + else + { + m_currentPropertyIdx = -1; + } + } + + void UpdateFromId() + { + + if( m_shaderProperties != null ) + { + if( m_shaderProperties.Count == 0 ) + { + for( int i = 0; i < 4; i++ ) + m_containerGraph.DeleteConnection( false, UniqueId, i, false, true ); + + m_headerColor = UIUtils.GetColorFromCategory( "Default" ); + m_content.text = "None"; + m_additionalContent.text = string.Empty; + m_previewMaterialPassId = 1; + PreviewMaterial.SetFloat( FloatPropertyId, 0 ); + m_showPreview = false; + m_drawPreviewExpander = false; + m_outputPorts[ 0 ].ChangeProperties( "None", WirePortDataType.FLOAT, false ); + ConfigurePorts(); + return; + } + + m_drawPreviewExpander = true; + bool areCompatible = TemplateHelperFunctions.CheckIfCompatibles( m_outputPorts[ 0 ].DataType, m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType ); + switch( m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType ) + { + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + m_outputPorts[ 0 ].ChangeProperties( "Tex", m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType, false ); + m_headerColor = UIUtils.GetColorFromCategory( "Textures" ); + break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType, false ); + m_headerColor = UIUtils.GetColorFromCategory( "Constants And Properties" ); + break; + case WirePortDataType.FLOAT4: + m_outputPorts[ 0 ].ChangeProperties( "XYZW", m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType, false ); + m_headerColor = UIUtils.GetColorFromCategory( "Constants And Properties" ); + break; + case WirePortDataType.COLOR: + m_outputPorts[ 0 ].ChangeProperties( "RGBA", m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType, false ); + m_headerColor = UIUtils.GetColorFromCategory( "Constants And Properties" ); + break; + default: + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + m_outputPorts[ 0 ].ChangeProperties( "Out", m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType, false ); + m_headerColor = UIUtils.GetColorFromCategory( "Constants And Properties" ); + break; + } + + if( !areCompatible ) + { + for( int i = 0; i < 4; i++ ) + m_containerGraph.DeleteConnection( false, UniqueId, i, false, true ); + } + + ConfigurePorts(); + + m_propertyName = m_shaderProperties[ m_currentPropertyIdx ].PropertyName; + m_content.text = m_shaderProperties[ m_currentPropertyIdx ].PropertyInspectorName; + m_propertyNameId = Shader.PropertyToID( m_propertyName ); + m_typeName = TypeLabelStr + m_shaderProperties[ m_currentPropertyIdx ].PropertyType.ToString(); + if( m_shaderProperties[ m_currentPropertyIdx ].PropertyType != PropertyType.Global ) + { + m_propertyNameLabel = PropertyNameStr + m_shaderProperties[ m_currentPropertyIdx ].PropertyName; + } + + m_sizeIsDirty = true; + Material currMat = m_containerGraph.CurrentMaterial; + if( currMat != null ) + { + if( m_shaderProperties[ m_currentPropertyIdx ].PropertyType == PropertyType.Global ) + { + m_previewMaterialPassId = 0; + if( !m_showErrorMessage && m_showPreview ) + { + ShowTab( NodeMessageType.Info, WarningStr ); + } + } + else + { + if( m_showErrorMessage && m_errorMessageTypeIsError != NodeMessageType.Error ) + { + HideTab(); + } + switch( m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType ) + { + case WirePortDataType.INT: m_previewMaterialPassId = 0; break; + case WirePortDataType.FLOAT: m_previewMaterialPassId = 1; break; + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: m_previewMaterialPassId = 2; break; + case WirePortDataType.SAMPLER2D: m_previewMaterialPassId = 3; break; + case WirePortDataType.SAMPLER3D: m_previewMaterialPassId = 4; break; + case WirePortDataType.SAMPLERCUBE: m_previewMaterialPassId = 5; break; + default: PreviewMaterial.SetPass( 0 ); break; + } + } + } + + CheckWarningState(); + } + } + + string GenerateTitle( params float[] values ) + { + //string finalResult = "( "; + string finalResult = string.Empty; + if( values.Length == 1 ) + { + finalResult += values[ 0 ].ToString( Mathf.Abs( values[ 0 ] ) > 1000 ? Constants.PropertyBigFloatFormatLabel : Constants.PropertyFloatFormatLabel ); + } + else + { + for( int i = 0; i < values.Length; i++ ) + { + finalResult += values[ i ].ToString( Mathf.Abs( values[ i ] ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel ); + if( i < ( values.Length - 1 ) ) + finalResult += ","; + } + } + //finalResult += " )"; + return finalResult; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.MasterNodeCategory != AvailableShaderTypes.Template ) + { + UIUtils.ShowMessage( UniqueId, "Template Parameter node is only intended for templates use only" ); + return m_outputPorts[ outputId ].ErrorValue; + } + + if( m_shaderProperties == null || m_shaderProperties.Count ==0 ) + { + UIUtils.ShowMessage( UniqueId, "Attempting to fetch inexistant parameter on " + m_nodeAttribs.Name +" node"); + return m_outputPorts[ outputId ].ErrorValue; + } + + if( m_multiPassMode ) + { + switch( m_currentScope ) + { + case ShaderPropertyScope.SubShader: + { + if( dataCollector.TemplateDataCollectorInstance.MultipassSubshaderIdx != SubShaderIdx ) + { + UIUtils.ShowMessage( UniqueId, string.Format( "{0} is only intended for subshader {1}", m_propertyLabels[ m_currentPropertyIdx ], SubShaderIdx ) ); + return m_outputPorts[ outputId ].ErrorValue; + } + } + break; + case ShaderPropertyScope.Pass: + { + if( dataCollector.TemplateDataCollectorInstance.MultipassSubshaderIdx != SubShaderIdx || + dataCollector.TemplateDataCollectorInstance.MultipassPassIdx != PassIdx + ) + { + UIUtils.ShowMessage( UniqueId, string.Format( "{0} is only intended for subshader {1} and pass {2}", m_propertyLabels[ m_currentPropertyIdx ], SubShaderIdx, PassIdx ) ); + return m_outputPorts[ outputId ].ErrorValue; + } + } + break; + } + } + + return GetOutputVectorItem( 0, outputId, m_propertyName ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_propertyName = GetCurrentParam( ref nodeParams ); + m_propertyNameId = Shader.PropertyToID( m_propertyName ); + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + m_currentScope = (ShaderPropertyScope)Enum.Parse( typeof( ShaderPropertyScope ), GetCurrentParam( ref nodeParams ) ); + } + else + { + m_fetchScopeFromProperty = true; + } + m_fetchPropertyId = true; + + if( UIUtils.CurrentShaderVersion() > 18502 ) + { + m_advancedView = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); + } + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_propertyName ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentScope ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_advancedView ); + + } + + public override void OnMasterNodeReplaced( MasterNode newMasterNode ) + { + base.OnMasterNodeReplaced( newMasterNode ); + if( newMasterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template ) + { + SetTemplate( newMasterNode ); + if( m_fetchScopeFromProperty ) + { + m_fetchScopeFromProperty = false; + FetchScope(); + } + FetchShaderProperties(); + FetchPropertyId(); + //m_containerGraph.DeleteConnection( false, UniqueId, 0, false, true ); + } + } + + bool SetTemplate( MasterNode newMasterNode ) + { + if( m_containerGraph.MultiPassMasterNodes.NodesList.Count > 0 ) + { + m_multiPassMode = true; + TemplateMultiPassMasterNode templateMasterNode = ( newMasterNode as TemplateMultiPassMasterNode ); + if( templateMasterNode != null ) + { + m_templateMPData = templateMasterNode.CurrentTemplate; + UpdateSubShaderAmount(); + FetchShaderProperties(); + return true; + } + } + else + { + m_multiPassMode = false; + TemplateMasterNode templateMasterNode = ( newMasterNode as TemplateMasterNode ); + if( templateMasterNode != null ) + { + m_shaderProperties = templateMasterNode.CurrentTemplate.AvailableShaderProperties; + return true; + } + } + return false; + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + CheckWarningState(); + } + + public override void Destroy() + { + base.Destroy(); + m_propertyLabels = null; + m_shaderProperties = null; + m_upperLeftWidgetHelper = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs.meta new file mode 100644 index 0000000..825090d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1579d32d6529f33418f210a5bd730436 +timeCreated: 1496398185 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs new file mode 100644 index 0000000..dac5c5c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs @@ -0,0 +1,173 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateSubShader + { + [SerializeField] + private int m_idx = -1; + + [SerializeField] + private List m_passes = new List(); + + [SerializeField] + private TemplateModulesData m_modules; + + [SerializeField] + private string m_uniquePrefix; + + [SerializeField] + private TemplatePropertyContainer m_templateProperties = new TemplatePropertyContainer(); + + [SerializeField] + private List m_availableShaderGlobals = new List(); + + [SerializeField] + private TemplateInfoContainer m_LODContainer = new TemplateInfoContainer(); + + [SerializeField] + private int m_passAmount = 0; + + [SerializeField] + private int m_mainPass = -1; + + [SerializeField] + private bool m_foundMainPassTag = false; + + [SerializeField] + TemplateOptionsContainer m_customOptionsContainer = new TemplateOptionsContainer(); + + public TemplateSubShader( TemplateMultiPass template , int subShaderIx , TemplateIdManager idManager , string uniquePrefix , TemplateSubShaderInfo subShaderInfo , ref Dictionary duplicatesHelper ) + { + m_idx = subShaderIx; + + m_uniquePrefix = uniquePrefix; + + FetchLOD( subShaderInfo.StartIdx , subShaderInfo.Modules ); + if( m_LODContainer.Index > -1 ) + { + idManager.RegisterId( m_LODContainer.Index , uniquePrefix + "Module" + m_LODContainer.Id , m_LODContainer.Id ); + } + + m_customOptionsContainer = TemplateOptionsToolsHelper.GenerateOptionsContainer( true , subShaderInfo.Data ); + if( m_customOptionsContainer.Enabled ) + { + idManager.RegisterId( m_customOptionsContainer.Index , uniquePrefix + m_customOptionsContainer.Body , m_customOptionsContainer.Body , true ); + } + + m_modules = new TemplateModulesData( m_customOptionsContainer , idManager , m_templateProperties , uniquePrefix + "Module" , subShaderInfo.StartIdx , subShaderInfo.Modules , true ); + if( m_modules.SRPType == TemplateSRPType.HD ) + { + m_modules.SRPIsPBR = subShaderInfo.Data.Contains( TemplateHelperFunctions.HDPBRTag ); + } + + Dictionary ownDuplicatesDict = new Dictionary( duplicatesHelper ); + + TemplateHelperFunctions.CreateShaderGlobalsList( subShaderInfo.Modules , ref m_availableShaderGlobals , ref ownDuplicatesDict , subShaderIx , -1 ); + if( m_modules.SRPType == TemplateSRPType.BuiltIn ) + { + TemplateHelperFunctions.CheckUnityBuiltinGlobalMacros( subShaderInfo.Modules , ref m_availableShaderGlobals , ref ownDuplicatesDict , subShaderIx , -1 ); + } + + m_passAmount = subShaderInfo.Passes.Count; + + //if( !m_modules.PassTag.IsValid ) + //{ + // m_modules.PassTag.StartIdx = subShaderData.Passes[ 0 ].GlobalStartIdx; + // m_templateProperties.AddId( subShaderData.Data, m_modules.PassTag.Id, subShaderData.Passes[ 0 ].LocalStartIdx, m_modules.PassTag.SearchIndentation ); + // m_modules.PassTag.StartIdx -= m_templateProperties.PropertyDict[ m_modules.PassTag.Id ].Indentation.Length; + // m_templateProperties.PropertyDict[ m_modules.PassTag.Id ].UseIndentationAtStart = true; + // idManager.RegisterId( m_modules.PassTag.StartIdx, m_modules.UniquePrefix + m_modules.PassTag.Id, string.Empty ); + //} + + int firstVisible = -1; + int currAddedPassIdx = 0; + for( int passIdx = 0 ; passIdx < m_passAmount ; passIdx++ ) + { + TemplatePass newPass = new TemplatePass( template , this , subShaderIx , passIdx , idManager , uniquePrefix + "Pass" + passIdx , subShaderInfo.Passes[ passIdx ].GlobalStartIdx , subShaderInfo.Passes[ passIdx ] , ref ownDuplicatesDict ); + if( newPass.AddToList ) + { + if( newPass.IsMainPass && m_mainPass < 0 ) + { + m_mainPass = currAddedPassIdx; + m_foundMainPassTag = true; + } + else if( !newPass.IsInvisible && firstVisible < 0 ) + { + firstVisible = currAddedPassIdx; + } + + m_passes.Add( newPass ); + currAddedPassIdx++; + } + else + { + newPass.Destroy(); + newPass = null; + } + + } + + if( m_mainPass < 0 ) + { + // If no main pass was set then choose the first visible one + m_mainPass = ( firstVisible < 0 ) ? 0 : firstVisible; + m_passes[ m_mainPass ].IsMainPass = true; + } + + ownDuplicatesDict.Clear(); + ownDuplicatesDict = null; + } + + public void Destroy() + { + m_LODContainer = null; + + m_customOptionsContainer = null; + + m_templateProperties.Destroy(); + m_templateProperties = null; + + m_passes.Clear(); + m_passes = null; + + m_modules.Destroy(); + m_modules = null; + + m_availableShaderGlobals.Clear(); + m_availableShaderGlobals = null; + + } + + void FetchLOD( int offsetIdx , string body ) + { + Match match = Regex.Match( body , TemplateHelperFunctions.SubShaderLODPattern ); + if( match != null && match.Groups.Count > 1 ) + { + m_LODContainer.Id = match.Groups[ 0 ].Value; + m_LODContainer.Data = match.Groups[ 1 ].Value; + m_LODContainer.Index = offsetIdx + match.Index; + } + } + + public List Passes { get { return m_passes; } } + public TemplateModulesData Modules { get { return m_modules; } } + public string UniquePrefix { get { return m_uniquePrefix; } } + public TemplatePropertyContainer TemplateProperties { get { return m_templateProperties; } } + public List AvailableShaderGlobals { get { return m_availableShaderGlobals; } } + public TemplateInfoContainer LODContainer { get { return m_LODContainer; } } + public int PassAmount { get { return m_passAmount; } } + public bool FoundMainPass { get { return m_foundMainPassTag; } } + public int MainPass { get { return m_mainPass; } } + public int Idx { get { return m_idx; } } + public TemplateOptionsContainer CustomOptionsContainer { get { return m_customOptionsContainer; } } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs.meta new file mode 100644 index 0000000..41a7886 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f4ff24a5a4c92f745a159f247574c07a +timeCreated: 1517854017 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs new file mode 100644 index 0000000..4bd19c6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs @@ -0,0 +1,465 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateTagsModule : TemplateModuleParent + { + private const string CustomTagsStr = "Tags"; + private const string TagNameStr = "Name"; + private const string TagValueStr = "Value"; + private const string QueueIndexStr = "Index"; + private const string QueueLabelStr = "Queue"; + private const string RenderTypeLabelStr = "Type"; + private const string CustomRenderTypeLabelStr = "Custom"; + + private const float ShaderKeywordButtonLayoutWidth = 15; + private UndoParentNode m_currentOwner; + + private double m_tagNameCheckTimestamp = 0; + private bool m_tagNameCheckFlag = true; + private int m_tagNameCheckItemId = 0; + private const double TagNameCheckMaxInterval = 1.5; + + [SerializeField] + private bool m_foldout = false; + + [SerializeField] + private List m_availableTags = new List(); + + private Dictionary m_availableTagsDict = new Dictionary(); + + public TemplateTagsModule() : base( "Tags" ) { } + + public void CopyFrom( TemplateTagsModule other ) + { + m_availableTags.Clear(); + m_availableTagsDict.Clear(); + + int count = other.AvailableTags.Count; + for( int i = 0; i < count; i++ ) + { + CustomTagData newData = new CustomTagData( other.AvailableTags[ i ] ); + m_availableTags.Add( newData ); + m_availableTagsDict.Add( newData.TagName, newData ); + } + } + + public void ConfigureFromTemplateData( TemplateTagsModuleData tagsData ) + { + bool newValidData = tagsData.DataCheck == TemplateDataCheck.Valid; + if( newValidData && newValidData != m_validData ) + { + m_availableTags.Clear(); + m_availableTagsDict.Clear(); + int count = tagsData.Tags.Count; + for( int i = 0; i < count; i++ ) + { + CustomTagData tagData = new CustomTagData( tagsData.Tags[ i ].Name, tagsData.Tags[ i ].Value, i ); + m_availableTags.Add( tagData ); + m_availableTagsDict.Add( tagsData.Tags[ i ].Name, tagData ); + } + } + m_validData = newValidData; + } + + public override void ShowUnreadableDataMessage( ParentNode owner ) + { + //bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedCustomTags; + NodeUtils.DrawPropertyGroup( ref m_foldout, CustomTagsStr, base.ShowUnreadableDataMessage ); + //owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedCustomTags = foldout; + } + + public void OnLogicUpdate() + { + if( m_tagNameCheckFlag && ( EditorApplication.timeSinceStartup - m_tagNameCheckTimestamp ) > TagNameCheckMaxInterval ) + { + m_tagNameCheckFlag = false; + if( m_tagNameCheckItemId < m_availableTags.Count ) + { + if( m_availableTags[ m_tagNameCheckItemId ].TagName.Equals( Constants.RenderQueueHelperStr ) ) + { + m_availableTags[ m_tagNameCheckItemId ].SpecialTag = TemplateSpecialTags.Queue; + } + else if( m_availableTags[ m_tagNameCheckItemId ].TagName.Equals( Constants.RenderTypeHelperStr ) ) + { + m_availableTags[ m_tagNameCheckItemId ].SpecialTag = TemplateSpecialTags.RenderType; + } + else if( m_availableTags[ m_tagNameCheckItemId ].TagName.Equals( Constants.DisableBatchingHelperStr ) ) + { + m_availableTags[ m_tagNameCheckItemId ].SpecialTag = TemplateSpecialTags.DisableBatching; + } + else + { + m_availableTags[ m_tagNameCheckItemId ].SpecialTag = TemplateSpecialTags.None; + } + } + } + } + + public override void Draw( UndoParentNode owner, bool style = true ) + { + m_currentOwner = owner; + //bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedCustomTags; + if( style ) + { + NodeUtils.DrawPropertyGroup( ref m_foldout, CustomTagsStr, DrawMainBody, DrawButtons ); + } + else + { + NodeUtils.DrawNestedPropertyGroup( ref m_foldout, CustomTagsStr, DrawMainBody, DrawButtons ); + } + //owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedCustomTags = foldout; + } + + void DrawButtons() + { + EditorGUILayout.Separator(); + + // Add tag + if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_availableTags.Add( new CustomTagData() ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove tag + if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + if( m_availableTags.Count > 0 ) + { + m_availableTags.RemoveAt( m_availableTags.Count - 1 ); + EditorGUI.FocusTextInControl( null ); + } + } + } + + void DrawMainBody() + { + EditorGUI.BeginChangeCheck(); + { + EditorGUILayout.Separator(); + int itemCount = m_availableTags.Count; + + if( itemCount == 0 ) + { + EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one.", MessageType.Info ); + } + + int markedToDelete = -1; + float originalLabelWidth = EditorGUIUtility.labelWidth; + for( int i = 0; i < itemCount; i++ ) + { + m_availableTags[ i ].TagFoldout = m_currentOwner.EditorGUILayoutFoldout( m_availableTags[ i ].TagFoldout, string.Format( "[{0}] - {1}", i, m_availableTags[ i ].TagName ) ); + if( m_availableTags[ i ].TagFoldout ) + { + EditorGUI.indentLevel += 1; + EditorGUIUtility.labelWidth = 70; + //Tag Name + EditorGUI.BeginChangeCheck(); + m_availableTags[ i ].TagName = m_currentOwner.EditorGUILayoutTextField( TagNameStr, m_availableTags[ i ].TagName ); + if( EditorGUI.EndChangeCheck() ) + { + m_availableTags[ i ].TagName = UIUtils.RemoveShaderInvalidCharacters( m_availableTags[ i ].TagName ); + m_tagNameCheckFlag = true; + m_tagNameCheckItemId = i; + m_tagNameCheckTimestamp = EditorApplication.timeSinceStartup; + } + + //Tag Value + switch( m_availableTags[ i ].SpecialTag ) + { + case TemplateSpecialTags.DisableBatching: + { + m_availableTags[ i ].Batching = (DisableBatching)m_currentOwner.EditorGUILayoutEnumPopup( RenderTypeLabelStr, m_availableTags[ i ].Batching ); + m_availableTags[ i ].TagValue = m_availableTags[ i ].Batching.ToString(); + } + break; + case TemplateSpecialTags.RenderType: + { + m_availableTags[ i ].RenderType = (RenderType)m_currentOwner.EditorGUILayoutEnumPopup( RenderTypeLabelStr, m_availableTags[ i ].RenderType ); + if( m_availableTags[ i ].RenderType == RenderType.Custom ) + { + m_availableTags[ i ].TagValue = m_currentOwner.EditorGUILayoutTextField( CustomRenderTypeLabelStr, m_availableTags[ i ].TagValue ); + } + } + break; + case TemplateSpecialTags.Queue: + { + + EditorGUI.BeginChangeCheck(); + m_availableTags[ i ].RenderQueue = (RenderQueue)m_currentOwner.EditorGUILayoutEnumPopup( QueueLabelStr, m_availableTags[ i ].RenderQueue, GUILayout.MinWidth( 150 ) ); + m_availableTags[ i ].RenderQueueOffset = m_currentOwner.EditorGUILayoutIntField( QueueIndexStr, m_availableTags[ i ].RenderQueueOffset ); + if( EditorGUI.EndChangeCheck() ) + { + m_availableTags[ i ].BuildQueueTagValue(); + } + + } + break; + case TemplateSpecialTags.None: + { + EditorGUI.BeginChangeCheck(); + m_availableTags[ i ].TagValue = m_currentOwner.EditorGUILayoutTextField( TagValueStr, m_availableTags[ i ].TagValue ); + if( EditorGUI.EndChangeCheck() ) + { + m_availableTags[ i ].TagValue = UIUtils.RemoveShaderInvalidCharacters( m_availableTags[ i ].TagValue ); + } + } + break; + + } + + EditorGUIUtility.labelWidth = originalLabelWidth; + + EditorGUILayout.BeginHorizontal(); + { + GUILayout.Label( " " ); + // Add new port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + m_availableTags.Insert( i + 1, new CustomTagData() ); + EditorGUI.FocusTextInControl( null ); + } + + //Remove port + if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) ) + { + markedToDelete = i; + } + } + EditorGUILayout.EndHorizontal(); + + EditorGUI.indentLevel -= 1; + } + + } + if( markedToDelete > -1 ) + { + if( m_availableTags.Count > markedToDelete ) + { + m_availableTags.RemoveAt( markedToDelete ); + EditorGUI.FocusTextInControl( null ); + } + } + EditorGUILayout.Separator(); + } + if( EditorGUI.EndChangeCheck() ) + { + m_isDirty = true; + } + } + + //Method used by template options + // As such. Render Queue will have value and offset separated by , + public void AddSpecialTag( TemplateSpecialTags tag, TemplateActionItem item ) + { + if( tag == TemplateSpecialTags.None ) + return; + + int count = m_availableTags.Count; + for( int i = 0; i < count; i++ ) + { + if( m_availableTags[ i ].SpecialTag == tag ) + { + switch( tag ) + { + case TemplateSpecialTags.DisableBatching: + { + m_availableTags[ i ].Batching = TemplateHelperFunctions.StringToDisableBatching[ item.ActionData ]; + return; + } + case TemplateSpecialTags.RenderType: + { + m_availableTags[ i ].RenderType = TemplateHelperFunctions.StringToRenderType[ item.ActionData ]; + return; + } + case TemplateSpecialTags.Queue: + { + + m_availableTags[ i ].RenderQueue = TemplateHelperFunctions.StringToRenderQueue[ item.ActionData ]; + m_availableTags[ i ].RenderQueueOffset = item.ActionDataIdx; + m_availableTags[ i ].BuildQueueTagValue(); + return; + } + } + } + } + + CustomTagData data = new CustomTagData(); + switch( tag ) + { + case TemplateSpecialTags.DisableBatching: + { + data.SpecialTag = TemplateSpecialTags.DisableBatching; + data.TagName = "DisableBatching"; + data.Batching = TemplateHelperFunctions.StringToDisableBatching[ item.ActionData ]; + } + break; + case TemplateSpecialTags.RenderType: + { + data.SpecialTag = TemplateSpecialTags.RenderType; + data.TagName = "RenderType"; + data.RenderType = TemplateHelperFunctions.StringToRenderType[ item.ActionData ]; + } + break; + case TemplateSpecialTags.Queue: + { + data.SpecialTag = TemplateSpecialTags.Queue; + data.TagName = "Queue"; + data.RenderQueue = TemplateHelperFunctions.StringToRenderQueue[ item.ActionData ]; + data.RenderQueueOffset = item.ActionDataIdx; + data.BuildQueueTagValue(); + } + break; + } + m_availableTags.Add( data ); + } + + void AddTagFromRead( string data ) + { + string[] arr = data.Split( IOUtils.VALUE_SEPARATOR ); + if( arr.Length > 1 ) + { + string name = arr[ 0 ]; + string value = arr[ 1 ]; + + if( !m_availableTagsDict.ContainsKey( name ) ) + { + CustomTagData tagData = new CustomTagData( data, m_availableTags.Count - 1 ); + m_availableTags.Add( tagData ); + m_availableTagsDict.Add( name, tagData ); + } + else + { + if( m_availableTagsDict[ name ].TagId > -1 && + m_availableTagsDict[ name ].TagId < m_availableTags.Count ) + { + if( arr.Length == 4 ) + { + m_availableTags[ m_availableTagsDict[ name ].TagId ].SetTagValue( value, arr[ 3 ] ); + } + else + { + m_availableTags[ m_availableTagsDict[ name ].TagId ].SetTagValue( value ); + } + + } + else + { + int count = m_availableTags.Count; + for( int i = 0; i < count; i++ ) + { + if( m_availableTags[ i ].TagName.Equals( name ) ) + { + m_availableTags[ i ].SetTagValue( value ); + } + } + } + } + } + } + + public override void ReadFromString( ref uint index, ref string[] nodeParams ) + { + bool validDataOnMeta = m_validData; + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( validDataOnMeta ) + { + int count = Convert.ToInt32( nodeParams[ index++ ] ); + for( int i = 0; i < count; i++ ) + { + AddTagFromRead( nodeParams[ index++ ] ); + } + } + } + + public override void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_validData ); + if( m_validData ) + { + int tagsCount = m_availableTags.Count; + IOUtils.AddFieldValueToString( ref nodeInfo, tagsCount ); + for( int i = 0; i < tagsCount; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_availableTags[ i ].ToString() ); + } + } + } + + public string GenerateTags() + { + int tagsCount = m_availableTags.Count; + if( tagsCount == 0 ) + return string.Empty; + + string result = "Tags { "; + + for( int i = 0; i < tagsCount; i++ ) + { + if( m_availableTags[ i ].IsValid ) + { + result += m_availableTags[ i ].GenerateTag(); + if( i < tagsCount - 1 ) + { + result += " "; + } + } + } + + result += " }"; + + return result; + } + + public override void Destroy() + { + m_availableTags.Clear(); + m_availableTags = null; + m_currentOwner = null; + m_availableTagsDict.Clear(); + m_availableTagsDict = null; + } + + public List AvailableTags { get { return m_availableTags; } } + + public bool HasRenderInfo( ref RenderType renderType, ref RenderQueue renderQueue ) + { + if( !m_validData ) + return false; + + bool foundRenderType = false; + bool foundRenderQueue = false; + int count = m_availableTags.Count; + for( int i = 0; i < count; i++ ) + { + if( m_availableTags[ i ].TagName.Equals( Constants.RenderTypeHelperStr ) ) + { + if( TemplateHelperFunctions.StringToRenderType.ContainsKey( m_availableTags[ i ].TagValue ) ) + { + renderType = TemplateHelperFunctions.StringToRenderType[ m_availableTags[ i ].TagValue ]; + foundRenderType = true; + } + } + else if( m_availableTags[ i ].TagName.Equals( Constants.RenderQueueHelperStr ) ) + { + string value = m_availableTags[ i ].TagValue.Split( '+' )[ 0 ].Split( '-' )[ 0 ]; + if( TemplateHelperFunctions.StringToRenderQueue.ContainsKey( value ) ) + { + renderQueue = TemplateHelperFunctions.StringToRenderQueue[ value ]; + foundRenderQueue = true; + } + } + } + return foundRenderType && foundRenderQueue; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs.meta new file mode 100644 index 0000000..b5888f7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 905b4a4de4a974a489d7a8aac14e4fcb +timeCreated: 1516719540 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs new file mode 100644 index 0000000..3b82e04 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs @@ -0,0 +1,190 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateVertexData + { + [SerializeField] + private TemplateSemantics m_semantics = TemplateSemantics.NONE; + [SerializeField] + private WirePortDataType m_dataType = WirePortDataType.OBJECT; + [SerializeField] + private string m_varName = string.Empty; + [SerializeField] + private TemplateInfoOnSematics m_dataInfo = TemplateInfoOnSematics.NONE; + [SerializeField] + private string m_dataSwizzle = string.Empty; + [SerializeField] + private bool m_available = false; + [SerializeField] + private string m_varNameWithSwizzle = string.Empty; + [SerializeField] + private bool m_isSingleComponent = true; + [SerializeField] + private bool m_excludeStructPrefix = false; + [SerializeField] + private string[] m_components = { "0", "0", "0", "0" }; + [SerializeField] + private bool[] m_componentUsage = { false, false,false,false }; + + public TemplateVertexData( TemplateSemantics semantics, WirePortDataType dataType, string varName ) + { + m_semantics = semantics; + m_dataType = dataType; + m_varName = varName; + m_varNameWithSwizzle = varName; + } + + public TemplateVertexData( TemplateSemantics semantics, WirePortDataType dataType, string varName, string dataSwizzle ) + { + m_semantics = semantics; + m_dataType = dataType; + m_varName = varName; + m_dataSwizzle = dataSwizzle; + m_varNameWithSwizzle = varName + dataSwizzle; + } + + public TemplateVertexData( TemplateVertexData other ) + { + m_semantics = other.m_semantics; + m_dataType = other.m_dataType; + m_varName = other.m_varName; + m_dataInfo = other.m_dataInfo; + m_dataSwizzle = other.m_dataSwizzle; + m_available = other.m_available; + m_varNameWithSwizzle = other.m_varNameWithSwizzle; + m_isSingleComponent = other.IsSingleComponent; + m_excludeStructPrefix = other.ExcludeStructPrefix; + for( int i = 0; i < 4; i++ ) + { + m_components[ i ] = other.Components[ i ]; + } + } + + public void RegisterComponent( char channelId, string value ) + { + int channelIdInt = -1; + switch( channelId ) + { + case 'r': + case 'x': channelIdInt = 0; break; + case 'g': + case 'y': channelIdInt = 1; break; + case 'b': + case 'z': channelIdInt = 2; break; + case 'a': + case 'w': channelIdInt = 3; break; + } + + if( channelId < 0 ) + { + Debug.LogWarning( "Attempting to create interpolated data from invalid channel " + channelId ); + return; + } + + RegisterComponent( channelIdInt, value ); + } + + public void RegisterComponent( int channelId, string value ) + { + channelId = Mathf.Clamp( channelId, 0, 3 ); + m_components[ channelId ] = value; + m_componentUsage[ channelId ] = true; + m_isSingleComponent = false; + } + + public void BuildVar( PrecisionType precisionType = PrecisionType.Float ) + { + if( m_isSingleComponent ) + return; + WirePortDataType dataType = WirePortDataType.FLOAT; + if( m_componentUsage[ 3 ] ) + { + dataType = WirePortDataType.FLOAT4; + } + else if( m_componentUsage[ 2 ] ) + { + dataType = WirePortDataType.FLOAT3; + } + else if( m_componentUsage[ 1 ] ) + { + dataType = WirePortDataType.FLOAT2; + } + + string newVar = UIUtils.PrecisionWirePortToCgType( precisionType, dataType ); + newVar += "( "; + switch( dataType ) + { + default: newVar += "0"; break; + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + { + newVar += "{0}."+Components[ 0 ]; + } + break; + case WirePortDataType.FLOAT2: + { + newVar += "{0}." + Components[ 0 ] + ", " + + "{0}." + Components[ 1 ]; + } + break; + case WirePortDataType.FLOAT3: + { + newVar += "{0}." + Components[ 0 ] + ", " + + "{0}." + Components[ 1 ] + ", " + + "{0}." + Components[ 2 ]; + } + break; + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + { + newVar += "{0}." + Components[ 0 ] + ", " + + "{0}." + Components[ 1 ] + ", " + + "{0}." + Components[ 2 ] + ", " + + "{0}." + Components[ 3 ]; + } + break; + + } + newVar += " )"; + m_varName = newVar; + m_varNameWithSwizzle = newVar; + } + + public bool ExcludeStructPrefix { get { return m_excludeStructPrefix; } set { m_excludeStructPrefix = value; } } + public bool IsSingleComponent { get { return m_isSingleComponent; } } + public string[] Components { get { return m_components; } } + public TemplateSemantics Semantics { get { return m_semantics; } } + public WirePortDataType DataType { get { return m_dataType; } } + public string VarName { get { return m_varName; } set { m_varName = value; m_varNameWithSwizzle = value + m_dataSwizzle; } } + public string DataSwizzle { get { return m_dataSwizzle; } set { m_dataSwizzle = value; m_varNameWithSwizzle = m_varName + value; } } + public TemplateInfoOnSematics DataInfo { get { return m_dataInfo; } set { m_dataInfo = value; } } + public bool Available { get { return m_available; } set { m_available = value; } } + public string VarNameWithSwizzle { get { return m_varNameWithSwizzle; } } + public WirePortDataType SwizzleType + { + get + { + if ( string.IsNullOrEmpty( m_dataSwizzle ) ) + return m_dataType; + + WirePortDataType newType = m_dataType; + switch ( m_dataSwizzle.Length ) + { + case 2: newType = WirePortDataType.FLOAT;break; + case 3: newType = WirePortDataType.FLOAT2; break; + case 4: newType = WirePortDataType.FLOAT3; break; + case 5: newType = WirePortDataType.FLOAT4; break; + } + + return newType; + } + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs.meta new file mode 100644 index 0000000..d457534 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d11e7a9026804bd46962c527fe30d933 +timeCreated: 1496053368 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs new file mode 100644 index 0000000..187c32f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs @@ -0,0 +1,278 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Template Vertex Data", "Vertex Data", "Select and use available vertex data from the template" )] + public class TemplateVertexDataNode : TemplateNodeParent + { + private List m_interpolatorData = null; + + [SerializeField] + private int m_currentDataIdx = -1; + + [SerializeField] + private string m_dataName = string.Empty; + [SerializeField] + private string m_inVarName = string.Empty; + + private string[] m_dataLabels = null; + + private bool m_fetchDataId = false; + private UpperLeftWidgetHelper m_upperLeftWidgetHelper = new UpperLeftWidgetHelper(); + + protected override void CommonInit( int uniqueId ) + { + base.CommonInit( uniqueId ); + m_autoWrapProperties = true; + } + + void FetchDataId() + { + if( m_interpolatorData != null ) + { + m_currentDataIdx = 0; + int count = m_interpolatorData.Count; + m_dataLabels = new string[ count ]; + for( int i = 0; i < count; i++ ) + { + m_dataLabels[ i ] = m_interpolatorData[ i ].VarName; + if( m_interpolatorData[ i ].VarName.Equals( m_dataName ) ) + { + m_currentDataIdx = i; + } + } + UpdateFromId(); + } + else + { + m_currentDataIdx = -1; + } + } + + void UpdateFromId() + { + if( m_interpolatorData != null ) + { + if( m_interpolatorData.Count == 0 ) + { + for( int i = 0; i < 4; i++ ) + m_containerGraph.DeleteConnection( false, UniqueId, i, false, true ); + + m_headerColor = UIUtils.GetColorFromCategory( "Default" ); + m_content.text = "None"; + m_additionalContent.text = string.Empty; + m_outputPorts[ 0 ].ChangeProperties( "None", WirePortDataType.OBJECT, false ); + ConfigurePorts(); + return; + } + + bool areCompatible = TemplateHelperFunctions.CheckIfCompatibles( m_outputPorts[ 0 ].DataType, m_interpolatorData[ m_currentDataIdx ].DataType ); + switch( m_interpolatorData[ m_currentDataIdx ].DataType ) + { + default: + case WirePortDataType.INT: + case WirePortDataType.FLOAT: + m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, m_interpolatorData[ m_currentDataIdx ].DataType, false ); + break; + case WirePortDataType.FLOAT2: + m_outputPorts[ 0 ].ChangeProperties( "XY", m_interpolatorData[ m_currentDataIdx ].DataType, false ); + break; + case WirePortDataType.FLOAT3: + m_outputPorts[ 0 ].ChangeProperties( "XYZ", m_interpolatorData[ m_currentDataIdx ].DataType, false ); + break; + case WirePortDataType.FLOAT4: + m_outputPorts[ 0 ].ChangeProperties( "XYZW", m_interpolatorData[ m_currentDataIdx ].DataType, false ); + break; + case WirePortDataType.COLOR: + m_outputPorts[ 0 ].ChangeProperties( "RGBA", m_interpolatorData[ m_currentDataIdx ].DataType, false ); + break; + } + + ConfigurePorts(); + + if( !areCompatible ) + { + m_containerGraph.DeleteConnection( false, UniqueId, 0, false, true ); + } + + m_dataName = m_interpolatorData[ m_currentDataIdx ].VarName; + m_content.text = m_dataName; + m_sizeIsDirty = true; + CheckWarningState(); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + if( m_multiPassMode ) + { + DrawMultipassProperties(); + } + + if( m_currentDataIdx > -1 ) + { + EditorGUI.BeginChangeCheck(); + m_currentDataIdx = EditorGUILayoutPopup( DataLabelStr, m_currentDataIdx, m_dataLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromId(); + } + } + } + protected override void OnSubShaderChange() + { + FetchInterpolator(); + FetchDataId(); + } + + protected override void OnPassChange() + { + FetchInterpolator(); + FetchDataId(); + } + + void DrawMultipassProperties() + { + DrawSubShaderUI(); + DrawPassUI(); + } + + public override void Draw( DrawInfo drawInfo ) + { + base.Draw( drawInfo ); + if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader ) + return; + + if( m_interpolatorData == null || m_interpolatorData.Count == 0 ) + { + MasterNode masterNode = m_containerGraph.CurrentMasterNode; + FetchInterpolator( masterNode ); + } + + if( m_fetchDataId ) + { + m_fetchDataId = false; + FetchDataId(); + } + + if( m_currentDataIdx > -1 ) + { + EditorGUI.BeginChangeCheck(); + m_currentDataIdx = m_upperLeftWidgetHelper.DrawWidget( this, m_currentDataIdx, m_dataLabels ); + if( EditorGUI.EndChangeCheck() ) + { + UpdateFromId(); + } + } + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + if( dataCollector.MasterNodeCategory != AvailableShaderTypes.Template ) + { + UIUtils.ShowMessage( UniqueId, "Template Vertex Data node is only intended for templates use only" ); + return m_outputPorts[ 0 ].ErrorValue; + } + + if( dataCollector.IsFragmentCategory ) + { + UIUtils.ShowMessage( UniqueId, "Template Vertex Data node node is only intended for vertex use use only" ); + return m_outputPorts[ 0 ].ErrorValue; + } + + if( m_multiPassMode ) + { + if( dataCollector.TemplateDataCollectorInstance.MultipassSubshaderIdx != SubShaderIdx || + dataCollector.TemplateDataCollectorInstance.MultipassPassIdx != PassIdx + ) + { + UIUtils.ShowMessage( UniqueId, string.Format( "{0} is only intended for subshader {1} and pass {2}", m_dataLabels[ m_currentDataIdx ], SubShaderIdx, PassIdx ) ); + return m_outputPorts[ outputId ].ErrorValue; + } + } + + return GetOutputVectorItem( 0, outputId, m_inVarName + m_dataName ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_dataName = GetCurrentParam( ref nodeParams ); + m_fetchDataId = true; + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_dataName ); + } + + protected override bool ValidatePass( int passIdx ) + { + return ( m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ passIdx ].VertexFunctionData != null && + m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ passIdx ].VertexDataContainer != null ); + } + + void FetchInterpolator( MasterNode masterNode = null ) + { + FetchMultiPassTemplate( masterNode ); + if( m_multiPassMode ) + { + if( m_templateMPData != null ) + { + m_inVarName = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].VertexFunctionData.InVarName + "."; + m_interpolatorData = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].VertexDataContainer.VertexData; + m_fetchDataId = true; + } + } + else + { + if( masterNode == null ) + masterNode = m_containerGraph.CurrentMasterNode; + + TemplateData currentTemplate = ( masterNode as TemplateMasterNode ).CurrentTemplate; + if( currentTemplate != null ) + { + m_inVarName = currentTemplate.VertexFunctionData.InVarName + "."; + m_interpolatorData = currentTemplate.VertexDataList; + m_fetchDataId = true; + } + else + { + m_interpolatorData = null; + m_currentDataIdx = -1; + } + } + } + + public override void OnMasterNodeReplaced( MasterNode newMasterNode ) + { + base.OnMasterNodeReplaced( newMasterNode ); + if( newMasterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template ) + { + FetchInterpolator( newMasterNode ); + } + else + { + m_interpolatorData = null; + m_currentDataIdx = -1; + } + } + + public override void Destroy() + { + base.Destroy(); + m_dataLabels = null; + m_interpolatorData = null; + m_upperLeftWidgetHelper = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs.meta new file mode 100644 index 0000000..e697d68 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5eb32f2452052fb43b6b93c9baa8f02f +timeCreated: 1506610215 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs new file mode 100644 index 0000000..fa435aa --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs @@ -0,0 +1,756 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + [Serializable] + public sealed class TemplatesBlendModule : TemplateModuleParent + { + private const string AlphaToMaskStr = "Alpha To Coverage"; + private const string BlendModeStr = " Blend Mode"; + + private const string BlendModesRGBStr = "Blend RGB"; + private const string BlendModesAlphaStr = "Blend Alpha"; + + private const string BlendOpsRGBStr = "Blend Op RGB"; + private const string BlendOpsAlphaStr = "Blend Op Alpha"; + + private const string SourceFactorStr = "Src"; + private const string DstFactorStr = "Dst"; + + private const string AlphaToMaskFormat = "AlphaToMask {0}"; + private const string BlendFactorOff = "Blend Off"; + private const string SingleBlendFactorStr = "Blend{0} {1} {2}"; + private const string SeparateBlendFactorStr = "Blend{0} {1} {2}, {3} {4}"; + + private const string SingleBlendOpStr = "BlendOp{0} {1}"; + private const string SeparateBlendOpStr = "BlendOp{0} {1}, {2}"; + private const string BlendOpOffStr = "BlendOp Off"; + + + private string[] m_commonBlendTypesArr; + private List m_commonBlendTypes = new List + { + new CommonBlendTypes("", AvailableBlendFactor.Zero, AvailableBlendFactor.Zero ), + new CommonBlendTypes("Custom", AvailableBlendFactor.Zero, AvailableBlendFactor.Zero ) , + new CommonBlendTypes("Alpha Blend", AvailableBlendFactor.SrcAlpha, AvailableBlendFactor.OneMinusSrcAlpha ) , + new CommonBlendTypes("Premultiplied", AvailableBlendFactor.One, AvailableBlendFactor.OneMinusSrcAlpha ), + new CommonBlendTypes("Additive", AvailableBlendFactor.One, AvailableBlendFactor.One ), + new CommonBlendTypes("Soft Additive", AvailableBlendFactor.OneMinusDstColor, AvailableBlendFactor.One ), + new CommonBlendTypes("Multiplicative", AvailableBlendFactor.DstColor, AvailableBlendFactor.Zero ), + new CommonBlendTypes("2x Multiplicative", AvailableBlendFactor.DstColor, AvailableBlendFactor.SrcColor ), + new CommonBlendTypes("Particle Additive", AvailableBlendFactor.SrcAlpha, AvailableBlendFactor.One ) + }; + + [SerializeField] + private string m_target = string.Empty; + + [SerializeField] + private bool m_validBlendMode = false; + + [SerializeField] + private bool m_validBlendOp = false; + + [SerializeField] + private bool m_blendModeEnabled = false; + + // Blend Factor + // RGB + [SerializeField] + private int m_currentRGBIndex = 0; + + [SerializeField] + private AvailableBlendFactor m_sourceFactorRGB = AvailableBlendFactor.Zero; + [SerializeField] + private InlineProperty m_sourceFactorRGBInline = new InlineProperty(); + + [SerializeField] + private AvailableBlendFactor m_destFactorRGB = AvailableBlendFactor.Zero; + [SerializeField] + private InlineProperty m_destFactorRGBInline = new InlineProperty(); + + //Alpha + [SerializeField] + private int m_currentAlphaIndex = 0; + + [SerializeField] + private AvailableBlendFactor m_sourceFactorAlpha = AvailableBlendFactor.Zero; + [SerializeField] + private InlineProperty m_sourceFactorAlphaInline = new InlineProperty(); + + [SerializeField] + private AvailableBlendFactor m_destFactorAlpha = AvailableBlendFactor.Zero; + [SerializeField] + private InlineProperty m_destFactorAlphaInline = new InlineProperty(); + + //Blend Ops + [SerializeField] + private bool m_blendOpEnabled = false; + + [SerializeField] + private AvailableBlendOps m_blendOpRGB = AvailableBlendOps.OFF; + + [SerializeField] + private InlineProperty m_blendOpRGBInline = new InlineProperty(); + + [SerializeField] + private AvailableBlendOps m_blendOpAlpha = AvailableBlendOps.OFF; + + [SerializeField] + private InlineProperty m_blendOpAlphaInline = new InlineProperty(); + + public TemplatesBlendModule() : base( "Blend Mode and Ops" ) + { + m_commonBlendTypesArr = new string[ m_commonBlendTypes.Count ]; + for( int i = 0; i < m_commonBlendTypesArr.Length; i++ ) + { + m_commonBlendTypesArr[ i ] = m_commonBlendTypes[ i ].Name; + } + } + + public void CopyFrom( TemplatesBlendModule other, bool allData ) + { + if( allData ) + { + m_independentModule = other.IndependentModule; + m_validBlendMode = other.ValidBlendMode; + m_target = other.Target; + m_validBlendOp = other.ValidBlendOp; + } + m_blendModeEnabled = other.BlendModeEnabled; + m_currentRGBIndex = other.CurrentRGBIndex; + m_sourceFactorRGB = other.SourceFactorRGB; + m_destFactorRGB = other.DestFactorRGB; + m_currentAlphaIndex = other.CurrentAlphaIndex; + m_sourceFactorAlpha = other.SourceFactorAlpha; + m_destFactorAlpha = other.DestFactorAlpha; + m_blendOpEnabled = other.BlendOpEnabled; + m_blendOpRGB = other.BlendOpRGB; + m_blendOpAlpha = other.BlendOpAlpha; + m_sourceFactorRGBInline = other.SourceFactorRGBInline; + m_destFactorRGBInline = other.DestFactorRGBInline; + m_sourceFactorAlphaInline = other.SourceFactorAlphaInline; + m_destFactorAlphaInline = other.DestFactorAlphaInline; + m_blendOpRGBInline = other.BlendOpRGBInline; + m_blendOpAlphaInline = other.BlendOpAlphaInline; + } + + public void ConfigureFromTemplateData( TemplateBlendData blendData ) + { + if( blendData.ValidBlendMode ) + { + if( m_validBlendMode != blendData.ValidBlendMode ) + { + m_blendModeEnabled = true; + m_independentModule = blendData.IndependentModule; + if( string.IsNullOrEmpty( blendData.SourceFactorRGBInline ) ) + { + m_sourceFactorRGB = blendData.SourceFactorRGB; + m_sourceFactorRGBInline.ResetProperty(); + } + else + { + m_sourceFactorRGBInline.SetInlineByName( blendData.SourceFactorRGBInline ); + } + + if( string.IsNullOrEmpty( blendData.DestFactorRGBInline ) ) + { + m_destFactorRGB = blendData.DestFactorRGB; + m_destFactorRGBInline.ResetProperty(); + } + else + { + m_destFactorRGBInline.SetInlineByName( blendData.DestFactorRGBInline ); + } + + if( string.IsNullOrEmpty( blendData.SourceFactorAlphaInline ) ) + { + m_sourceFactorAlpha = blendData.SourceFactorAlpha; + m_sourceFactorAlphaInline.ResetProperty(); + } + else + { + m_sourceFactorAlphaInline.SetInlineByName( blendData.SourceFactorAlphaInline ); + } + if( string.IsNullOrEmpty( blendData.DestFactorAlphaInline ) ) + { + m_destFactorAlpha = blendData.DestFactorAlpha; + m_destFactorAlphaInline.ResetProperty(); + } + else + { + m_destFactorAlphaInline.SetInlineByName( blendData.DestFactorAlphaInline ); + } + + if( blendData.SeparateBlendFactors ) + { + if( blendData.BlendModeOff ) + { + m_currentRGBIndex = 0; + } + else + { + CheckRGBIndex(); + } + CheckAlphaIndex(); + } + else + { + if( blendData.BlendModeOff ) + { + m_currentRGBIndex = 0; + } + else + { + CheckRGBIndex(); + } + m_currentAlphaIndex = 0; + } + } + } + else + { + m_blendModeEnabled = false; + } + + if( blendData.ValidBlendOp ) + { + if( m_validBlendOp != blendData.ValidBlendOp ) + { + m_blendOpEnabled = true; + if( string.IsNullOrEmpty( blendData.BlendOpRGBInline ) ) + { + m_blendOpRGB = blendData.BlendOpRGB; + m_blendOpRGBInline.ResetProperty(); + } + else + { + m_blendOpRGBInline.SetInlineByName( blendData.BlendOpRGBInline ); + } + + if( string.IsNullOrEmpty( blendData.BlendOpAlphaInline ) ) + { + m_blendOpAlpha = blendData.BlendOpAlpha; + m_blendOpAlphaInline.ResetProperty(); + } + else + { + m_blendOpAlphaInline.SetInlineByName( blendData.BlendOpAlphaInline ); + } + } + } + else + { + m_blendOpEnabled = false; + } + + m_target = blendData.Target; + m_validBlendMode = blendData.ValidBlendMode; + m_validBlendOp = blendData.ValidBlendOp; + m_validData = m_validBlendMode || m_validBlendOp; + } + + public override void ShowUnreadableDataMessage( ParentNode owner ) + { + bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedBlendModeModule; + NodeUtils.DrawPropertyGroup( ref foldout, BlendModeStr, base.ShowUnreadableDataMessage ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedBlendModeModule = foldout; + } + + public override void Draw( UndoParentNode owner, bool style = true ) + { + bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedBlendModeModule; + if( style ) + { + NodeUtils.DrawPropertyGroup( ref foldout, BlendModeStr + Target, () => + { + DrawBlock( owner, style ); + } ); + } + else + { + NodeUtils.DrawNestedPropertyGroup( ref foldout, BlendModeStr + Target, () => + { + DrawBlock( owner, style ); + } ); + } + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedBlendModeModule = foldout; + } + + void DrawBlock( UndoParentNode owner, bool style ) + { + EditorGUI.BeginChangeCheck(); + { + var cache = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = EditorGUIUtility.labelWidth - 20; + + if( m_blendModeEnabled ) + { + // RGB + EditorGUI.BeginChangeCheck(); + m_currentRGBIndex = owner.EditorGUILayoutPopup( BlendModesRGBStr, m_currentRGBIndex, m_commonBlendTypesArr ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_currentRGBIndex > 1 ) + { + m_sourceFactorRGB = m_commonBlendTypes[ m_currentRGBIndex ].SourceFactor; + m_sourceFactorRGBInline.IntValue = (int)m_sourceFactorRGB; + m_sourceFactorRGBInline.SetInlineNodeValue(); + + m_destFactorRGB = m_commonBlendTypes[ m_currentRGBIndex ].DestFactor; + m_destFactorRGBInline.IntValue = (int)m_destFactorRGB; + m_destFactorRGBInline.SetInlineNodeValue(); + } + } + EditorGUI.BeginDisabledGroup( m_currentRGBIndex == 0 ); + + EditorGUI.BeginChangeCheck(); + float cached = EditorGUIUtility.labelWidth; + if( style ) + { + EditorGUIUtility.labelWidth = 40; + } + else + { + EditorGUIUtility.labelWidth = 25; + } + + EditorGUILayout.BeginHorizontal(); + //m_sourceFactorRGB = (AvailableBlendFactor)owner.EditorGUILayoutEnumPopup( SourceFactorStr, m_sourceFactorRGB ); + m_sourceFactorRGBInline.CustomDrawer( ref owner, ( x ) => { m_sourceFactorRGB = (AvailableBlendFactor)x.EditorGUILayoutEnumPopup( SourceFactorStr, m_sourceFactorRGB ); }, SourceFactorStr ); + if( style ) + { + EditorGUI.indentLevel--; + EditorGUIUtility.labelWidth = 25; + } + //m_destFactorRGB = (AvailableBlendFactor)owner.EditorGUILayoutEnumPopup( DstFactorStr, m_destFactorRGB ); + m_destFactorRGBInline.CustomDrawer( ref owner, ( x ) => { m_destFactorRGB = (AvailableBlendFactor)x.EditorGUILayoutEnumPopup( DstFactorStr, m_destFactorRGB ); }, DstFactorStr ); + if( style ) + EditorGUI.indentLevel++; + + EditorGUILayout.EndHorizontal(); + + EditorGUIUtility.labelWidth = cached; + if( EditorGUI.EndChangeCheck() ) + { + CheckRGBIndex(); + } + EditorGUI.EndDisabledGroup(); + } + + if( m_blendOpEnabled ) + { + // Both these tests should be removed on a later stage + // ASE v154dev004 changed AvailableBlendOps.OFF value from -1 to 0 + // If importing the new package into an already opened ASE window makes + // hotcode to preserve the -1 value on these variables + if( (int)m_blendOpRGB == -1 ) + m_blendOpRGB = AvailableBlendOps.OFF; + + //m_blendOpRGB = (AvailableBlendOps)owner.EditorGUILayoutEnumPopup( BlendOpsRGBStr, m_blendOpRGB ); + m_blendOpRGBInline.CustomDrawer( ref owner, ( x ) => { m_blendOpRGB = (AvailableBlendOps)x.EditorGUILayoutPopup( BlendOpsRGBStr, (int)m_blendOpRGB, BlendOpsHelper.BlendOpsLabels ); }, BlendOpsRGBStr ); + } + + if( m_blendModeEnabled ) + { + // Alpha + EditorGUILayout.Separator(); + + EditorGUI.BeginChangeCheck(); + m_currentAlphaIndex = owner.EditorGUILayoutPopup( BlendModesAlphaStr, m_currentAlphaIndex, m_commonBlendTypesArr ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_currentAlphaIndex > 0 ) + { + m_sourceFactorAlpha = m_commonBlendTypes[ m_currentAlphaIndex ].SourceFactor; + m_sourceFactorAlphaInline.IntValue = (int)m_sourceFactorAlpha; + m_sourceFactorAlphaInline.SetInlineNodeValue(); + + m_destFactorAlpha = m_commonBlendTypes[ m_currentAlphaIndex ].DestFactor; + m_destFactorAlphaInline.IntValue = (int)m_destFactorAlpha; + m_destFactorAlphaInline.SetInlineNodeValue(); + } + } + EditorGUI.BeginDisabledGroup( m_currentAlphaIndex == 0 ); + + EditorGUI.BeginChangeCheck(); + float cached = EditorGUIUtility.labelWidth; + if( style ) + { + EditorGUIUtility.labelWidth = 40; + } + else + { + EditorGUIUtility.labelWidth = 25; + } + EditorGUILayout.BeginHorizontal(); + //m_sourceFactorAlpha = (AvailableBlendFactor)owner.EditorGUILayoutEnumPopup( SourceFactorStr, m_sourceFactorAlpha ); + m_sourceFactorAlphaInline.CustomDrawer( ref owner, ( x ) => { m_sourceFactorAlpha = (AvailableBlendFactor)x.EditorGUILayoutEnumPopup( SourceFactorStr, m_sourceFactorAlpha ); }, SourceFactorStr ); + if( style ) + { + EditorGUI.indentLevel--; + EditorGUIUtility.labelWidth = 25; + } + //m_destFactorAlpha = (AvailableBlendFactor)owner.EditorGUILayoutEnumPopup( DstFactorStr, m_destFactorAlpha ); + m_destFactorAlphaInline.CustomDrawer( ref owner, ( x ) => { m_destFactorAlpha = (AvailableBlendFactor)x.EditorGUILayoutEnumPopup( DstFactorStr, m_destFactorAlpha ); }, DstFactorStr ); + if( style ) + EditorGUI.indentLevel++; + EditorGUILayout.EndHorizontal(); + EditorGUIUtility.labelWidth = cached; + + if( EditorGUI.EndChangeCheck() ) + { + CheckAlphaIndex(); + } + + EditorGUI.EndDisabledGroup(); + //EditorGUILayout.Separator(); + } + + if( m_blendOpEnabled ) + { + if( (int)m_blendOpAlpha == -1 ) + m_blendOpAlpha = AvailableBlendOps.OFF; + + //m_blendOpAlpha = (AvailableBlendOps)owner.EditorGUILayoutEnumPopup( BlendOpsAlphaStr, m_blendOpAlpha ); + m_blendOpAlphaInline.CustomDrawer( ref owner, ( x ) => { m_blendOpAlpha = (AvailableBlendOps)x.EditorGUILayoutPopup( BlendOpsAlphaStr, (int)m_blendOpAlpha, BlendOpsHelper.BlendOpsLabels ); }, BlendOpsAlphaStr ); + } + + EditorGUIUtility.labelWidth = cache; + } + + if( EditorGUI.EndChangeCheck() ) + { + m_isDirty = true; + CustomEdited = true; + } + } + + void CheckRGBIndex() + { + int count = m_commonBlendTypes.Count; + m_currentRGBIndex = 1; + for( int i = 1; i < count; i++ ) + { + if( m_commonBlendTypes[ i ].SourceFactor == m_sourceFactorRGB && m_commonBlendTypes[ i ].DestFactor == m_destFactorRGB ) + { + m_currentRGBIndex = i; + return; + } + } + + } + + void CheckAlphaIndex() + { + int count = m_commonBlendTypes.Count; + m_currentAlphaIndex = 1; + for( int i = 1; i < count; i++ ) + { + if( m_commonBlendTypes[ i ].SourceFactor == m_sourceFactorAlpha && m_commonBlendTypes[ i ].DestFactor == m_destFactorAlpha ) + { + m_currentAlphaIndex = i; + if( m_currentAlphaIndex > 0 && m_currentRGBIndex == 0 ) + m_currentRGBIndex = 1; + return; + } + } + + if( m_currentAlphaIndex > 0 && m_currentRGBIndex == 0 ) + m_currentRGBIndex = 1; + } + + public void ReadAlphaToMaskFromString( ref uint index, ref string[] nodeParams ) + { + //TODO: we should send this data to the alpha to mask module instead + if( UIUtils.CurrentShaderVersion() > 16102 && UIUtils.CurrentShaderVersion() <= 18103) + { + bool validAlphaToMask = Convert.ToBoolean( nodeParams[ index++ ] ); + if( validAlphaToMask ) + { + /*bool alphaToMaskValue = */Convert.ToBoolean( nodeParams[ index++ ] ); + } + } + } + + public void ReadBlendModeFromString( ref uint index, ref string[] nodeParams ) + { + bool validDataOnMeta = m_validBlendMode; + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( validDataOnMeta ) + { + if( UIUtils.CurrentShaderVersion() < 15304 ) + { + m_currentRGBIndex = Convert.ToInt32( nodeParams[ index++ ] ); + m_sourceFactorRGB = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), nodeParams[ index++ ] ); + m_destFactorRGB = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), nodeParams[ index++ ] ); + + m_currentAlphaIndex = Convert.ToInt32( nodeParams[ index++ ] ); + m_sourceFactorAlpha = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), nodeParams[ index++ ] ); + m_destFactorAlpha = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), nodeParams[ index++ ] ); + } + else + { + m_currentRGBIndex = Convert.ToInt32( nodeParams[ index++ ] ); + m_sourceFactorRGBInline.ReadFromString( ref index, ref nodeParams ); + m_sourceFactorRGB = (AvailableBlendFactor)m_sourceFactorRGBInline.IntValue; + m_destFactorRGBInline.ReadFromString( ref index, ref nodeParams ); + m_destFactorRGB = (AvailableBlendFactor)m_destFactorRGBInline.IntValue; + + m_currentAlphaIndex = Convert.ToInt32( nodeParams[ index++ ] ); + m_sourceFactorAlphaInline.ReadFromString( ref index, ref nodeParams ); + m_sourceFactorAlpha = (AvailableBlendFactor)m_sourceFactorAlphaInline.IntValue; + m_destFactorAlphaInline.ReadFromString( ref index, ref nodeParams ); + m_destFactorAlpha = (AvailableBlendFactor)m_destFactorAlphaInline.IntValue; + } + } + } + + public void ReadBlendOpFromString( ref uint index, ref string[] nodeParams ) + { + bool validDataOnMeta = m_validBlendOp; + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( validDataOnMeta ) + { + if( UIUtils.CurrentShaderVersion() < 15304 ) + { + m_blendOpRGB = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), nodeParams[ index++ ] ); + m_blendOpAlpha = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), nodeParams[ index++ ] ); + } + else + { + m_blendOpRGBInline.ReadFromString( ref index, ref nodeParams ); + m_blendOpAlphaInline.ReadFromString( ref index, ref nodeParams ); + + if( UIUtils.CurrentShaderVersion() < 15404 ) + { + // Now BlendOps enum starts at 0 and not -1 + m_blendOpRGBInline.FloatValue += 1; + m_blendOpAlphaInline.FloatValue += 1; + } + + m_blendOpRGB = (AvailableBlendOps)m_blendOpRGBInline.IntValue; + m_blendOpAlpha = (AvailableBlendOps)m_blendOpAlphaInline.IntValue; + } + //m_blendOpEnabled = ( m_blendOpRGB != AvailableBlendOps.OFF ); + } + } + + public void WriteBlendModeToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_validBlendMode ); + if( m_validBlendMode ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentRGBIndex ); + if( !m_sourceFactorRGBInline.IsValid ) m_sourceFactorRGBInline.IntValue = (int)m_sourceFactorRGB; + m_sourceFactorRGBInline.WriteToString( ref nodeInfo ); + + if( !m_destFactorRGBInline.IsValid ) m_destFactorRGBInline.IntValue = (int)m_destFactorRGB; + m_destFactorRGBInline.WriteToString( ref nodeInfo ); + + IOUtils.AddFieldValueToString( ref nodeInfo, m_currentAlphaIndex ); + if( !m_sourceFactorAlphaInline.IsValid ) m_sourceFactorAlphaInline.IntValue = (int)m_sourceFactorAlpha; + m_sourceFactorAlphaInline.WriteToString( ref nodeInfo ); + + if( !m_destFactorAlphaInline.IsValid ) m_destFactorAlphaInline.IntValue = (int)m_destFactorAlpha; + m_destFactorAlphaInline.WriteToString( ref nodeInfo ); + } + } + + public void WriteBlendOpToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_validBlendOp ); + if( m_validBlendOp ) + { + if( !m_blendOpRGBInline.IsValid ) m_blendOpRGBInline.IntValue = (int)m_blendOpRGB; + m_blendOpRGBInline.WriteToString( ref nodeInfo ); + + if( !m_blendOpAlphaInline.IsValid ) m_blendOpAlphaInline.IntValue = (int)m_blendOpAlpha; + m_blendOpAlphaInline.WriteToString( ref nodeInfo ); + } + } + + public override void ReadFromString( ref uint index, ref string[] nodeParams ) + { + base.ReadFromString( ref index, ref nodeParams ); + ReadBlendModeFromString( ref index, ref nodeParams ); + ReadBlendOpFromString( ref index, ref nodeParams ); + ReadAlphaToMaskFromString( ref index, ref nodeParams ); + } + + public override void WriteToString( ref string nodeInfo ) + { + base.WriteToString( ref nodeInfo ); + WriteBlendModeToString( ref nodeInfo ); + WriteBlendOpToString( ref nodeInfo ); + } + + public override void Destroy() + { + base.Destroy(); + m_sourceFactorRGBInline = null; + m_destFactorRGBInline = null; + m_sourceFactorAlphaInline = null; + m_destFactorAlphaInline = null; + m_blendOpRGBInline = null; + m_blendOpAlphaInline = null; + } + + public string CurrentBlendFactorSingle + { + get + { + return ( m_currentRGBIndex > 0 ) ? string.Format( SingleBlendFactorStr, m_target, m_sourceFactorRGBInline.GetValueOrProperty( m_sourceFactorRGB.ToString() ), m_destFactorRGBInline.GetValueOrProperty( m_destFactorRGB.ToString() ) ) : BlendFactorOff; + } + } + + public string CurrentBlendFactorSeparate + { + get + { + return string.Format( SeparateBlendFactorStr, m_target, + m_sourceFactorRGBInline.GetValueOrProperty( ( m_currentRGBIndex > 0 ? m_sourceFactorRGB.ToString() : AvailableBlendFactor.One.ToString() ) ), + m_destFactorRGBInline.GetValueOrProperty( m_currentRGBIndex > 0 ? m_destFactorRGB.ToString() : AvailableBlendFactor.Zero.ToString() ), + m_sourceFactorAlphaInline.GetValueOrProperty( m_sourceFactorAlpha.ToString() ), + m_destFactorAlphaInline.GetValueOrProperty( m_destFactorAlpha.ToString() ) ); + } + } + + public string CurrentBlendFactor + { + get + { + return ( ( m_currentAlphaIndex > 0 ) ? CurrentBlendFactorSeparate : CurrentBlendFactorSingle ); + } + } + + + public string CurrentBlendOpSingle + { + get + { + return ( m_blendOpRGB != AvailableBlendOps.OFF || m_blendOpRGBInline.IsValid ) ? string.Format( SingleBlendOpStr, Target, m_blendOpRGBInline.GetValueOrProperty( m_blendOpRGB.ToString() ) ) : string.Empty; + } + } + + public string CurrentBlendOpSeparate + { + get + { + return string.Format( SeparateBlendOpStr, Target, m_blendOpRGBInline.GetValueOrProperty( ( m_currentRGBIndex > 0 && m_blendOpRGB != AvailableBlendOps.OFF ) ? m_blendOpRGB.ToString() : AvailableBlendOps.Add.ToString() ), m_blendOpAlphaInline.GetValueOrProperty( m_blendOpAlpha.ToString() ) ); + } + } + + public string CurrentBlendOp { get { return ( ( m_blendOpAlpha != AvailableBlendOps.OFF || m_blendOpAlphaInline.IsValid ) ? CurrentBlendOpSeparate : CurrentBlendOpSingle ); } } + public bool Active { get { return m_blendModeEnabled && ( m_currentRGBIndex > 0 || m_currentAlphaIndex > 0 ); } } + public bool BlendOpActive + { + get + { + return m_blendOpEnabled && + ( + m_blendOpRGBInline.Active || + m_blendOpAlphaInline.Active || + ( !m_blendOpRGBInline.Active && m_blendOpRGB != AvailableBlendOps.OFF ) || + ( !m_blendOpAlphaInline.Active && m_blendOpAlpha != AvailableBlendOps.OFF ) ); + } + } + + public string Target { get { return m_target; } } + public bool ValidBlendMode { get { return m_validBlendMode; } } + public bool ValidBlendOp { get { return m_validBlendOp; } } + public int CurrentRGBIndex { get { return m_currentRGBIndex; } } + + public AvailableBlendFactor SourceFactorRGB + { + get { return m_sourceFactorRGB; } + set + { + m_sourceFactorRGB = value; + m_sourceFactorRGBInline.IntValue = (int)m_sourceFactorRGB; + m_sourceFactorRGBInline.Active = false; + } + + } + public AvailableBlendFactor DestFactorRGB + { + get { return m_destFactorRGB; } + set + { + m_destFactorRGB = value; + m_destFactorRGBInline.IntValue = (int)value; + } + } + + public int CurrentAlphaIndex { get { return m_currentAlphaIndex; } set { m_currentAlphaIndex = value; } } + + public AvailableBlendFactor SourceFactorAlpha + { + get { return m_sourceFactorAlpha; } + set + { + m_sourceFactorAlpha = value; + m_sourceFactorAlphaInline.IntValue = (int)value; + m_sourceFactorAlphaInline.Active = false; + } + } + + public AvailableBlendFactor DestFactorAlpha + { + get { return m_destFactorAlpha; } + set + { + m_destFactorAlpha = value; + m_destFactorAlphaInline.IntValue = (int)value; + m_destFactorAlphaInline.Active = false; + + } + } + + public bool BlendModeEnabled { get { return m_blendModeEnabled; } } + public bool BlendOpEnabled { get { return m_blendOpEnabled; } } + public AvailableBlendOps BlendOpRGB + { + get { return m_blendOpRGB; } + set + { + m_blendOpRGB = value; + m_blendOpRGBInline.IntValue = (int)value; + m_blendOpRGBInline.Active = false; + } + } + + public AvailableBlendOps BlendOpAlpha + { + get { return m_blendOpAlpha; } + set + { + m_blendOpAlpha = value; + m_blendOpAlphaInline.IntValue = (int)value; + m_blendOpAlphaInline.Active = false; + } + } + + public InlineProperty SourceFactorRGBInline { get { return m_sourceFactorRGBInline; } } + public InlineProperty DestFactorRGBInline { get { return m_destFactorRGBInline; } } + public InlineProperty SourceFactorAlphaInline { get { return m_sourceFactorAlphaInline; } } + public InlineProperty DestFactorAlphaInline { get { return m_destFactorAlphaInline; } } + public InlineProperty BlendOpRGBInline { get { return m_blendOpRGBInline; } } + public InlineProperty BlendOpAlphaInline { get { return m_blendOpAlphaInline; } } + public bool IsAdditiveRGB { get { return m_validBlendMode && m_blendModeEnabled && ( m_currentRGBIndex > 0 ) && ( m_sourceFactorRGB == AvailableBlendFactor.One ) && ( m_destFactorRGB == AvailableBlendFactor.One ); } } + public bool IsAlphaBlendRGB { get { return m_validBlendMode && m_blendModeEnabled && ( m_currentRGBIndex > 0 ) && ( m_sourceFactorRGB == AvailableBlendFactor.SrcAlpha ) && ( m_destFactorRGB == AvailableBlendFactor.OneMinusSrcAlpha ); } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs.meta new file mode 100644 index 0000000..b4eeb76 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7c88941c5badfb7428059cc3ff0c0df9 +timeCreated: 1510933946 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs new file mode 100644 index 0000000..9e53af9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs @@ -0,0 +1,937 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEditor; +using System.Collections.Generic; +using UnityEngine; +using System.Text.RegularExpressions; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TemplateInputData + { + public string PortName; + public WirePortDataType DataType; + public MasterNodePortCategory PortCategory; + public int PortUniqueId; + public int OrderId; + public int TagGlobalStartIdx; + public int TagLocalStartIdx; + public string TagId; + public string DefaultValue; + public string LinkId; + + public TemplateInputData( int tagLocalStartIdx, int tagGlobalStartIdx, string tagId, string portName, string defaultValue, WirePortDataType dataType, MasterNodePortCategory portCategory, int portUniqueId, int orderId, string linkId ) + { + DefaultValue = defaultValue; + PortName = portName; + DataType = dataType; + PortCategory = portCategory; + PortUniqueId = portUniqueId; + OrderId = orderId; + TagId = tagId; + TagGlobalStartIdx = tagGlobalStartIdx; + TagLocalStartIdx = tagLocalStartIdx; + LinkId = linkId; + } + + public TemplateInputData( TemplateInputData other ) + { + DefaultValue = other.DefaultValue; + PortName = other.PortName; + DataType = other.DataType; + PortCategory = other.PortCategory; + PortUniqueId = other.PortUniqueId; + OrderId = other.OrderId; + TagId = other.TagId; + TagGlobalStartIdx = other.TagGlobalStartIdx; + LinkId = other.LinkId; + } + } + + + + [Serializable] + public class TemplatePropertyContainer + { + [SerializeField] + private List m_propertyList = new List(); + private Dictionary m_propertyDict = new Dictionary(); + + + public void AddId( TemplateProperty templateProperty ) + { + BuildInfo(); + m_propertyList.Add( templateProperty ); + m_propertyDict.Add( templateProperty.Id, templateProperty ); + } + + public void AddId( string body, string ID, bool searchIndentation = true ) + { + AddId( body, ID, searchIndentation, string.Empty ); + } + + public void AddId( string body, string ID, bool searchIndentation, string customIndentation ) + { + BuildInfo(); + + int propertyIndex = body.IndexOf( ID ); + if( propertyIndex > -1 ) + { + if( searchIndentation ) + { + int identationIndex = -1; + for( int i = propertyIndex; i >= 0; i-- ) + { + if( body[ i ] == TemplatesManager.TemplateNewLine ) + { + identationIndex = i + 1; + break; + } + + if( i == 0 ) + { + identationIndex = 0; + } + } + if( identationIndex > -1 ) + { + int length = propertyIndex - identationIndex; + string indentation = ( length > 0 ) ? body.Substring( identationIndex, length ) : string.Empty; + TemplateProperty templateProperty = new TemplateProperty( ID, indentation, false ); + m_propertyList.Add( templateProperty ); + m_propertyDict.Add( templateProperty.Id, templateProperty ); + } + else + { + TemplateProperty templateProperty = new TemplateProperty( ID, string.Empty, false ); + m_propertyList.Add( templateProperty ); + m_propertyDict.Add( templateProperty.Id, templateProperty ); + } + } + else + { + TemplateProperty templateProperty = new TemplateProperty( ID, customIndentation, true ); + m_propertyList.Add( templateProperty ); + m_propertyDict.Add( templateProperty.Id, templateProperty ); + } + } + } + + + public void AddId( string body, string ID, int propertyIndex, bool searchIndentation ) + { + AddId( body, ID, propertyIndex, searchIndentation, string.Empty ); + } + + public void AddId( string body, string ID, int propertyIndex, bool searchIndentation, string customIndentation ) + { + if( body == null || string.IsNullOrEmpty( body ) ) + return; + + BuildInfo(); + if( searchIndentation && propertyIndex > -1 && propertyIndex < body.Length ) + { + int indentationIndex = -1; + for( int i = propertyIndex; i > 0; i-- ) + { + if( body[ i ] == TemplatesManager.TemplateNewLine ) + { + indentationIndex = i + 1; + break; + } + } + + if( indentationIndex > -1 ) + { + int length = propertyIndex - indentationIndex; + string indentation = ( length > 0 ) ? body.Substring( indentationIndex, length ) : string.Empty; + TemplateProperty templateProperty = new TemplateProperty( ID, indentation, false ); + m_propertyList.Add( templateProperty ); + m_propertyDict.Add( templateProperty.Id, templateProperty ); + } + } + else + { + TemplateProperty templateProperty = new TemplateProperty( ID, customIndentation, true ); + m_propertyList.Add( templateProperty ); + m_propertyDict.Add( templateProperty.Id, templateProperty ); + } + + } + public void BuildInfo() + { + if( m_propertyDict == null ) + { + m_propertyDict = new Dictionary(); + } + + if( m_propertyList.Count != m_propertyDict.Count ) + { + m_propertyDict.Clear(); + for( int i = 0; i < m_propertyList.Count; i++ ) + { + m_propertyDict.Add( m_propertyList[ i ].Id, m_propertyList[ i ] ); + } + } + } + + public void ResetTemplateUsageData() + { + BuildInfo(); + for( int i = 0; i < m_propertyList.Count; i++ ) + { + m_propertyList[ i ].Used = false; + } + } + + public void Reset() + { + m_propertyList.Clear(); + m_propertyDict.Clear(); + } + + public void Destroy() + { + m_propertyList.Clear(); + m_propertyList = null; + m_propertyDict.Clear(); + m_propertyDict = null; + } + + + public Dictionary PropertyDict + { + get + { + BuildInfo(); + return m_propertyDict; + } + } + public List PropertyList { get { return m_propertyList; } } + } + + [Serializable] + public class TemplateProperty + { + public bool UseIndentationAtStart = false; + public string Indentation; + public bool UseCustomIndentation; + public string Id; + public bool AutoLineFeed; + public bool Used; + + public TemplateProperty( string id, string indentation, bool useCustomIndentation ) + { + Id = id; + Indentation = indentation; + UseCustomIndentation = useCustomIndentation; + AutoLineFeed = !string.IsNullOrEmpty( indentation ); + Used = false; + } + } + + [Serializable] + public class TemplateTessVControlTag + { + public string Id; + public int StartIdx; + + public TemplateTessVControlTag() + { + StartIdx = -1; + } + + public bool IsValid { get { return StartIdx >= 0; } } + } + + [Serializable] + public class TemplateTessControlData + { + public string Id; + public int StartIdx; + public string InVarType; + public string InVarName; + public string OutVarType; + public string OutVarName; + + public bool IsValid { get { return StartIdx >= 0; } } + + public TemplateTessControlData() + { + StartIdx = -1; + } + + public TemplateTessControlData( int startIdx, string id, string inVarInfo, string outVarInfo ) + { + StartIdx = startIdx; + Id = id; + string[] inVarInfoArr = inVarInfo.Split( IOUtils.VALUE_SEPARATOR ); + if( inVarInfoArr.Length > 1 ) + { + InVarType = inVarInfoArr[ 1 ]; + InVarName = inVarInfoArr[ 0 ]; + } + + string[] outVarInfoArr = outVarInfo.Split( IOUtils.VALUE_SEPARATOR ); + if( outVarInfoArr.Length > 1 ) + { + OutVarType = outVarInfoArr[ 1 ]; + OutVarName = outVarInfoArr[ 0 ]; + } + } + + public string[] GenerateControl( Dictionary vertexData, List inputList ) + { + List value = new List(); + if( vertexData != null && vertexData.Count > 0 ) + { + foreach( var item in vertexData ) + { + if( inputList.FindIndex( x => { return x.Contains( item.Value.VarName ); } ) > -1 ) + value.Add( string.Format( "{0}.{1} = {2}.{1};", OutVarName, item.Value.VarName, InVarName ) ); + } + } + return value.ToArray(); + } + } + + [Serializable] + public class TemplateTessDomainData + { + public string Id; + public int StartIdx; + public string InVarType; + public string InVarName; + public string OutVarType; + public string OutVarName; + public string BaryVarType; + public string BaryVarName; + + public bool IsValid { get { return StartIdx >= 0; } } + + public TemplateTessDomainData() + { + StartIdx = -1; + } + + public TemplateTessDomainData( int startIdx, string id, string inVarInfo, string outVarInfo, string baryVarInfo ) + { + StartIdx = startIdx; + Id = id; + string[] inVarInfoArr = inVarInfo.Split( IOUtils.VALUE_SEPARATOR ); + if( inVarInfoArr.Length > 1 ) + { + InVarType = inVarInfoArr[ 1 ]; + InVarName = inVarInfoArr[ 0 ]; + } + + string[] outVarInfoArr = outVarInfo.Split( IOUtils.VALUE_SEPARATOR ); + if( outVarInfoArr.Length > 1 ) + { + OutVarType = outVarInfoArr[ 1 ]; + OutVarName = outVarInfoArr[ 0 ]; + } + + string[] baryVarInfoArr = baryVarInfo.Split( IOUtils.VALUE_SEPARATOR ); + if( baryVarInfoArr.Length > 1 ) + { + BaryVarType = baryVarInfoArr[ 1 ]; + BaryVarName = baryVarInfoArr[ 0 ]; + } + } + + public string[] GenerateDomain( Dictionary vertexData, List inputList ) + { + List value = new List(); + if( vertexData != null && vertexData.Count > 0 ) + { + foreach( var item in vertexData ) + { + //o.ase_normal = patch[0].ase_normal * bary.x + patch[1].ase_normal * bary.y + patch[2].ase_normal * bary.z; + if( inputList.FindIndex( x => { return x.Contains( item.Value.VarName ); } ) > -1 ) + value.Add( string.Format( "{0}.{1} = {2}[0].{1} * {3}.x + {2}[1].{1} * {3}.y + {2}[2].{1} * {3}.z;", OutVarName, item.Value.VarName, InVarName, BaryVarName ) ); + } + } + return value.ToArray(); + } + } + + [Serializable] + public class TemplateFunctionData + { + public int MainBodyLocalIdx; + public string MainBodyName; + + public string Id; + public int Position; + public string InVarType; + public string InVarName; + public string OutVarType; + public string OutVarName; + public MasterNodePortCategory Category; + public TemplateFunctionData( int mainBodyLocalIdx, string mainBodyName, string id, int position, string inVarInfo, string outVarInfo, MasterNodePortCategory category ) + { + MainBodyLocalIdx = mainBodyLocalIdx; + MainBodyName = mainBodyName; + Id = id; + Position = position; + { + string[] inVarInfoArr = inVarInfo.Split( IOUtils.VALUE_SEPARATOR ); + if( inVarInfoArr.Length > 1 ) + { + InVarType = inVarInfoArr[ 1 ]; + InVarName = inVarInfoArr[ 0 ]; + } + } + { + string[] outVarInfoArr = outVarInfo.Split( IOUtils.VALUE_SEPARATOR ); + if( outVarInfoArr.Length > 1 ) + { + OutVarType = outVarInfoArr[ 1 ]; + OutVarName = outVarInfoArr[ 0 ]; + } + } + Category = category; + } + } + + [Serializable] + public class TemplateTagData + { + public int StartIdx = -1; + public string Id; + public bool SearchIndentation; + public string CustomIndentation; + + + public TemplateTagData( int startIdx, string id, bool searchIndentation ) + { + StartIdx = startIdx; + Id = id; + SearchIndentation = searchIndentation; + CustomIndentation = string.Empty; + } + + public TemplateTagData( string id, bool searchIndentation ) + { + Id = id; + SearchIndentation = searchIndentation; + CustomIndentation = string.Empty; + } + + public TemplateTagData( string id, bool searchIndentation, string customIndentation ) + { + Id = id; + SearchIndentation = searchIndentation; + CustomIndentation = customIndentation; + } + + public bool IsValid { get { return StartIdx >= 0; } } + } + + public enum TemplatePortIds + { + Name = 0, + DataType, + UniqueId, + OrderId, + Link + } + + public enum TemplateCommonTagId + { + Property = 0, + Global = 1, + Function = 2, + Tag = 3, + Pragmas = 4, + Pass = 5, + Params_Vert = 6, + Params_Frag = 7 + //CullMode = 8, + //BlendMode = 9, + //BlendOp = 10, + //ColorMask = 11, + //StencilOp = 12 + } + + [Serializable] + public class TemplatesManager : ScriptableObject + { + public static int MPShaderVersion = 14503; + + public static readonly string TemplateShaderNameBeginTag = "/*ase_name*/"; + public static readonly string TemplateStencilTag = "/*ase_stencil*/\n"; + public static readonly string TemplateRenderPlatformsTag = "/*ase_render_platforms*/"; + public static readonly string TemplateAllModulesTag = "/*ase_all_modules*/\n"; + public static readonly string TemplateMPSubShaderTag = "\\bSubShader\\b\\s*{"; + //public static readonly string TemplateMPPassTag = "^\\s*Pass\b\\s*{";//"\\bPass\\b\\s*{"; + public static readonly string TemplateMPPassTag = "\\bPass\\b\\s*{"; + public static readonly string TemplateLocalVarTag = "/*ase_local_var*/"; + public static readonly string TemplateDependenciesListTag = "/*ase_dependencies_list*/"; + public static readonly string TemplatePragmaBeforeTag = "/*ase_pragma_before*/"; + public static readonly string TemplatePragmaTag = "/*ase_pragma*/"; + public static readonly string TemplatePassTag = "/*ase_pass*/"; + public static readonly string TemplatePassesEndTag = "/*ase_pass_end*/"; + public static readonly string TemplateLODsTag = "/*ase_lod*/"; + //public static readonly string TemplatePassTagPattern = @"\s\/\*ase_pass\*\/"; + public static readonly string TemplatePassTagPattern = @"\s\/\*ase_pass[:\*]+"; + public static readonly string TemplatePropertyTag = "/*ase_props*/"; + public static readonly string TemplateGlobalsTag = "/*ase_globals*/"; + public static readonly string TemplateSRPBatcherTag = "/*ase_srp_batcher*/\n"; + public static readonly string TemplateInterpolatorBeginTag = "/*ase_interp("; + public static readonly string TemplateVertexDataTag = "/*ase_vdata:"; + + public static readonly string TemplateTessVControlTag = "/*ase_vcontrol*/"; + public static readonly string TemplateTessControlCodeArea = "/*ase_control_code:"; + public static readonly string TemplateTessDomainCodeArea = "/*ase_domain_code:"; + + //public static readonly string TemplateExcludeFromGraphTag = "/*ase_hide_pass*/"; + public static readonly string TemplateMainPassTag = "/*ase_main_pass*/"; + + public static readonly string TemplateFunctionsTag = "/*ase_funcs*/\n"; + //public static readonly string TemplateTagsTag = "/*ase_tags*/"; + + //public static readonly string TemplateCullModeTag = "/*ase_cull_mode*/"; + //public static readonly string TemplateBlendModeTag = "/*ase_blend_mode*/"; + //public static readonly string TemplateBlendOpTag = "/*ase_blend_op*/"; + //public static readonly string TemplateColorMaskTag = "/*ase_color_mask*/"; + //public static readonly string TemplateStencilOpTag = "/*ase_stencil*/"; + + public static readonly string TemplateCodeSnippetAttribBegin = "#CODE_SNIPPET_ATTRIBS_BEGIN#"; + public static readonly string TemplateCodeSnippetAttribEnd = "#CODE_SNIPPET_ATTRIBS_END#\n"; + public static readonly string TemplateCodeSnippetEnd = "#CODE_SNIPPET_END#\n"; + + public static readonly char TemplateNewLine = '\n'; + + // INPUTS AREA + public static readonly string TemplateInputsVertBeginTag = "/*ase_vert_out:"; + public static readonly string TemplateInputsFragBeginTag = "/*ase_frag_out:"; + public static readonly string TemplateInputsVertParamsTag = "/*ase_vert_input*/"; + public static readonly string TemplateInputsFragParamsTag = "/*ase_frag_input*/"; + + + // CODE AREA + public static readonly string TemplateVertexCodeBeginArea = "/*ase_vert_code:"; + public static readonly string TemplateFragmentCodeBeginArea = "/*ase_frag_code:"; + + + public static readonly string TemplateEndOfLine = "*/\n"; + public static readonly string TemplateEndSectionTag = "*/"; + public static readonly string TemplateFullEndTag = "/*end*/"; + + public static readonly string NameFormatter = "\"{0}\""; + + public static readonly TemplateTagData[] CommonTags = { new TemplateTagData( TemplatePropertyTag,true), + new TemplateTagData( TemplateGlobalsTag,true), + new TemplateTagData( TemplateSRPBatcherTag,true), + new TemplateTagData( TemplateFunctionsTag,true), + //new TemplateTagData( TemplateTagsTag,false," "), + new TemplateTagData( TemplatePragmaBeforeTag,true), + new TemplateTagData( TemplatePragmaTag,true), + new TemplateTagData( TemplatePassTag,true), + new TemplateTagData( TemplateInputsVertParamsTag,false), + new TemplateTagData( TemplateInputsFragParamsTag,false), + new TemplateTagData( TemplateLODsTag,true) + //new TemplateTagData( TemplateCullModeTag,false), + //new TemplateTagData( TemplateBlendModeTag,false), + //new TemplateTagData( TemplateBlendOpTag,false), + //new TemplateTagData( TemplateColorMaskTag,false), + //new TemplateTagData( TemplateStencilOpTag,true), + }; + public static string LightweigthPBRGUID = "1976390536c6c564abb90fe41f6ee334"; + public static string LightweigthUnlitGUID = "e2514bdcf5e5399499a9eb24d175b9db"; + public static string UniversalPBRGUID = "94348b07e5e8bab40bd6c8a1e3df54cd"; + public static string UniversalUnlitGUID = "2992e84f91cbeb14eab234972e07ea9d"; + + public static string HDNewLitGUID = "53b46d85872c5b24c8f4f0a1c3fe4c87"; + public static string HDNewPBRGUID = "41e04be03f2c20941bc749271be1c937"; + public static string HDNewUnlitGUID = "7f5cb9c3ea6481f469fdd856555439ef"; + public static string HDLitGUID = "091c43ba8bd92c9459798d59b089ce4e"; + public static string HDPBRGUID = "bb308bce79762c34e823049efce65141"; + public static string HDUnlitGUID = "dfe2f27ac20b08c469b2f95c236be0c3"; + + public static Dictionary DeprecatedTemplates = new Dictionary() + { + { HDLitGUID, HDNewLitGUID}, + { HDUnlitGUID,HDNewUnlitGUID}, + { HDPBRGUID,HDNewLitGUID}, + { HDNewPBRGUID,HDNewLitGUID} + }; + + public static Dictionary OfficialTemplates = new Dictionary() + { + { "0770190933193b94aaa3065e307002fa","Legacy/Unlit"}, + { "32139be9c1eb75640a847f011acf3bcf","Legacy/Post-Processing Stack"}, + { "6ce779933eb99f049b78d6163735e06f","Legacy/Custom RT Init"}, + { "32120270d1b3a8746af2aca8bc749736","Legacy/Custom RT Update"}, + { LightweigthPBRGUID,"LW/PBR"}, + { LightweigthUnlitGUID,"LW/Unlit"}, + { UniversalPBRGUID,"Universal/PBR"}, + { UniversalUnlitGUID,"Universal/Unlit"}, + { "53b46d85872c5b24c8f4f0a1c3fe4c87","HD/Lit"}, + { HDLitGUID,"Deprecated/HD/Lit"}, + { HDPBRGUID,"Deprecated/HD/PBR"}, + { HDUnlitGUID,"Deprecated/HD/Unlit"}, + { "c71b220b631b6344493ea3cf87110c93","Legacy/Post Process" }, + { "6e114a916ca3e4b4bb51972669d463bf","Deprecated/Legacy/Default Unlit" }, + { "5056123faa0c79b47ab6ad7e8bf059a4","Legacy/Default UI" }, + { "899e609c083c74c4ca567477c39edef0","Legacy/Unlit Lightmap" }, + { "0f8ba0101102bb14ebf021ddadce9b49","Legacy/Default Sprites" }, + { "0b6a9f8b4f707c74ca64c0be8e590de0","Legacy/Particles Alpha Blended" }, + { "e1de45c0d41f68c41b2cc20c8b9c05ef","Legacy/Multi Pass Unlit" } + }; + + public static readonly string TemplateMenuItemsFileGUID = "da0b931bd234a1e43b65f684d4b59bfb"; + + private Dictionary m_availableTemplates = new Dictionary(); + + [SerializeField] + private List m_sortedTemplates = new List(); + + [SerializeField] + public string[] AvailableTemplateNames; + + [SerializeField] + public bool Initialized = false; + + private Dictionary m_optionsInitialSetup = new Dictionary(); + + public static string CurrTemplateGUIDLoaded = string.Empty; + + public static bool IsTestTemplate { get { return CurrTemplateGUIDLoaded.Equals( "a95a019bbc760714bb8228af04c291d1" ); } } + public static bool ShowDebugMessages = false; + public void RefreshAvailableTemplates() + { + if( m_availableTemplates.Count != m_sortedTemplates.Count ) + { + m_availableTemplates.Clear(); + int count = m_sortedTemplates.Count; + for( int i = 0; i < count; i++ ) + { + m_availableTemplates.Add( m_sortedTemplates[ i ].GUID, m_sortedTemplates[ i ] ); + } + } + } + + public void Init() + { + if( !Initialized ) + { + if( ShowDebugMessages ) + Debug.Log( "Initialize" ); + + string templateMenuItems = IOUtils.LoadTextFileFromDisk( AssetDatabase.GUIDToAssetPath( TemplateMenuItemsFileGUID ) ); + bool refreshTemplateMenuItems = false; + + foreach( KeyValuePair kvp in OfficialTemplates ) + { + if( !string.IsNullOrEmpty( AssetDatabase.GUIDToAssetPath( kvp.Key ) ) ) + { + TemplateMultiPass template = ScriptableObject.CreateInstance(); + template.Init( kvp.Value, kvp.Key, false ); + AddTemplate( template ); + if( !refreshTemplateMenuItems && templateMenuItems.IndexOf( kvp.Value ) < 0 ) + refreshTemplateMenuItems = true; + } + } + + // Search for other possible templates on the project + string[] allShaders = AssetDatabase.FindAssets( "t:shader" ); + for( int i = 0; i < allShaders.Length; i++ ) + { + if( !m_availableTemplates.ContainsKey( allShaders[ i ] ) ) + { + CheckAndLoadTemplate( allShaders[ i ] ); + } + } + + // TODO: Sort list alphabeticaly + AvailableTemplateNames = new string[ m_sortedTemplates.Count + 1 ]; + AvailableTemplateNames[ 0 ] = "Custom"; + for( int i = 0; i < m_sortedTemplates.Count; i++ ) + { + m_sortedTemplates[ i ].OrderId = i; + AvailableTemplateNames[ i + 1 ] = m_sortedTemplates[ i ].Name; + } + + if( refreshTemplateMenuItems ) + CreateTemplateMenuItems(); + + Initialized = true; + } + } + + //[MenuItem( "Window/Amplify Shader Editor/Create Menu Items", false, 1000 )] + //public static void ForceCreateTemplateMenuItems() + //{ + // UIUtils.CurrentWindow.TemplatesManagerInstance.CreateTemplateMenuItems(); + //} + + public void CreateTemplateMenuItems() + { + if( m_sortedTemplates == null || m_sortedTemplates.Count == 0 ) + return; + + // change names for duplicates + for( int i = 0; i < m_sortedTemplates.Count; i++ ) + { + for( int j = 0; j < i; j++ ) + { + if( m_sortedTemplates[ i ].Name == m_sortedTemplates[ j ].Name ) + { + var match = Regex.Match( m_sortedTemplates[ i ].Name, @".+(\d+)" ); + if( match.Success ) + { + string strNumber = match.Groups[ 1 ].Value; + int number = int.Parse( strNumber ) + 1; + string firstPart = m_sortedTemplates[ i ].Name.Substring( 0, match.Groups[ 1 ].Index ); + string secondPart = m_sortedTemplates[ i ].Name.Substring( match.Groups[ 1 ].Index + strNumber.Length ); + m_sortedTemplates[ i ].Name = firstPart + number + secondPart; + } + else + { + m_sortedTemplates[ i ].Name += " 1"; + } + } + } + } + + System.Text.StringBuilder fileContents = new System.Text.StringBuilder(); + fileContents.Append( "// Amplify Shader Editor - Visual Shader Editing Tool\n" ); + fileContents.Append( "// Copyright (c) Amplify Creations, Lda \n" ); + fileContents.Append( "using UnityEditor;\n" ); + fileContents.Append( "\n" ); + fileContents.Append( "namespace AmplifyShaderEditor\n" ); + fileContents.Append( "{\n" ); + fileContents.Append( "\tpublic class TemplateMenuItems\n" ); + fileContents.Append( "\t{\n" ); + int fixedPriority = 85; + for( int i = 0; i < m_sortedTemplates.Count; i++ ) + { + fileContents.AppendFormat( "\t\t[MenuItem( \"Assets/Create/Amplify Shader/{0}\", false, {1} )]\n", m_sortedTemplates[ i ].Name, fixedPriority ); + string itemName = UIUtils.RemoveInvalidCharacters( m_sortedTemplates[ i ].Name ); + fileContents.AppendFormat( "\t\tpublic static void ApplyTemplate{0}()\n", itemName/*i*/ ); + fileContents.Append( "\t\t{\n" ); + //fileContents.AppendFormat( "\t\t\tAmplifyShaderEditorWindow.CreateNewTemplateShader( \"{0}\" );\n", m_sortedTemplates[ i ].GUID ); + fileContents.AppendFormat( "\t\t\tAmplifyShaderEditorWindow.CreateConfirmationTemplateShader( \"{0}\" );\n", m_sortedTemplates[ i ].GUID ); + fileContents.Append( "\t\t}\n" ); + } + fileContents.Append( "\t}\n" ); + fileContents.Append( "}\n" ); + string filePath = AssetDatabase.GUIDToAssetPath( TemplateMenuItemsFileGUID ); + IOUtils.SaveTextfileToDisk( fileContents.ToString(), filePath, false ); + m_filepath = filePath; + //AssetDatabase.ImportAsset( filePath ); + } + + string m_filepath = string.Empty; + + public void ReimportMenuItems() + { + if( !string.IsNullOrEmpty( m_filepath ) ) + { + AssetDatabase.ImportAsset( m_filepath ); + m_filepath = string.Empty; + } + } + + public int GetIdForTemplate( TemplateData templateData ) + { + if( templateData == null ) + return -1; + + for( int i = 0; i < m_sortedTemplates.Count; i++ ) + { + if( m_sortedTemplates[ i ].GUID.Equals( templateData.GUID ) ) + return m_sortedTemplates[ i ].OrderId; + } + return -1; + } + + + + public void AddTemplate( TemplateDataParent templateData ) + { + if( templateData == null || !templateData.IsValid ) + return; + RefreshAvailableTemplates(); + if( !m_availableTemplates.ContainsKey( templateData.GUID ) ) + { + m_sortedTemplates.Add( templateData ); + m_availableTemplates.Add( templateData.GUID, templateData ); + } + } + + public void RemoveTemplate( string guid ) + { + TemplateDataParent templateData = GetTemplate( guid ); + if( templateData != null ) + { + RemoveTemplate( templateData ); + } + } + + public void RemoveTemplate( TemplateDataParent templateData ) + { + RefreshAvailableTemplates(); + + if( m_availableTemplates != null ) + m_availableTemplates.Remove( templateData.GUID ); + + m_sortedTemplates.Remove( templateData ); + templateData.Destroy(); + } + + public void Destroy() + { + if( TemplatesManager.ShowDebugMessages ) + Debug.Log( "Destroy Manager" ); + if( m_availableTemplates != null ) + { + foreach( KeyValuePair kvp in m_availableTemplates ) + { + kvp.Value.Destroy(); + } + m_availableTemplates.Clear(); + m_availableTemplates = null; + } + int count = m_sortedTemplates.Count; + + for( int i = 0; i < count; i++ ) + { + ScriptableObject.DestroyImmediate( m_sortedTemplates[ i ] ); + } + + m_sortedTemplates.Clear(); + m_sortedTemplates = null; + + AvailableTemplateNames = null; + Initialized = false; + } + + public TemplateDataParent GetTemplate( int id ) + { + if( id < m_sortedTemplates.Count ) + return m_sortedTemplates[ id ]; + + return null; + } + + public TemplateDataParent GetTemplate( string guid ) + { + RefreshAvailableTemplates(); + if( m_availableTemplates == null && m_sortedTemplates != null ) + { + m_availableTemplates = new Dictionary(); + for( int i = 0; i < m_sortedTemplates.Count; i++ ) + { + m_availableTemplates.Add( m_sortedTemplates[ i ].GUID, m_sortedTemplates[ i ] ); + } + } + + if( m_availableTemplates.ContainsKey( guid ) ) + return m_availableTemplates[ guid ]; + + return null; + } + + + public TemplateDataParent GetTemplateByName( string name ) + { + RefreshAvailableTemplates(); + if( m_availableTemplates == null && m_sortedTemplates != null ) + { + m_availableTemplates = new Dictionary(); + for( int i = 0; i < m_sortedTemplates.Count; i++ ) + { + m_availableTemplates.Add( m_sortedTemplates[ i ].GUID, m_sortedTemplates[ i ] ); + } + } + + foreach( KeyValuePair kvp in m_availableTemplates ) + { + if( kvp.Value.DefaultShaderName.Equals( name ) ) + { + return kvp.Value; + } + } + return null; + } + + public TemplateDataParent CheckAndLoadTemplate( string guid ) + { + TemplateDataParent templateData = GetTemplate( guid ); + if( templateData == null ) + { + string datapath = AssetDatabase.GUIDToAssetPath( guid ); + string body = IOUtils.LoadTextFileFromDisk( datapath ); + + if( body.IndexOf( TemplatesManager.TemplateShaderNameBeginTag ) > -1 ) + { + templateData = ScriptableObject.CreateInstance(); + templateData.Init( string.Empty, guid, true ); + if( templateData.IsValid ) + { + AddTemplate( templateData ); + return templateData; + } + } + } + + return null; + } + + private void OnEnable() + { + if( !Initialized ) + { + Init(); + } + else + { + RefreshAvailableTemplates(); + } + hideFlags = HideFlags.HideAndDontSave; + if( ShowDebugMessages ) + Debug.Log( "On Enable Manager: " + this.GetInstanceID() ); + } + + public void ResetOptionsSetupData() + { + if( ShowDebugMessages ) + Debug.Log( "Reseting options setup data" ); + m_optionsInitialSetup.Clear(); + } + + public bool SetOptionsValue( string optionId, bool value ) + { + if( m_optionsInitialSetup.ContainsKey( optionId ) ) + { + m_optionsInitialSetup[ optionId ] = m_optionsInitialSetup[ optionId ] || value; + } + else + { + m_optionsInitialSetup.Add( optionId, value ); + } + return m_optionsInitialSetup[ optionId ]; + } + + public bool CheckIfDeprecated( string guid , out string newGUID ) + { + if( DeprecatedTemplates.ContainsKey( guid ) ) + { + UIUtils.ShowMessage( "Shader using deprecated template which no longer exists on ASE. Pointing to new correct one, options and connections to master node were reset." ); + newGUID = DeprecatedTemplates[ guid ]; + return true; + } + newGUID = string.Empty; + return false; + } + + public int TemplateCount { get { return m_sortedTemplates.Count; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs.meta new file mode 100644 index 0000000..b49d069 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9f0aacdb47cf3b94ebbe9e72af9d3cf1 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs new file mode 100644 index 0000000..a8dd4d3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs @@ -0,0 +1,669 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + + [Serializable] + public sealed class TemplatesStencilBufferModule : TemplateModuleParent + { + private const string FoldoutLabelStr = " Stencil Buffer"; + private GUIContent ReferenceValueContent = new GUIContent( "Reference", "The value to be compared against (if Comparison is anything else than always) and/or the value to be written to the buffer (if either Pass, Fail or ZFail is set to replace)" ); + private GUIContent ReadMaskContent = new GUIContent( "Read Mask", "An 8 bit mask as an 0-255 integer, used when comparing the reference value with the contents of the buffer (referenceValue & readMask) comparisonFunction (stencilBufferValue & readMask)" ); + private GUIContent WriteMaskContent = new GUIContent( "Write Mask", "An 8 bit mask as an 0-255 integer, used when writing to the buffer" ); + private const string ComparisonStr = "Comparison"; + private const string PassStr = "Pass"; + private const string FailStr = "Fail"; + private const string ZFailStr = "ZFail"; + + private const string ComparisonFrontStr = "Comp. Front"; + private const string PassFrontStr = "Pass Front"; + private const string FailFrontStr = "Fail Front"; + private const string ZFailFrontStr = "ZFail Front"; + + private const string ComparisonBackStr = "Comp. Back"; + private const string PassBackStr = "Pass Back"; + private const string FailBackStr = "Fail Back"; + private const string ZFailBackStr = "ZFail Back"; + + private Dictionary m_comparisonDict = new Dictionary(); + private Dictionary m_stencilOpsDict = new Dictionary(); + + [SerializeField] + private bool m_active = true; + + [SerializeField] + private InlineProperty m_reference = new InlineProperty(); + + // Read Mask + private const int ReadMaskDefaultValue = 255; + [SerializeField] + private InlineProperty m_readMask = new InlineProperty( ReadMaskDefaultValue ); + + //Write Mask + private const int WriteMaskDefaultValue = 255; + [SerializeField] + private InlineProperty m_writeMask = new InlineProperty( WriteMaskDefaultValue ); + + //Comparison Function + private const int ComparisonDefaultValue = 0; + [SerializeField] + private InlineProperty m_comparisonFunctionFrontIdx = new InlineProperty( ComparisonDefaultValue ); + + [SerializeField] + private InlineProperty m_comparisonFunctionBackIdx = new InlineProperty( ComparisonDefaultValue ); + + //Pass Stencil Op + private const int PassStencilOpDefaultValue = 0; + [SerializeField] + private InlineProperty m_passStencilOpFrontIdx = new InlineProperty( PassStencilOpDefaultValue ); + + [SerializeField] + private InlineProperty m_passStencilOpBackIdx = new InlineProperty( PassStencilOpDefaultValue ); + + //Fail Stencil Op + private const int FailStencilOpDefaultValue = 0; + + [SerializeField] + private InlineProperty m_failStencilOpFrontIdx = new InlineProperty( FailStencilOpDefaultValue ); + + [SerializeField] + private InlineProperty m_failStencilOpBackIdx = new InlineProperty( FailStencilOpDefaultValue ); + + //ZFail Stencil Op + private const int ZFailStencilOpDefaultValue = 0; + [SerializeField] + private InlineProperty m_zFailStencilOpFrontIdx = new InlineProperty( ZFailStencilOpDefaultValue ); + + [SerializeField] + private InlineProperty m_zFailStencilOpBackIdx = new InlineProperty( ZFailStencilOpDefaultValue ); + + public TemplatesStencilBufferModule() : base("Stencil Buffer") + { + for( int i = 0; i < StencilBufferOpHelper.StencilComparisonValues.Length; i++ ) + { + m_comparisonDict.Add( StencilBufferOpHelper.StencilComparisonValues[ i ].ToLower(), i ); + } + + for( int i = 0; i < StencilBufferOpHelper.StencilOpsValues.Length; i++ ) + { + m_stencilOpsDict.Add( StencilBufferOpHelper.StencilOpsValues[ i ].ToLower(), i ); + } + } + + public void CopyFrom( TemplatesStencilBufferModule other , bool allData ) + { + if( allData ) + m_independentModule = other.IndependentModule; + + m_active = other.Active; + m_reference.CopyFrom( other.Reference ); + m_readMask.CopyFrom( other.ReadMask ); + m_writeMask.CopyFrom( other.WriteMask ); + m_comparisonFunctionFrontIdx.CopyFrom( other.ComparisonFunctionIdx ); + m_comparisonFunctionBackIdx.CopyFrom( other.ComparisonFunctionBackIdx ); + m_passStencilOpFrontIdx.CopyFrom( other.PassStencilOpIdx ); + m_passStencilOpBackIdx.CopyFrom( other.PassStencilOpBackIdx ); + m_failStencilOpFrontIdx.CopyFrom( other.FailStencilOpIdx ); + m_failStencilOpBackIdx.CopyFrom( other.FailStencilOpBackIdx ); + m_zFailStencilOpFrontIdx.CopyFrom( other.ZFailStencilOpIdx ); + m_zFailStencilOpBackIdx.CopyFrom( other.ZFailStencilOpBackIdx ); + } + + public void ConfigureFromTemplateData( TemplateStencilData stencilData ) + { + bool newValidData = ( stencilData.DataCheck == TemplateDataCheck.Valid ); + if( newValidData && m_validData != newValidData ) + { + m_active = stencilData.Active; + m_independentModule = stencilData.IndependentModule; + if( string.IsNullOrEmpty( stencilData.ReferenceInline ) ) + { + m_reference.IntValue = stencilData.Reference; + m_reference.ResetProperty(); + } + else + { + m_reference.SetInlineByName( stencilData.ReferenceInline ); + } + + if( string.IsNullOrEmpty( stencilData.ReadMaskInline ) ) + { + m_readMask.IntValue = stencilData.ReadMask; + m_readMask.ResetProperty(); + } + else + { + m_readMask.SetInlineByName( stencilData.ReadMaskInline ); + } + + if( string.IsNullOrEmpty( stencilData.WriteMaskInline ) ) + { + m_writeMask.IntValue = stencilData.WriteMask; + m_writeMask.ResetProperty(); + } + else + { + m_writeMask.SetInlineByName( stencilData.WriteMaskInline ); + } + + if( string.IsNullOrEmpty( stencilData.ComparisonFrontInline ) ) + { + if( !string.IsNullOrEmpty( stencilData.ComparisonFront ) ) + { + m_comparisonFunctionFrontIdx.IntValue = m_comparisonDict[ stencilData.ComparisonFront.ToLower() ]; + } + else + { + m_comparisonFunctionFrontIdx.IntValue = m_comparisonDict[ "always" ]; + } + m_comparisonFunctionFrontIdx.ResetProperty(); + } + else + { + m_comparisonFunctionFrontIdx.SetInlineByName( stencilData.ComparisonFrontInline ); + } + + if( string.IsNullOrEmpty( stencilData.PassFrontInline ) ) + { + if( !string.IsNullOrEmpty( stencilData.PassFront ) ) + { + m_passStencilOpFrontIdx.IntValue = m_stencilOpsDict[ stencilData.PassFront.ToLower() ]; + } + else + { + m_passStencilOpFrontIdx.IntValue = m_stencilOpsDict[ "keep" ]; + } + m_passStencilOpFrontIdx.ResetProperty(); + } + else + { + m_passStencilOpFrontIdx.SetInlineByName( stencilData.PassFrontInline ); + } + + if( string.IsNullOrEmpty( stencilData.FailFrontInline ) ) + { + if( !string.IsNullOrEmpty( stencilData.FailFront ) ) + { + m_failStencilOpFrontIdx.IntValue = m_stencilOpsDict[ stencilData.FailFront.ToLower() ]; + } + else + { + m_failStencilOpFrontIdx.IntValue = m_stencilOpsDict[ "keep" ]; + } + m_failStencilOpFrontIdx.ResetProperty(); + } + else + { + m_failStencilOpFrontIdx.SetInlineByName( stencilData.FailFrontInline ); + } + + if( string.IsNullOrEmpty( stencilData.ZFailFrontInline ) ) + { + if( !string.IsNullOrEmpty( stencilData.ZFailFront ) ) + { + m_zFailStencilOpFrontIdx.IntValue = m_stencilOpsDict[ stencilData.ZFailFront.ToLower() ]; + } + else + { + m_zFailStencilOpFrontIdx.IntValue = m_stencilOpsDict[ "keep" ]; + } + m_zFailStencilOpFrontIdx.ResetProperty(); + } + else + { + m_zFailStencilOpFrontIdx.SetInlineByName( stencilData.ZFailFrontInline ); + } + + if( string.IsNullOrEmpty( stencilData.ComparisonBackInline ) ) + { + if( !string.IsNullOrEmpty( stencilData.ComparisonBack ) ) + { + m_comparisonFunctionBackIdx.IntValue = m_comparisonDict[ stencilData.ComparisonBack.ToLower() ]; + } + else + { + m_comparisonFunctionBackIdx.IntValue = m_comparisonDict[ "always" ]; + } + m_comparisonFunctionBackIdx.ResetProperty(); + } + else + { + m_comparisonFunctionBackIdx.SetInlineByName( stencilData.ComparisonBackInline ); + } + + if( string.IsNullOrEmpty( stencilData.PassBackInline ) ) + { + + if( !string.IsNullOrEmpty( stencilData.PassBack ) ) + { + m_passStencilOpBackIdx.IntValue = m_stencilOpsDict[ stencilData.PassBack.ToLower() ]; + } + else + { + m_passStencilOpBackIdx.IntValue = m_stencilOpsDict[ "keep" ]; + } + m_passStencilOpBackIdx.ResetProperty(); + } + else + { + m_passStencilOpBackIdx.SetInlineByName( stencilData.PassBackInline ); + } + + if( string.IsNullOrEmpty( stencilData.FailBackInline ) ) + { + if( !string.IsNullOrEmpty( stencilData.FailBack ) ) + { + m_failStencilOpBackIdx.IntValue = m_stencilOpsDict[ stencilData.FailBack.ToLower() ]; + } + else + { + m_failStencilOpBackIdx.IntValue = m_stencilOpsDict[ "keep" ]; + } + m_failStencilOpBackIdx.ResetProperty(); + } + else + { + m_failStencilOpBackIdx.SetInlineByName( stencilData.FailBackInline ); + } + + + if( string.IsNullOrEmpty( stencilData.ZFailBackInline ) ) + { + if( !string.IsNullOrEmpty( stencilData.ZFailBack ) ) + { + m_zFailStencilOpBackIdx.IntValue = m_stencilOpsDict[ stencilData.ZFailBack.ToLower() ]; + } + else + { + m_zFailStencilOpBackIdx.IntValue = m_stencilOpsDict[ "keep" ]; + } + m_zFailStencilOpBackIdx.ResetProperty(); + } + else + { + m_zFailStencilOpBackIdx.SetInlineByName( stencilData.ZFailBackInline ); + } + } + m_validData = newValidData; + } + + public string CreateStencilOp( CullMode cullMode ) + { + if( !m_active ) + return string.Empty; + + string result = "Stencil\n{\n"; + result += string.Format( "\tRef {0}\n", m_reference.GetValueOrProperty() ); + if( m_readMask.IsValid || m_readMask.IntValue != ReadMaskDefaultValue ) + { + result += string.Format( "\tReadMask {0}\n", m_readMask.GetValueOrProperty() ); + } + + if( m_writeMask.IsValid || m_writeMask.IntValue != WriteMaskDefaultValue ) + { + result += string.Format( "\tWriteMask {0}\n", m_writeMask.GetValueOrProperty() ); + } + + if( cullMode == CullMode.Off && + ( m_comparisonFunctionBackIdx.IsValid || m_comparisonFunctionBackIdx.IntValue != ComparisonDefaultValue || + m_passStencilOpBackIdx.IsValid || m_passStencilOpBackIdx.IntValue != PassStencilOpDefaultValue || + m_failStencilOpBackIdx.IsValid || m_failStencilOpBackIdx.IntValue != FailStencilOpDefaultValue || + m_zFailStencilOpBackIdx.IsValid || m_zFailStencilOpBackIdx.IntValue != ZFailStencilOpDefaultValue ) ) + { + if( m_comparisonFunctionFrontIdx.IsValid || m_comparisonFunctionFrontIdx.IntValue != ComparisonDefaultValue ) + result += string.Format( "\tCompFront {0}\n", m_comparisonFunctionFrontIdx.GetValueOrProperty( StencilBufferOpHelper.StencilComparisonValues[ m_comparisonFunctionFrontIdx.IntValue ] ) ); + + if( m_passStencilOpFrontIdx.IsValid || m_passStencilOpFrontIdx.IntValue != PassStencilOpDefaultValue ) + result += string.Format( "\tPassFront {0}\n", m_passStencilOpFrontIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_passStencilOpFrontIdx.IntValue ] ) ); + + if( m_failStencilOpFrontIdx.IsValid || m_failStencilOpFrontIdx.IntValue != FailStencilOpDefaultValue ) + result += string.Format( "\tFailFront {0}\n", m_failStencilOpFrontIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_failStencilOpFrontIdx.IntValue ] ) ); + + if( m_zFailStencilOpFrontIdx.IsValid || m_zFailStencilOpFrontIdx.IntValue != ZFailStencilOpDefaultValue ) + result += string.Format( "\tZFailFront {0}\n", m_zFailStencilOpFrontIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_zFailStencilOpFrontIdx.IntValue ] ) ); + + if( m_comparisonFunctionBackIdx.IsValid || m_comparisonFunctionBackIdx.IntValue != ComparisonDefaultValue ) + result += string.Format( "\tCompBack {0}\n", m_comparisonFunctionBackIdx.GetValueOrProperty( StencilBufferOpHelper.StencilComparisonValues[ m_comparisonFunctionBackIdx.IntValue ] ) ); + + if( m_passStencilOpBackIdx.IsValid || m_passStencilOpBackIdx.IntValue != PassStencilOpDefaultValue ) + result += string.Format( "\tPassBack {0}\n", m_passStencilOpBackIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_passStencilOpBackIdx.IntValue ] ) ); + + if( m_failStencilOpBackIdx.IsValid || m_failStencilOpBackIdx.IntValue != FailStencilOpDefaultValue ) + result += string.Format( "\tFailBack {0}\n", m_failStencilOpBackIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_failStencilOpBackIdx.IntValue ] )); + + if( m_zFailStencilOpBackIdx.IsValid || m_zFailStencilOpBackIdx.IntValue != ZFailStencilOpDefaultValue ) + result += string.Format( "\tZFailBack {0}\n", m_zFailStencilOpBackIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_zFailStencilOpBackIdx.IntValue ] )); + } + else + { + if( m_comparisonFunctionFrontIdx.IsValid || m_comparisonFunctionFrontIdx.IntValue != ComparisonDefaultValue ) + result += string.Format( "\tComp {0}\n", m_comparisonFunctionFrontIdx.GetValueOrProperty(StencilBufferOpHelper.StencilComparisonValues[ m_comparisonFunctionFrontIdx.IntValue ] )); + if( m_passStencilOpFrontIdx.IsValid || m_passStencilOpFrontIdx.IntValue != PassStencilOpDefaultValue ) + result += string.Format( "\tPass {0}\n", m_passStencilOpFrontIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_passStencilOpFrontIdx.IntValue ] )); + if( m_failStencilOpFrontIdx.IsValid || m_failStencilOpFrontIdx.IntValue != FailStencilOpDefaultValue ) + result += string.Format( "\tFail {0}\n", m_failStencilOpFrontIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_failStencilOpFrontIdx.IntValue ] )); + if( m_zFailStencilOpFrontIdx.IsValid || m_zFailStencilOpFrontIdx.IntValue != ZFailStencilOpDefaultValue ) + result += string.Format( "\tZFail {0}\n", m_zFailStencilOpFrontIdx.GetValueOrProperty(StencilBufferOpHelper.StencilOpsValues[ m_zFailStencilOpFrontIdx.IntValue ] )); + } + + result += "}"; + return result; + } + + public override void ShowUnreadableDataMessage( ParentNode owner ) + { + bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions; + NodeUtils.DrawPropertyGroup( ref foldout, FoldoutLabelStr, base.ShowUnreadableDataMessage ); + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions = foldout; + } + + public void Draw( UndoParentNode owner, CullMode cullMode , bool style = true ) + { + bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions; + if( style ) + { + NodeUtils.DrawPropertyGroup( ref foldout, FoldoutLabelStr, () => + { + DrawBlock( owner, cullMode ); + } ); + } + else + { + NodeUtils.DrawNestedPropertyGroup( owner, ref foldout, ref m_active, FoldoutLabelStr, () => + { + DrawBlock( owner, cullMode ); + } ); + } + owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions = foldout; + } + + void DrawBlock( UndoParentNode owner, CullMode cullMode ) + { + bool guiEnabled = GUI.enabled; + GUI.enabled = m_active; + EditorGUI.BeginChangeCheck(); + { + var cache = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = EditorGUIUtility.labelWidth - 20; + m_reference.IntSlider( ref owner, ReferenceValueContent, 0, 255 ); + m_readMask.IntSlider( ref owner, ReadMaskContent, 0, 255 ); + m_writeMask.IntSlider( ref owner, WriteMaskContent, 0, 255 ); + if( cullMode == CullMode.Off ) + { + m_comparisonFunctionFrontIdx.EnumTypePopup( ref owner, ComparisonFrontStr, StencilBufferOpHelper.StencilComparisonLabels ); + m_passStencilOpFrontIdx.EnumTypePopup( ref owner, PassFrontStr, StencilBufferOpHelper.StencilOpsLabels ); + m_failStencilOpFrontIdx.EnumTypePopup( ref owner, FailFrontStr, StencilBufferOpHelper.StencilOpsLabels ); + m_zFailStencilOpFrontIdx.EnumTypePopup( ref owner, ZFailFrontStr, StencilBufferOpHelper.StencilOpsLabels ); + EditorGUILayout.Separator(); + m_comparisonFunctionBackIdx.EnumTypePopup( ref owner, ComparisonBackStr, StencilBufferOpHelper.StencilComparisonLabels ); + m_passStencilOpBackIdx.EnumTypePopup( ref owner, PassBackStr, StencilBufferOpHelper.StencilOpsLabels ); + m_failStencilOpBackIdx.EnumTypePopup( ref owner, FailBackStr, StencilBufferOpHelper.StencilOpsLabels ); + m_zFailStencilOpBackIdx.EnumTypePopup( ref owner, ZFailBackStr, StencilBufferOpHelper.StencilOpsLabels ); + } + else + { + m_comparisonFunctionFrontIdx.EnumTypePopup( ref owner, ComparisonStr, StencilBufferOpHelper.StencilComparisonLabels ); + m_passStencilOpFrontIdx.EnumTypePopup( ref owner, PassFrontStr, StencilBufferOpHelper.StencilOpsLabels ); + m_failStencilOpFrontIdx.EnumTypePopup( ref owner, FailFrontStr, StencilBufferOpHelper.StencilOpsLabels ); + m_zFailStencilOpFrontIdx.EnumTypePopup( ref owner, ZFailFrontStr, StencilBufferOpHelper.StencilOpsLabels ); + } + + EditorGUIUtility.labelWidth = cache; + } + if( EditorGUI.EndChangeCheck() ) + { + m_isDirty = true; + CustomEdited = true; + } + GUI.enabled = guiEnabled; + } + + public override void ReadFromString( ref uint index, ref string[] nodeParams ) + { + base.ReadFromString( ref index, ref nodeParams ); + bool validDataOnMeta = m_validData; + if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion ) + { + validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( validDataOnMeta ) + { + if( UIUtils.CurrentShaderVersion() > 15307 ) + { + m_active = Convert.ToBoolean( nodeParams[ index++ ] ); + } + + if( UIUtils.CurrentShaderVersion() < 15304 ) + { + m_reference.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_readMask.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_writeMask.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_comparisonFunctionFrontIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_passStencilOpFrontIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_failStencilOpFrontIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_zFailStencilOpFrontIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_comparisonFunctionBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_passStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_failStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + m_zFailStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] ); + } + else + { + m_reference.ReadFromString( ref index, ref nodeParams ); + m_readMask.ReadFromString( ref index, ref nodeParams ); + m_writeMask.ReadFromString( ref index, ref nodeParams ); + m_comparisonFunctionFrontIdx.ReadFromString( ref index, ref nodeParams ); + m_passStencilOpFrontIdx.ReadFromString( ref index, ref nodeParams ); + m_failStencilOpFrontIdx.ReadFromString( ref index, ref nodeParams ); + m_zFailStencilOpFrontIdx.ReadFromString( ref index, ref nodeParams ); + m_comparisonFunctionBackIdx.ReadFromString( ref index, ref nodeParams ); + m_passStencilOpBackIdx.ReadFromString( ref index, ref nodeParams ); + m_failStencilOpBackIdx.ReadFromString( ref index, ref nodeParams ); + m_zFailStencilOpBackIdx.ReadFromString( ref index, ref nodeParams ); + } + + } + } + + public override void WriteToString( ref string nodeInfo ) + { + base.WriteToString( ref nodeInfo ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_validData ); + if( m_validData ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_active ); + m_reference.WriteToString( ref nodeInfo ); + m_readMask.WriteToString( ref nodeInfo ); + m_writeMask.WriteToString( ref nodeInfo ); + m_comparisonFunctionFrontIdx.WriteToString( ref nodeInfo ); + m_passStencilOpFrontIdx.WriteToString( ref nodeInfo ); + m_failStencilOpFrontIdx.WriteToString( ref nodeInfo ); + m_zFailStencilOpFrontIdx.WriteToString( ref nodeInfo ); + m_comparisonFunctionBackIdx.WriteToString( ref nodeInfo ); + m_passStencilOpBackIdx.WriteToString( ref nodeInfo ); + m_failStencilOpBackIdx.WriteToString( ref nodeInfo ); + m_zFailStencilOpBackIdx.WriteToString( ref nodeInfo ); + } + } + + public override void Destroy() + { + m_comparisonDict.Clear(); + m_comparisonDict = null; + + m_stencilOpsDict.Clear(); + m_stencilOpsDict = null; + + m_reference = null; + m_readMask = null; + m_writeMask = null; + m_comparisonFunctionFrontIdx = null; + m_passStencilOpFrontIdx = null; + m_failStencilOpFrontIdx = null; + m_zFailStencilOpFrontIdx = null; + m_comparisonFunctionBackIdx = null; + m_passStencilOpBackIdx = null; + m_failStencilOpBackIdx = null; + m_zFailStencilOpBackIdx = null; + } + public bool Active { get { return m_active; } } + public InlineProperty Reference { get { return m_reference; } } + public InlineProperty ReadMask { get { return m_readMask; } } + public InlineProperty WriteMask { get { return m_writeMask; } } + public InlineProperty ComparisonFunctionIdx { get { return m_comparisonFunctionFrontIdx; } } + public InlineProperty ComparisonFunctionBackIdx { get { return m_comparisonFunctionBackIdx; } } + public InlineProperty PassStencilOpIdx { get { return m_passStencilOpFrontIdx; } } + public InlineProperty PassStencilOpBackIdx { get { return m_passStencilOpBackIdx; } } + public InlineProperty FailStencilOpIdx { get { return m_failStencilOpFrontIdx; } } + public InlineProperty FailStencilOpBackIdx { get { return m_failStencilOpBackIdx; } } + public InlineProperty ZFailStencilOpIdx { get { return m_zFailStencilOpFrontIdx; } } + public InlineProperty ZFailStencilOpBackIdx { get { return m_zFailStencilOpBackIdx; } } + + + public int ReferenceValue + { + set + { + m_reference.IntValue = value; + m_reference.Active = false; + } + get + { + return m_reference.IntValue; + } + } + + public int ReadMaskValue + { + set + { + m_readMask.IntValue = value; + m_reference.Active = false; + } + get + { + return m_readMask.IntValue; + } + } + + public int WriteMaskValue + { + set + { + m_writeMask.IntValue = value; + m_writeMask.Active = false; + } + get + { + return m_writeMask.IntValue; + } + } + + public int ComparisonFunctionIdxValue + { + set + { + m_comparisonFunctionFrontIdx.IntValue = value; + m_comparisonFunctionFrontIdx.Active = false; + } + get + { + return m_comparisonFunctionFrontIdx.IntValue; + } + } + + public int ComparisonFunctionBackIdxValue + { + set + { + m_comparisonFunctionBackIdx.IntValue = value; + m_comparisonFunctionBackIdx.Active = false; + } + get + { + return m_comparisonFunctionBackIdx.IntValue; + } + } + + public int PassStencilOpIdxValue + { + set + { + m_passStencilOpFrontIdx.IntValue = value; + m_passStencilOpFrontIdx.Active = false; + } + get + { + return m_passStencilOpFrontIdx.IntValue; + } + } + + public int PassStencilOpBackIdxValue + { + set + { + m_passStencilOpBackIdx.IntValue = value; + m_passStencilOpBackIdx.Active = false; + } + get + { + return m_passStencilOpBackIdx.IntValue; + } + } + + public int FailStencilOpIdxValue + { + set + { + m_failStencilOpFrontIdx.IntValue = value; + m_failStencilOpFrontIdx.Active = false; + } + get + { + return m_failStencilOpFrontIdx.IntValue; + } + } + public int FailStencilOpBackIdxValue + { + set + { + m_failStencilOpBackIdx.IntValue = value; + m_failStencilOpBackIdx.Active = false; + } + get + { + return m_failStencilOpBackIdx.IntValue; + } + } + + public int ZFailStencilOpIdxValue + { + set + { + m_zFailStencilOpFrontIdx.IntValue = value; + m_zFailStencilOpFrontIdx.Active = false; + } + get + { + return m_zFailStencilOpFrontIdx.IntValue; + } + } + + public int ZFailStencilOpBackIdxValue + { + set + { + m_zFailStencilOpBackIdx.IntValue = value; + m_zFailStencilOpBackIdx.Active = false; + } + get + { + return m_zFailStencilOpBackIdx.IntValue; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs.meta new file mode 100644 index 0000000..552dbaf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: fa41b984209fa624aa1fdea5949d9d59 +timeCreated: 1511548974 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils.meta new file mode 100644 index 0000000..f81a149 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 77f9dcd6b7a403a47b926073779ee42f +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPPSHelperTool.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPPSHelperTool.cs new file mode 100644 index 0000000..782980f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPPSHelperTool.cs @@ -0,0 +1,464 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +using System; +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +//using UnityEngine.Rendering.PostProcessing; + + +namespace AmplifyShaderEditor +{ + public enum ASEPostProcessEvent + { + BeforeTransparent = 0, + BeforeStack = 1, + AfterStack = 2 + } + + [Serializable] + public class ASEPPSHelperBuffer + { + public string Name; + public string Tooltip; + } + + [Serializable] + public class ASEPPSHelperTool : EditorWindow + { + private const string PPSFullTemplate = + "// Amplify Shader Editor - Visual Shader Editing Tool\n" + + "// Copyright (c) Amplify Creations, Lda \n" + + "#if UNITY_POST_PROCESSING_STACK_V2\n" + + "using System;\n" + + "using UnityEngine;\n" + + "using UnityEngine.Rendering.PostProcessing;\n" + + "\n" + + "[Serializable]\n" + + "[PostProcess( typeof( /*PPSRendererClass*/ ), PostProcessEvent./*PPSEventType*/, \"/*PPSMenuEntry*/\", /*AllowInSceneView*/ )]\n" + + "public sealed class /*PPSSettingsClass*/ : PostProcessEffectSettings\n" + + "{\n" + + "/*PPSPropertiesDeclaration*/" + + "}\n" + + "\n" + + "public sealed class /*PPSRendererClass*/ : PostProcessEffectRenderer\n" + + "{\n" + + "\tpublic override void Render( PostProcessRenderContext context )\n" + + "\t{\n" + + "\t\tvar sheet = context.propertySheets.Get( Shader.Find( \"/*PPSShader*/\" ) );\n" + + "/*PPSPropertySet*/" + + "\t\tcontext.command.BlitFullscreenTriangle( context.source, context.destination, sheet, 0 );\n" + + "\t}\n" + + "}\n" + + "#endif\n"; + + private const string PPSEventType = "/*PPSEventType*/"; + private const string PPSRendererClass = "/*PPSRendererClass*/"; + private const string PPSSettingsClass = "/*PPSSettingsClass*/"; + private const string PPSMenuEntry = "/*PPSMenuEntry*/"; + private const string PPSAllowInSceneView = "/*AllowInSceneView*/"; + private const string PPSShader = "/*PPSShader*/"; + private const string PPSPropertiesDecl = "/*PPSPropertiesDeclaration*/"; + private const string PPSPropertySet = "/*PPSPropertySet*/"; + + public static readonly string PPSPropertySetFormat = "\t\tsheet.properties.{0}( \"{1}\", settings.{1} );\n"; + public static readonly string PPSPropertySetNullPointerCheckFormat = "\t\tif(settings.{1}.value != null) sheet.properties.{0}( \"{1}\", settings.{1} );\n"; + public static readonly string PPSPropertyDecFormat = + "\t[{0}Tooltip( \"{1}\" )]\n" + + "\tpublic {2} {3} = new {2} {{ {4} }};\n"; + public static readonly Dictionary WireToPPSType = new Dictionary() + { + { WirePortDataType.FLOAT,"FloatParameter"}, + { WirePortDataType.FLOAT2,"Vector4Parameter"}, + { WirePortDataType.FLOAT3,"Vector4Parameter"}, + { WirePortDataType.FLOAT4,"Vector4Parameter"}, + { WirePortDataType.COLOR,"ColorParameter"}, + { WirePortDataType.SAMPLER1D,"TextureParameter"}, + { WirePortDataType.SAMPLER2D,"TextureParameter"}, + { WirePortDataType.SAMPLER3D,"TextureParameter"}, + { WirePortDataType.SAMPLERCUBE,"TextureParameter"}, + { WirePortDataType.SAMPLER2DARRAY,"TextureParameter"} + }; + + public static readonly Dictionary WireToPPSValueSet = new Dictionary() + { + { WirePortDataType.FLOAT,"SetFloat"}, + { WirePortDataType.FLOAT2,"SetVector"}, + { WirePortDataType.FLOAT3,"SetVector"}, + { WirePortDataType.FLOAT4,"SetVector"}, + { WirePortDataType.COLOR,"SetColor"}, + { WirePortDataType.SAMPLER1D, "SetTexture"}, + { WirePortDataType.SAMPLER2D, "SetTexture"}, + { WirePortDataType.SAMPLER3D, "SetTexture"}, + { WirePortDataType.SAMPLERCUBE,"SetTexture"}, + { WirePortDataType.SAMPLER2DARRAY,"SetTexture"} + }; + + public static readonly Dictionary ShaderPropertyToPPSType = new Dictionary() + { + { UnityEditor.ShaderUtil.ShaderPropertyType.Float,"FloatParameter"}, + { UnityEditor.ShaderUtil.ShaderPropertyType.Range,"FloatParameter"}, + { UnityEditor.ShaderUtil.ShaderPropertyType.Vector,"Vector4Parameter"}, + { UnityEditor.ShaderUtil.ShaderPropertyType.Color,"ColorParameter"}, + { UnityEditor.ShaderUtil.ShaderPropertyType.TexEnv,"TextureParameter"} + }; + + + public static readonly Dictionary ShaderPropertyToPPSSet = new Dictionary() + { + { UnityEditor.ShaderUtil.ShaderPropertyType.Float,"SetFloat"}, + { UnityEditor.ShaderUtil.ShaderPropertyType.Range,"SetFloat"}, + { UnityEditor.ShaderUtil.ShaderPropertyType.Vector,"SetVector"}, + { UnityEditor.ShaderUtil.ShaderPropertyType.Color,"SetColor"}, + { UnityEditor.ShaderUtil.ShaderPropertyType.TexEnv,"SetTexture"} + }; + + private Dictionary m_excludedProperties = new Dictionary + { + { "_texcoord",true }, + { "__dirty",true} + }; + + private Material m_dummyMaterial = null; + + private DragAndDropTool m_dragAndDropTool; + private Rect m_draggableArea; + + [SerializeField] + private string m_rendererClassName = "PPSRenderer"; + + [SerializeField] + private string m_settingsClassName = "PPSSettings"; + + [SerializeField] + private string m_folderPath = "Assets/"; + + [SerializeField] + private string m_menuEntry = string.Empty; + + [SerializeField] + private bool m_allowInSceneView = true; + + [SerializeField] + private ASEPostProcessEvent m_eventType = ASEPostProcessEvent.AfterStack; + + [SerializeField] + private Shader m_currentShader = null; + + [SerializeField] + private List m_tooltips = new List(); + + [SerializeField] + private bool m_tooltipsFoldout = true; + + private GUIStyle m_contentStyle = null; + private GUIStyle m_pathButtonStyle = null; + private GUIContent m_pathButtonContent = new GUIContent(); + private Vector2 m_scrollPos = Vector2.zero; + + [MenuItem( "Window/Amplify Shader Editor/Post-Processing Stack Tool", false, 1001 )] + static void ShowWindow() + { + ASEPPSHelperTool window = EditorWindow.GetWindow(); + window.titleContent.text = "Post-Processing Stack Tool"; + window.minSize = new Vector2( 302, 350 ); + window.Show(); + } + + void FetchTooltips() + { + m_tooltips.Clear(); + int propertyCount = UnityEditor.ShaderUtil.GetPropertyCount( m_currentShader ); + for( int i = 0; i < propertyCount; i++ ) + { + //UnityEditor.ShaderUtil.ShaderPropertyType type = UnityEditor.ShaderUtil.GetPropertyType( m_currentShader, i ); + string name = UnityEditor.ShaderUtil.GetPropertyName( m_currentShader, i ); + string description = UnityEditor.ShaderUtil.GetPropertyDescription( m_currentShader, i ); + + if( m_excludedProperties.ContainsKey( name )) + continue; + + m_tooltips.Add( new ASEPPSHelperBuffer { Name = name, Tooltip = description } ); + } + } + + void OnGUI() + { + if( m_pathButtonStyle == null ) + m_pathButtonStyle = "minibutton"; + + m_scrollPos = EditorGUILayout.BeginScrollView( m_scrollPos, GUILayout.Height( position.height ) ); + + EditorGUILayout.BeginVertical( m_contentStyle ); + EditorGUI.BeginChangeCheck(); + m_currentShader = EditorGUILayout.ObjectField( "Shader", m_currentShader, typeof( Shader ), false ) as Shader; + if( EditorGUI.EndChangeCheck() ) + { + GetInitialInfo( m_currentShader ); + } + + EditorGUILayout.Separator(); + EditorGUILayout.LabelField( "Path and Filename" ); + EditorGUILayout.BeginHorizontal(); + m_pathButtonContent.text = m_folderPath; + Vector2 buttonSize = m_pathButtonStyle.CalcSize( m_pathButtonContent ); + if( GUILayout.Button( m_pathButtonContent, m_pathButtonStyle, GUILayout.MaxWidth( Mathf.Min( position.width * 0.5f, buttonSize.x ) ) ) ) + { + string folderpath = EditorUtility.OpenFolderPanel( "Save Texture Array to folder", "Assets/", "" ); + folderpath = FileUtil.GetProjectRelativePath( folderpath ); + if( string.IsNullOrEmpty( folderpath ) ) + m_folderPath = "Assets/"; + else + m_folderPath = folderpath + "/"; + } + + m_settingsClassName = EditorGUILayout.TextField( m_settingsClassName, GUILayout.ExpandWidth( true ) ); + + EditorGUILayout.LabelField( ".cs", GUILayout.MaxWidth( 40 ) ); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.HelpBox( "The path for the generated script should be outside of Amplify Shader Editor folder structure due to use of Assembly Definition files which will conflict and prevent to compile correctly.", MessageType.Warning ); + + EditorGUILayout.Separator(); + + m_menuEntry = EditorGUILayout.TextField( "Name", m_menuEntry ); + + EditorGUILayout.Separator(); + + m_allowInSceneView = EditorGUILayout.Toggle( "Allow In Scene View", m_allowInSceneView ); + + EditorGUILayout.Separator(); + + m_eventType = (ASEPostProcessEvent)EditorGUILayout.EnumPopup( "Event Type", m_eventType ); + + EditorGUILayout.Separator(); + + m_tooltipsFoldout = EditorGUILayout.Foldout( m_tooltipsFoldout, "Tooltips" ); + if( m_tooltipsFoldout ) + { + EditorGUI.indentLevel++; + for( int i = 0; i < m_tooltips.Count; i++ ) + { + m_tooltips[ i ].Tooltip = EditorGUILayout.TextField( m_tooltips[ i ].Name, m_tooltips[ i ].Tooltip ); + } + EditorGUI.indentLevel--; + } + + EditorGUILayout.Separator(); + + if( GUILayout.Button( "Build" ) ) + { + System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; + string propertiesDecl = string.Empty; + string propertiesSet = string.Empty; + GetShaderInfoFromShaderAsset( ref propertiesDecl, ref propertiesSet ); + string template = PPSFullTemplate; + template = template.Replace( PPSRendererClass, m_rendererClassName ); + template = template.Replace( PPSSettingsClass, m_settingsClassName ); + template = template.Replace( PPSEventType, m_eventType.ToString() ); + template = template.Replace( PPSPropertiesDecl, propertiesDecl ); + template = template.Replace( PPSPropertySet, propertiesSet ); + template = template.Replace( PPSMenuEntry, m_menuEntry ); + template = template.Replace( PPSAllowInSceneView, m_allowInSceneView?"true":"false" ); + template = template.Replace( PPSShader, m_currentShader.name ); + string path = m_folderPath + m_settingsClassName + ".cs"; + IOUtils.SaveTextfileToDisk( template, path, false ); + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + AssetDatabase.Refresh(); + } + + EditorGUILayout.EndVertical(); + EditorGUILayout.EndScrollView(); + m_draggableArea.size = position.size; + m_dragAndDropTool.TestDragAndDrop( m_draggableArea ); + } + + public void GetShaderInfoFromASE( ref string propertiesDecl, ref string propertiesSet ) + { + List properties = UIUtils.CurrentWindow.OutsideGraph.PropertyNodes.NodesList; + int propertyCount = properties.Count; + for( int i = 0; i < propertyCount; i++ ) + { + properties[ i ].GeneratePPSInfo( ref propertiesDecl, ref propertiesSet ); + } + } + + public void GetShaderInfoFromShaderAsset( ref string propertiesDecl, ref string propertiesSet ) + { + bool fetchInitialInfo = false; + if( m_currentShader == null ) + { + Material mat = Selection.activeObject as Material; + if( mat != null ) + { + m_currentShader = mat.shader; + } + else + { + m_currentShader = Selection.activeObject as Shader; + } + fetchInitialInfo = true; + } + + if( m_currentShader != null ) + { + if( fetchInitialInfo ) + GetInitialInfo( m_currentShader ); + + if( m_dummyMaterial == null ) + { + m_dummyMaterial = new Material( m_currentShader ); + } + else + { + m_dummyMaterial.shader = m_currentShader; + } + + int propertyCount = UnityEditor.ShaderUtil.GetPropertyCount( m_currentShader ); + //string allProperties = string.Empty; + int validIds = 0; + for( int i = 0; i < propertyCount; i++ ) + { + UnityEditor.ShaderUtil.ShaderPropertyType type = UnityEditor.ShaderUtil.GetPropertyType( m_currentShader, i ); + string name = UnityEditor.ShaderUtil.GetPropertyName( m_currentShader, i ); + //string description = UnityEditor.ShaderUtil.GetPropertyDescription( m_currentShader, i ); + if( m_excludedProperties.ContainsKey( name )) + continue; + + string defaultValue = string.Empty; + bool nullPointerCheck = false; + switch( type ) + { + case UnityEditor.ShaderUtil.ShaderPropertyType.Color: + { + Color value = m_dummyMaterial.GetColor( name ); + defaultValue = string.Format( "value = new Color({0}f,{1}f,{2}f,{3}f)", value.r, value.g, value.b, value.a ); + } + break; + case UnityEditor.ShaderUtil.ShaderPropertyType.Vector: + { + Vector4 value = m_dummyMaterial.GetVector( name ); + defaultValue = string.Format( "value = new Vector4({0}f,{1}f,{2}f,{3}f)", value.x, value.y, value.z, value.w ); + } + break; + case UnityEditor.ShaderUtil.ShaderPropertyType.Float: + { + float value = m_dummyMaterial.GetFloat( name ); + defaultValue = "value = " + value + "f"; + } + break; + case UnityEditor.ShaderUtil.ShaderPropertyType.Range: + { + float value = m_dummyMaterial.GetFloat( name ); + defaultValue = "value = " + value + "f"; + } + break; + case UnityEditor.ShaderUtil.ShaderPropertyType.TexEnv: + { + nullPointerCheck = true; + } + break; + } + + propertiesDecl += string.Format( PPSPropertyDecFormat, string.Empty, m_tooltips[ validIds ].Tooltip, ShaderPropertyToPPSType[ type ], name, defaultValue ); + propertiesSet += string.Format( nullPointerCheck ? PPSPropertySetNullPointerCheckFormat : PPSPropertySetFormat, ShaderPropertyToPPSSet[ type ], name ); + validIds++; + } + + } + } + + private void GetInitialInfo() + { + MasterNode masterNode = UIUtils.CurrentWindow.OutsideGraph.CurrentMasterNode; + m_menuEntry = masterNode.ShaderName.Replace( "Hidden/", string.Empty ).Replace( ".shader", string.Empty ); + string name = m_menuEntry; + m_rendererClassName = name + "PPSRenderer"; + m_settingsClassName = name + "PPSSettings"; + m_folderPath = "Assets/"; + } + + private void GetInitialInfo( Shader shader ) + { + if( shader == null ) + { + m_scrollPos = Vector2.zero; + m_menuEntry = string.Empty; + m_rendererClassName = "PPSRenderer"; + m_settingsClassName = "PPSSettings"; + m_folderPath = "Assets/"; + m_tooltips.Clear(); + return; + } + + m_menuEntry = shader.name.Replace( "Hidden/", string.Empty ).Replace( ".shader", string.Empty ); + m_menuEntry = UIUtils.RemoveInvalidCharacters( m_menuEntry ); + string name = m_menuEntry.Replace( "/", string.Empty ); + m_rendererClassName = name + "PPSRenderer"; + m_settingsClassName = name + "PPSSettings"; + m_folderPath = AssetDatabase.GetAssetPath( shader ); + m_folderPath = m_folderPath.Replace( System.IO.Path.GetFileName( m_folderPath ), string.Empty ); + + FetchTooltips(); + } + + public void OnValidObjectsDropped( UnityEngine.Object[] droppedObjs ) + { + for( int objIdx = 0; objIdx < droppedObjs.Length; objIdx++ ) + { + Material mat = droppedObjs[ objIdx ] as Material; + if( mat != null ) + { + m_currentShader = mat.shader; + GetInitialInfo( mat.shader ); + return; + } + else + { + Shader shader = droppedObjs[ objIdx ] as Shader; + if( shader != null ) + { + m_currentShader = shader; + GetInitialInfo( shader ); + return; + } + } + } + } + + private void OnEnable() + { + m_draggableArea = new Rect( 0, 0, 1, 1 ); + m_dragAndDropTool = new DragAndDropTool(); + m_dragAndDropTool.OnValidDropObjectEvt += OnValidObjectsDropped; + + if( m_contentStyle == null ) + { + m_contentStyle = new GUIStyle( GUIStyle.none ); + m_contentStyle.margin = new RectOffset( 6, 4, 5, 5 ); + } + + m_pathButtonStyle = null; + + //GetInitialInfo(); + } + + private void OnDestroy() + { + if( m_dummyMaterial != null ) + { + GameObject.DestroyImmediate( m_dummyMaterial ); + m_dummyMaterial = null; + } + + m_dragAndDropTool.Destroy(); + m_dragAndDropTool = null; + + m_tooltips.Clear(); + m_tooltips = null; + + m_contentStyle = null; + m_pathButtonStyle = null; + m_currentShader = null; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPPSHelperTool.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPPSHelperTool.cs.meta new file mode 100644 index 0000000..581a622 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPPSHelperTool.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ccaa3765dae023d4b8657544c1aeef4a +timeCreated: 1550254201 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPackageManagerHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPackageManagerHelper.cs new file mode 100644 index 0000000..d0534d7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPackageManagerHelper.cs @@ -0,0 +1,701 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +#if UNITY_2018_3_OR_NEWER +using System; +using UnityEngine; +using UnityEditor; +using UnityEditor.PackageManager.Requests; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +namespace AmplifyShaderEditor +{ + public enum ASESRPVersions + { + ASE_SRP_3_0_0 = 030000, + ASE_SRP_3_1_0 = 030100, + ASE_SRP_3_3_0 = 030300, + ASE_SRP_4_1_0 = 040100, + ASE_SRP_4_2_0 = 040200, + ASE_SRP_4_3_0 = 040300, + ASE_SRP_4_6_0 = 040600, + ASE_SRP_4_8_0 = 040800, + ASE_SRP_4_9_0 = 040900, + ASE_SRP_4_10_0 = 041000, + ASE_SRP_5_7_2 = 050702, + ASE_SRP_5_8_2 = 050802, + ASE_SRP_5_9_0 = 050900, + ASE_SRP_5_10_0 = 051000, + ASE_SRP_5_13_0 = 051300, + ASE_SRP_5_16_1 = 051601, + ASE_SRP_6_9_0 = 060900, + ASE_SRP_6_9_1 = 060901, + ASE_SRP_6_9_2 = 060902, + ASE_SRP_7_0_1 = 070001, + ASE_SRP_7_1_1 = 070101, + ASE_SRP_7_1_2 = 070102, + ASE_SRP_7_1_5 = 070105, + ASE_SRP_7_1_6 = 070106, + ASE_SRP_7_1_7 = 070107, + ASE_SRP_7_1_8 = 070108, + ASE_SRP_7_2_0 = 070200, + ASE_SRP_7_2_1 = 070201, + ASE_SRP_7_3_1 = 070301, + ASE_SRP_7_4_1 = 070401, + ASE_SRP_7_4_2 = 070402, + ASE_SRP_7_4_3 = 070403, + ASE_SRP_7_5_1 = 070501, + ASE_SRP_7_5_2 = 070502, + ASE_SRP_7_5_3 = 070503, + ASE_SRP_7_6_0 = 070600, + ASE_SRP_8_2_0 = 080200, + ASE_SRP_8_3_1 = 080301, + ASE_SRP_9_0_0 = 090000, + ASE_SRP_10_0_0 = 100000, + ASE_SRP_10_1_0 = 100100, + ASE_SRP_10_2_2 = 100202, + ASE_SRP_10_3_1 = 100301, + ASE_SRP_10_3_2 = 100302, + ASE_SRP_10_4_0 = 100400, + ASE_SRP_10_5_0 = 100500, + ASE_SRP_10_5_1 = 100501, + ASE_SRP_11_0_0 = 110000, + ASE_SRP_RECENT = 999999 + } + + public enum ASEImportState + { + None, + Lightweight, + HD, + Both + } + + public static class AssetDatabaseEX + { + private static System.Type type = null; + public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEditor.AssetDatabase, UnityEditor" ) : type; } } + + public static void ImportPackageImmediately( string packagePath ) + { + AssetDatabaseEX.Type.InvokeMember( "ImportPackageImmediately", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { packagePath } ); + } + } + + + [Serializable] + public static class ASEPackageManagerHelper + { + private static string LightweightNewVersionDetected = "A new Lighweight RP version was detected and new templates are being imported.\n" + + "Please hit the Update button on your ASE canvas to recompile your shader under the newest version."; + + private static string HDNewVersionDetected = "A new HD RP version was detected and new templates are being imported.\n" + + "Please hit the Update button on your ASE canvas to recompile your shader under the newest version."; + + private static string HDPackageId = "com.unity.render-pipelines.high-definition"; + private static string LWPackageId = "com.unity.render-pipelines.lightweight"; + private static string UniversalPackageId = "com.unity.render-pipelines.universal"; + private static string HDEditorPrefsId = "ASEHDEditorPrefsId"; + private static string LWEditorPrefsId = "ASELightweigthEditorPrefsId "; + + private static string URPTemplateVersion = "ASEURPtemplate" + Application.productName; + private static string HDRPTemplateVersion = "ASEHDRPtemplate" + Application.productName; + + private static string SPKeywordFormat = "ASE_SRP_VERSION {0}"; + private static ListRequest m_packageListRequest = null; + private static UnityEditor.PackageManager.PackageInfo m_lwPackageInfo; + private static UnityEditor.PackageManager.PackageInfo m_hdPackageInfo; + + // V4.8.0 and bellow + // HD + private static readonly string[] GetNormalWSFunc = + { + "inline void GetNormalWS( FragInputs input, float3 normalTS, out float3 normalWS, float3 doubleSidedConstants )\n", + "{\n", + "\tGetNormalWS( input, normalTS, normalWS );\n", + "}\n" + }; + + // v4.6.0 and below + private static readonly string[] BuildWordTangentFunc = + { + "float3x3 BuildWorldToTangent(float4 tangentWS, float3 normalWS)\n", + "{\n", + "\tfloat3 unnormalizedNormalWS = normalWS;\n", + "\tfloat renormFactor = 1.0 / length(unnormalizedNormalWS);\n", + "\tfloat3x3 worldToTangent = CreateWorldToTangent(unnormalizedNormalWS, tangentWS.xyz, tangentWS.w > 0.0 ? 1.0 : -1.0);\n", + "\tworldToTangent[0] = worldToTangent[0] * renormFactor;\n", + "\tworldToTangent[1] = worldToTangent[1] * renormFactor;\n", + "\tworldToTangent[2] = worldToTangent[2] * renormFactor;\n", + "\treturn worldToTangent;\n", + "}\n" + }; + + private static bool m_lateImport = false; + private static string m_latePackageToImport; + + private static bool m_requireUpdateList = false; + private static ASEImportState m_importingPackage = ASEImportState.None; + + + private static ASESRPVersions m_currentHDVersion = ASESRPVersions.ASE_SRP_RECENT; + private static ASESRPVersions m_currentLWVersion = ASESRPVersions.ASE_SRP_RECENT; + + private static int m_urpTemplateVersion = 20; + private static int m_hdrpTemplateVersion = 16; + + private static Dictionary m_srpVersionConverter = new Dictionary() + { + {"3.0.0-preview", ASESRPVersions.ASE_SRP_3_0_0}, + {"3.1.0-preview", ASESRPVersions.ASE_SRP_3_1_0}, + {"3.3.0-preview", ASESRPVersions.ASE_SRP_3_3_0}, + {"4.1.0-preview", ASESRPVersions.ASE_SRP_4_1_0}, + {"4.2.0-preview", ASESRPVersions.ASE_SRP_4_2_0}, + {"4.3.0-preview", ASESRPVersions.ASE_SRP_4_3_0}, + {"4.6.0-preview", ASESRPVersions.ASE_SRP_4_6_0}, + {"4.8.0-preview", ASESRPVersions.ASE_SRP_4_8_0}, + {"4.9.0-preview", ASESRPVersions.ASE_SRP_4_9_0}, + {"4.10.0-preview", ASESRPVersions.ASE_SRP_4_10_0}, + {"5.7.2-preview", ASESRPVersions.ASE_SRP_5_7_2}, + {"5.7.2", ASESRPVersions.ASE_SRP_5_7_2}, + {"5.8.2-preview", ASESRPVersions.ASE_SRP_5_8_2}, + {"5.8.2", ASESRPVersions.ASE_SRP_5_8_2}, + {"5.9.0-preview", ASESRPVersions.ASE_SRP_5_9_0}, + {"5.9.0", ASESRPVersions.ASE_SRP_5_9_0}, + {"5.10.0-preview", ASESRPVersions.ASE_SRP_5_10_0}, + {"5.10.0", ASESRPVersions.ASE_SRP_5_10_0}, + {"5.13.0-preview", ASESRPVersions.ASE_SRP_5_13_0}, + {"5.13.0", ASESRPVersions.ASE_SRP_5_13_0}, + {"5.16.1-preview", ASESRPVersions.ASE_SRP_5_16_1}, + {"5.16.1", ASESRPVersions.ASE_SRP_5_16_1}, + {"6.9.0", ASESRPVersions.ASE_SRP_6_9_0}, + {"6.9.0-preview", ASESRPVersions.ASE_SRP_6_9_0}, + {"6.9.1", ASESRPVersions.ASE_SRP_6_9_1}, + {"6.9.1-preview", ASESRPVersions.ASE_SRP_6_9_1}, + {"6.9.2", ASESRPVersions.ASE_SRP_6_9_2}, + {"6.9.2-preview", ASESRPVersions.ASE_SRP_6_9_2}, + {"7.0.1", ASESRPVersions.ASE_SRP_7_0_1}, + {"7.0.1-preview", ASESRPVersions.ASE_SRP_7_0_1}, + {"7.1.1", ASESRPVersions.ASE_SRP_7_1_1}, + {"7.1.1-preview", ASESRPVersions.ASE_SRP_7_1_1}, + {"7.1.2", ASESRPVersions.ASE_SRP_7_1_2}, + {"7.1.2-preview", ASESRPVersions.ASE_SRP_7_1_2}, + {"7.1.5", ASESRPVersions.ASE_SRP_7_1_5}, + {"7.1.5-preview", ASESRPVersions.ASE_SRP_7_1_5}, + {"7.1.6", ASESRPVersions.ASE_SRP_7_1_6}, + {"7.1.6-preview", ASESRPVersions.ASE_SRP_7_1_6}, + {"7.1.7", ASESRPVersions.ASE_SRP_7_1_7}, + {"7.1.7-preview", ASESRPVersions.ASE_SRP_7_1_7}, + {"7.1.8", ASESRPVersions.ASE_SRP_7_1_8}, + {"7.1.8-preview", ASESRPVersions.ASE_SRP_7_1_8}, + {"7.2.0", ASESRPVersions.ASE_SRP_7_2_0}, + {"7.2.0-preview", ASESRPVersions.ASE_SRP_7_2_0}, + {"7.2.1", ASESRPVersions.ASE_SRP_7_2_1}, + {"7.2.1-preview", ASESRPVersions.ASE_SRP_7_2_1}, + {"7.3.1", ASESRPVersions.ASE_SRP_7_3_1}, + {"7.3.1-preview", ASESRPVersions.ASE_SRP_7_3_1}, + {"7.4.1", ASESRPVersions.ASE_SRP_7_4_1}, + {"7.4.1-preview", ASESRPVersions.ASE_SRP_7_4_1}, + {"7.4.2", ASESRPVersions.ASE_SRP_7_4_2}, + {"7.4.2-preview", ASESRPVersions.ASE_SRP_7_4_2}, + {"7.4.3", ASESRPVersions.ASE_SRP_7_4_3}, + {"7.4.3-preview", ASESRPVersions.ASE_SRP_7_4_3}, + {"7.5.1", ASESRPVersions.ASE_SRP_7_5_1}, + {"7.5.1-preview", ASESRPVersions.ASE_SRP_7_5_1}, + {"7.5.2", ASESRPVersions.ASE_SRP_7_5_2}, + {"7.5.2-preview", ASESRPVersions.ASE_SRP_7_5_2}, + {"7.5.3", ASESRPVersions.ASE_SRP_7_5_3}, + {"7.5.3-preview", ASESRPVersions.ASE_SRP_7_5_3}, + {"7.6.0", ASESRPVersions.ASE_SRP_7_6_0}, + {"7.6.0-preview", ASESRPVersions.ASE_SRP_7_6_0}, + {"8.2.0", ASESRPVersions.ASE_SRP_8_2_0}, + {"8.2.0-preview", ASESRPVersions.ASE_SRP_8_2_0}, + {"8.3.1", ASESRPVersions.ASE_SRP_8_3_1}, + {"8.3.1-preview", ASESRPVersions.ASE_SRP_8_3_1}, + {"9.0.0", ASESRPVersions.ASE_SRP_9_0_0}, + {"9.0.0-preview.13", ASESRPVersions.ASE_SRP_9_0_0}, + {"9.0.0-preview.14", ASESRPVersions.ASE_SRP_9_0_0}, + {"9.0.0-preview.33", ASESRPVersions.ASE_SRP_9_0_0}, + {"9.0.0-preview.35", ASESRPVersions.ASE_SRP_9_0_0}, + {"9.0.0-preview.54", ASESRPVersions.ASE_SRP_9_0_0}, + {"9.0.0-preview.55", ASESRPVersions.ASE_SRP_9_0_0}, + {"9.0.0-preview.71", ASESRPVersions.ASE_SRP_9_0_0}, + {"9.0.0-preview.72", ASESRPVersions.ASE_SRP_9_0_0}, + {"10.0.0-preview.26", ASESRPVersions.ASE_SRP_10_0_0}, + {"10.0.0-preview.27", ASESRPVersions.ASE_SRP_10_0_0}, + {"10.1.0", ASESRPVersions.ASE_SRP_10_1_0}, + {"10.2.2", ASESRPVersions.ASE_SRP_10_2_2}, + {"10.3.1", ASESRPVersions.ASE_SRP_10_3_1}, + {"10.3.2", ASESRPVersions.ASE_SRP_10_3_2}, + {"10.4.0", ASESRPVersions.ASE_SRP_10_4_0}, + {"10.5.0", ASESRPVersions.ASE_SRP_10_5_0}, + {"10.5.1", ASESRPVersions.ASE_SRP_10_5_1}, + {"11.0.0", ASESRPVersions.ASE_SRP_11_0_0}, + }; + + + + private static Dictionary m_srpToASEPackageLW = new Dictionary() + { + {ASESRPVersions.ASE_SRP_3_0_0, "b53d2f3b156ff104f90d4d7693d769c8"}, + {ASESRPVersions.ASE_SRP_3_1_0, "b53d2f3b156ff104f90d4d7693d769c8"}, + {ASESRPVersions.ASE_SRP_3_3_0, "b53d2f3b156ff104f90d4d7693d769c8"}, + {ASESRPVersions.ASE_SRP_4_1_0, "3e8eabcfae1e5aa4397de89fedeb48db"}, + {ASESRPVersions.ASE_SRP_4_2_0, "3e8eabcfae1e5aa4397de89fedeb48db"}, + {ASESRPVersions.ASE_SRP_4_3_0, "3e8eabcfae1e5aa4397de89fedeb48db"}, + {ASESRPVersions.ASE_SRP_4_6_0, "3e8eabcfae1e5aa4397de89fedeb48db"}, + {ASESRPVersions.ASE_SRP_4_8_0, "3e8eabcfae1e5aa4397de89fedeb48db"}, + {ASESRPVersions.ASE_SRP_4_9_0, "3e8eabcfae1e5aa4397de89fedeb48db"}, + {ASESRPVersions.ASE_SRP_4_10_0, "3e8eabcfae1e5aa4397de89fedeb48db"}, + {ASESRPVersions.ASE_SRP_5_7_2, "4c816894a3147d343891060451241bfe"}, + {ASESRPVersions.ASE_SRP_5_8_2, "4c816894a3147d343891060451241bfe"}, + {ASESRPVersions.ASE_SRP_5_9_0, "4c816894a3147d343891060451241bfe"}, + {ASESRPVersions.ASE_SRP_5_10_0, "4c816894a3147d343891060451241bfe"}, + {ASESRPVersions.ASE_SRP_5_13_0, "4c816894a3147d343891060451241bfe"}, + {ASESRPVersions.ASE_SRP_5_16_1, "4c816894a3147d343891060451241bfe"}, + {ASESRPVersions.ASE_SRP_6_9_0, "4c816894a3147d343891060451241bfe"}, + {ASESRPVersions.ASE_SRP_6_9_1, "4c816894a3147d343891060451241bfe"}, + {ASESRPVersions.ASE_SRP_6_9_2, "4c816894a3147d343891060451241bfe"}, + {ASESRPVersions.ASE_SRP_7_0_1, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_1_1, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_1_2, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_1_5, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_1_6, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_1_7, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_1_8, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_2_0, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_2_1, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_3_1, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_4_1, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_4_2, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_4_3, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_5_1, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_5_2, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_5_3, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_7_6_0, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_8_2_0, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_8_3_1, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_9_0_0, "f54faaaf4faf8784183ede7f87dfeb23"}, + {ASESRPVersions.ASE_SRP_10_0_0, "57fcea0ed8b5eb347923c4c21fa31b57"}, + {ASESRPVersions.ASE_SRP_10_1_0, "57fcea0ed8b5eb347923c4c21fa31b57"}, + {ASESRPVersions.ASE_SRP_10_2_2, "57fcea0ed8b5eb347923c4c21fa31b57"}, + {ASESRPVersions.ASE_SRP_10_3_1, "57fcea0ed8b5eb347923c4c21fa31b57"}, + {ASESRPVersions.ASE_SRP_10_3_2, "57fcea0ed8b5eb347923c4c21fa31b57"}, + {ASESRPVersions.ASE_SRP_10_4_0, "57fcea0ed8b5eb347923c4c21fa31b57"}, + {ASESRPVersions.ASE_SRP_10_5_0, "57fcea0ed8b5eb347923c4c21fa31b57"}, + {ASESRPVersions.ASE_SRP_10_5_1, "57fcea0ed8b5eb347923c4c21fa31b57"}, + {ASESRPVersions.ASE_SRP_11_0_0, "57fcea0ed8b5eb347923c4c21fa31b57"}, + {ASESRPVersions.ASE_SRP_RECENT, "57fcea0ed8b5eb347923c4c21fa31b57"} + }; + + private static Dictionary m_srpToASEPackageHD = new Dictionary() + { + {ASESRPVersions.ASE_SRP_3_0_0, "4dc1afbcc68875c4780502f5e6b80158"}, + {ASESRPVersions.ASE_SRP_3_1_0, "4dc1afbcc68875c4780502f5e6b80158"}, + {ASESRPVersions.ASE_SRP_3_3_0, "4dc1afbcc68875c4780502f5e6b80158"}, + {ASESRPVersions.ASE_SRP_4_1_0, "5d615bf612f33364e96fb9fd2959ae9c"}, + {ASESRPVersions.ASE_SRP_4_2_0, "5d615bf612f33364e96fb9fd2959ae9c"}, + {ASESRPVersions.ASE_SRP_4_3_0, "5d615bf612f33364e96fb9fd2959ae9c"}, + {ASESRPVersions.ASE_SRP_4_6_0, "5d615bf612f33364e96fb9fd2959ae9c"}, + {ASESRPVersions.ASE_SRP_4_8_0, "5d615bf612f33364e96fb9fd2959ae9c"}, + {ASESRPVersions.ASE_SRP_4_9_0, "5d615bf612f33364e96fb9fd2959ae9c"}, + {ASESRPVersions.ASE_SRP_4_10_0, "5d615bf612f33364e96fb9fd2959ae9c"}, + {ASESRPVersions.ASE_SRP_5_7_2, "f51b7b861facbc3429fcc5f1f6f91183"}, + {ASESRPVersions.ASE_SRP_5_8_2, "2d7fe4f7c19e90f41b893bc01fc17230"}, + {ASESRPVersions.ASE_SRP_5_9_0, "2d7fe4f7c19e90f41b893bc01fc17230"}, + {ASESRPVersions.ASE_SRP_5_10_0, "2d7fe4f7c19e90f41b893bc01fc17230"}, + {ASESRPVersions.ASE_SRP_5_13_0, "2d7fe4f7c19e90f41b893bc01fc17230"}, + {ASESRPVersions.ASE_SRP_5_16_1, "2d7fe4f7c19e90f41b893bc01fc17230"}, + {ASESRPVersions.ASE_SRP_6_9_0, "e137dba02f4d0f542ab09dcedea27314"}, + {ASESRPVersions.ASE_SRP_6_9_1, "e137dba02f4d0f542ab09dcedea27314"}, + {ASESRPVersions.ASE_SRP_6_9_2, "e137dba02f4d0f542ab09dcedea27314"}, + {ASESRPVersions.ASE_SRP_7_0_1, "e137dba02f4d0f542ab09dcedea27314"}, + {ASESRPVersions.ASE_SRP_7_1_1, "e137dba02f4d0f542ab09dcedea27314"}, + {ASESRPVersions.ASE_SRP_7_1_2, "e137dba02f4d0f542ab09dcedea27314"}, + {ASESRPVersions.ASE_SRP_7_1_5, "e137dba02f4d0f542ab09dcedea27314"}, + {ASESRPVersions.ASE_SRP_7_1_6, "e137dba02f4d0f542ab09dcedea27314"}, + {ASESRPVersions.ASE_SRP_7_1_7, "e137dba02f4d0f542ab09dcedea27314"}, + {ASESRPVersions.ASE_SRP_7_1_8, "38b4bfd7c725505409f8f4d944961db4"}, + {ASESRPVersions.ASE_SRP_7_2_0, "38b4bfd7c725505409f8f4d944961db4"}, + {ASESRPVersions.ASE_SRP_7_2_1, "38b4bfd7c725505409f8f4d944961db4"}, + {ASESRPVersions.ASE_SRP_7_3_1, "38b4bfd7c725505409f8f4d944961db4"}, + {ASESRPVersions.ASE_SRP_7_4_1, "38b4bfd7c725505409f8f4d944961db4"}, + {ASESRPVersions.ASE_SRP_7_4_2, "38b4bfd7c725505409f8f4d944961db4"}, + {ASESRPVersions.ASE_SRP_7_4_3, "38b4bfd7c725505409f8f4d944961db4"}, + {ASESRPVersions.ASE_SRP_7_5_1, "3aeabe705b70b154ea99893f91351100"}, + {ASESRPVersions.ASE_SRP_7_5_2, "3aeabe705b70b154ea99893f91351100"}, + {ASESRPVersions.ASE_SRP_7_5_3, "3aeabe705b70b154ea99893f91351100"}, + {ASESRPVersions.ASE_SRP_7_6_0, "3aeabe705b70b154ea99893f91351100"}, + {ASESRPVersions.ASE_SRP_8_2_0, "3aeabe705b70b154ea99893f91351100"}, + {ASESRPVersions.ASE_SRP_8_3_1, "3aeabe705b70b154ea99893f91351100"}, + {ASESRPVersions.ASE_SRP_9_0_0, "3aeabe705b70b154ea99893f91351100"}, + {ASESRPVersions.ASE_SRP_10_0_0, "9a5e61a8b3421b944863d0946e32da0a"}, + {ASESRPVersions.ASE_SRP_10_1_0, "9a5e61a8b3421b944863d0946e32da0a"}, + {ASESRPVersions.ASE_SRP_10_2_2, "9a5e61a8b3421b944863d0946e32da0a"}, + {ASESRPVersions.ASE_SRP_10_3_1, "9a5e61a8b3421b944863d0946e32da0a"}, + {ASESRPVersions.ASE_SRP_10_3_2, "9a5e61a8b3421b944863d0946e32da0a"}, + {ASESRPVersions.ASE_SRP_10_4_0, "9a5e61a8b3421b944863d0946e32da0a"}, + {ASESRPVersions.ASE_SRP_10_5_0, "9a5e61a8b3421b944863d0946e32da0a"}, + {ASESRPVersions.ASE_SRP_10_5_1, "9a5e61a8b3421b944863d0946e32da0a"}, + {ASESRPVersions.ASE_SRP_11_0_0, "9a5e61a8b3421b944863d0946e32da0a"}, + {ASESRPVersions.ASE_SRP_RECENT, "9a5e61a8b3421b944863d0946e32da0a"} + + }; + + private static Shader m_lateShader; + private static Material m_lateMaterial; + private static AmplifyShaderFunction m_lateShaderFunction; + + + public static void RequestInfo() + { + if( !m_requireUpdateList && m_importingPackage == ASEImportState.None ) + { + m_requireUpdateList = true; + m_packageListRequest = UnityEditor.PackageManager.Client.List( true ); + } + } + + static void FailedPackageImport( string packageName, string errorMessage ) + { + FinishImporter(); + } + + static void CancelledPackageImport( string packageName ) + { + FinishImporter(); + } + + static void CompletedPackageImport( string packageName ) + { + FinishImporter(); + } + + public static void CheckLatePackageImport() + { + if( !Application.isPlaying && m_lateImport && !string.IsNullOrEmpty( m_latePackageToImport ) ) + { + m_lateImport = false; + StartImporting( m_latePackageToImport ); + m_latePackageToImport = string.Empty; + } + } + + public static void StartImporting( string packagePath ) + { + if( !Preferences.GlobalAutoSRP ) + { + m_importingPackage = ASEImportState.None; + return; + } + + if( Application.isPlaying ) + { + if( !m_lateImport ) + { + m_lateImport = true; + m_latePackageToImport = packagePath; + Debug.LogWarning( "Amplify Shader Editor requires the \""+ packagePath +"\" package to be installed in order to continue. Please exit Play mode to proceed." ); + } + return; + } + + AssetDatabase.importPackageCancelled += CancelledPackageImport; + AssetDatabase.importPackageCompleted += CompletedPackageImport; + AssetDatabase.importPackageFailed += FailedPackageImport; + AssetDatabase.ImportPackage( packagePath, false ); + //AssetDatabaseEX.ImportPackageImmediately( packagePath ); + } + + public static void FinishImporter() + { + m_importingPackage = ASEImportState.None; + AssetDatabase.importPackageCancelled -= CancelledPackageImport; + AssetDatabase.importPackageCompleted -= CompletedPackageImport; + AssetDatabase.importPackageFailed -= FailedPackageImport; + } + + public static void SetupLateShader( Shader shader ) + { + if( shader == null ) + return; + + //If a previous delayed object is pending discard it and register the new one + // So the last selection will be the choice of opening + //This can happen when trying to open an ASE canvas while importing templates or in play mode + if( m_lateShader != null ) + { + EditorApplication.delayCall -= LateShaderOpener; + } + + RequestInfo(); + m_lateShader = shader; + EditorApplication.delayCall += LateShaderOpener; + } + + public static void LateShaderOpener() + { + Preferences.LoadDefaults(); + Update(); + if( IsProcessing ) + { + EditorApplication.delayCall += LateShaderOpener; + } + else + { + AmplifyShaderEditorWindow.ConvertShaderToASE( m_lateShader ); + m_lateShader = null; + } + } + + public static void SetupLateMaterial( Material material ) + { + if( material == null ) + return; + + //If a previous delayed object is pending discard it and register the new one + // So the last selection will be the choice of opening + //This can happen when trying to open an ASE canvas while importing templates or in play mode + if( m_lateMaterial != null ) + { + EditorApplication.delayCall -= LateMaterialOpener; + } + + RequestInfo(); + m_lateMaterial = material; + EditorApplication.delayCall += LateMaterialOpener; + } + + public static void LateMaterialOpener() + { + Preferences.LoadDefaults(); + Update(); + if( IsProcessing ) + { + EditorApplication.delayCall += LateMaterialOpener; + } + else + { + AmplifyShaderEditorWindow.LoadMaterialToASE( m_lateMaterial ); + m_lateMaterial = null; + } + } + + public static void SetupLateShaderFunction( AmplifyShaderFunction shaderFunction ) + { + if( shaderFunction == null ) + return; + + //If a previous delayed object is pending discard it and register the new one + // So the last selection will be the choice of opening + //This can happen when trying to open an ASE canvas while importing templates or in play mode + if( m_lateShaderFunction != null ) + { + EditorApplication.delayCall -= LateShaderFunctionOpener; + } + + RequestInfo(); + m_lateShaderFunction = shaderFunction; + EditorApplication.delayCall += LateShaderFunctionOpener; + } + + public static void LateShaderFunctionOpener() + { + Preferences.LoadDefaults(); + Update(); + if( IsProcessing ) + { + EditorApplication.delayCall += LateShaderFunctionOpener; + } + else + { + AmplifyShaderEditorWindow.LoadShaderFunctionToASE( m_lateShaderFunction, false ); + m_lateShaderFunction = null; + } + } + + public static void Update() + { + //if( Application.isPlaying ) + // return; + + CheckLatePackageImport(); + //if( m_lwPackageInfo != null ) + //{ + // if( m_srpVersionConverter[ m_lwPackageInfo.version ] != m_currentLWVersion ) + // { + // m_currentLWVersion = m_srpVersionConverter[ m_lwPackageInfo.version ]; + // EditorPrefs.SetInt( LWEditorPrefsId, (int)m_currentLWVersion ); + // m_importingPackage = ASEImportState.Lightweight; + // string packagePath = AssetDatabase.GUIDToAssetPath( m_srpToASEPackageLW[ m_currentLWVersion ] ); + // StartImporting( packagePath ); + // } + //} + + //if( m_hdPackageInfo != null ) + //{ + // if( m_srpVersionConverter[ m_hdPackageInfo.version ] != m_currentHDVersion ) + // { + // m_currentHDVersion = m_srpVersionConverter[ m_hdPackageInfo.version ]; + // EditorPrefs.SetInt( HDEditorPrefsId, (int)m_currentHDVersion ); + // m_importingPackage = ASEImportState.HD; + // string packagePath = AssetDatabase.GUIDToAssetPath( m_srpToASEPackageHD[ m_currentHDVersion ] ); + // StartImporting( packagePath ); + // } + //} + + if( m_requireUpdateList && m_importingPackage == ASEImportState.None ) + { + if( m_packageListRequest != null && m_packageListRequest.IsCompleted ) + { + m_requireUpdateList = false; + foreach( UnityEditor.PackageManager.PackageInfo pi in m_packageListRequest.Result ) + { + if( pi.name.Equals( LWPackageId ) ) + { + m_currentLWVersion = ASESRPVersions.ASE_SRP_RECENT; + m_lwPackageInfo = pi; + ASESRPVersions oldVersion = (ASESRPVersions)EditorPrefs.GetInt( LWEditorPrefsId ); + if( m_srpVersionConverter.ContainsKey( pi.version ) ) + { + m_currentLWVersion = m_srpVersionConverter[ pi.version ]; + } + else + { + m_currentLWVersion = ASESRPVersions.ASE_SRP_RECENT; + } + + EditorPrefs.SetInt( LWEditorPrefsId, (int)m_currentLWVersion ); + bool foundNewVersion = oldVersion != m_currentLWVersion; + if( !File.Exists( AssetDatabase.GUIDToAssetPath( TemplatesManager.LightweigthPBRGUID ) ) || + !File.Exists( AssetDatabase.GUIDToAssetPath( TemplatesManager.LightweigthUnlitGUID ) ) || + foundNewVersion + ) + { + if( foundNewVersion ) + Debug.Log( LightweightNewVersionDetected ); + + m_importingPackage = ASEImportState.Lightweight; + string guid = m_srpToASEPackageLW.ContainsKey( m_currentLWVersion ) ? m_srpToASEPackageLW[ m_currentLWVersion ] : m_srpToASEPackageLW[ ASESRPVersions.ASE_SRP_RECENT ]; + string packagePath = AssetDatabase.GUIDToAssetPath( guid ); + StartImporting( packagePath ); + } + } + + if( pi.name.Equals( UniversalPackageId ) ) + { + m_currentLWVersion = ASESRPVersions.ASE_SRP_RECENT; + m_lwPackageInfo = pi; + ASESRPVersions oldVersion = (ASESRPVersions)EditorPrefs.GetInt( LWEditorPrefsId ); + if( m_srpVersionConverter.ContainsKey( pi.version ) ) + { + m_currentLWVersion = m_srpVersionConverter[ pi.version ]; + } + else + { + m_currentLWVersion = ASESRPVersions.ASE_SRP_RECENT; + } + + EditorPrefs.SetInt( LWEditorPrefsId, (int)m_currentLWVersion ); + bool foundNewVersion = oldVersion != m_currentLWVersion; + + int urpVersion = EditorPrefs.GetInt( URPTemplateVersion, m_urpTemplateVersion ); + if( urpVersion < m_urpTemplateVersion ) + foundNewVersion = true; + EditorPrefs.SetInt( URPTemplateVersion, m_urpTemplateVersion ); + + if( !File.Exists( AssetDatabase.GUIDToAssetPath( TemplatesManager.UniversalPBRGUID ) ) || + !File.Exists( AssetDatabase.GUIDToAssetPath( TemplatesManager.UniversalUnlitGUID ) ) || + foundNewVersion + ) + { + if( foundNewVersion ) + Debug.Log( LightweightNewVersionDetected ); + + m_importingPackage = ASEImportState.Lightweight; + string guid = m_srpToASEPackageLW.ContainsKey( m_currentLWVersion ) ? m_srpToASEPackageLW[ m_currentLWVersion ] : m_srpToASEPackageLW[ ASESRPVersions.ASE_SRP_RECENT ]; + string packagePath = AssetDatabase.GUIDToAssetPath( guid ); + StartImporting( packagePath ); + } + + } + + if( pi.name.Equals( HDPackageId ) ) + { + m_currentHDVersion = ASESRPVersions.ASE_SRP_RECENT; + m_hdPackageInfo = pi; + ASESRPVersions oldVersion = (ASESRPVersions)EditorPrefs.GetInt( HDEditorPrefsId ); + if( m_srpVersionConverter.ContainsKey( pi.version ) ) + { + m_currentHDVersion = m_srpVersionConverter[ pi.version ]; + } + else + { + m_currentHDVersion = ASESRPVersions.ASE_SRP_RECENT; + } + + EditorPrefs.SetInt( HDEditorPrefsId, (int)m_currentHDVersion ); + bool foundNewVersion = oldVersion != m_currentHDVersion; + + int hdrpVersion = EditorPrefs.GetInt( HDRPTemplateVersion, m_hdrpTemplateVersion ); + if( hdrpVersion < m_hdrpTemplateVersion ) + foundNewVersion = true; + EditorPrefs.SetInt( HDRPTemplateVersion, m_hdrpTemplateVersion ); + +#if UNITY_2019_3_OR_NEWER + if( !File.Exists( AssetDatabase.GUIDToAssetPath( TemplatesManager.HDNewLitGUID ) ) || + !File.Exists( AssetDatabase.GUIDToAssetPath( TemplatesManager.HDNewPBRGUID ) ) || + !File.Exists( AssetDatabase.GUIDToAssetPath( TemplatesManager.HDNewUnlitGUID ) ) || +#else + if( !File.Exists( AssetDatabase.GUIDToAssetPath( TemplatesManager.HDLitGUID ) ) || + !File.Exists( AssetDatabase.GUIDToAssetPath( TemplatesManager.HDPBRGUID ) ) || + !File.Exists( AssetDatabase.GUIDToAssetPath( TemplatesManager.HDUnlitGUID ) ) || +#endif + foundNewVersion + ) + { + if( foundNewVersion ) + Debug.Log( HDNewVersionDetected ); + + m_importingPackage = m_importingPackage == ASEImportState.Lightweight ? ASEImportState.Both : ASEImportState.HD; + string guid = m_srpToASEPackageHD.ContainsKey( m_currentHDVersion ) ? m_srpToASEPackageHD[ m_currentHDVersion ] : m_srpToASEPackageHD[ ASESRPVersions.ASE_SRP_RECENT ]; + string packagePath = AssetDatabase.GUIDToAssetPath( guid ); + StartImporting( packagePath ); + } + + } + } + } + } + } + + public static void SetSRPInfoOnDataCollector( ref MasterNodeDataCollector dataCollector ) + { + Preferences.LoadDefaults(); + if( m_requireUpdateList ) + Update(); + + if( dataCollector.CurrentSRPType == TemplateSRPType.HD ) + { + dataCollector.AddToDirectives( string.Format( SPKeywordFormat, (int)m_currentHDVersion ) ,-1, AdditionalLineType.Define ); + if( m_currentHDVersion < ASESRPVersions.ASE_SRP_4_9_0 ) + { + dataCollector.AddFunction( GetNormalWSFunc[ 0 ], GetNormalWSFunc, false ); + } + + if( m_currentHDVersion < ASESRPVersions.ASE_SRP_4_8_0 ) + { + dataCollector.AddFunction( BuildWordTangentFunc[ 0 ], BuildWordTangentFunc, false ); + } + } + + if( dataCollector.CurrentSRPType == TemplateSRPType.Lightweight ) + dataCollector.AddToDirectives( string.Format( SPKeywordFormat, (int)m_currentLWVersion ), -1, AdditionalLineType.Define ); + } + public static ASESRPVersions CurrentHDVersion { get { return m_currentHDVersion; } } + public static ASESRPVersions CurrentLWVersion { get { return m_currentLWVersion; } } + public static bool CheckImporter { get { return m_importingPackage != ASEImportState.None; } } + public static bool IsProcessing { get { return m_requireUpdateList && m_importingPackage == ASEImportState.None; } } + } +} +#endif diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPackageManagerHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPackageManagerHelper.cs.meta new file mode 100644 index 0000000..67f628a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPackageManagerHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f48de3e34ed250945ba8c16d98b8ca0e +timeCreated: 1548881060 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEStartScreen.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEStartScreen.cs new file mode 100644 index 0000000..c11cf8b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEStartScreen.cs @@ -0,0 +1,495 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using UnityEngine.Networking; +using System.Collections; + +namespace AmplifyShaderEditor +{ + public class ASEStartScreen : EditorWindow + { + [MenuItem( "Window/Amplify Shader Editor/Start Screen", false, 1999 )] + public static void Init() + { + ASEStartScreen window = (ASEStartScreen)GetWindow( typeof( ASEStartScreen ), true, "Amplify Shader Editor Start Screen" ); + window.minSize = new Vector2( 650, 500 ); + window.maxSize = new Vector2( 650, 500 ); + window.Show(); + } + + private static readonly string ChangeLogGUID = "580cccd3e608b7f4cac35ea46d62d429"; + private static readonly string ResourcesGUID = "c0a0a980c9ba86345bc15411db88d34f"; + private static readonly string BuiltInGUID = "e00e6f90ab8233e46a41c5e33917c642"; + private static readonly string UniversalGUID = "a9d68dd8913f05d4d9ce75e7b40c6044"; + private static readonly string HighDefinitionGUID = "d1c0b77896049554fa4b635531caf741"; + private static readonly string OLDHighDefinitionGUID = "dff05fea7446d7b4e9029bfab77455d2"; + private static readonly string LightWeightGUID = "6ecbfd0a046659943a69328c98ff0442"; + private static readonly string OLDLightWeightGUID = "f7c4e22642de60d448f4e4809190f7b1"; + + private static readonly string IconGUID = "2c6536772776dd84f872779990273bfc"; + + public static readonly string ChangelogURL = "http://amplify.pt/Banner/ASEchangelog.json"; + + private static readonly string ManualURL = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/Manual"; + private static readonly string BasicURL = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/Tutorials#Official_-_Basics"; + private static readonly string BeginnerURL = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/Tutorials#Official_-_Beginner_Series"; + private static readonly string NodesURL = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/Nodes"; + private static readonly string SRPURL = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/Scriptable_Rendering_Pipeline"; + private static readonly string FunctionsURL = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/Manual#Shader_Functions"; + private static readonly string TemplatesURL = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/Templates"; + private static readonly string APIURL = "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/API"; + + private static readonly string DiscordURL = "https://discordapp.com/invite/EdrVAP5"; + private static readonly string ForumURL = "https://forum.unity.com/threads/best-tool-asset-store-award-amplify-shader-editor-node-based-shader-creation-tool.430959/"; + + private static readonly string SiteURL = "http://amplify.pt/download/"; + private static readonly string StoreURL = "https://assetstore.unity.com/packages/tools/visual-scripting/amplify-shader-editor-68570"; + + private static readonly GUIContent SamplesTitle = new GUIContent( "Shader Samples", "Import samples according to you project rendering pipeline" ); + private static readonly GUIContent ResourcesTitle = new GUIContent( "Learning Resources", "Check the online wiki for various topics about how to use ASE with node examples and explanations" ); + private static readonly GUIContent CommunityTitle = new GUIContent( "Community", "Need help? Reach us through our discord server or the offitial support Unity forum" ); + private static readonly GUIContent UpdateTitle = new GUIContent( "Latest Update", "Check the lastest additions, improvements and bug fixes done to ASE" ); + private static readonly GUIContent ASETitle = new GUIContent( "Amplify Shader Editor", "Are you using the latest version? Now you know" ); + + private static readonly string DownArrow = "\u25BC"; +#if UNITY_2019_3_OR_NEWER + private int DownButtonSize = 22; +#else + private int DownButtonSize = 21; +#endif + + Vector2 m_scrollPosition = Vector2.zero; + Preferences.ShowOption m_startup = Preferences.ShowOption.Never; + bool m_showLWRP = false; + bool m_showHDRP = false; + + [NonSerialized] + Texture packageIcon = null; + [NonSerialized] + Texture textIcon = null; + [NonSerialized] + Texture webIcon = null; + + GUIContent HDRPbutton = null; + GUIContent HDRPOLDbutton = null; + GUIContent URPbutton = null; + GUIContent LWRPbutton = null; + GUIContent LWRPOLDbutton = null; + GUIContent BuiltInbutton = null; + + GUIContent Manualbutton = null; + GUIContent Basicbutton = null; + GUIContent Beginnerbutton = null; + GUIContent Nodesbutton = null; + GUIContent SRPusebutton = null; + GUIContent Functionsbutton = null; + GUIContent Templatesbutton = null; + GUIContent APIbutton = null; + + GUIContent DiscordButton = null; + GUIContent ForumButton = null; + + GUIContent ASEIcon = null; + RenderTexture rt; + + [NonSerialized] + GUIStyle m_buttonStyle = null; + [NonSerialized] + GUIStyle m_buttonLeftStyle = null; + [NonSerialized] + GUIStyle m_buttonRightStyle = null; + [NonSerialized] + GUIStyle m_minibuttonStyle = null; + [NonSerialized] + GUIStyle m_labelStyle = null; + [NonSerialized] + GUIStyle m_linkStyle = null; + + private ChangeLogInfo m_changeLog; + private bool m_infoDownloaded = false; + private string m_newVersion = string.Empty; + + private void OnEnable() + { + rt = new RenderTexture( 16, 16, 0 ); + rt.Create(); + + m_startup = (Preferences.ShowOption)EditorPrefs.GetInt( Preferences.PrefStartUp, 0 ); + + if( textIcon == null ) + { + Texture icon = EditorGUIUtility.IconContent( "TextAsset Icon" ).image; + var cache = RenderTexture.active; + RenderTexture.active = rt; + Graphics.Blit( icon, rt ); + RenderTexture.active = cache; + textIcon = rt; + + Manualbutton = new GUIContent( " Manual", textIcon ); + Basicbutton = new GUIContent( " Basic use tutorials", textIcon ); + Beginnerbutton = new GUIContent( " Beginner Series", textIcon ); + Nodesbutton = new GUIContent( " Node List", textIcon ); + SRPusebutton = new GUIContent( " SRP HD/URP/LW use", textIcon ); + Functionsbutton = new GUIContent( " Shader Functions", textIcon ); + Templatesbutton = new GUIContent( " Shader Templates", textIcon ); + APIbutton = new GUIContent( " Node API", textIcon ); + } + + if( packageIcon == null ) + { + packageIcon = EditorGUIUtility.IconContent( "BuildSettings.Editor.Small" ).image; + HDRPbutton = new GUIContent( " HDRP Samples", packageIcon ); + HDRPOLDbutton = new GUIContent( " HDRP Samples 6.X.X", packageIcon ); + URPbutton = new GUIContent( " URP Samples", packageIcon ); + LWRPbutton = new GUIContent( " LWRP Samples 6.X.X", packageIcon ); + LWRPOLDbutton = new GUIContent( " LWRP Samples 3.X.X", packageIcon ); + BuiltInbutton = new GUIContent( " Built-In Samples", packageIcon ); + } + + if( webIcon == null ) + { + webIcon = EditorGUIUtility.IconContent( "BuildSettings.Web.Small" ).image; + DiscordButton = new GUIContent( " Discord", webIcon ); + ForumButton = new GUIContent( " Unity Forum", webIcon ); + } + + if( m_changeLog == null ) + { + var changelog = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( ChangeLogGUID ) ); + string lastUpdate = string.Empty; + if(changelog != null ) + { + lastUpdate = changelog.text.Substring( 0, changelog.text.IndexOf( "\nv", 50 ) );// + "\n..."; + lastUpdate = lastUpdate.Replace( " *", " \u25CB" ); + lastUpdate = lastUpdate.Replace( "* ", "\u2022 " ); + } + m_changeLog = new ChangeLogInfo( VersionInfo.FullNumber, lastUpdate ); + } + + if( ASEIcon == null ) + { + ASEIcon = new GUIContent( AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( IconGUID ) ) ); + } + } + + private void OnDisable() + { + if( rt != null ) + { + rt.Release(); + DestroyImmediate( rt ); + } + } + + public void OnGUI() + { + if( !m_infoDownloaded ) + { + m_infoDownloaded = true; + + StartBackgroundTask( StartRequest( ChangelogURL, () => + { + var temp = ChangeLogInfo.CreateFromJSON( www.downloadHandler.text ); + if( temp != null && temp.Version >= m_changeLog.Version ) + { + m_changeLog = temp; + } + // improve this later + int major = m_changeLog.Version / 10000; + int minor = ( m_changeLog.Version / 1000 ) - major * 10; + int release = ( m_changeLog.Version / 100 ) - major * 100 - minor * 10; + int revision = ( ( m_changeLog.Version / 10 ) - major * 1000 - minor * 100 - release * 10 ) + ( m_changeLog.Version - major * 10000 - minor * 1000 - release * 100 ); + m_newVersion = major + "." + minor + "." + release + "r" + revision; + Repaint(); + } ) ); + } + + if( m_buttonStyle == null ) + { + m_buttonStyle = new GUIStyle( GUI.skin.button ); + m_buttonStyle.alignment = TextAnchor.MiddleLeft; + } + + if( m_buttonLeftStyle == null ) + { + m_buttonLeftStyle = new GUIStyle( "ButtonLeft" ); + m_buttonLeftStyle.alignment = TextAnchor.MiddleLeft; + m_buttonLeftStyle.margin = m_buttonStyle.margin; + m_buttonLeftStyle.margin.right = 0; + } + + if( m_buttonRightStyle == null ) + { + m_buttonRightStyle = new GUIStyle( "ButtonRight" ); + m_buttonRightStyle.alignment = TextAnchor.MiddleLeft; + m_buttonRightStyle.margin = m_buttonStyle.margin; + m_buttonRightStyle.margin.left = 0; + } + + if( m_minibuttonStyle == null ) + { + m_minibuttonStyle = new GUIStyle( "MiniButton" ); + m_minibuttonStyle.alignment = TextAnchor.MiddleLeft; + m_minibuttonStyle.margin = m_buttonStyle.margin; + m_minibuttonStyle.margin.left = 20; + m_minibuttonStyle.normal.textColor = m_buttonStyle.normal.textColor; + m_minibuttonStyle.hover.textColor = m_buttonStyle.hover.textColor; + } + + if( m_labelStyle == null ) + { + m_labelStyle = new GUIStyle( "BoldLabel" ); + m_labelStyle.margin = new RectOffset( 4, 4, 4, 4 ); + m_labelStyle.padding = new RectOffset( 2, 2, 2, 2 ); + m_labelStyle.fontSize = 13; + } + + if( m_linkStyle == null ) + { + var inv = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "1004d06b4b28f5943abdf2313a22790a" ) ); // find a better solution for transparent buttons + m_linkStyle = new GUIStyle(); + m_linkStyle.normal.textColor = new Color( 0.2980392f, 0.4901961f, 1f ); + m_linkStyle.hover.textColor = Color.white; + m_linkStyle.active.textColor = Color.grey; + m_linkStyle.margin.top = 3; + m_linkStyle.margin.bottom = 2; + m_linkStyle.hover.background = inv; + m_linkStyle.active.background = inv; + } + + EditorGUILayout.BeginHorizontal( GUIStyle.none, GUILayout.ExpandWidth( true ) ); + { + // left column + EditorGUILayout.BeginVertical( GUILayout.Width( 175 ) ); + { + GUILayout.Label( SamplesTitle, m_labelStyle ); + EditorGUILayout.BeginHorizontal(); + if( GUILayout.Button( HDRPbutton, m_buttonLeftStyle ) ) + ImportSample( HDRPbutton.text, HighDefinitionGUID ); + + if( GUILayout.Button( DownArrow, m_buttonRightStyle, GUILayout.Width( DownButtonSize ), GUILayout.Height( DownButtonSize ) ) ) + { + m_showHDRP = !m_showHDRP; + m_showLWRP = false; + } + EditorGUILayout.EndHorizontal(); + if( m_showHDRP ) + { + if( GUILayout.Button( HDRPOLDbutton, m_minibuttonStyle ) ) + ImportSample( HDRPOLDbutton.text, OLDHighDefinitionGUID ); + } + EditorGUILayout.BeginHorizontal(); + if( GUILayout.Button( URPbutton, m_buttonLeftStyle ) ) + ImportSample( URPbutton.text, UniversalGUID ); + + if( GUILayout.Button( DownArrow, m_buttonRightStyle, GUILayout.Width( DownButtonSize ), GUILayout.Height( DownButtonSize ) ) ) + { + m_showLWRP = !m_showLWRP; + m_showHDRP = false; + } + EditorGUILayout.EndHorizontal(); + if( m_showLWRP ) + { + EditorGUILayout.BeginVertical(); + if( GUILayout.Button( LWRPbutton, m_minibuttonStyle ) ) + ImportSample( LWRPbutton.text, LightWeightGUID ); + if( GUILayout.Button( LWRPOLDbutton, m_minibuttonStyle ) ) + ImportSample( LWRPOLDbutton.text, OLDLightWeightGUID ); + EditorGUILayout.EndVertical(); + } + if( GUILayout.Button( BuiltInbutton, m_buttonStyle ) ) + ImportSample( BuiltInbutton.text, BuiltInGUID ); + + GUILayout.Space( 10 ); + + GUILayout.Label( ResourcesTitle, m_labelStyle ); + if( GUILayout.Button( Manualbutton, m_buttonStyle ) ) + Application.OpenURL( ManualURL ); + + if( GUILayout.Button( Basicbutton, m_buttonStyle ) ) + Application.OpenURL( BasicURL ); + + if( GUILayout.Button( Beginnerbutton, m_buttonStyle ) ) + Application.OpenURL( BeginnerURL ); + + if( GUILayout.Button( Nodesbutton, m_buttonStyle ) ) + Application.OpenURL( NodesURL ); + + if( GUILayout.Button( SRPusebutton, m_buttonStyle ) ) + Application.OpenURL( SRPURL ); + + if( GUILayout.Button( Functionsbutton, m_buttonStyle ) ) + Application.OpenURL( FunctionsURL ); + + if( GUILayout.Button( Templatesbutton, m_buttonStyle ) ) + Application.OpenURL( TemplatesURL ); + + if( GUILayout.Button( APIbutton, m_buttonStyle ) ) + Application.OpenURL( APIURL ); + } + EditorGUILayout.EndVertical(); + + // right column + EditorGUILayout.BeginVertical( GUILayout.Width( 650 - 175 - 9 ), GUILayout.ExpandHeight( true ) ); + { + GUILayout.Label( CommunityTitle, m_labelStyle ); + EditorGUILayout.BeginHorizontal( GUILayout.ExpandWidth( true ) ); + { + if( GUILayout.Button( DiscordButton, GUILayout.ExpandWidth( true ) ) ) + { + Application.OpenURL( DiscordURL ); + } + if( GUILayout.Button( ForumButton, GUILayout.ExpandWidth( true ) ) ) + { + Application.OpenURL( ForumURL ); + } + } + EditorGUILayout.EndHorizontal(); + GUILayout.Label( UpdateTitle, m_labelStyle ); + m_scrollPosition = GUILayout.BeginScrollView( m_scrollPosition, "ProgressBarBack", GUILayout.ExpandHeight( true ), GUILayout.ExpandWidth( true ) ); + GUILayout.Label( m_changeLog.LastUpdate, "WordWrappedMiniLabel", GUILayout.ExpandHeight( true ) ); + GUILayout.EndScrollView(); + + EditorGUILayout.BeginHorizontal( GUILayout.ExpandWidth( true ) ); + { + EditorGUILayout.BeginVertical(); + GUILayout.Label( ASETitle, m_labelStyle ); + + GUILayout.Label( "Installed Version: " + VersionInfo.StaticToString() ); + + if( m_changeLog.Version > VersionInfo.FullNumber ) + { + var cache = GUI.color; + GUI.color = Color.red; + GUILayout.Label( "New version available: " + m_newVersion, "BoldLabel" ); + GUI.color = cache; + } + else + { + var cache = GUI.color; + GUI.color = Color.green; + GUILayout.Label( "You are using the latest version", "BoldLabel" ); + GUI.color = cache; + } + + EditorGUILayout.BeginHorizontal(); + GUILayout.Label( "Download links:" ); + if( GUILayout.Button( "Amplify", m_linkStyle ) ) + Application.OpenURL( SiteURL ); + GUILayout.Label( "-" ); + if( GUILayout.Button( "Asset Store", m_linkStyle ) ) + Application.OpenURL( StoreURL ); + EditorGUILayout.EndHorizontal(); + GUILayout.Space( 7 ); + EditorGUILayout.EndVertical(); + + GUILayout.FlexibleSpace(); + EditorGUILayout.BeginVertical(); + GUILayout.Space( 7 ); + GUILayout.Label( ASEIcon ); + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndHorizontal(); + + + EditorGUILayout.BeginHorizontal( "ProjectBrowserBottomBarBg", GUILayout.ExpandWidth( true ), GUILayout.Height(22) ); + { + GUILayout.FlexibleSpace(); + EditorGUI.BeginChangeCheck(); + var cache = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 100; + m_startup = (Preferences.ShowOption)EditorGUILayout.EnumPopup( "Show At Startup", m_startup, GUILayout.Width( 220 ) ); + EditorGUIUtility.labelWidth = cache; + if( EditorGUI.EndChangeCheck() ) + { + EditorPrefs.SetInt( Preferences.PrefStartUp, (int)m_startup ); + } + } + EditorGUILayout.EndHorizontal(); + + // Find a better way to update link buttons without repainting the window + Repaint(); + } + + void ImportSample( string pipeline, string guid ) + { + if( EditorUtility.DisplayDialog( "Import Sample", "This will import the samples for" + pipeline.Replace( " Samples", "" ) + ", please make sure the pipeline is properly installed and/or selected before importing the samples.\n\nContinue?", "Yes", "No" ) ) + { + AssetDatabase.ImportPackage( AssetDatabase.GUIDToAssetPath( ResourcesGUID ), false ); + AssetDatabase.ImportPackage( AssetDatabase.GUIDToAssetPath( guid ), false ); + } + } + + UnityWebRequest www; + + IEnumerator StartRequest( string url, Action success = null ) + { + using( www = UnityWebRequest.Get( url ) ) + { +#if UNITY_2017_2_OR_NEWER + yield return www.SendWebRequest(); +#else + yield return www.Send(); +#endif + + while( www.isDone == false ) + yield return null; + + if( success != null ) + success(); + } + } + + public static void StartBackgroundTask( IEnumerator update, Action end = null ) + { + EditorApplication.CallbackFunction closureCallback = null; + + closureCallback = () => + { + try + { + if( update.MoveNext() == false ) + { + if( end != null ) + end(); + EditorApplication.update -= closureCallback; + } + } + catch( Exception ex ) + { + if( end != null ) + end(); + Debug.LogException( ex ); + EditorApplication.update -= closureCallback; + } + }; + + EditorApplication.update += closureCallback; + } + } + + [Serializable] + internal class ChangeLogInfo + { + public int Version; + public string LastUpdate; + + public static ChangeLogInfo CreateFromJSON( string jsonString ) + { + return JsonUtility.FromJson( jsonString ); + } + + public ChangeLogInfo( int version, string lastUpdate ) + { + Version = version; + LastUpdate = lastUpdate; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEStartScreen.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEStartScreen.cs.meta new file mode 100644 index 0000000..b9441e3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEStartScreen.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3e7433fb42db4d9428571bfcd0da64f3 +timeCreated: 1585827066 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASETextureArrayCreator.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASETextureArrayCreator.cs new file mode 100644 index 0000000..db01c9c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASETextureArrayCreator.cs @@ -0,0 +1,813 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda +//#define NEW_TEXTURE_3D_METHOD + +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using UnityEditorInternal; +using System; +using System.IO; + +namespace AmplifyShaderEditor +{ + [CustomEditor( typeof( TextureArrayCreatorAsset ) )] + public class TextureArrayCreatorAssetEditor : Editor + { + private string[] m_sizesStr = { "32", "64", "128", "256", "512", "1024", "2048", "4096", "8192" }; + private int[] m_sizes = { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; + + private const string ArrayFilename = "NewTextureArray"; + private const string Texture3DFilename = "NewTexture3D"; + + private GUIContent m_pathButtonContent = new GUIContent(); + private GUIStyle m_pathButtonStyle = null; + + public TextureArrayCreatorAsset Instance; + + private DragAndDropTool m_dragAndDropTool; + + SerializedObject m_so; + SerializedProperty m_selectedSize; + SerializedProperty m_lockRatio; + SerializedProperty m_sizeX; + SerializedProperty m_sizeY; + SerializedProperty m_tex3DMode; + SerializedProperty m_linearMode; + SerializedProperty m_mipMaps; + SerializedProperty m_wrapMode; + SerializedProperty m_filterMode; + SerializedProperty m_anisoLevel; + SerializedProperty m_selectedFormatEnum; + SerializedProperty m_quality; + SerializedProperty m_folderPath; + SerializedProperty m_fileName; + SerializedProperty m_filenameChanged; + SerializedProperty m_allTextures; + + [SerializeField] + private ReorderableList m_listTextures = null; + + [SerializeField] + private int m_previewSize; + + public void OnEnable() + { + Instance = (TextureArrayCreatorAsset)target; + + m_so = serializedObject; + m_selectedSize = m_so.FindProperty( "m_selectedSize" ); + m_lockRatio = m_so.FindProperty( "m_lockRatio" ); + m_sizeX = m_so.FindProperty( "m_sizeX" ); + m_sizeY = m_so.FindProperty( "m_sizeY" ); + m_tex3DMode = m_so.FindProperty( "m_tex3DMode" ); + m_linearMode = m_so.FindProperty( "m_linearMode" ); + m_mipMaps = m_so.FindProperty( "m_mipMaps" ); + m_wrapMode = m_so.FindProperty( "m_wrapMode" ); + m_filterMode = m_so.FindProperty( "m_filterMode" ); + m_anisoLevel = m_so.FindProperty( "m_anisoLevel" ); + m_selectedFormatEnum = m_so.FindProperty( "m_selectedFormatEnum" ); + m_quality = m_so.FindProperty( "m_quality" ); + m_folderPath = m_so.FindProperty( "m_folderPath" ); + m_fileName = m_so.FindProperty( "m_fileName" ); + m_filenameChanged = m_so.FindProperty( "m_filenameChanged" ); + m_allTextures = m_so.FindProperty( "m_allTextures" ); + + if( m_listTextures == null ) + { + m_listTextures = new ReorderableList( m_so, m_allTextures, true, true, true, true ); + m_listTextures.elementHeight = 16; + + m_listTextures.drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) => + { + m_allTextures.GetArrayElementAtIndex( index ).objectReferenceValue = (Texture2D)EditorGUI.ObjectField( rect, "Texture " + index, m_allTextures.GetArrayElementAtIndex( index ).objectReferenceValue, typeof( Texture2D ), false ); + }; + + m_listTextures.drawHeaderCallback = ( Rect rect ) => + { + m_previewSize = EditorGUI.IntSlider( rect, "Texture List", m_previewSize, 16, 64 ); + if( (float)m_previewSize != m_listTextures.elementHeight ) + m_listTextures.elementHeight = m_previewSize; + }; + + m_listTextures.onAddCallback = ( list ) => + { + m_allTextures.InsertArrayElementAtIndex( m_allTextures.arraySize ); + m_allTextures.GetArrayElementAtIndex( m_allTextures.arraySize - 1 ).objectReferenceValue = null; + }; + + m_listTextures.onRemoveCallback = ( list ) => + { + m_allTextures.GetArrayElementAtIndex( list.index ).objectReferenceValue = null; + m_allTextures.DeleteArrayElementAtIndex( list.index ); + }; + } + + m_dragAndDropTool = new DragAndDropTool(); + m_dragAndDropTool.OnValidDropObjectEvt += OnValidObjectsDropped; + } + + public void OnValidObjectsDropped( UnityEngine.Object[] droppedObjs ) + { + for( int objIdx = 0; objIdx < droppedObjs.Length; objIdx++ ) + { + Texture2D tex = droppedObjs[ objIdx ] as Texture2D; + if( tex != null ) + { + m_allTextures.InsertArrayElementAtIndex( m_allTextures.arraySize ); + m_allTextures.GetArrayElementAtIndex( m_allTextures.arraySize - 1 ).objectReferenceValue = tex; + m_so.ApplyModifiedProperties(); + } + else + { + DefaultAsset asset = droppedObjs[ objIdx ] as DefaultAsset; + if( asset != null ) + { + string path = AssetDatabase.GetAssetPath( asset ); + if( AssetDatabase.IsValidFolder( path ) ) + { + string[] pathArr = { path }; + string[] texInDir = AssetDatabase.FindAssets( "t:Texture2D", pathArr ); + for( int texIdx = 0; texIdx < texInDir.Length; texIdx++ ) + { + Texture2D internalTex = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( texInDir[ texIdx ] ) ); + if( internalTex != null ) + { + m_allTextures.InsertArrayElementAtIndex( m_allTextures.arraySize ); + m_allTextures.GetArrayElementAtIndex( m_allTextures.arraySize - 1 ).objectReferenceValue = internalTex; + m_so.ApplyModifiedProperties(); + } + } + } + } + } + } + + Instance.AllTextures.Sort( ( x, y ) => string.Compare( x.name, y.name ) ); + m_so.Update(); + } + + private void OnDestroy() + { + m_dragAndDropTool.Destroy(); + m_dragAndDropTool = null; + } + + public override void OnInspectorGUI() + { + m_so.Update(); + + if( m_pathButtonStyle == null ) + m_pathButtonStyle = "minibutton"; + + EditorGUILayout.BeginHorizontal(); + var cache = EditorGUIUtility.labelWidth; + EditorGUILayout.PrefixLabel( "Size" ); + EditorGUIUtility.labelWidth = 16; + if( m_lockRatio.boolValue ) + { + m_selectedSize.intValue = EditorGUILayout.Popup( "X", m_selectedSize.intValue, m_sizesStr ); + EditorGUI.BeginDisabledGroup( m_lockRatio.boolValue ); + EditorGUILayout.Popup( "Y", m_selectedSize.intValue, m_sizesStr ); + EditorGUI.EndDisabledGroup(); + } + else + { + EditorGUILayout.PropertyField( m_sizeX, new GUIContent( "X" ) ); + EditorGUILayout.PropertyField( m_sizeY, new GUIContent( "Y" ) ); + } + EditorGUIUtility.labelWidth = 100; +#if UNITY_2017_1_OR_NEWER + m_lockRatio.boolValue = GUILayout.Toggle( m_lockRatio.boolValue, "L", "minibutton", GUILayout.Width( 18 ) ); +#else + GUILayout.Toggle( m_lockRatio.boolValue, "L", "minibutton", GUILayout.Width( 18 ) ); + m_lockRatio.boolValue = true; +#endif + if( m_lockRatio.boolValue ) + { + m_sizeX.intValue = m_sizes[ m_selectedSize.intValue ]; + m_sizeY.intValue = m_sizes[ m_selectedSize.intValue ]; + } + EditorGUIUtility.labelWidth = cache; + EditorGUILayout.EndHorizontal(); + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField( m_tex3DMode, new GUIContent( "Texture 3D" ) ); + if( EditorGUI.EndChangeCheck() ) + { + if( !m_filenameChanged.boolValue ) + { + m_fileName.stringValue = m_tex3DMode.boolValue ? Texture3DFilename : ArrayFilename; + } + } + EditorGUILayout.PropertyField( m_linearMode, new GUIContent( "Linear" ) ); + EditorGUILayout.PropertyField( m_mipMaps ); + EditorGUILayout.PropertyField( m_wrapMode ); + EditorGUILayout.PropertyField( m_filterMode ); + m_anisoLevel.intValue = EditorGUILayout.IntSlider( "Aniso Level", m_anisoLevel.intValue, 0, 16 ); + EditorGUILayout.PropertyField( m_selectedFormatEnum, new GUIContent( "Format" ) ); + + if( m_selectedFormatEnum.intValue == (int)TextureFormat.DXT1Crunched ) + { + m_selectedFormatEnum.intValue = (int)TextureFormat.DXT1; + Debug.Log( "Texture Array does not support crunched DXT1 format. Changing to DXT1..." ); + } + else if( m_selectedFormatEnum.intValue == (int)TextureFormat.DXT5Crunched ) + { + m_selectedFormatEnum.intValue = (int)TextureFormat.DXT5; + Debug.Log( "Texture Array does not support crunched DXT5 format. Changing to DXT5..." ); + } + + m_quality.intValue = EditorGUILayout.IntSlider( "Format Quality", m_quality.intValue, 0, 100 ); + EditorGUILayout.Separator(); + + EditorGUILayout.LabelField( "Path and Name" ); + EditorGUILayout.BeginHorizontal(); + m_pathButtonContent.text = m_folderPath.stringValue; + Vector2 buttonSize = m_pathButtonStyle.CalcSize( m_pathButtonContent ); + if( GUILayout.Button( m_pathButtonContent, m_pathButtonStyle, GUILayout.MaxWidth( Mathf.Min( Screen.width * 0.5f, buttonSize.x ) ) ) ) + { + string folderpath = EditorUtility.OpenFolderPanel( "Save Texture Array to folder", "Assets/", "" ); + folderpath = FileUtil.GetProjectRelativePath( folderpath ); + if( string.IsNullOrEmpty( folderpath ) ) + m_folderPath.stringValue = "Assets/"; + else + m_folderPath.stringValue = folderpath + "/"; + } + EditorGUI.BeginChangeCheck(); + m_fileName.stringValue = EditorGUILayout.TextField( m_fileName.stringValue, GUILayout.ExpandWidth( true ) ); + if( EditorGUI.EndChangeCheck() ) + { + m_filenameChanged.boolValue = m_fileName.stringValue == ArrayFilename ? false : true; + } + EditorGUILayout.LabelField( ".asset", GUILayout.MaxWidth( 40 ) ); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.Separator(); + + if( GUILayout.Button( "Clear" ) ) + { + m_allTextures.ClearArray(); + } + + if( m_listTextures != null ) + m_listTextures.DoLayoutList(); + + EditorGUILayout.Separator(); + + m_dragAndDropTool.TestDragAndDrop( new Rect( 0, 0, Screen.width, Screen.height ) ); + + m_so.ApplyModifiedProperties(); + } + } + + public class ASETextureArrayCreator : EditorWindow + { + [MenuItem( "Window/Amplify Shader Editor/Texture Array Creator", false, 1001 )] + static void ShowWindow() + { + ASETextureArrayCreator window = EditorWindow.GetWindow(); + window.titleContent.text = "Texture Array"; + window.minSize = new Vector2( 302, 350 ); + window.Show(); + } + + private const string ClearButtonStr = "Clear"; + private const string TextureFilter = "t:Texture2D"; + private const string BuildArrayMessage = "Build Array"; + private const string BuildTexture3DMessage = "Build Texture 3D"; + private const string ArrayFilename = "NewTextureArray"; + private const string Texture3DFilename = "NewTexture3D"; + + TextureArrayCreatorAssetEditor m_editor; + + [SerializeField] + private TextureArrayCreatorAsset m_asset; + + [SerializeField] + private TextureArrayCreatorAsset m_dummyAsset; + + private static List UncompressedFormats = new List() + { + TextureFormat.RGBAFloat, + TextureFormat.RGBAHalf, + TextureFormat.ARGB32, + TextureFormat.RGBA32, + TextureFormat.RGB24, + TextureFormat.Alpha8 + }; + + private GUIStyle m_contentStyle = null; + + private Vector2 m_scrollPos; + private Texture m_lastSaved; + private string m_message = string.Empty; + + private void OnEnable() + { + if( m_contentStyle == null ) + { + m_contentStyle = new GUIStyle( GUIStyle.none ); + m_contentStyle.margin = new RectOffset( 6, 4, 5, 5 ); + } + } + + private void OnDestroy() + { + DestroyImmediate( m_editor ); + if( m_dummyAsset != null && m_dummyAsset != m_asset ) + DestroyImmediate( m_dummyAsset ); + } + + void OnGUI() + { + TextureArrayCreatorAsset currentAsset = null; + if( m_asset != null ) + { + currentAsset = m_asset; + } + else + { + if( m_dummyAsset == null ) + { + m_dummyAsset = ScriptableObject.CreateInstance(); + m_dummyAsset.name = "Dummy"; + } + currentAsset = m_dummyAsset; + } + + m_scrollPos = EditorGUILayout.BeginScrollView( m_scrollPos, GUILayout.Height( position.height ) ); + float cachedWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 100; + EditorGUILayout.BeginVertical( m_contentStyle ); + + string buildButtonStr = currentAsset.Tex3DMode ? BuildTexture3DMessage : BuildArrayMessage; + // build button + EditorGUILayout.BeginHorizontal(); + EditorGUI.BeginDisabledGroup( currentAsset.AllTextures.Count <= 0 ); + if( GUILayout.Button( buildButtonStr, "prebutton", GUILayout.Height( 20 ) ) ) + { + bool showWarning = false; + for( int i = 0; i < currentAsset.AllTextures.Count; i++ ) + { + if( currentAsset.AllTextures[ i ].width != currentAsset.SizeX || currentAsset.AllTextures[ i ].height != currentAsset.SizeY ) + { + showWarning = true; + } + } + + if( !showWarning ) + { + m_message = string.Empty; + if( currentAsset.Tex3DMode ) + BuildTexture3D( currentAsset ); + else + BuildArray( currentAsset ); + } + else if( EditorUtility.DisplayDialog( "Warning!", "Some textures need to be resized to fit the selected size. Do you want to continue?", "Yes", "No" ) ) + { + m_message = string.Empty; + if( currentAsset.Tex3DMode ) + BuildTexture3D( currentAsset ); + else + BuildArray( currentAsset ); + } + } + EditorGUI.EndDisabledGroup(); + EditorGUI.BeginDisabledGroup( m_lastSaved == null ); + GUIContent icon = EditorGUIUtility.IconContent( "icons/d_ViewToolZoom.png" ); + if( GUILayout.Button( icon, "prebutton", GUILayout.Width( 28 ), GUILayout.Height( 20 ) ) ) + { + EditorGUIUtility.PingObject( m_lastSaved ); + } + EditorGUI.EndDisabledGroup(); + EditorGUILayout.EndHorizontal(); + + // message + if( !string.IsNullOrEmpty( m_message ) ) + if( GUILayout.Button( "BUILD REPORT (click to hide):\n\n" + m_message, "helpbox" ) ) + m_message = string.Empty; + + // asset + EditorGUILayout.BeginHorizontal(); + m_asset = EditorGUILayout.ObjectField( "Asset Preset", m_asset, typeof( TextureArrayCreatorAsset ), false ) as TextureArrayCreatorAsset; + if( GUILayout.Button( m_asset != null ? "Save" : "Create", "minibutton", GUILayout.Width( 50 ) ) ) + { + string defaultName = "ArrayPreset"; + if( m_asset != null ) + defaultName = m_asset.name; + + string path = EditorUtility.SaveFilePanelInProject( "Save as", defaultName, "asset", string.Empty ); + if( !string.IsNullOrEmpty( path ) ) + { + TextureArrayCreatorAsset outfile = AssetDatabase.LoadMainAssetAtPath( path ) as TextureArrayCreatorAsset; + if( outfile != null ) + { + EditorUtility.CopySerialized( currentAsset, outfile ); + AssetDatabase.SaveAssets(); + Selection.activeObject = outfile; + EditorGUIUtility.PingObject( outfile ); + } + else + { + if( m_asset != null ) + { + currentAsset = ScriptableObject.CreateInstance(); + EditorUtility.CopySerialized( m_asset, currentAsset ); + } + AssetDatabase.CreateAsset( currentAsset, path ); + Selection.activeObject = currentAsset; + EditorGUIUtility.PingObject( currentAsset ); + m_asset = currentAsset; + } + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.Separator(); + + if( Event.current.type == EventType.Layout ) + { + if( m_editor == null ) + { + m_editor = Editor.CreateEditor( currentAsset, typeof( TextureArrayCreatorAssetEditor ) ) as TextureArrayCreatorAssetEditor; + } + else + { + if( m_editor.Instance != currentAsset ) + { + DestroyImmediate( m_editor ); + m_editor = Editor.CreateEditor( currentAsset, typeof( TextureArrayCreatorAssetEditor ) ) as TextureArrayCreatorAssetEditor; + } + } + } + if( m_editor != null ) + m_editor.OnInspectorGUI(); + + GUILayout.Space( 20 ); + EditorGUILayout.EndVertical(); + EditorGUIUtility.labelWidth = cachedWidth; + EditorGUILayout.EndScrollView(); + } + + private void CopyToArray( ref Texture2D from, ref Texture2DArray to, int arrayIndex, int mipLevel, bool compressed = true ) + { + if( compressed ) + { + Graphics.CopyTexture( from, 0, mipLevel, to, arrayIndex, mipLevel ); + } + else + { + to.SetPixels( from.GetPixels(), arrayIndex, mipLevel ); + to.Apply(); + } + } + +#if NEW_TEXTURE_3D_METHOD + private void BuildTexture3D( TextureArrayCreatorAsset asset ) + { + int sizeX = asset.SizeX; + int sizeY = asset.SizeY; + + Texture3D texture3D = new Texture3D( sizeX, sizeY, asset.AllTextures.Count, asset.SelectedFormatEnum, asset.MipMaps ); + texture3D.wrapMode = asset.WrapMode; + texture3D.filterMode = asset.FilterMode; + texture3D.anisoLevel = asset.AnisoLevel; + //texture3D.Apply( false ); + RenderTexture cache = RenderTexture.active; + RenderTexture rt = new RenderTexture( sizeX, sizeY, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default ); + rt.Create(); + List textures = new List( asset.AllTextures.Count ); + + for( int i = 0; i < asset.AllTextures.Count; i++ ) + { + // build report + int widthChanges = asset.AllTextures[ i ].width < sizeX ? -1 : asset.AllTextures[ i ].width > sizeX ? 1 : 0; + int heightChanges = asset.AllTextures[ i ].height < sizeY ? -1 : asset.AllTextures[ i ].height > sizeY ? 1 : 0; + if( ( widthChanges < 0 && heightChanges <= 0 ) || ( widthChanges <= 0 && heightChanges < 0 ) ) + m_message += asset.AllTextures[ i ].name + " was upscaled\n"; + else if( ( widthChanges > 0 && heightChanges >= 0 ) || ( widthChanges >= 0 && heightChanges > 0 ) ) + m_message += asset.AllTextures[ i ].name + " was downscaled\n"; + else if( ( widthChanges > 0 && heightChanges < 0 ) || ( widthChanges < 0 && heightChanges > 0 ) ) + m_message += asset.AllTextures[ i ].name + " changed dimensions\n"; + + // blit image to upscale or downscale the image to any size + RenderTexture.active = rt; + + bool cachedsrgb = GL.sRGBWrite; + GL.sRGBWrite = !asset.LinearMode; + Graphics.Blit( asset.AllTextures[ i ], rt ); + GL.sRGBWrite = cachedsrgb; + + textures.Add( new Texture2D( sizeX, sizeY, TextureFormat.ARGB32, asset.MipMaps, asset.LinearMode ) ); + textures[ i ].ReadPixels( new Rect( 0, 0, sizeX, sizeY ), 0, 0, asset.MipMaps ); + RenderTexture.active = null; + + bool isCompressed = UncompressedFormats.FindIndex( x => x.Equals( asset.SelectedFormatEnum ) ) < 0; + if( isCompressed ) + { + EditorUtility.CompressTexture( textures[ i ], asset.SelectedFormatEnum, asset.Quality ); + // t2d.Apply( false ); + } + textures[ i ].Apply( false ); + } + + rt.Release(); + RenderTexture.active = cache; + + if( m_message.Length > 0 ) + m_message = m_message.Substring( 0, m_message.Length - 1 ); + + int sizeZ = textures.Count; + Color[] colors = new Color[ sizeX * sizeY * sizeZ ]; + int idx = 0; + for( int z = 0; z < sizeZ; z++ ) + { + for( int y = 0; y < sizeY; y++ ) + { + for( int x = 0; x < sizeX; x++, idx++ ) + { + colors[ idx ] = textures[ z ].GetPixel(x,y); + } + } + } + + texture3D.SetPixels( colors ); + texture3D.Apply(); + + string path = asset.FolderPath + asset.FileName + ".asset"; + Texture3D outfile = AssetDatabase.LoadMainAssetAtPath( path ) as Texture3D; + if( outfile != null ) + { + EditorUtility.CopySerialized( texture3D, outfile ); + AssetDatabase.SaveAssets(); + EditorGUIUtility.PingObject( outfile ); + m_lastSaved = outfile; + } + else + { + AssetDatabase.CreateAsset( texture3D, path ); + EditorGUIUtility.PingObject( texture3D ); + m_lastSaved = texture3D; + } + } +#else + private void BuildTexture3D( TextureArrayCreatorAsset asset ) + { + int sizeX = asset.SizeX; + int sizeY = asset.SizeY; + int numLevels = 1 + (int)Mathf.Floor( Mathf.Log( Mathf.Max( sizeX, sizeY ), 2 ) ); + int mipCount = asset.MipMaps ? numLevels : 1; + + Texture3D texture3D = new Texture3D( sizeX, sizeY, asset.AllTextures.Count, asset.SelectedFormatEnum, asset.MipMaps ); + texture3D.wrapMode = asset.WrapMode; + texture3D.filterMode = asset.FilterMode; + texture3D.anisoLevel = asset.AnisoLevel; + texture3D.Apply( false ); + RenderTexture cache = RenderTexture.active; + RenderTexture rt = new RenderTexture( sizeX, sizeY, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Default ); + rt.Create(); + List> mipColor = new List>(); + if( asset.MipMaps ) + { + for( int i = 0; i < mipCount; i++ ) + { + mipColor.Add( new List() ); + } + } + else + { + mipColor.Add( new List() ); + } + + for( int i = 0; i < asset.AllTextures.Count; i++ ) + { + // build report + int widthChanges = asset.AllTextures[ i ].width < sizeX ? -1 : asset.AllTextures[ i ].width > sizeX ? 1 : 0; + int heightChanges = asset.AllTextures[ i ].height < sizeY ? -1 : asset.AllTextures[ i ].height > sizeY ? 1 : 0; + if( ( widthChanges < 0 && heightChanges <= 0 ) || ( widthChanges <= 0 && heightChanges < 0 ) ) + m_message += asset.AllTextures[ i ].name + " was upscaled\n"; + else if( ( widthChanges > 0 && heightChanges >= 0 ) || ( widthChanges >= 0 && heightChanges > 0 ) ) + m_message += asset.AllTextures[ i ].name + " was downscaled\n"; + else if( ( widthChanges > 0 && heightChanges < 0 ) || ( widthChanges < 0 && heightChanges > 0 ) ) + m_message += asset.AllTextures[ i ].name + " changed dimensions\n"; + + // blit image to upscale or downscale the image to any size + RenderTexture.active = rt; + + bool cachedsrgb = GL.sRGBWrite; + GL.sRGBWrite = !asset.LinearMode; + Graphics.Blit( asset.AllTextures[ i ], rt ); + GL.sRGBWrite = cachedsrgb; + + bool isCompressed = UncompressedFormats.FindIndex( x => x.Equals( asset.SelectedFormatEnum ) ) < 0; + TextureFormat validReadPixelsFormat = isCompressed ? TextureFormat.RGBAFloat : asset.SelectedFormatEnum; + Texture2D t2d = new Texture2D( sizeX, sizeY, validReadPixelsFormat, asset.MipMaps, asset.LinearMode ); + t2d.ReadPixels( new Rect( 0, 0, sizeX, sizeY ), 0, 0, asset.MipMaps ); + RenderTexture.active = null; + + if( isCompressed ) + { + EditorUtility.CompressTexture( t2d, asset.SelectedFormatEnum, asset.Quality ); + // t2d.Apply( false ); + } + t2d.Apply( false ); + + if( asset.MipMaps ) + { + for( int mip = 0; mip < mipCount; mip++ ) + { + mipColor[ mip ].AddRange( t2d.GetPixels( mip ) ); + } + } + else + { + mipColor[ 0 ].AddRange( t2d.GetPixels( 0 ) ); + } + } + + rt.Release(); + RenderTexture.active = cache; + + if( m_message.Length > 0 ) + m_message = m_message.Substring( 0, m_message.Length - 1 ); + + for( int i = 0; i < mipCount; i++ ) + { + texture3D.SetPixels( mipColor[ i ].ToArray(), i ); + } + + texture3D.Apply( false ); + + string path = asset.FolderPath + asset.FileName + ".asset"; + Texture3D outfile = AssetDatabase.LoadMainAssetAtPath( path ) as Texture3D; + if( outfile != null ) + { + EditorUtility.CopySerialized( texture3D, outfile ); + AssetDatabase.SaveAssets(); + EditorGUIUtility.PingObject( outfile ); + m_lastSaved = outfile; + } + else + { + AssetDatabase.CreateAsset( texture3D, path ); + EditorGUIUtility.PingObject( texture3D ); + m_lastSaved = texture3D; + } + } +#endif + private void BuildTexture3DAutoMips( TextureArrayCreatorAsset asset ) + { + int sizeX = asset.SizeX; + int sizeY = asset.SizeY; + + Texture3D texture3D = new Texture3D( sizeX, sizeY, asset.AllTextures.Count, asset.SelectedFormatEnum, asset.MipMaps ); + texture3D.wrapMode = asset.WrapMode; + texture3D.filterMode = asset.FilterMode; + texture3D.anisoLevel = asset.AnisoLevel; + texture3D.Apply( false ); + RenderTexture cache = RenderTexture.active; + RenderTexture rt = new RenderTexture( sizeX, sizeY, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Default ); + rt.Create(); + List texColors = new List(); + + for( int i = 0; i < asset.AllTextures.Count; i++ ) + { + // build report + int widthChanges = asset.AllTextures[ i ].width < sizeX ? -1 : asset.AllTextures[ i ].width > sizeX ? 1 : 0; + int heightChanges = asset.AllTextures[ i ].height < sizeY ? -1 : asset.AllTextures[ i ].height > sizeY ? 1 : 0; + if( ( widthChanges < 0 && heightChanges <= 0 ) || ( widthChanges <= 0 && heightChanges < 0 ) ) + m_message += asset.AllTextures[ i ].name + " was upscaled\n"; + else if( ( widthChanges > 0 && heightChanges >= 0 ) || ( widthChanges >= 0 && heightChanges > 0 ) ) + m_message += asset.AllTextures[ i ].name + " was downscaled\n"; + else if( ( widthChanges > 0 && heightChanges < 0 ) || ( widthChanges < 0 && heightChanges > 0 ) ) + m_message += asset.AllTextures[ i ].name + " changed dimensions\n"; + + // blit image to upscale or downscale the image to any size + RenderTexture.active = rt; + + bool cachedsrgb = GL.sRGBWrite; + GL.sRGBWrite = !asset.LinearMode; + Graphics.Blit( asset.AllTextures[ i ], rt ); + GL.sRGBWrite = cachedsrgb; + + bool isCompressed = UncompressedFormats.FindIndex( x => x.Equals( asset.SelectedFormatEnum ) ) < 0; + TextureFormat validReadPixelsFormat = isCompressed ? TextureFormat.RGBAFloat : asset.SelectedFormatEnum; + Texture2D t2d = new Texture2D( sizeX, sizeY, validReadPixelsFormat, asset.MipMaps, asset.LinearMode ); + t2d.ReadPixels( new Rect( 0, 0, sizeX, sizeY ), 0, 0, asset.MipMaps ); + RenderTexture.active = null; + + if( isCompressed ) + { + EditorUtility.CompressTexture( t2d, asset.SelectedFormatEnum, asset.Quality ); + t2d.Apply( false ); + } + texColors.AddRange( t2d.GetPixels() ); + } + + rt.Release(); + RenderTexture.active = cache; + + if( m_message.Length > 0 ) + m_message = m_message.Substring( 0, m_message.Length - 1 ); + + texture3D.SetPixels( texColors.ToArray() ); + texture3D.Apply(); + + string path = asset.FolderPath + asset.FileName + ".asset"; + Texture3D outfile = AssetDatabase.LoadMainAssetAtPath( path ) as Texture3D; + if( outfile != null ) + { + EditorUtility.CopySerialized( texture3D, outfile ); + AssetDatabase.SaveAssets(); + EditorGUIUtility.PingObject( outfile ); + m_lastSaved = outfile; + } + else + { + AssetDatabase.CreateAsset( texture3D, path ); + EditorGUIUtility.PingObject( texture3D ); + m_lastSaved = texture3D; + } + } + + private void BuildArray( TextureArrayCreatorAsset asset ) + { + int sizeX = asset.SizeX; + int sizeY = asset.SizeY; + + Texture2DArray textureArray = new Texture2DArray( sizeX, sizeY, asset.AllTextures.Count, asset.SelectedFormatEnum, asset.MipMaps, asset.LinearMode ); + textureArray.wrapMode = asset.WrapMode; + textureArray.filterMode = asset.FilterMode; + textureArray.anisoLevel = asset.AnisoLevel; + textureArray.Apply( false ); + RenderTexture cache = RenderTexture.active; + RenderTexture rt = new RenderTexture( sizeX, sizeY, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Default ); + rt.Create(); + for( int i = 0; i < asset.AllTextures.Count; i++ ) + { + // build report + int widthChanges = asset.AllTextures[ i ].width < sizeX ? -1 : asset.AllTextures[ i ].width > sizeX ? 1 : 0; + int heightChanges = asset.AllTextures[ i ].height < sizeY ? -1 : asset.AllTextures[ i ].height > sizeY ? 1 : 0; + if( ( widthChanges < 0 && heightChanges <= 0 ) || ( widthChanges <= 0 && heightChanges < 0 ) ) + m_message += asset.AllTextures[ i ].name + " was upscaled\n"; + else if( ( widthChanges > 0 && heightChanges >= 0 ) || ( widthChanges >= 0 && heightChanges > 0 ) ) + m_message += asset.AllTextures[ i ].name + " was downscaled\n"; + else if( ( widthChanges > 0 && heightChanges < 0 ) || ( widthChanges < 0 && heightChanges > 0 ) ) + m_message += asset.AllTextures[ i ].name + " changed dimensions\n"; + + // blit image to upscale or downscale the image to any size + RenderTexture.active = rt; + + bool cachedsrgb = GL.sRGBWrite; + GL.sRGBWrite = !asset.LinearMode; + Graphics.Blit( asset.AllTextures[ i ], rt ); + GL.sRGBWrite = cachedsrgb; + + bool isCompressed = UncompressedFormats.FindIndex( x => x.Equals( asset.SelectedFormatEnum ) ) < 0; + TextureFormat validReadPixelsFormat = isCompressed ? TextureFormat.RGBAFloat : asset.SelectedFormatEnum; + Texture2D t2d = new Texture2D( sizeX, sizeY, validReadPixelsFormat, asset.MipMaps, asset.LinearMode ); + t2d.ReadPixels( new Rect( 0, 0, sizeX, sizeY ), 0, 0, asset.MipMaps ); + RenderTexture.active = null; + + if( isCompressed ) + { + EditorUtility.CompressTexture( t2d, asset.SelectedFormatEnum, asset.Quality ); + t2d.Apply( false ); + } + + if( asset.MipMaps ) + { + int maxSize = Mathf.Max( sizeX, sizeY ); + int numLevels = 1 + (int)Mathf.Floor( Mathf.Log( maxSize, 2 ) ); + for( int mip = 0; mip < numLevels; mip++ ) + { + CopyToArray( ref t2d, ref textureArray, i, mip, isCompressed ); + } + } + else + { + CopyToArray( ref t2d, ref textureArray, i, 0, isCompressed ); + } + } + + rt.Release(); + RenderTexture.active = cache; + if( m_message.Length > 0 ) + m_message = m_message.Substring( 0, m_message.Length - 1 ); + + string path = asset.FolderPath + asset.FileName + ".asset"; + Texture2DArray outfile = AssetDatabase.LoadMainAssetAtPath( path ) as Texture2DArray; + if( outfile != null ) + { + EditorUtility.CopySerialized( textureArray, outfile ); + AssetDatabase.SaveAssets(); + EditorGUIUtility.PingObject( outfile ); + m_lastSaved = outfile; + } + else + { + AssetDatabase.CreateAsset( textureArray, path ); + EditorGUIUtility.PingObject( textureArray ); + m_lastSaved = textureArray; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASETextureArrayCreator.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASETextureArrayCreator.cs.meta new file mode 100644 index 0000000..7a01b4f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASETextureArrayCreator.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 436dc8bc09773454db57b9fbf799ec9d +timeCreated: 1504633068 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomMaterialInspector.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomMaterialInspector.cs new file mode 100644 index 0000000..b4584fe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomMaterialInspector.cs @@ -0,0 +1,543 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System; +using System.Reflection; +using AmplifyShaderEditor; + + +public static class MaterialPropertyHandlerEx +{ + private static System.Type type = null; + public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEditor.MaterialPropertyHandler, UnityEditor" ) : type; } } + public static object GetHandler( Shader shader, string name ) + { + return MaterialPropertyHandlerEx.Type.InvokeMember( "GetHandler", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { shader, name } ); + } + + public static void OnGUI( object obj, ref Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor ) + { + Type.InvokeMember( "OnGUI", BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, obj, new object[] { position, prop, label, editor } ); + } + + public static float GetPropertyHeight( object obj, MaterialProperty prop, string label, MaterialEditor editor ) + { + return (float)Type.InvokeMember( "GetPropertyHeight", BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, obj, new object[] { prop, label, editor } ); + } + + public static object PropertyDrawer( object obj ) + { + return Type.InvokeMember( "propertyDrawer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty, null, obj, new object[] {} ); + } +} + +internal class ASEMaterialInspector : ShaderGUI +{ + private const string CopyButtonStr = "Copy Values"; + private const string PasteButtonStr = "Paste Values"; + private const string PreviewModelPref = "ASEMI_PREVIEWMODEL"; + + private static MaterialEditor m_instance = null; + private static bool m_refreshOnUndo = false; + + private bool m_initialized = false; + private double m_lastRenderedTime; + private PreviewRenderUtility m_previewRenderUtility; + private Mesh m_targetMesh; + private Vector2 m_previewDir = new Vector2( 120f, -20f ); + private int m_selectedMesh = 0; + + + // Reflection Fields + private Type m_modelInspectorType = null; + private MethodInfo m_renderMeshMethod = null; + private Type m_previewGUIType = null; + private MethodInfo m_dragMethod = null; + private FieldInfo m_selectedField = null; + private FieldInfo m_infoField = null; + +#if UNITY_2020_1_OR_NEWER + private Type m_previewSettingsType = null; + object m_previewSettingsInstance; + FieldInfo previewDirInfo; + FieldInfo shadedMaterialInfo; + FieldInfo activeMaterialInfo; +#endif + +#if UNITY_2018_2_OR_NEWER + public override void OnClosed( Material material ) + { + base.OnClosed( material ); + CleanUp(); + } +#endif + + void CleanUp() + { + if( m_previewRenderUtility != null ) + { + m_previewRenderUtility.Cleanup(); + m_previewRenderUtility = null; + } + } + + void UndoRedoPerformed() + { + m_refreshOnUndo = true; + } + + ~ASEMaterialInspector() + { + Undo.undoRedoPerformed -= UndoRedoPerformed; + CleanUp(); + } + public override void OnGUI( MaterialEditor materialEditor, MaterialProperty[] properties ) + { + IOUtils.Init(); + Material mat = materialEditor.target as Material; + + if( mat == null ) + return; + + m_instance = materialEditor; + + if( !m_initialized ) + { + Init(); + m_initialized = true; + Undo.undoRedoPerformed += UndoRedoPerformed; + } + + if( Event.current.type == EventType.Repaint && + mat.HasProperty( IOUtils.DefaultASEDirtyCheckId ) && + mat.GetInt( IOUtils.DefaultASEDirtyCheckId ) == 1 ) + { + mat.SetInt( IOUtils.DefaultASEDirtyCheckId, 0 ); + UIUtils.ForceUpdateFromMaterial(); + //Event.current.Use(); + } + + if( materialEditor.isVisible ) + { + GUILayout.BeginVertical(); + { + GUILayout.Space( 3 ); + if( GUILayout.Button( "Open in Shader Editor" ) ) + { +#if UNITY_2018_3_OR_NEWER + ASEPackageManagerHelper.SetupLateMaterial( mat ); + +#else + AmplifyShaderEditorWindow.LoadMaterialToASE( mat ); +#endif + } + + GUILayout.BeginHorizontal(); + { + if( GUILayout.Button( CopyButtonStr ) ) + { + System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; + + Shader shader = mat.shader; + int propertyCount = UnityEditor.ShaderUtil.GetPropertyCount( shader ); + string allProperties = string.Empty; + for( int i = 0; i < propertyCount; i++ ) + { + UnityEditor.ShaderUtil.ShaderPropertyType type = UnityEditor.ShaderUtil.GetPropertyType( shader, i ); + string name = UnityEditor.ShaderUtil.GetPropertyName( shader, i ); + string valueStr = string.Empty; + switch( type ) + { + case UnityEditor.ShaderUtil.ShaderPropertyType.Color: + { + Color value = mat.GetColor( name ); + valueStr = value.r.ToString() + IOUtils.VECTOR_SEPARATOR + + value.g.ToString() + IOUtils.VECTOR_SEPARATOR + + value.b.ToString() + IOUtils.VECTOR_SEPARATOR + + value.a.ToString(); + } + break; + case UnityEditor.ShaderUtil.ShaderPropertyType.Vector: + { + Vector4 value = mat.GetVector( name ); + valueStr = value.x.ToString() + IOUtils.VECTOR_SEPARATOR + + value.y.ToString() + IOUtils.VECTOR_SEPARATOR + + value.z.ToString() + IOUtils.VECTOR_SEPARATOR + + value.w.ToString(); + } + break; + case UnityEditor.ShaderUtil.ShaderPropertyType.Float: + { + float value = mat.GetFloat( name ); + valueStr = value.ToString(); + } + break; + case UnityEditor.ShaderUtil.ShaderPropertyType.Range: + { + float value = mat.GetFloat( name ); + valueStr = value.ToString(); + } + break; + case UnityEditor.ShaderUtil.ShaderPropertyType.TexEnv: + { + Texture value = mat.GetTexture( name ); + valueStr = AssetDatabase.GetAssetPath( value ); + Vector2 offset = mat.GetTextureOffset( name ); + Vector2 scale = mat.GetTextureScale( name ); + valueStr += IOUtils.VECTOR_SEPARATOR + scale.x.ToString() + + IOUtils.VECTOR_SEPARATOR + scale.y.ToString() + + IOUtils.VECTOR_SEPARATOR + offset.x.ToString() + + IOUtils.VECTOR_SEPARATOR + offset.y.ToString(); + } + break; + } + + allProperties += name + IOUtils.FIELD_SEPARATOR + type + IOUtils.FIELD_SEPARATOR + valueStr; + + if( i < ( propertyCount - 1 ) ) + { + allProperties += IOUtils.LINE_TERMINATOR; + } + } + EditorPrefs.SetString( IOUtils.MAT_CLIPBOARD_ID, allProperties ); + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + } + + if( GUILayout.Button( PasteButtonStr ) ) + { + System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; + string propertiesStr = EditorPrefs.GetString( IOUtils.MAT_CLIPBOARD_ID, string.Empty ); + if( !string.IsNullOrEmpty( propertiesStr ) ) + { + string[] propertyArr = propertiesStr.Split( IOUtils.LINE_TERMINATOR ); + bool validData = true; + try + { + for( int i = 0; i < propertyArr.Length; i++ ) + { + string[] valuesArr = propertyArr[ i ].Split( IOUtils.FIELD_SEPARATOR ); + if( valuesArr.Length != 3 ) + { + Debug.LogWarning( "Material clipboard data is corrupted" ); + validData = false; + break; + } + else if( mat.HasProperty( valuesArr[ 0 ] ) ) + { + UnityEditor.ShaderUtil.ShaderPropertyType type = (UnityEditor.ShaderUtil.ShaderPropertyType)Enum.Parse( typeof( UnityEditor.ShaderUtil.ShaderPropertyType ), valuesArr[ 1 ] ); + switch( type ) + { + case UnityEditor.ShaderUtil.ShaderPropertyType.Color: + { + string[] colorVals = valuesArr[ 2 ].Split( IOUtils.VECTOR_SEPARATOR ); + if( colorVals.Length != 4 ) + { + Debug.LogWarning( "Material clipboard data is corrupted" ); + validData = false; + break; + } + else + { + mat.SetColor( valuesArr[ 0 ], new Color( Convert.ToSingle( colorVals[ 0 ] ), + Convert.ToSingle( colorVals[ 1 ] ), + Convert.ToSingle( colorVals[ 2 ] ), + Convert.ToSingle( colorVals[ 3 ] ) ) ); + } + } + break; + case UnityEditor.ShaderUtil.ShaderPropertyType.Vector: + { + string[] vectorVals = valuesArr[ 2 ].Split( IOUtils.VECTOR_SEPARATOR ); + if( vectorVals.Length != 4 ) + { + Debug.LogWarning( "Material clipboard data is corrupted" ); + validData = false; + break; + } + else + { + mat.SetVector( valuesArr[ 0 ], new Vector4( Convert.ToSingle( vectorVals[ 0 ] ), + Convert.ToSingle( vectorVals[ 1 ] ), + Convert.ToSingle( vectorVals[ 2 ] ), + Convert.ToSingle( vectorVals[ 3 ] ) ) ); + } + } + break; + case UnityEditor.ShaderUtil.ShaderPropertyType.Float: + { + mat.SetFloat( valuesArr[ 0 ], Convert.ToSingle( valuesArr[ 2 ] ) ); + } + break; + case UnityEditor.ShaderUtil.ShaderPropertyType.Range: + { + mat.SetFloat( valuesArr[ 0 ], Convert.ToSingle( valuesArr[ 2 ] ) ); + } + break; + case UnityEditor.ShaderUtil.ShaderPropertyType.TexEnv: + { + string[] texVals = valuesArr[ 2 ].Split( IOUtils.VECTOR_SEPARATOR ); + if( texVals.Length != 5 ) + { + Debug.LogWarning( "Material clipboard data is corrupted" ); + validData = false; + break; + } + else + { + mat.SetTexture( valuesArr[ 0 ], AssetDatabase.LoadAssetAtPath( texVals[ 0 ] ) ); + mat.SetTextureScale( valuesArr[ 0 ], new Vector2( Convert.ToSingle( texVals[ 1 ] ), Convert.ToSingle( texVals[ 2 ] ) ) ); + mat.SetTextureOffset( valuesArr[ 0 ], new Vector2( Convert.ToSingle( texVals[ 3 ] ), Convert.ToSingle( texVals[ 4 ] ) ) ); + } + } + break; + } + } + } + } + catch( Exception e ) + { + Debug.LogException( e ); + validData = false; + } + + + if( validData ) + { + materialEditor.PropertiesChanged(); + UIUtils.CopyValuesFromMaterial( mat ); + } + else + { + EditorPrefs.SetString( IOUtils.MAT_CLIPBOARD_ID, string.Empty ); + } + } + System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture; + } + } + GUILayout.EndHorizontal(); + GUILayout.Space( 5 ); + } + GUILayout.EndVertical(); + } + EditorGUI.BeginChangeCheck(); + //base.OnGUI( materialEditor, properties ); + + // Draw custom properties instead of calling BASE to use single line texture properties + materialEditor.SetDefaultGUIWidths(); + + if( m_infoField == null ) + { + m_infoField = typeof( MaterialEditor ).GetField( "m_InfoMessage", BindingFlags.Instance | BindingFlags.NonPublic ); + } + + string info = m_infoField.GetValue( materialEditor ) as string; + if( !string.IsNullOrEmpty( info ) ) + { + EditorGUILayout.HelpBox( info, MessageType.Info ); + } + else + { + GUIUtility.GetControlID( "EditorTextField".GetHashCode(), FocusType.Passive, new Rect( 0f, 0f, 0f, 0f ) ); + } + + for( int i = 0; i < properties.Length; i++ ) + { + if( ( properties[ i ].flags & ( MaterialProperty.PropFlags.HideInInspector | MaterialProperty.PropFlags.PerRendererData ) ) == MaterialProperty.PropFlags.None ) + { + // Removed no scale offset one line texture property for consistency :( sad face + //if( ( properties[ i ].flags & MaterialProperty.PropFlags.NoScaleOffset ) == MaterialProperty.PropFlags.NoScaleOffset ) + //{ + // object obj = MaterialPropertyHandlerEx.GetHandler( mat.shader, properties[ i ].name ); + // if( obj != null ) + // { + // float height = MaterialPropertyHandlerEx.GetPropertyHeight( obj, properties[ i ], properties[ i ].displayName, materialEditor ); + // //Rect rect = (Rect)materialEditor.GetType().InvokeMember( "GetPropertyRect", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, materialEditor, new object[] { properties[ i ], properties[ i ].displayName, true } ); + // Rect rect = EditorGUILayout.GetControlRect( true, height, EditorStyles.layerMaskField ); + // MaterialPropertyHandlerEx.OnGUI( obj, ref rect, properties[ i ], new GUIContent( properties[ i ].displayName ), materialEditor ); + + // if( MaterialPropertyHandlerEx.PropertyDrawer( obj ) != null ) + // continue; + + // rect = EditorGUILayout.GetControlRect( true, height, EditorStyles.layerMaskField ); + // materialEditor.TexturePropertyMiniThumbnail( rect, properties[ i ], properties[ i ].displayName, string.Empty ); + // } + // else + // { + // materialEditor.TexturePropertySingleLine( new GUIContent( properties[ i ].displayName ), properties[ i ] ); + // } + //} + //else + //{ + float propertyHeight = materialEditor.GetPropertyHeight( properties[ i ], properties[ i ].displayName ); + Rect controlRect = EditorGUILayout.GetControlRect( true, propertyHeight, EditorStyles.layerMaskField, new GUILayoutOption[ 0 ] ); + materialEditor.ShaderProperty( controlRect, properties[ i ], properties[ i ].displayName ); + //} + } + } + + EditorGUILayout.Space(); + materialEditor.RenderQueueField(); +#if UNITY_5_6_OR_NEWER + materialEditor.EnableInstancingField(); +#endif +#if UNITY_5_6_2 || UNITY_5_6_3 || UNITY_5_6_4 || UNITY_2017_1_OR_NEWER + materialEditor.DoubleSidedGIField(); +#endif + materialEditor.LightmapEmissionProperty(); + if( m_refreshOnUndo || EditorGUI.EndChangeCheck() ) + { + m_refreshOnUndo = false; + + string isEmissive = mat.GetTag( "IsEmissive", false, "false" ); + if( isEmissive.Equals( "true" ) ) + { + mat.globalIlluminationFlags &= (MaterialGlobalIlluminationFlags)3; + } + else + { + mat.globalIlluminationFlags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack; + } + + UIUtils.CopyValuesFromMaterial( mat ); + } + + if( materialEditor.RequiresConstantRepaint() && m_lastRenderedTime + 0.032999999821186066 < EditorApplication.timeSinceStartup ) + { + this.m_lastRenderedTime = EditorApplication.timeSinceStartup; + materialEditor.Repaint(); + } + } + + private void Init() + { + string guid = EditorPrefs.GetString( PreviewModelPref, "" ); + if( !string.IsNullOrEmpty( guid ) ) + { + m_targetMesh = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( guid ) ); + } + } + + public override void OnMaterialPreviewSettingsGUI( MaterialEditor materialEditor ) + { + + base.OnMaterialPreviewSettingsGUI( materialEditor ); + + if( UnityEditor.ShaderUtil.hardwareSupportsRectRenderTexture ) + { + EditorGUI.BeginChangeCheck(); + m_targetMesh = (Mesh)EditorGUILayout.ObjectField( m_targetMesh, typeof( Mesh ), false, GUILayout.MaxWidth( 120 ) ); + if( EditorGUI.EndChangeCheck() ) + { + if( m_targetMesh != null ) + { + EditorPrefs.SetString( PreviewModelPref, AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_targetMesh ) ) ); + } + else + { + EditorPrefs.SetString( PreviewModelPref, "" ); + } + } + + if( m_selectedField == null ) + { + m_selectedField = typeof( MaterialEditor ).GetField( "m_SelectedMesh", BindingFlags.Instance | BindingFlags.NonPublic ); + } + + m_selectedMesh = (int)m_selectedField.GetValue( materialEditor ); + + if( m_selectedMesh != 0 ) + { + if( m_targetMesh != null ) + { + m_targetMesh = null; + EditorPrefs.SetString( PreviewModelPref, "" ); + } + } + } + } + + public override void OnMaterialInteractivePreviewGUI( MaterialEditor materialEditor, Rect r, GUIStyle background ) + { + if( Event.current.type == EventType.DragExited ) + { + if( DragAndDrop.objectReferences.Length > 0 ) + { + GameObject dropped = DragAndDrop.objectReferences[ 0 ] as GameObject; + if( dropped != null ) + { + m_targetMesh = AssetDatabase.LoadAssetAtPath( AssetDatabase.GetAssetPath( dropped ) ); + EditorPrefs.SetString( PreviewModelPref, AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_targetMesh ) ) ); + } + } + } + + if( m_targetMesh == null ) + { + base.OnMaterialInteractivePreviewGUI( materialEditor, r, background ); + return; + } + + Material mat = materialEditor.target as Material; + + if( m_previewRenderUtility == null ) + { + m_previewRenderUtility = new PreviewRenderUtility(); +#if UNITY_2017_1_OR_NEWER + m_previewRenderUtility.cameraFieldOfView = 30f; +#else + m_previewRenderUtility.m_CameraFieldOfView = 30f; +#endif + } + + if( m_previewGUIType == null ) + { + m_previewGUIType = Type.GetType( "PreviewGUI, UnityEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" ); + m_dragMethod = m_previewGUIType.GetMethod( "Drag2D", BindingFlags.Static | BindingFlags.Public ); + } + + if( m_modelInspectorType == null ) + { + m_modelInspectorType = Type.GetType( "UnityEditor.ModelInspector, UnityEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" ); + m_renderMeshMethod = m_modelInspectorType.GetMethod( "RenderMeshPreview", BindingFlags.Static | BindingFlags.NonPublic ); + } + + m_previewDir = (Vector2)m_dragMethod.Invoke( m_previewGUIType, new object[] { m_previewDir, r } ); + +#if UNITY_2020_1_OR_NEWER + if( m_previewSettingsType == null ) + { + m_previewSettingsType = m_modelInspectorType.GetNestedType( "PreviewSettings",BindingFlags.NonPublic); + } + + if( m_previewSettingsInstance == null ) + { + m_previewSettingsInstance = Activator.CreateInstance( m_previewSettingsType ); + previewDirInfo = m_previewSettingsType.GetField( "previewDir", BindingFlags.Instance | BindingFlags.Public ); + shadedMaterialInfo = m_previewSettingsType.GetField( "shadedPreviewMaterial", BindingFlags.Instance | BindingFlags.Public ); + activeMaterialInfo = m_previewSettingsType.GetField( "activeMaterial", BindingFlags.Instance | BindingFlags.Public ); + } + + shadedMaterialInfo.SetValue( m_previewSettingsInstance, mat ); + activeMaterialInfo.SetValue( m_previewSettingsInstance, mat ); + previewDirInfo.SetValue( m_previewSettingsInstance, m_previewDir ); + + if( Event.current.type == EventType.Repaint ) + { + m_previewRenderUtility.BeginPreview( r, background ); + m_renderMeshMethod.Invoke( m_modelInspectorType, new object[] { m_targetMesh, m_previewRenderUtility, m_previewSettingsInstance, -1 } ); + m_previewRenderUtility.EndAndDrawPreview( r ); + } +#else + if( Event.current.type == EventType.Repaint ) + { + m_previewRenderUtility.BeginPreview( r, background ); + m_renderMeshMethod.Invoke( m_modelInspectorType, new object[] { m_targetMesh, m_previewRenderUtility, mat, null, m_previewDir, -1 } ); + m_previewRenderUtility.EndAndDrawPreview( r ); + } +#endif + } + + public static MaterialEditor Instance { get { return m_instance; } set { m_instance = value; } } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomMaterialInspector.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomMaterialInspector.cs.meta new file mode 100644 index 0000000..c587b4c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomMaterialInspector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a1c012872b428594f95e585bd19e5347 +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomShaderInspector.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomShaderInspector.cs new file mode 100644 index 0000000..95310d4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomShaderInspector.cs @@ -0,0 +1,969 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Reflection; +using System.Globalization; +using UnityEngine; +using AmplifyShaderEditor; + +namespace UnityEditor +{ + [CustomEditor( typeof( Shader ) )] + internal class CustomShaderInspector : Editor + { + internal class Styles + { + public static Texture2D errorIcon = EditorGUIUtilityEx.LoadIcon( "console.erroricon.sml" ); + + public static Texture2D warningIcon = EditorGUIUtilityEx.LoadIcon( "console.warnicon.sml" ); + #if UNITY_2020_1_OR_NEWER + public static GUIContent togglePreprocess = EditorGUIUtilityEx.TextContent( "Preprocess only|Show preprocessor output instead of compiled shader code" ); + #if UNITY_2020_2_OR_NEWER + public static GUIContent toggleStripLineDirective = EditorGUIUtility.TrTextContent( "Strip #line directives", "Strip #line directives from preprocessor output" ); + #endif + #endif + public static GUIContent showSurface = EditorGUIUtilityEx.TextContent( "Show generated code|Show generated code of a surface shader" ); + + public static GUIContent showFF = EditorGUIUtilityEx.TextContent( "Show generated code|Show generated code of a fixed function shader" ); + + public static GUIContent showCurrent = new GUIContent( "Compile and show code | ▾" ); + + public static GUIStyle messageStyle = "CN StatusInfo"; + + public static GUIStyle evenBackground = "CN EntryBackEven"; + + public static GUIContent no = EditorGUIUtilityEx.TextContent( "no" ); + + public static GUIContent builtinShader = EditorGUIUtilityEx.TextContent( "Built-in shader" ); + + public static GUIContent arrayValuePopupButton = EditorGUIUtilityEx.TextContent( "..." ); + } +#if UNITY_2020_1_OR_NEWER + private static bool s_PreprocessOnly = false; +#if UNITY_2020_2_OR_NEWER + private static bool s_StripLineDirectives = true; +#endif +#endif + private const float kSpace = 5f; + + const float kValueFieldWidth = 200.0f; + const float kArrayValuePopupBtnWidth = 25.0f; + + private static readonly string[] kPropertyTypes = new string[] + { + "Color: ", + "Vector: ", + "Float: ", + "Range: ", + "Texture: " + }; + + private static readonly string[] kTextureTypes = new string[] + { + "No Texture?: ", + "1D?: ", + "2D: ", + "3D: ", + "Cube: ", + "2DArray: ", + "Any texture: " + }; + + private static readonly int kErrorViewHash = "ShaderErrorView".GetHashCode(); + + private Vector2 m_ScrollPosition = Vector2.zero; + + private PreviewRenderUtility m_previewRenderUtility; + private Material m_material; + private Mesh m_previewMesh; + private Vector2 m_mouseDelta; + private Transform m_cameraTransform; + + private static int m_sliderHashCode = -1; + private const float MaxDeltaY = 90; + private const int DefaultMouseSpeed = 1; + private const int ShiftMouseSpeed = 3; + private const float DeltaMultiplier = 135f; + private void ValidateData() + { + if ( m_previewRenderUtility == null ) + { + m_previewRenderUtility = new PreviewRenderUtility(); +#if UNITY_2017_1_OR_NEWER + m_cameraTransform = m_previewRenderUtility.camera.transform; +#else + m_cameraTransform = m_previewRenderUtility.m_Camera.transform; +#endif + m_cameraTransform.position = new Vector3( 0, 0, -4 ); + m_cameraTransform.rotation = Quaternion.identity; + } + + if ( m_material == null ) + { + m_material = new Material( target as Shader ); + m_material.hideFlags = HideFlags.DontSave; + } + + if ( m_previewMesh == null ) + { + m_previewMesh = Resources.GetBuiltinResource( "Sphere.fbx" ); + } + + if ( m_sliderHashCode < 0 ) + { + "Slider".GetHashCode(); + } + } + + public override bool HasPreviewGUI() + { + ValidateData(); + return true; + } + + public static Vector2 CheckMouseMovement( Vector2 scrollPosition, Rect position ) + { + int controlID = GUIUtility.GetControlID( m_sliderHashCode, FocusType.Passive ); + Event current = Event.current; + switch ( current.GetTypeForControl( controlID ) ) + { + case EventType.MouseDown: + { + if ( position.Contains( current.mousePosition ) && position.width > 50f ) + { + GUIUtility.hotControl = controlID; + current.Use(); + EditorGUIUtility.SetWantsMouseJumping( 1 ); + } + } + break; + case EventType.MouseUp: + { + if ( GUIUtility.hotControl == controlID ) + { + GUIUtility.hotControl = 0; + } + EditorGUIUtility.SetWantsMouseJumping( 0 ); + } + break; + case EventType.MouseDrag: + { + if ( GUIUtility.hotControl == controlID ) + { + scrollPosition -= DeltaMultiplier * current.delta * ( float ) ( ( current.shift ) ? ShiftMouseSpeed : DefaultMouseSpeed ) / Mathf.Min( position.width, position.height ); + scrollPosition.y = Mathf.Clamp( scrollPosition.y, -MaxDeltaY, MaxDeltaY ); + current.Use(); + } + } + break; + } + return scrollPosition; + } + + public override void OnPreviewGUI( Rect r, GUIStyle background ) + { + m_mouseDelta = CheckMouseMovement( m_mouseDelta, r ); + + if ( Event.current.type == EventType.Repaint ) + { + m_previewRenderUtility.BeginPreview( r, background ); + + Texture resultRender = m_previewRenderUtility.EndPreview(); + m_previewRenderUtility.DrawMesh( m_previewMesh, Matrix4x4.identity, m_material, 0 ); + m_cameraTransform.rotation = Quaternion.Euler( new Vector3( -m_mouseDelta.y, -m_mouseDelta.x, 0 ) ); + m_cameraTransform.position = m_cameraTransform.forward * -8f; +#if UNITY_2017_1_OR_NEWER + m_previewRenderUtility.camera.Render(); +#else + m_previewRenderUtility.m_Camera.Render(); +#endif + GUI.DrawTexture( r, resultRender, ScaleMode.StretchToFill, false ); + } + } + + void OnDestroy() + { + CleanUp(); + } + + public void OnDisable() + { + CleanUp(); + if( m_SrpCompatibilityCheckMaterial != null ) + { + GameObject.DestroyImmediate( m_SrpCompatibilityCheckMaterial ); + } + } + + void CleanUp() + { + if( m_previewRenderUtility != null ) + { + m_previewRenderUtility.Cleanup(); + m_previewRenderUtility = null; + } + + if( m_previewMesh != null ) + { + Resources.UnloadAsset( m_previewMesh ); + m_previewMesh = null; + } + + if( m_previewRenderUtility != null ) + { + m_previewRenderUtility.Cleanup(); + m_previewRenderUtility = null; + } + m_material = null; + } + + private Material m_SrpCompatibilityCheckMaterial = null; + public Material srpCompatibilityCheckMaterial + { + get + { + if( m_SrpCompatibilityCheckMaterial == null ) + { + m_SrpCompatibilityCheckMaterial = new Material( target as Shader ); + } + return m_SrpCompatibilityCheckMaterial; + } + } + + public virtual void OnEnable() + { + Shader s = this.target as Shader; + if( s!= null ) + ShaderUtilEx.FetchCachedErrors( s ); + } + + private static string GetPropertyType( Shader s, int index ) + { + UnityEditor.ShaderUtil.ShaderPropertyType propertyType = UnityEditor.ShaderUtil.GetPropertyType( s, index ); + if ( propertyType == UnityEditor.ShaderUtil.ShaderPropertyType.TexEnv ) + { + return CustomShaderInspector.kTextureTypes[ ( int ) UnityEditor.ShaderUtil.GetTexDim( s, index ) ]; + } + return CustomShaderInspector.kPropertyTypes[ ( int ) propertyType ]; + } + + public override void OnInspectorGUI() + { + Shader shader = this.target as Shader; + if ( shader == null ) + { + return; + } + + GUI.enabled = true; + + GUILayout.Space( 3 ); + GUILayout.BeginHorizontal(); + { + if ( GUILayout.Button( "Open in Shader Editor" ) ) + { +#if UNITY_2018_3_OR_NEWER + ASEPackageManagerHelper.SetupLateShader( shader ); +#else + AmplifyShaderEditorWindow.ConvertShaderToASE( shader ); +#endif + } + + if ( GUILayout.Button( "Open in Text Editor" ) ) + { + if( UIUtils.IsUnityNativeShader( shader ) ) + { + Debug.LogWarningFormat( "Action not allowed. Attempting to load the native {0} shader into Text Editor", shader.name ); + } + else + { + AssetDatabase.OpenAsset( shader, 1 ); + } + } + } + GUILayout.EndHorizontal(); + + GUILayout.Space( 5 ); + EditorGUI.indentLevel = 0; + this.ShowShaderCodeArea( shader ); + if ( shader.isSupported ) + { + EditorGUILayout.LabelField( "Cast shadows", ( !ShaderUtilEx.HasShadowCasterPass( shader ) ) ? "no" : "yes", new GUILayoutOption[ 0 ] ); + EditorGUILayout.LabelField( "Render queue", ShaderUtilEx.GetRenderQueue( shader ).ToString( System.Globalization.CultureInfo.InvariantCulture ), new GUILayoutOption[ 0 ] ); + EditorGUILayout.LabelField( "LOD", ShaderUtilEx.GetLOD( shader ).ToString( System.Globalization.CultureInfo.InvariantCulture ), new GUILayoutOption[ 0 ] ); + EditorGUILayout.LabelField( "Ignore projector", ( !ShaderUtilEx.DoesIgnoreProjector( shader ) ) ? "no" : "yes", new GUILayoutOption[ 0 ] ); + string label; + switch ( ShaderEx.GetDisableBatching( shader ) ) + { + case DisableBatchingType.False: + label = "no"; + break; + case DisableBatchingType.True: + label = "yes"; + break; + case DisableBatchingType.WhenLODFading: + label = "when LOD fading is on"; + break; + default: + label = "unknown"; + break; + } + EditorGUILayout.LabelField( "Disable batching", label, new GUILayoutOption[ 0 ] ); +#if UNITY_2019_3_OR_NEWER + ShowKeywords( shader ); + srpCompatibilityCheckMaterial.SetPass( 0 ); +#endif + +#if UNITY_2018_3_OR_NEWER + int shaderActiveSubshaderIndex = ShaderUtilEx.GetShaderActiveSubshaderIndex( shader ); + int sRPBatcherCompatibilityCode = ShaderUtilEx.GetSRPBatcherCompatibilityCode( shader, shaderActiveSubshaderIndex ); + string label2 = ( sRPBatcherCompatibilityCode != 0 ) ? "not compatible" : "compatible"; + EditorGUILayout.LabelField( "SRP Batcher", label2 ); + if( sRPBatcherCompatibilityCode != 0 ) + { + EditorGUILayout.HelpBox( ShaderUtilEx.GetSRPBatcherCompatibilityIssueReason( shader, shaderActiveSubshaderIndex, sRPBatcherCompatibilityCode ), MessageType.Info ); + } +#endif + CustomShaderInspector.ShowShaderProperties( shader ); + } + } +#if UNITY_2019_3_OR_NEWER + private void ShowKeywords( Shader s ) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PrefixLabel( "Keywords", EditorStyles.miniButton ); + + Rect buttonRect = GUILayoutUtility.GetRect( Styles.arrayValuePopupButton, GUI.skin.button, GUILayout.MinWidth( kValueFieldWidth ) ); + buttonRect.width = kArrayValuePopupBtnWidth; + if( GUI.Button( buttonRect, Styles.arrayValuePopupButton, EditorStyles.miniButton ) ) + { + var globalKeywords = ShaderUtilEx.GetShaderGlobalKeywords( s ); + var localKeywords = ShaderUtilEx.GetShaderLocalKeywords( s ); + PopupWindow.Show( buttonRect, new KeywordsPopup( globalKeywords, localKeywords, 150.0f ) ); + } + + EditorGUILayout.EndHorizontal(); + } +#endif + private void ShowShaderCodeArea( Shader s ) + { + CustomShaderInspector.ShowSurfaceShaderButton( s ); + CustomShaderInspector.ShowFixedFunctionShaderButton( s ); + this.ShowCompiledCodeButton( s ); + this.ShowShaderErrors( s ); + } + + private static void ShowShaderProperties( Shader s ) + { + GUILayout.Space( 5f ); + GUILayout.Label( "Properties:", EditorStyles.boldLabel, new GUILayoutOption[ 0 ] ); + int propertyCount = UnityEditor.ShaderUtil.GetPropertyCount( s ); + for ( int i = 0; i < propertyCount; i++ ) + { + string propertyName = UnityEditor.ShaderUtil.GetPropertyName( s, i ); + string label = CustomShaderInspector.GetPropertyType( s, i ) + UnityEditor.ShaderUtil.GetPropertyDescription( s, i ); + EditorGUILayout.LabelField( propertyName, label, new GUILayoutOption[ 0 ] ); + } + } + + internal static void ShaderErrorListUI( UnityEngine.Object shader, ShaderError[] errors, ref Vector2 scrollPosition ) + { + int num = errors.Length; + GUILayout.Space( 5f ); + GUILayout.Label( string.Format( "Errors ({0}):", num ), EditorStyles.boldLabel, new GUILayoutOption[ 0 ] ); + int controlID = GUIUtility.GetControlID( CustomShaderInspector.kErrorViewHash, FocusType.Passive ); + float minHeight = Mathf.Min( ( float ) num * 20f + 40f, 150f ); + scrollPosition = GUILayout.BeginScrollView( scrollPosition, GUISkinEx.GetCurrentSkin().box, new GUILayoutOption[] + { + GUILayout.MinHeight(minHeight) + } ); + EditorGUIUtility.SetIconSize( new Vector2( 16f, 16f ) ); + float height = CustomShaderInspector.Styles.messageStyle.CalcHeight( EditorGUIUtilityEx.TempContent( CustomShaderInspector.Styles.errorIcon ), 100f ); + Event current = Event.current; + for ( int i = 0; i < num; i++ ) + { + Rect controlRect = EditorGUILayout.GetControlRect( false, height, new GUILayoutOption[ 0 ] ); + string message = errors[ i ].message; + string platform = errors[ i ].platform; + bool flag = errors[ i ].warning != 0; + string lastPathNameComponent = FileUtilEx.GetLastPathNameComponent( errors[ i ].file ); + int line = errors[ i ].line; + if ( current.type == EventType.MouseDown && current.button == 0 && controlRect.Contains( current.mousePosition ) ) + { + GUIUtility.keyboardControl = controlID; + if ( current.clickCount == 2 ) + { + string file = errors[ i ].file; + UnityEngine.Object @object = ( !string.IsNullOrEmpty( file ) ) ? AssetDatabase.LoadMainAssetAtPath( file ) : null; + AssetDatabase.OpenAsset( @object ?? shader, line ); + GUIUtility.ExitGUI(); + } + current.Use(); + } + if ( current.type == EventType.ContextClick && controlRect.Contains( current.mousePosition ) ) + { + current.Use(); + GenericMenu genericMenu = new GenericMenu(); + int errorIndex = i; + genericMenu.AddItem( new GUIContent( "Copy error text" ), false, delegate + { + string text = errors[ errorIndex ].message; + if ( !string.IsNullOrEmpty( errors[ errorIndex ].messageDetails ) ) + { + text += '\n'; + text += errors[ errorIndex ].messageDetails; + } + EditorGUIUtility.systemCopyBuffer = text; + } ); + genericMenu.ShowAsContext(); + } + if ( current.type == EventType.Repaint && ( i & 1 ) == 0 ) + { + GUIStyle evenBackground = CustomShaderInspector.Styles.evenBackground; + evenBackground.Draw( controlRect, false, false, false, false ); + } + Rect rect = controlRect; + rect.xMin = rect.xMax; + if ( line > 0 ) + { + GUIContent content; + if ( string.IsNullOrEmpty( lastPathNameComponent ) ) + { + content = EditorGUIUtilityEx.TempContent( line.ToString( System.Globalization.CultureInfo.InvariantCulture ) ); + } + else + { + content = EditorGUIUtilityEx.TempContent( lastPathNameComponent + ":" + line.ToString( System.Globalization.CultureInfo.InvariantCulture ) ); + } + Vector2 vector = EditorStyles.miniLabel.CalcSize( content ); + rect.xMin -= vector.x; + GUI.Label( rect, content, EditorStyles.miniLabel ); + rect.xMin -= 2f; + if ( rect.width < 30f ) + { + rect.xMin = rect.xMax - 30f; + } + } + Rect position = rect; + position.width = 0f; + if ( platform.Length > 0 ) + { + GUIContent content2 = EditorGUIUtilityEx.TempContent( platform ); + Vector2 vector2 = EditorStyles.miniLabel.CalcSize( content2 ); + position.xMin -= vector2.x; + Color contentColor = GUI.contentColor; + GUI.contentColor = new Color( 1f, 1f, 1f, 0.5f ); + GUI.Label( position, content2, EditorStyles.miniLabel ); + GUI.contentColor = contentColor; + position.xMin -= 2f; + } + Rect position2 = controlRect; + position2.xMax = position.xMin; + GUI.Label( position2, EditorGUIUtilityEx.TempContent( message, ( !flag ) ? CustomShaderInspector.Styles.errorIcon : CustomShaderInspector.Styles.warningIcon ), CustomShaderInspector.Styles.messageStyle ); + } + EditorGUIUtility.SetIconSize( Vector2.zero ); + GUILayout.EndScrollView(); + } + +#if UNITY_2019_3_OR_NEWER + ShaderMessage[] m_ShaderMessages; +#endif + private void ShowShaderErrors( Shader s ) + { +#if UNITY_2019_3_OR_NEWER + if( Event.current.type == EventType.Layout ) + { + int n = ShaderUtil.GetShaderMessageCount( s ); + m_ShaderMessages = null; + if( n >= 1 ) + { + m_ShaderMessages = ShaderUtil.GetShaderMessages( s ); + } + } + + if( m_ShaderMessages == null ) + return; + + ShaderInspectorEx.ShaderErrorListUI( s, m_ShaderMessages, ref this.m_ScrollPosition ); +#else + int shaderErrorCount = ShaderUtilEx.GetShaderErrorCount( s ); + if ( shaderErrorCount < 1 ) + { + return; + } + CustomShaderInspector.ShaderErrorListUI( s, ShaderUtilEx.GetShaderErrors( s ), ref this.m_ScrollPosition ); +#endif + } + + private void ShowCompiledCodeButton( Shader s ) + { +#if UNITY_2020_1_OR_NEWER + using( new EditorGUI.DisabledScope( !EditorSettings.cachingShaderPreprocessor ) ) + { + s_PreprocessOnly = EditorGUILayout.Toggle( Styles.togglePreprocess, s_PreprocessOnly ); +#if UNITY_2020_2_OR_NEWER + if( s_PreprocessOnly ) + { + s_StripLineDirectives = EditorGUILayout.Toggle( Styles.toggleStripLineDirective, s_StripLineDirectives ); + } +#endif + } +#endif + EditorGUILayout.BeginHorizontal( new GUILayoutOption[ 0 ] ); + EditorGUILayout.PrefixLabel( "Compiled code", EditorStyles.miniButton ); + bool hasCode = ShaderUtilEx.HasShaderSnippets( s ) || ShaderUtilEx.HasSurfaceShaders( s ) || ShaderUtilEx.HasFixedFunctionShaders( s ); + if( hasCode ) + { + GUIContent showCurrent = Styles.showCurrent; + Rect rect = GUILayoutUtility.GetRect( showCurrent, EditorStyles.miniButton, new GUILayoutOption[] + { + GUILayout.ExpandWidth(false) + } ); + Rect position = new Rect( rect.xMax - 16f, rect.y, 16f, rect.height ); + if( EditorGUIEx.ButtonMouseDown( position, GUIContent.none, FocusType.Passive, GUIStyle.none ) ) + { + Rect last = GUILayoutUtilityEx.TopLevel_GetLast(); + PopupWindow.Show( last, (PopupWindowContent)Activator.CreateInstance( System.Type.GetType( "UnityEditor.ShaderInspectorPlatformsPopup, UnityEditor" ), new object[] { s } ) ); + GUIUtility.ExitGUI(); + } + if( GUI.Button( rect, showCurrent, EditorStyles.miniButton ) ) + { +#if UNITY_2020_1 + ShaderUtilEx.OpenCompiledShader( s, ShaderInspectorPlatformsPopupEx.GetCurrentMode(), ShaderInspectorPlatformsPopupEx.GetCurrentPlatformMask(), ShaderInspectorPlatformsPopupEx.GetCurrentVariantStripping() == 0, s_PreprocessOnly ); +#elif UNITY_2020_2_OR_NEWER + ShaderUtilEx.OpenCompiledShader( s, ShaderInspectorPlatformsPopupEx.GetCurrentMode(), ShaderInspectorPlatformsPopupEx.GetCurrentPlatformMask(), ShaderInspectorPlatformsPopupEx.GetCurrentVariantStripping() == 0, s_PreprocessOnly, s_StripLineDirectives ); +#else + ShaderUtilEx.OpenCompiledShader( s, ShaderInspectorPlatformsPopupEx.GetCurrentMode(), ShaderInspectorPlatformsPopupEx.GetCurrentPlatformMask(), ShaderInspectorPlatformsPopupEx.GetCurrentVariantStripping() == 0 ); +#endif + GUIUtility.ExitGUI(); + } + } + else + { + GUILayout.Button( "none (precompiled shader)", GUI.skin.label, new GUILayoutOption[ 0 ] ); + } + EditorGUILayout.EndHorizontal(); + } + + private static void ShowSurfaceShaderButton( Shader s ) + { + bool flag = ShaderUtilEx.HasSurfaceShaders( s ); + EditorGUILayout.BeginHorizontal( new GUILayoutOption[ 0 ] ); + EditorGUILayout.PrefixLabel( "Surface shader", EditorStyles.miniButton ); + if ( flag ) + { + if ( !( AssetImporter.GetAtPath( AssetDatabase.GetAssetPath( s ) ) == null ) ) + { + if ( GUILayout.Button( CustomShaderInspector.Styles.showSurface, EditorStyles.miniButton, new GUILayoutOption[] + { + GUILayout.ExpandWidth(false) + } ) ) + { + ShaderUtilEx.OpenParsedSurfaceShader( s ); + GUIUtility.ExitGUI(); + } + } + else + { + GUILayout.Button( CustomShaderInspector.Styles.builtinShader, GUI.skin.label, new GUILayoutOption[ 0 ] ); + } + } + else + { + GUILayout.Button( CustomShaderInspector.Styles.no, GUI.skin.label, new GUILayoutOption[ 0 ] ); + } + EditorGUILayout.EndHorizontal(); + } + + private static void ShowFixedFunctionShaderButton( Shader s ) + { + bool flag = ShaderUtilEx.HasFixedFunctionShaders( s ); + EditorGUILayout.BeginHorizontal( new GUILayoutOption[ 0 ] ); + EditorGUILayout.PrefixLabel( "Fixed function", EditorStyles.miniButton ); + if ( flag ) + { + if ( !( AssetImporter.GetAtPath( AssetDatabase.GetAssetPath( s ) ) == null ) ) + { + if ( GUILayout.Button( CustomShaderInspector.Styles.showFF, EditorStyles.miniButton, new GUILayoutOption[] + { + GUILayout.ExpandWidth(false) + } ) ) + { + ShaderUtilEx.OpenGeneratedFixedFunctionShader( s ); + GUIUtility.ExitGUI(); + } + } + else + { + GUILayout.Button( CustomShaderInspector.Styles.builtinShader, GUI.skin.label, new GUILayoutOption[ 0 ] ); + } + } + else + { + GUILayout.Button( CustomShaderInspector.Styles.no, GUI.skin.label, new GUILayoutOption[ 0 ] ); + } + EditorGUILayout.EndHorizontal(); + } + } + + internal class KeywordsPopup : PopupWindowContent + { + private Vector2 m_ScrollPos = Vector2.zero; + private string[] m_GlobalKeywords; + private string[] m_LocalKeywords; + private bool m_GlobalKeywordsExpended; + private bool m_LocalKeywordsExpended; + private float m_WindowWidth; + + private static readonly GUIStyle m_Style = EditorStyles.miniLabel; + + public KeywordsPopup( string[] globalKeywords, string[] localKeywords, float windowWidth ) + { + m_GlobalKeywords = globalKeywords; + m_LocalKeywords = localKeywords; + m_GlobalKeywordsExpended = true; + m_LocalKeywordsExpended = true; + m_WindowWidth = windowWidth; + } + + public override Vector2 GetWindowSize() + { + var numValues = m_GlobalKeywords.Length + m_LocalKeywords.Length + 2; + var lineHeight = m_Style.lineHeight + m_Style.padding.vertical + m_Style.margin.top; + return new Vector2( m_WindowWidth, Math.Min( lineHeight * numValues, 250.0f ) ); + } + + public override void OnGUI( Rect rect ) + { + m_ScrollPos = EditorGUILayout.BeginScrollView( m_ScrollPos ); + + m_GlobalKeywordsExpended = KeywordsFoldout( m_GlobalKeywordsExpended, "Global Keywords", m_GlobalKeywords ); + m_LocalKeywordsExpended = KeywordsFoldout( m_LocalKeywordsExpended, "Local Keywords", m_LocalKeywords ); + + EditorGUILayout.EndScrollView(); + } + + private bool KeywordsFoldout( bool expended, string name, string[] values ) + { + expended = EditorGUILayout.Foldout( expended, name, true, m_Style ); + + if( expended ) + { + EditorGUI.indentLevel++; + for( int i = 0; i < values.Length; ++i ) + { + EditorGUILayout.LabelField( values[ i ], m_Style ); + } + EditorGUI.indentLevel--; + } + + return expended; + } + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // UNITY EDITOR EXTENSIONS + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + public enum DisableBatchingType + { + False, + True, + WhenLODFading + } + + public struct ShaderError + { + public string message; + public string messageDetails; + public string platform; + public string file; + public int line; + public int warning; + } + + public static class EditorGUIUtilityEx + { + private static System.Type type = null; + public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEditor.EditorGUIUtility, UnityEditor" ) : type; } } + + public static Texture2D LoadIcon( string icon ) + { + return ( Texture2D ) EditorGUIUtilityEx.Type.InvokeMember( "LoadIcon", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { icon } ); + } + + public static GUIContent TextContent( string t ) + { + return ( GUIContent ) EditorGUIUtilityEx.Type.InvokeMember( "TextContent", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { t } ); + } + + internal static GUIContent TempContent( string t ) + { + return ( GUIContent ) EditorGUIUtilityEx.Type.InvokeMember( "TempContent", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { t } ); + } + + internal static GUIContent TempContent( Texture i ) + { + return ( GUIContent ) EditorGUIUtilityEx.Type.InvokeMember( "TempContent", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { i } ); + } + + internal static GUIContent TempContent( string t, Texture i ) + { + return ( GUIContent ) EditorGUIUtilityEx.Type.InvokeMember( "TempContent", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { t, i } ); + } + } + + public static class GUILayoutUtilityEx + { + private static System.Type type = null; + public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEngine.GUILayoutUtility, UnityEngine" ) : type; } } + + public static Rect TopLevel_GetLast() + { + System.Type guiLayoutGroup = System.Type.GetType( "UnityEngine.GUILayoutGroup, UnityEngine" ); + var topLevel = GUILayoutUtilityEx.Type.GetProperty( "topLevel", BindingFlags.NonPublic | BindingFlags.Static ).GetValue( null, null ); + return ( Rect ) guiLayoutGroup.InvokeMember( "GetLast", BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, topLevel, new object[] { } ); + } + } + + public static class ShaderEx + { + private static System.Type type = null; + public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEngine.Shader, UnityEngine" ) : type; } } + + public static DisableBatchingType GetDisableBatching( Shader s ) + { + return ( DisableBatchingType ) ShaderEx.Type.GetProperty( "disableBatching", BindingFlags.NonPublic | BindingFlags.Instance ).GetValue( s, new object[ 0 ] ); + } + } + + public static class ShaderUtilEx + { + private static System.Type type = null; + public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEditor.ShaderUtil, UnityEditor" ) : type; } } + + public static void OpenParsedSurfaceShader( Shader s ) + { + ShaderUtilEx.Type.InvokeMember( "OpenParsedSurfaceShader", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); + } + + public static void OpenGeneratedFixedFunctionShader( Shader s ) + { + ShaderUtilEx.Type.InvokeMember( "OpenGeneratedFixedFunctionShader", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); + } + +#if UNITY_2020_1 + public static void OpenCompiledShader( Shader shader, int mode, int customPlatformsMask, bool includeAllVariants, bool preprocessOnly ) + { + ShaderUtilEx.Type.InvokeMember( "OpenCompiledShader", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { shader, mode, customPlatformsMask, includeAllVariants, preprocessOnly } ); + } +#elif UNITY_2020_2_OR_NEWER + public static void OpenCompiledShader( Shader shader, int mode, int customPlatformsMask, bool includeAllVariants, bool preprocessOnly, bool stripLineDirectives ) + { + ShaderUtilEx.Type.InvokeMember( "OpenCompiledShader", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { shader, mode, customPlatformsMask, includeAllVariants, preprocessOnly, stripLineDirectives } ); + } +#else + public static void OpenCompiledShader( Shader shader, int mode, int customPlatformsMask, bool includeAllVariants ) + { + ShaderUtilEx.Type.InvokeMember( "OpenCompiledShader", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { shader, mode, customPlatformsMask, includeAllVariants } ); + } +#endif + public static void FetchCachedErrors( Shader s ) + { +#if UNITY_2019_3_OR_NEWER + ShaderUtilEx.Type.InvokeMember( "FetchCachedMessages", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); +#else + ShaderUtilEx.Type.InvokeMember( "FetchCachedErrors", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); +#endif + } + + public static string[] GetShaderGlobalKeywords( Shader s ) + { + return ShaderUtilEx.Type.InvokeMember( "GetShaderGlobalKeywords", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ) as string[]; + } + + public static string[] GetShaderLocalKeywords( Shader s ) + { + return ShaderUtilEx.Type.InvokeMember( "GetShaderLocalKeywords", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ) as string[]; + } + + public static int GetShaderErrorCount( Shader s ) + { +#if UNITY_2019_3_OR_NEWER + return ShaderUtil.GetShaderMessageCount( s ); +#else + return ( int ) ShaderUtilEx.Type.InvokeMember( "GetShaderErrorCount", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); +#endif + } + + public static int GetAvailableShaderCompilerPlatforms() + { + return (int)ShaderUtilEx.Type.InvokeMember( "GetAvailableShaderCompilerPlatforms", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { } ); + } + + public static ShaderError[] GetShaderErrors( Shader s ) + { + System.Type shaderErrorType = System.Type.GetType( "UnityEditor.ShaderError, UnityEditor" ); + var errorList = ( System.Collections.IList ) ShaderUtilEx.Type.InvokeMember( "GetShaderErrors", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); + + FieldInfo messageField = shaderErrorType.GetField( "message", BindingFlags.Public | BindingFlags.Instance ); + FieldInfo messageDetailsField = shaderErrorType.GetField( "messageDetails", BindingFlags.Public | BindingFlags.Instance ); + FieldInfo platformField = shaderErrorType.GetField( "platform", BindingFlags.Public | BindingFlags.Instance ); + FieldInfo fileField = shaderErrorType.GetField( "file", BindingFlags.Public | BindingFlags.Instance ); + FieldInfo lineField = shaderErrorType.GetField( "line", BindingFlags.Public | BindingFlags.Instance ); + FieldInfo warningField = shaderErrorType.GetField( "warning", BindingFlags.Public | BindingFlags.Instance ); + + ShaderError[] errors = new ShaderError[ errorList.Count ]; + for ( int i = 0; i < errorList.Count; i++ ) + { + errors[ i ].message = ( string ) messageField.GetValue( errorList[ i ] ); + errors[ i ].messageDetails = ( string ) messageDetailsField.GetValue( errorList[ i ] ); + errors[ i ].platform = ( string ) platformField.GetValue( errorList[ i ] ); + errors[ i ].file = ( string ) fileField.GetValue( errorList[ i ] ); + errors[ i ].line = ( int ) lineField.GetValue( errorList[ i ] ); + errors[ i ].warning = ( int ) warningField.GetValue( errorList[ i ] ); + } + return errors; + } + + public static bool HasShaderSnippets( Shader s ) + { + return ( bool ) ShaderUtilEx.Type.InvokeMember( "HasShaderSnippets", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); + } + + public static bool HasSurfaceShaders( Shader s ) + { + return ( bool ) ShaderUtilEx.Type.InvokeMember( "HasSurfaceShaders", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); + } + + public static bool HasFixedFunctionShaders( Shader s ) + { + return ( bool ) ShaderUtilEx.Type.InvokeMember( "HasFixedFunctionShaders", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); + } + + public static bool HasShadowCasterPass( Shader s ) + { + return ( bool ) ShaderUtilEx.Type.InvokeMember( "HasShadowCasterPass", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); + } + + public static int GetRenderQueue( Shader s ) + { + return ( int ) ShaderUtilEx.Type.InvokeMember( "GetRenderQueue", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); + } + + public static int GetLOD( Shader s ) + { + return ( int ) ShaderUtilEx.Type.InvokeMember( "GetLOD", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); + } + + public static bool DoesIgnoreProjector( Shader s ) + { + return ( bool ) ShaderUtilEx.Type.InvokeMember( "DoesIgnoreProjector", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); + } + +#if UNITY_2018_3_OR_NEWER + public static int GetShaderActiveSubshaderIndex( Shader s ) + { + return (int)ShaderUtilEx.Type.InvokeMember( "GetShaderActiveSubshaderIndex", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s } ); + } + + public static int GetSRPBatcherCompatibilityCode( Shader s, int subShaderIdx ) + { + return (int)ShaderUtilEx.Type.InvokeMember( "GetSRPBatcherCompatibilityCode", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s, subShaderIdx } ); + } + + public static string GetSRPBatcherCompatibilityIssueReason( Shader s, int subShaderIdx, int err ) + { + return (string)ShaderUtilEx.Type.InvokeMember( "GetSRPBatcherCompatibilityIssueReason", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { s, subShaderIdx, err } ); + } +#endif + } + + public static class FileUtilEx + { + private static System.Type type = null; + public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEditor.FileUtil, UnityEditor" ) : type; } } + + public static string GetLastPathNameComponent( string path ) + { + return ( string ) FileUtilEx.Type.InvokeMember( "GetLastPathNameComponent", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { path } ); + } + } + + public static class ShaderInspectorEx + { + private static System.Type type = null; + public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEditor.ShaderInspector, UnityEditor" ) : type; } } + +#if UNITY_2019_3_OR_NEWER + public static void ShaderErrorListUI( UnityEngine.Object shader, ShaderMessage[] messages, ref Vector2 scrollPosition ) + { + Type.InvokeMember( "ShaderErrorListUI", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { shader, messages, scrollPosition } ); + } +#endif + } + + public static class GUISkinEx + { + private static System.Type type = null; + public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEngine.GUISkin, UnityEngine" ) : type; } } + + public static GUISkin GetCurrentSkin() + { + return ( GUISkin ) GUISkinEx.Type.GetField( "current", BindingFlags.NonPublic | BindingFlags.Static ).GetValue( null ); + } + } + + public static class EditorGUIEx + { + public static System.Type Type = typeof( EditorGUI ); + + public static bool ButtonMouseDown( Rect position, GUIContent content, FocusType focusType, GUIStyle style ) + { +#if UNITY_5_6_OR_NEWER + return EditorGUI.DropdownButton( position, content, focusType, style ); +#else + return ( bool ) EditorGUIEx.Type.InvokeMember( "ButtonMouseDown", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { position, content, focusType, style } ); +#endif + } + + public static float kObjectFieldMiniThumbnailHeight + { + get + { + return (float)EditorGUIEx.Type.InvokeMember( "kObjectFieldMiniThumbnailHeight", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetField, null, null, new object[] {} ); + } + } + + public static float kSingleLineHeight + { + get + { + return (float)EditorGUIEx.Type.InvokeMember( "kSingleLineHeight", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetField, null, null, new object[] { } ); + } + } + + } + + public static class ShaderInspectorPlatformsPopupEx + { + private static System.Type type = null; + public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEditor.ShaderInspectorPlatformsPopup, UnityEditor" ) : type; } } + + public static int GetCurrentMode() + { + return ( int ) ShaderInspectorPlatformsPopupEx.Type.GetProperty( "currentMode", BindingFlags.Public | BindingFlags.Static ).GetValue( null, null ); + } + + public static int GetCurrentPlatformMask() + { + return ( int ) ShaderInspectorPlatformsPopupEx.Type.GetProperty( "currentPlatformMask", BindingFlags.Public | BindingFlags.Static ).GetValue( null, null ); + } + + public static int GetCurrentVariantStripping() + { + return ( int ) ShaderInspectorPlatformsPopupEx.Type.GetProperty( "currentVariantStripping", BindingFlags.Public | BindingFlags.Static ).GetValue( null, null ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomShaderInspector.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomShaderInspector.cs.meta new file mode 100644 index 0000000..0685175 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomShaderInspector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 641dff721f3c24c4188f01fea49484cb +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomTexture2DArrayInspector.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomTexture2DArrayInspector.cs new file mode 100644 index 0000000..b43ee4e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomTexture2DArrayInspector.cs @@ -0,0 +1,132 @@ +#if !UNITY_2019_1_OR_NEWER +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [CustomEditor( typeof( Texture2DArray ) )] + public class CustomTexture2DArrayInspector : Editor + { + Texture2DArray m_target; + [SerializeField] + float m_index; + Shader m_textureArrayPreview; + Material m_previewMaterial; + GUIStyle slider = null; + GUIStyle thumb = null; + GUIContent m_allButton = null; + [SerializeField] + bool m_seeAll; + void OnEnable() + { + m_target = ( target as Texture2DArray ); + m_textureArrayPreview = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "610c24aad350fba4583068c6c22fa428" ) ); + m_previewMaterial = new Material( m_textureArrayPreview ); + slider = null; + thumb = null; + } + + public override void OnPreviewGUI( Rect r, GUIStyle background ) + { + base.OnPreviewGUI( r, background ); + m_previewMaterial.SetTexture( "_MainTex", m_target ); + m_previewMaterial.SetFloat( "_Index", m_index ); + EditorGUI.DrawPreviewTexture( r, m_target, m_previewMaterial, ScaleMode.ScaleToFit, 1f ); + } + + private void OnDisable() + { + DestroyImmediate( m_previewMaterial ); + m_previewMaterial = null; + } + + public override void OnInspectorGUI() + { + if( slider == null ) + slider = "preSlider"; + + if( thumb == null ) + thumb = "preSliderThumb"; + + if( m_allButton == null ) + m_allButton = EditorGUIUtility.IconContent( "PreTextureMipMapLow" ); + + base.OnInspectorGUI(); + } + + public override bool HasPreviewGUI() + { + return true; + } + + public override void OnPreviewSettings() + { + base.OnPreviewSettings(); + m_seeAll = GUILayout.Toggle( m_seeAll, m_allButton, "preButton" ); + EditorGUI.BeginDisabledGroup( m_seeAll ); + m_index = Mathf.Round( GUILayout.HorizontalSlider( m_index, 0, m_target.depth - 1, slider, thumb ) ); + EditorGUI.EndDisabledGroup(); + } + + public override void OnInteractivePreviewGUI( Rect r, GUIStyle background ) + { + //base.OnInteractivePreviewGUI( r, background ); + if( m_seeAll ) + { + int columns = Mathf.CeilToInt( Mathf.Sqrt( m_target.depth ) ); + float sizeX = r.width / columns - 20; + float centerY = ( columns * columns ) - m_target.depth; + int rows = columns; + if( centerY >= columns ) + rows--; + float sizeY = ( r.height - 16 ) / rows - 15; + + if( centerY >= columns ) + centerY = sizeY * 0.5f; + else + centerY = 0; + + Rect smallRect = r; + if( rows > 1 ) + smallRect.y += ( 15 / ( rows - 1 ) ); + else + smallRect.y += 15; + smallRect.x = r.x + 10; + smallRect.width = sizeX; + smallRect.height = sizeY; + + for( int i = 0; i < m_target.depth; i++ ) + { + m_previewMaterial.SetTexture( "_MainTex", m_target ); + m_previewMaterial.SetFloat( "_Index", i ); + EditorGUI.DrawPreviewTexture( smallRect, m_target, m_previewMaterial, ScaleMode.ScaleToFit, 1 ); + Rect dropRect = smallRect; + + float diff = smallRect.height - smallRect.width; + if( diff > 0 ) + dropRect.y -= diff * 0.5f; + dropRect.y += 16; + EditorGUI.DropShadowLabel( dropRect, "[" + i + "]" ); + + smallRect.x += sizeX + 20; + if( ( ( i + 1 ) % ( columns ) ) == 0 ) + { + smallRect.x = r.x + 10; + smallRect.height = sizeY; + smallRect.y += sizeY + 30; + } + } + } + else + { + m_previewMaterial.SetTexture( "_MainTex", m_target ); + m_previewMaterial.SetFloat( "_Index", m_index ); + EditorGUI.DrawPreviewTexture( r, m_target, m_previewMaterial, ScaleMode.ScaleToFit, 1f ); + EditorGUI.DropShadowLabel( r, "[" + m_index + "]" ); + } + } + } +} +#endif diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomTexture2DArrayInspector.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomTexture2DArrayInspector.cs.meta new file mode 100644 index 0000000..7149ec0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/CustomTexture2DArrayInspector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 871ecf36e52b267449b9047596793d6f +timeCreated: 1517913060 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/EditorVariablesManager.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/EditorVariablesManager.cs new file mode 100644 index 0000000..7b9c67c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/EditorVariablesManager.cs @@ -0,0 +1,254 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEditor; +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public class EditorVariable + { + protected string m_labelName; + protected string m_name; + protected T m_value; + protected T m_defaultValue; + + public EditorVariable( string name, string labelName, T defaultValue ) { m_name = name; m_labelName = labelName; m_defaultValue = defaultValue; m_value = defaultValue; } + public string Name { get { return m_name; } } + + public virtual T Value + { + get { return m_value; } + set + { + m_value = value; + } + } + public string LabelName { get { return m_labelName; } } + } + + public sealed class EditorVariableFloat : EditorVariable + { + public EditorVariableFloat( string name, string labelName, float defaultValue ) : base( name, labelName, defaultValue ) + { + m_value = EditorPrefs.GetFloat( name, m_defaultValue ); + } + + public override float Value + { + get { return m_value; } + set + { + if( m_value != value ) + { + m_value = value; + EditorPrefs.SetFloat( m_name, m_value ); + } + } + } + } + + public sealed class EditorVariableBool : EditorVariable + { + public EditorVariableBool( string name, string labelName, bool defaultValue ) : base( name, labelName, defaultValue ) + { + m_value = EditorPrefs.GetBool( name, m_defaultValue ); + } + + public override bool Value + { + get { return m_value; } + set + { + if( m_value != value ) + { + m_value = value; + EditorPrefs.SetBool( m_name, m_value ); + } + } + } + } + + public sealed class EditorVariableInt : EditorVariable + { + public EditorVariableInt( string name, string labelName, int defaultValue ) : base( name, labelName, defaultValue ) + { + m_value = EditorPrefs.GetInt( name, m_defaultValue ); + } + + public override int Value + { + get { return m_value; } + set + { + if( m_value != value ) + { + m_value = value; + EditorPrefs.SetInt( m_name, m_value ); + } + } + } + } + + public sealed class EditorVariableString : EditorVariable + { + public EditorVariableString( string name, string labelName, string defaultValue ) : base( name, labelName, defaultValue ) + { + m_value = EditorPrefs.GetString( name, m_defaultValue ); + } + + public override string Value + { + get { return m_value; } + set + { + if( !m_value.Equals( value ) ) + { + m_value = value; + EditorPrefs.SetString( m_name, m_value ); + } + } + } + } + + public class EditorVariablesManager + { + public static EditorVariableBool LiveMode = new EditorVariableBool( "ASELiveMode", "LiveMode", false ); + public static EditorVariableBool OutlineActiveMode = new EditorVariableBool( "ASEOutlineActiveMode", " Outline", false ); + public static EditorVariableBool NodeParametersMaximized = new EditorVariableBool( "ASENodeParametersVisible", " NodeParameters", true ); + public static EditorVariableBool NodePaletteMaximized = new EditorVariableBool( "ASENodePaletteVisible", " NodePalette", true ); + public static EditorVariableBool ExpandedRenderingPlatforms = new EditorVariableBool( "ASEExpandedRenderingPlatforms", " ExpandedRenderingPlatforms", false ); + public static EditorVariableBool ExpandedRenderingOptions = new EditorVariableBool( "ASEExpandedRenderingOptions", " ExpandedRenderingPlatforms", false ); + public static EditorVariableBool ExpandedGeneralShaderOptions = new EditorVariableBool( "ASEExpandedGeneralShaderOptions", " ExpandedGeneralShaderOptions", false ); + public static EditorVariableBool ExpandedBlendOptions = new EditorVariableBool( "ASEExpandedBlendOptions", " ExpandedBlendOptions", false ); + public static EditorVariableBool ExpandedStencilOptions = new EditorVariableBool( "ASEExpandedStencilOptions", " ExpandedStencilOptions", false ); + public static EditorVariableBool ExpandedVertexOptions = new EditorVariableBool( "ASEExpandedVertexOptions", " ExpandedVertexOptions", false ); + public static EditorVariableBool ExpandedFunctionInputs = new EditorVariableBool( "ASEExpandedFunctionInputs", " ExpandedFunctionInputs", false ); + public static EditorVariableBool ExpandedFunctionSwitches = new EditorVariableBool( "ASEExpandedFunctionSwitches", " ExpandedFunctionSwitches", false ); + public static EditorVariableBool ExpandedFunctionOutputs = new EditorVariableBool( "ASEExpandedFunctionOutputs", " ExpandedFunctionOutputs", false ); + public static EditorVariableBool ExpandedAdditionalIncludes = new EditorVariableBool( "ASEExpandedAdditionalIncludes", " ExpandedAdditionalIncludes", false ); + public static EditorVariableBool ExpandedAdditionalDefines = new EditorVariableBool( "ASEExpandedAdditionalDefines", " ExpandedAdditionalDefines", false ); + public static EditorVariableBool ExpandedAdditionalDirectives = new EditorVariableBool( "ASEExpandedAdditionalDirectives", " ExpandedAdditionalDirectives", false ); + public static EditorVariableBool ExpandedCustomTags = new EditorVariableBool( "ASEExpandedCustomTags", " ExpandedCustomTags", false ); + public static EditorVariableBool ExpandedAdditionalSurfaceOptions = new EditorVariableBool( "ASEExpandedAdditionalSurfaceOptions", " ExpandedAdditionalSurfaceOptions", false ); + public static EditorVariableBool ExpandedAdditionalPragmas = new EditorVariableBool( "ASEExpandedAdditionalPragmas", " ExpandedAdditionalPragmas", false ); + public static EditorVariableBool ExpandedDependencies = new EditorVariableBool( "ASEExpandedDependencies", " ExpandedDependencies", false ); + public static EditorVariableBool ExpandedDepth = new EditorVariableBool( "ASEExpandedDepth", " ExpandedDepth", false ); + public static EditorVariableBool ExpandedTesselation = new EditorVariableBool( "ASEExpandedTesselation", " ExpandedTesselation", false ); + public static EditorVariableBool ExpandedProperties = new EditorVariableBool( "ASEExpandedProperties", " ExpandedProperties", false ); + public static EditorVariableBool ExpandedUsePass = new EditorVariableBool( "ASEUsePass", " UsePass", false ); + //Templates + public static EditorVariableBool ExpandedBlendModeModule = new EditorVariableBool( "ASEExpandedBlendModeModule", " ExpandedBlendModeModule", false ); + } + + [Serializable] + public class InnerWindowEditorVariables + { + [SerializeField] + private bool m_liveMode = false; + [SerializeField] + private bool m_outlineActiveMode = false; + [SerializeField] + private bool m_nodeParametersMaximized = false; + [SerializeField] + private bool m_nodePaletteMaximized = false; + [SerializeField] + private bool m_expandedRenderingPlatforms = false; + [SerializeField] + private bool m_expandedRenderingOptions = false; + [SerializeField] + private bool m_expandedGeneralShaderOptions = false; + [SerializeField] + private bool m_expandedBlendOptions = false; + [SerializeField] + private bool m_expandedStencilOptions = false; + [SerializeField] + private bool m_expandedVertexOptions = false; + [SerializeField] + private bool m_expandedFunctionInputs = false; + [SerializeField] + private bool m_expandedFunctionSwitches = false; + [SerializeField] + private bool m_expandedFunctionOutputs = false; + [SerializeField] + private bool m_expandedAdditionalIncludes = false; + [SerializeField] + private bool m_expandedAdditionalDefines = false; + [SerializeField] + private bool m_expandedAdditionalDirectives = false; + [SerializeField] + private bool m_expandedCustomTags = false; + [SerializeField] + private bool m_expandedAdditionalSurfaceOptions = false; + [SerializeField] + private bool m_expandedAdditionalPragmas = false; + [SerializeField] + private bool m_expandedDependencies = false; + [SerializeField] + private bool m_expandedBlendModeModule = false; + [SerializeField] + private bool m_expandedDepth = false; + [SerializeField] + private bool m_expandedTesselation = false; + [SerializeField] + private bool m_expandedProperties = false; + [SerializeField] + private bool m_expandedUsePass = false; + + public void Initialize() + { + m_liveMode = EditorVariablesManager.LiveMode.Value; + m_outlineActiveMode = EditorVariablesManager.OutlineActiveMode.Value; + m_nodeParametersMaximized = EditorVariablesManager.NodeParametersMaximized.Value; + m_nodePaletteMaximized = EditorVariablesManager.NodePaletteMaximized.Value; + m_expandedRenderingPlatforms = EditorVariablesManager.ExpandedRenderingPlatforms.Value; + m_expandedRenderingOptions = EditorVariablesManager.ExpandedRenderingOptions.Value; + m_expandedGeneralShaderOptions = EditorVariablesManager.ExpandedGeneralShaderOptions.Value; + m_expandedBlendOptions = EditorVariablesManager.ExpandedBlendOptions.Value; + m_expandedStencilOptions = EditorVariablesManager.ExpandedStencilOptions.Value; + m_expandedVertexOptions = EditorVariablesManager.ExpandedVertexOptions.Value; + m_expandedFunctionInputs = EditorVariablesManager.ExpandedFunctionInputs.Value; + m_expandedFunctionSwitches = EditorVariablesManager.ExpandedFunctionSwitches.Value; + m_expandedFunctionOutputs = EditorVariablesManager.ExpandedFunctionOutputs.Value; + m_expandedAdditionalIncludes = EditorVariablesManager.ExpandedAdditionalIncludes.Value; + m_expandedAdditionalDefines = EditorVariablesManager.ExpandedAdditionalDefines.Value; + m_expandedAdditionalDirectives = EditorVariablesManager.ExpandedAdditionalDirectives.Value; + m_expandedCustomTags = EditorVariablesManager.ExpandedCustomTags.Value; + m_expandedAdditionalSurfaceOptions = EditorVariablesManager.ExpandedAdditionalSurfaceOptions.Value; + m_expandedAdditionalPragmas = EditorVariablesManager.ExpandedAdditionalPragmas.Value; + m_expandedDependencies = EditorVariablesManager.ExpandedDependencies.Value; + m_expandedBlendModeModule = EditorVariablesManager.ExpandedBlendModeModule.Value; + m_expandedDepth = EditorVariablesManager.ExpandedDepth.Value; + m_expandedTesselation = EditorVariablesManager.ExpandedTesselation.Value; + m_expandedProperties = EditorVariablesManager.ExpandedProperties.Value; + m_expandedUsePass = EditorVariablesManager.ExpandedUsePass.Value; + } + + public bool LiveMode{ get { return m_liveMode; } set { m_liveMode = value; EditorVariablesManager.LiveMode.Value = value; } } + public bool OutlineActiveMode { get { return m_outlineActiveMode; } set { m_outlineActiveMode = value; EditorVariablesManager.OutlineActiveMode.Value = value; } } + public bool NodeParametersMaximized { get { return m_nodeParametersMaximized; } set { m_nodeParametersMaximized = value; EditorVariablesManager.NodeParametersMaximized.Value = value; } } + public bool NodePaletteMaximized { get { return m_nodePaletteMaximized; } set { m_nodePaletteMaximized = value; EditorVariablesManager.NodePaletteMaximized.Value = value; } } + public bool ExpandedRenderingPlatforms { get { return m_expandedRenderingPlatforms; } set { m_expandedRenderingPlatforms = value; EditorVariablesManager.ExpandedRenderingPlatforms.Value = value; } } + public bool ExpandedRenderingOptions { get { return m_expandedRenderingOptions; } set { m_expandedRenderingOptions = value; EditorVariablesManager.ExpandedRenderingOptions.Value = value; } } + public bool ExpandedGeneralShaderOptions { get { return m_expandedGeneralShaderOptions; } set { m_expandedGeneralShaderOptions = value; EditorVariablesManager.ExpandedGeneralShaderOptions.Value = value; } } + public bool ExpandedBlendOptions { get { return m_expandedBlendOptions; } set { m_expandedBlendOptions = value; EditorVariablesManager.ExpandedBlendOptions.Value = value; } } + public bool ExpandedStencilOptions { get { return m_expandedStencilOptions; } set { m_expandedStencilOptions = value; EditorVariablesManager.ExpandedStencilOptions.Value = value; } } + public bool ExpandedVertexOptions { get { return m_expandedVertexOptions; } set { m_expandedVertexOptions = value; EditorVariablesManager.ExpandedVertexOptions.Value = value; } } + public bool ExpandedFunctionInputs { get { return m_expandedFunctionInputs; } set { m_expandedFunctionInputs = value; EditorVariablesManager.ExpandedFunctionInputs.Value = value; } } + public bool ExpandedFunctionSwitches { get { return m_expandedFunctionSwitches; } set { m_expandedFunctionSwitches = value; EditorVariablesManager.ExpandedFunctionSwitches.Value = value; } } + public bool ExpandedFunctionOutputs { get { return m_expandedFunctionOutputs; } set { m_expandedFunctionOutputs = value; EditorVariablesManager.ExpandedFunctionOutputs.Value = value; } } + public bool ExpandedAdditionalIncludes { get { return m_expandedAdditionalIncludes; } set { m_expandedAdditionalIncludes = value; EditorVariablesManager.ExpandedAdditionalIncludes.Value = value; } } + public bool ExpandedAdditionalDefines { get { return m_expandedAdditionalDefines; } set { m_expandedAdditionalDefines = value; EditorVariablesManager.ExpandedAdditionalDefines.Value = value; } } + public bool ExpandedAdditionalDirectives { get { return m_expandedAdditionalDirectives; } set { m_expandedAdditionalDirectives = value; EditorVariablesManager.ExpandedAdditionalDirectives.Value = value; } } + public bool ExpandedCustomTags { get { return m_expandedCustomTags; } set { m_expandedCustomTags = value; EditorVariablesManager.ExpandedCustomTags.Value = value; } } + public bool ExpandedAdditionalSurfaceOptions { get { return m_expandedAdditionalSurfaceOptions; } set { m_expandedAdditionalSurfaceOptions = value; EditorVariablesManager.ExpandedAdditionalSurfaceOptions.Value = value; } } + public bool ExpandedAdditionalPragmas { get { return m_expandedAdditionalPragmas; } set { m_expandedAdditionalPragmas = value; EditorVariablesManager.ExpandedAdditionalPragmas.Value = value; } } + public bool ExpandedDependencies { get { return m_expandedDependencies; } set { m_expandedDependencies = value; EditorVariablesManager.ExpandedDependencies.Value = value; } } + public bool ExpandedBlendModeModule { get { return m_expandedBlendModeModule; } set { m_expandedBlendModeModule = value; EditorVariablesManager.ExpandedBlendModeModule.Value = value; } } + public bool ExpandedDepth { get { return m_expandedDepth; } set { m_expandedDepth = value; EditorVariablesManager.ExpandedDepth.Value = value; } } + public bool ExpandedTesselation { get { return m_expandedTesselation; } set { m_expandedTesselation = value; EditorVariablesManager.ExpandedTesselation.Value = value; } } + public bool ExpandedProperties { get { return m_expandedProperties; } set { m_expandedProperties = value; EditorVariablesManager.ExpandedProperties.Value = value; } } + public bool ExpandedUsePass { get { return m_expandedUsePass; } set { m_expandedUsePass = value; EditorVariablesManager.ExpandedUsePass.Value = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/EditorVariablesManager.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/EditorVariablesManager.cs.meta new file mode 100644 index 0000000..73d074d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/EditorVariablesManager.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d402e3c7d578ee046a5d0826b9a41c27 +timeCreated: 1487245046 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GeneratorUtils.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GeneratorUtils.cs new file mode 100644 index 0000000..604c09a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GeneratorUtils.cs @@ -0,0 +1,1377 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +namespace AmplifyShaderEditor +{ + public static class GeneratorUtils + { + public const string VertexBlendWeightsStr = "ase_blendWeights"; + public const string VertexBlendIndicesStr = "ase_blendIndices"; + public const string ObjectScaleStr = "ase_objectScale"; + public const string ParentObjectScaleStr = "ase_parentObjectScale"; + public const string ScreenDepthStr = "ase_screenDepth"; + public const string ViewPositionStr = "ase_viewPos"; + public const string WorldViewDirectionStr = "ase_worldViewDir"; + public const string TangentViewDirectionStr = "ase_tanViewDir"; + public const string NormalizedViewDirStr = "ase_normViewDir"; + public const string ClipPositionStr = "ase_clipPos"; + public const string VertexPosition3Str = "ase_vertex3Pos"; + public const string VertexPosition4Str = "ase_vertex4Pos"; + public const string VertexNormalStr = "ase_vertexNormal"; + public const string VertexTangentStr = "ase_vertexTangent"; + public const string VertexTangentSignStr = "ase_vertexTangentSign"; + public const string VertexBitangentStr = "ase_vertexBitangent"; + public const string ScreenPositionStr = "ase_screenPos"; + public const string NormalizedScreenPosFormat = "{0} / {0}.w"; + public const string ScreenPositionNormalizedStr = "ase_screenPosNorm"; + public const string GrabScreenPositionStr = "ase_grabScreenPos"; + public const string GrabScreenPositionNormalizedStr = "ase_grabScreenPosNorm"; + public const string WorldPositionStr = "ase_worldPos"; + public const string RelativeWorldPositionStr = "ase_relWorldPos"; + public const string VFaceStr = "ase_vface"; + public const string ShadowCoordsStr = "ase_shadowCoords"; + public const string WorldLightDirStr = "ase_worldlightDir"; + public const string ObjectLightDirStr = "ase_objectlightDir"; + public const string WorldNormalStr = "ase_worldNormal"; + public const string NormalizedWorldNormalStr = "ase_normWorldNormal"; + public const string WorldReflectionStr = "ase_worldReflection"; + public const string WorldTangentStr = "ase_worldTangent"; + public const string WorldBitangentStr = "ase_worldBitangent"; + public const string WorldToTangentStr = "ase_worldToTangent"; + public const string ObjectToTangentStr = "ase_objectToTangent"; + public const string TangentToWorldPreciseStr = "ase_tangentToWorldPrecise"; + public const string TangentToWorldFastStr = "ase_tangentToWorldFast"; + public const string TangentToObjectStr = "ase_tangentToObject"; + public const string TangentToObjectFastStr = "ase_tangentToObjectFast"; + private const string Float3Format = "float3 {0} = {1};"; + private const string Float4Format = "float4 {0} = {1};"; + private const string GrabFunctionHeader = "inline float4 ASE_ComputeGrabScreenPos( float4 pos )"; + private const string GrabFunctionCall = "ASE_ComputeGrabScreenPos( {0} )"; + private const string Identity4x4 = "ase_identity4x4"; + private static readonly string[] GrabFunctionBody = { + "#if UNITY_UV_STARTS_AT_TOP", + "float scale = -1.0;", + "#else", + "float scale = 1.0;", + "#endif", + "float4 o = pos;", + "o.y = pos.w * 0.5f;", + "o.y = ( pos.y - o.y ) * _ProjectionParams.x * scale + o.y;", + "return o;" + }; + + // MATRIX IDENTITY + static public string GenerateIdentity4x4( ref MasterNodeDataCollector dataCollector, int uniqueId ) + { + dataCollector.AddLocalVariable( uniqueId, "float4x4 ase_identity4x4 = float4x4(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1);" ); + return Identity4x4; + } + + + // OBJECT SCALE + static public string GenerateObjectScale( ref MasterNodeDataCollector dataCollector, int uniqueId ) + { + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GenerateObjectScale( ref dataCollector, uniqueId ); + + //string value= "1/float3( length( unity_WorldToObject[ 0 ].xyz ), length( unity_WorldToObject[ 1 ].xyz ), length( unity_WorldToObject[ 2 ].xyz ) );"; + string value = "float3( length( unity_ObjectToWorld[ 0 ].xyz ), length( unity_ObjectToWorld[ 1 ].xyz ), length( unity_ObjectToWorld[ 2 ].xyz ) )"; + dataCollector.AddLocalVariable( uniqueId, PrecisionType.Float, WirePortDataType.FLOAT3, ObjectScaleStr, value ); + return ObjectScaleStr; + } + + static public string GenerateRotationIndependentObjectScale( ref MasterNodeDataCollector dataCollector, int uniqueId ) + { + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GenerateRotationIndependentObjectScale( ref dataCollector, uniqueId ); + + string value = "(1.0/float3( length( unity_WorldToObject[ 0 ].xyz ), length( unity_WorldToObject[ 1 ].xyz ), length( unity_WorldToObject[ 2 ].xyz ) ))"; + dataCollector.AddLocalVariable( uniqueId, PrecisionType.Float, WirePortDataType.FLOAT3, ParentObjectScaleStr, value ); + return ParentObjectScaleStr; + } + + // WORLD POSITION + static public string GenerateWorldPosition( ref MasterNodeDataCollector dataCollector, int uniqueId ) + { + PrecisionType precision = PrecisionType.Float; + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetWorldPos(); + + dataCollector.AddToInput( -1, SurfaceInputs.WORLD_POS, precision ); + + string result = Constants.InputVarStr + ".worldPos"; + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + result = "mul( unity_ObjectToWorld, " + Constants.VertexShaderInputStr + ".vertex )"; + + //dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, string.Format( Float3Format, WorldPositionStr, result ) ); + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, WorldPositionStr, result ); + + return WorldPositionStr; + } + + // WORLD REFLECTION + static public string GenerateWorldReflection( ref MasterNodeDataCollector dataCollector, int uniqueId, bool normalize = false ) + { + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetWorldReflection( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision, true, MasterNodePortCategory.Fragment, normalize ); + + string precisionType = UIUtils.PrecisionWirePortToCgType( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision, WirePortDataType.FLOAT3 ); + string result = string.Empty; + if( !dataCollector.DirtyNormal ) + result = Constants.InputVarStr + ".worldRefl"; + else + result = "WorldReflectionVector( " + Constants.InputVarStr + ", " + precisionType + "( 0, 0, 1 ) )"; + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + result = "UnityObjectToWorldNormal( " + Constants.VertexShaderInputStr + ".normal )"; + if( normalize ) + { + result = string.Format( "normalize( {0} )", result ); + } + + dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, string.Concat( precisionType, " ", WorldReflectionStr, " = ", result, ";" ) ); + return WorldReflectionStr; + } + + // WORLD NORMAL + static public string GenerateWorldNormal( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precisionType, string normal, string outputId ) + { + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetWorldNormal( uniqueId, precisionType, normal, outputId ); + + string tanToWorld = GenerateTangentToWorldMatrixFast( ref dataCollector, uniqueId, precisionType ); + return string.Format( "mul({0},{1})", tanToWorld, normal ); + + } + static public string GenerateWorldNormal( ref MasterNodeDataCollector dataCollector, int uniqueId, bool normalize = false ) + { + PrecisionType precision = UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision; + + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetWorldNormal( precision, true, MasterNodePortCategory.Fragment, normalize ); + + string precisionType = UIUtils.PrecisionWirePortToCgType( precision, WirePortDataType.FLOAT3 ); + string result = string.Empty; + if( !dataCollector.DirtyNormal ) + result = Constants.InputVarStr + ".worldNormal"; + else + result = "WorldNormalVector( " + Constants.InputVarStr + ", " + precisionType + "( 0, 0, 1 ) )"; + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + result = "UnityObjectToWorldNormal( " + Constants.VertexShaderInputStr + ".normal )"; + + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, WorldNormalStr, result ); + if( normalize ) + { + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, NormalizedWorldNormalStr, "normalize( " + WorldNormalStr + " )" ); + return NormalizedWorldNormalStr; + } + return WorldNormalStr; + } + + // WORLD TANGENT + static public string GenerateWorldTangent( ref MasterNodeDataCollector dataCollector, int uniqueId ) + { + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetWorldTangent( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision ); + + string precisionType = UIUtils.PrecisionWirePortToCgType( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision, WirePortDataType.FLOAT3 ); + string result = "WorldNormalVector( " + Constants.InputVarStr + ", " + precisionType + "( 1, 0, 0 ) )"; + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + result = "UnityObjectToWorldDir( " + Constants.VertexShaderInputStr + ".tangent.xyz )"; + dataCollector.AddLocalVariable( uniqueId, UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision, WirePortDataType.FLOAT3, WorldTangentStr, result ); + //dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, string.Concat( precisionType, " ", WorldTangentStr, " = ", result, ";" ) ); + return WorldTangentStr; + } + + // WORLD BITANGENT + static public string GenerateWorldBitangent( ref MasterNodeDataCollector dataCollector, int uniqueId ) + { + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetWorldBinormal( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision ); + + string precisionType = UIUtils.PrecisionWirePortToCgType( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision, WirePortDataType.FLOAT3 ); + string result = "WorldNormalVector( " + Constants.InputVarStr + ", " + precisionType + "( 0, 1, 0 ) )"; + + if( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) + { + string worldNormal = GenerateWorldNormal( ref dataCollector, uniqueId ); + string worldTangent = GenerateWorldTangent( ref dataCollector, uniqueId ); + dataCollector.AddToVertexLocalVariables( uniqueId, string.Format( "half tangentSign = {0}.tangent.w * unity_WorldTransformParams.w;", Constants.VertexShaderInputStr ) ); + result = "cross( " + worldNormal + ", " + worldTangent + " ) * tangentSign"; + } + + dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, string.Concat( precisionType, " ", WorldBitangentStr, " = ", result, ";" ) ); + return WorldBitangentStr; + } + + // OBJECT TO TANGENT MATRIX + static public string GenerateObjectToTangentMatrix( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + string normal = GenerateVertexNormal( ref dataCollector, uniqueId, precision ); + string tangent = GenerateVertexTangent( ref dataCollector, uniqueId, precision, WirePortDataType.FLOAT3 ); + string bitangen = GenerateVertexBitangent( ref dataCollector, uniqueId, precision ); + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3x3, ObjectToTangentStr, "float3x3( " + tangent + ", " + bitangen + ", " + normal + " )" ); + return ObjectToTangentStr; + } + + // TANGENT TO OBJECT + //static public string GenerateTangentToObjectMatrixFast( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + //{ + // string normal = GenerateVertexNormal( ref dataCollector, uniqueId, precision ); + // string tangent = GenerateVertexTangent( ref dataCollector, uniqueId, precision ); + // string bitangent = GenerateVertexBitangent( ref dataCollector, uniqueId, precision ); + + // string result = string.Format( "float3x3({0}.x,{1}.x,{2}.x,{0}.y,{1}.y,{2}.y,{0}.z,{1}.z,{2}.z)",tangent,bitangent,normal ); + // dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3x3, TangentToObjectFastStr, result ); + // return TangentToObjectFastStr; + //} + + //static public string GenerateTangentToObjectMatrixPrecise( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + //{ + // string objectToTangent = GenerateObjectToTangentMatrix( ref dataCollector, uniqueId, precision ); + // Add3x3InverseFunction( ref dataCollector, UIUtils.PrecisionWirePortToCgType( precision, WirePortDataType.FLOAT ) ); + // dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3x3, TangentToObjectStr, string.Format( Inverse3x3Header, objectToTangent ) ); + // return TangentToObjectStr; + //} + + // WORLD TO TANGENT MATRIX + static public string GenerateWorldToTangentMatrix( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetWorldToTangentMatrix( precision ); + + if( dataCollector.IsFragmentCategory ) + { + dataCollector.ForceNormal = true; + + dataCollector.AddToInput( -1, SurfaceInputs.WORLD_NORMAL, precision ); + dataCollector.AddToInput( -1, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + } + + string worldNormal = GenerateWorldNormal( ref dataCollector, uniqueId ); + string worldTangent = GenerateWorldTangent( ref dataCollector, uniqueId ); + string worldBitangent = GenerateWorldBitangent( ref dataCollector, uniqueId ); + + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3x3, WorldToTangentStr, "float3x3( " + worldTangent + ", " + worldBitangent + ", " + worldNormal + " )" ); + return WorldToTangentStr; + } + + // TANGENT TO WORLD + static public string GenerateTangentToWorldMatrixFast( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetTangentToWorldMatrixFast( precision ); + + if( dataCollector.IsFragmentCategory ) + { + dataCollector.ForceNormal = true; + + dataCollector.AddToInput( -1, SurfaceInputs.WORLD_NORMAL, precision ); + dataCollector.AddToInput( -1, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + } + + string worldNormal = GenerateWorldNormal( ref dataCollector, uniqueId ); + string worldTangent = GenerateWorldTangent( ref dataCollector, uniqueId ); + string worldBitangent = GenerateWorldBitangent( ref dataCollector, uniqueId ); + + string result = string.Format( "float3x3({0}.x,{1}.x,{2}.x,{0}.y,{1}.y,{2}.y,{0}.z,{1}.z,{2}.z)", worldTangent, worldBitangent, worldNormal ); + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3x3, TangentToWorldFastStr, result ); + return TangentToWorldFastStr; + } + + static public string GenerateTangentToWorldMatrixPrecise( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetTangentToWorldMatrixPrecise( precision ); + + if( dataCollector.IsFragmentCategory ) + { + dataCollector.ForceNormal = true; + + dataCollector.AddToInput( -1, SurfaceInputs.WORLD_NORMAL, precision ); + dataCollector.AddToInput( -1, SurfaceInputs.INTERNALDATA, addSemiColon: false ); + } + + string worldToTangent = GenerateWorldToTangentMatrix( ref dataCollector, uniqueId, precision ); + Add3x3InverseFunction( ref dataCollector, UIUtils.PrecisionWirePortToCgType( precision, WirePortDataType.FLOAT ) ); + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3x3, TangentToWorldPreciseStr, string.Format( Inverse3x3Header, worldToTangent ) ); + return TangentToWorldPreciseStr; + } + + // SAMPLER STATES + static public string GenerateSamplerState( ref MasterNodeDataCollector dataCollector, int uniqueId, string propertyName, VariableMode varMode, bool returnPropertyName = false ) + { + + string sampler = string.Format( Constants.SamplerFormat, propertyName ); + string samplerDecl = string.Empty; + + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; +#if !UNITY_2018_1_OR_NEWER + if( outsideGraph.IsStandardSurface ) + return string.Empty; +#endif + if( outsideGraph.IsSRP ) + //if( dataCollector.IsSRP ) + samplerDecl = string.Format( Constants.SamplerDeclSRPFormat, sampler ) + ";"; + else + samplerDecl = string.Format( Constants.SamplerDeclFormat, sampler ) + ";"; + if( varMode == VariableMode.Create ) + dataCollector.AddToUniforms( uniqueId, samplerDecl ); + + if( returnPropertyName ) + return propertyName; + else + return sampler; + } + + public static string GetPropertyFromSamplerState( string sampler ) + { + if( sampler.StartsWith( "sampler" ) ) + return sampler.Remove( 0, 7 ); + else + return sampler; + } + + public static string GetSamplerDeclaraction( string texture, WirePortDataType type, string termination = "" ) + { + return GetSamplerDeclaraction( texture, Constants.WireToTexture[ type ], termination ); + } + + public static string GetSamplerDeclaraction( string sampler, TextureType type, string termination = "" ) + { + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; +#if UNITY_2018_1_OR_NEWER + if( outsideGraph.SamplingMacros || type == TextureType.Texture2DArray ) +#else + if( ( outsideGraph.SamplingMacros || type == TextureType.Texture2DArray ) && !outsideGraph.IsStandardSurface /*) || type == TextureType.Texture2DArray*/ ) +#endif + { + if( outsideGraph.IsSRP ) + return string.Format( Constants.SamplerDeclSRPFormat, sampler ) + termination; + else + return string.Format( Constants.SamplerDeclFormat, sampler ) + termination; + } + + // we don't use sampler states when macros are not available + return string.Empty; + } + + // PROPERTY MACRO + public static string GetPropertyDeclaraction( string texture, WirePortDataType type, string termination = "" ) + { + return GetPropertyDeclaraction( texture, Constants.WireToTexture[ type ], termination ); + } + + public static string GetPropertyDeclaraction( string texture, TextureType type, string termination = "" ) + { + if( type == TextureType.Texture1D ) + return "sampler1D " + texture + termination; + + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; +#if UNITY_2018_1_OR_NEWER + if( outsideGraph.SamplingMacros || type == TextureType.Texture2DArray ) +#else + if( ( outsideGraph.SamplingMacros || type == TextureType.Texture2DArray ) && !outsideGraph.IsStandardSurface ) +#endif + { + if( outsideGraph.IsSRP ) + return string.Format( Constants.TexDeclarationNoSamplerSRPMacros[ type ], texture ) + termination; + else + return string.Format( Constants.TexDeclarationNoSamplerStandardMacros[ type ], texture ) + termination; + } + + return UIUtils.TextureTypeToCgType( type )+ " " + texture + termination; + } + + // SAMPLING CALL + public static string GenerateSamplingCall( ref MasterNodeDataCollector dataCollector, WirePortDataType type, string property, string samplerState, string uv, MipType mip = MipType.Auto, params string[] mipData ) + { + ParentGraph ousideGraph = UIUtils.CurrentWindow.OutsideGraph; + string result = string.Empty; + string mipSuffix = string.Empty; + + //samplerState = GetPropertyFromSamplerState( samplerState ); + TextureType textureType = Constants.WireToTexture[ type ]; + + bool usingMacro = false; +#if UNITY_2018_1_OR_NEWER + if( ousideGraph.SamplingMacros || textureType == TextureType.Texture2DArray ) +#else + if( ( ousideGraph.SamplingMacros && !ousideGraph.IsStandardSurface ) || textureType == TextureType.Texture2DArray ) +#endif + usingMacro = true; + + switch( mip ) + { + default: + case MipType.Auto: + break; + case MipType.MipLevel: + mipSuffix = usingMacro ? "_LOD" : "lod"; + break; + case MipType.MipBias: + mipSuffix = usingMacro ? "_BIAS" : "bias"; + break; + case MipType.Derivative: + mipSuffix = usingMacro ? "_GRAD" : "grad"; + break; + } + + string mipParams = string.Empty; + if( mip != MipType.Auto ) + { + for( int i = 0; i < mipData.Length; i++ ) + { + mipParams += ", " + mipData[ i ]; + } + } + + if( usingMacro ) + { + if( ousideGraph.IsSRP ) + { + if( textureType == TextureType.Texture3D && ( mip == MipType.MipBias || mip == MipType.Derivative ) ) + AddCustom3DSRPMacros( ref dataCollector ); + // srp macro + result = string.Format( Constants.TexSampleSRPMacros[ textureType ], mipSuffix, property, samplerState, uv + mipParams ); + } + else + { + AddCustomStandardSamplingMacros( ref dataCollector, type, mip ); +#if !UNITY_2018_1_OR_NEWER + if( ousideGraph.IsStandardSurface ) + result = string.Format( Constants.TexSampleStandardMacros[ textureType ], mipSuffix, property, samplerState, uv + mipParams ); + else +#endif + result = string.Format( Constants.TexSampleSamplerStandardMacros[ textureType ], mipSuffix, property, samplerState, uv + mipParams ); + + } + } + else + { + //no macro : builtin and srp + string uvs = uv + mipParams; + string emptyParam = ", 0"; + if( textureType == TextureType.Texture3D || textureType == TextureType.Cube ) + emptyParam = string.Empty; + + if( ( mip == MipType.MipBias || mip == MipType.MipLevel ) ) + uvs = "float4(" + uv + emptyParam + mipParams + ")"; + + result = string.Format( Constants.TexSampleStandard[ textureType ], mipSuffix, property, uvs ); + } + return result; + } + + // AUTOMATIC UVS + static public string GenerateAutoUVs( ref MasterNodeDataCollector dataCollector, int uniqueId, int index, string propertyName = null, WirePortDataType size = WirePortDataType.FLOAT2, string scale = null, string offset = null, string outputId = null ) + { + string result = string.Empty; + string varName = string.Empty; + string indexStr = index > 0 ? ( index + 1 ).ToString() : ""; + string sizeDif = string.Empty; + if( size == WirePortDataType.FLOAT3 ) + sizeDif = "3"; + else if( size == WirePortDataType.FLOAT4 ) + sizeDif = "4"; + + if( !dataCollector.IsTemplate && index > 3 ) + { + string texCoordNameIn = TemplateHelperFunctions.BaseInterpolatorName + index; + string texCoordNameOut = TemplateHelperFunctions.BaseInterpolatorName + ( index + 1 ).ToString(); + if( dataCollector.IsFragmentCategory ) + { + + GenerateValueInVertex( ref dataCollector, uniqueId, size, PrecisionType.Float, Constants.VertexShaderInputStr + "." + texCoordNameIn, texCoordNameOut, true ); + result = Constants.InputVarStr + "." + texCoordNameOut; + } + else + { + result = Constants.VertexShaderInputStr + "." + texCoordNameIn; + } + + if( !string.IsNullOrEmpty( propertyName ) ) + { + + varName = "uv" + indexStr + ( size != WirePortDataType.FLOAT2 ? "s" + sizeDif : "" ) + propertyName; + dataCollector.AddToUniforms( uniqueId, "uniform float4 " + propertyName + "_ST;" ); + if( size > WirePortDataType.FLOAT2 ) + { + dataCollector.UsingHigherSizeTexcoords = true; + dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, PrecisionType.Float, size, varName, result ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, varName + ".xy = " + result + ".xy * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw;" ); + } + else + { + dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, PrecisionType.Float, size, varName, result + " * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw" ); + } + + result = varName; + } + + switch( size ) + { + default: + case WirePortDataType.FLOAT2: + { + result += ".xy"; + } + break; + case WirePortDataType.FLOAT3: + { + result += ".xyz"; + } + break; + case WirePortDataType.FLOAT4: break; + } + + return result; + } + + if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + { + string dummyPropUV = "_tex" + sizeDif + "coord" + indexStr; + string dummyUV = "uv" + indexStr + dummyPropUV; + + dataCollector.AddToProperties( uniqueId, "[HideInInspector] " + dummyPropUV + "( \"\", 2D ) = \"white\" {}", 100 ); + dataCollector.AddToInput( uniqueId, dummyUV, size ); + + result = Constants.InputVarStr + "." + dummyUV; + } + else + { + result = Constants.VertexShaderInputStr + ".texcoord"; + if( index > 0 ) + { + result += index.ToString(); + } + + switch( size ) + { + default: + case WirePortDataType.FLOAT2: + { + result += ".xy"; + } + break; + case WirePortDataType.FLOAT3: + { + result += ".xyz"; + } + break; + case WirePortDataType.FLOAT4: break; + } + } + + varName = "uv" + indexStr + ( size != WirePortDataType.FLOAT2 ? "s" + sizeDif : "" ) + "_TexCoord" + outputId; + + if( !string.IsNullOrEmpty( propertyName ) ) + { + string finalVarName = "uv" + indexStr + ( size != WirePortDataType.FLOAT2 ? "s" + sizeDif : "" ) + propertyName; + + dataCollector.AddToUniforms( uniqueId, "uniform float4 " + propertyName + "_ST;" ); + if( size > WirePortDataType.FLOAT2 ) + { + dataCollector.UsingHigherSizeTexcoords = true; + dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, PrecisionType.Float, size, finalVarName, result ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, finalVarName + ".xy = " + result + ".xy * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw;" ); + } + else + { + dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, PrecisionType.Float, size, finalVarName, result + " * " + propertyName + "_ST.xy + " + propertyName + "_ST.zw" ); + } + + result = finalVarName; + } + else if( !string.IsNullOrEmpty( scale ) || !string.IsNullOrEmpty( offset ) ) + { + if( size > WirePortDataType.FLOAT2 ) + { + dataCollector.UsingHigherSizeTexcoords = true; + dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, PrecisionType.Float, size, varName, result ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, varName + ".xy = " + result + ".xy" + ( string.IsNullOrEmpty( scale ) ? "" : " * " + scale ) + ( string.IsNullOrEmpty( offset ) ? "" : " + " + offset ) + ";" ); + } + else + { + dataCollector.AddToLocalVariables( dataCollector.PortCategory, uniqueId, PrecisionType.Float, size, varName, result + ( string.IsNullOrEmpty( scale ) ? "" : " * " + scale ) + ( string.IsNullOrEmpty( offset ) ? "" : " + " + offset ) ); + } + + result = varName; + } + else if( dataCollector.PortCategory == MasterNodePortCategory.Fragment ) + { + if( size > WirePortDataType.FLOAT2 ) + dataCollector.UsingHigherSizeTexcoords = true; + } + + return result; + } + + // SCREEN POSITION NORMALIZED + static public string GenerateScreenPositionNormalizedForValue( string customVertexPos, string outputId, ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, bool addInput = true ) + { + string stringPosVar = GenerateScreenPositionForValue( customVertexPos, outputId, ref dataCollector, uniqueId, precision, addInput ); + string varName = ScreenPositionNormalizedStr + uniqueId; + + // TODO: check later if precision can be half + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, varName, string.Format( NormalizedScreenPosFormat, stringPosVar ) ); + dataCollector.AddLocalVariable( uniqueId, varName + ".z = ( UNITY_NEAR_CLIP_VALUE >= 0 ) ? " + varName + ".z : " + varName + ".z * 0.5 + 0.5;" ); + + return varName; + } + + static public string GenerateScreenPositionNormalized( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, bool addInput = true, string customScreenPos = null ) + { + string stringPosVar = string.IsNullOrEmpty( customScreenPos ) ? GenerateScreenPosition( ref dataCollector, uniqueId, precision, addInput ) : customScreenPos; + + // TODO: check later if precision can be half + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, ScreenPositionNormalizedStr, string.Format( NormalizedScreenPosFormat, stringPosVar ) ); + dataCollector.AddLocalVariable( uniqueId, ScreenPositionNormalizedStr + ".z = ( UNITY_NEAR_CLIP_VALUE >= 0 ) ? " + ScreenPositionNormalizedStr + ".z : " + ScreenPositionNormalizedStr + ".z * 0.5 + 0.5;" ); + + return ScreenPositionNormalizedStr; + } + + // SCREEN POSITION + static public string GenerateScreenPositionForValue( string customVertexPosition, string outputId, ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, bool addInput = true ) + { + // overriding precision + precision = PrecisionType.Float; + + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetScreenPosForValue( precision, customVertexPosition, outputId ); + + + string value = GenerateVertexScreenPositionForValue( customVertexPosition, outputId, ref dataCollector, uniqueId, precision ); + + if( !dataCollector.IsFragmentCategory ) + { + return value; + } + + string screenPosVarName = "screenPosition" + outputId; + dataCollector.AddToInput( uniqueId, screenPosVarName, WirePortDataType.FLOAT4, precision ); + dataCollector.AddToVertexLocalVariables( uniqueId, Constants.VertexShaderOutputStr + "." + screenPosVarName + " = " + value + ";" ); + + + + string screenPosVarNameOnFrag = ScreenPositionStr + outputId; + string globalResult = Constants.InputVarStr + "." + screenPosVarName; + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, screenPosVarNameOnFrag, globalResult ); + return screenPosVarNameOnFrag; + + } + + static public string GenerateScreenPosition( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, bool addInput = true ) + { + // overriding precision + precision = PrecisionType.Float; + + if( dataCollector.UsingCustomScreenPos && dataCollector.IsFragmentCategory ) + { + string value = GenerateVertexScreenPosition( ref dataCollector, uniqueId, precision ); + dataCollector.AddToInput( uniqueId, "screenPosition", WirePortDataType.FLOAT4, precision ); + dataCollector.AddToVertexLocalVariables( uniqueId, Constants.VertexShaderOutputStr + ".screenPosition = " + value + ";" ); + + string globalResult = Constants.InputVarStr + ".screenPosition"; + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, ScreenPositionStr, globalResult ); + return ScreenPositionStr; + } + else + { + if( !dataCollector.IsFragmentCategory ) + return GenerateVertexScreenPosition( ref dataCollector, uniqueId, precision ); + + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetScreenPos( precision ); + } + + + if( addInput ) + dataCollector.AddToInput( uniqueId, SurfaceInputs.SCREEN_POS, precision ); + + string result = Constants.InputVarStr + ".screenPos"; + dataCollector.AddLocalVariable( uniqueId, string.Format( "float4 {0} = float4( {1}.xyz , {1}.w + 0.00000000001 );", ScreenPositionStr, result ) ); + + return ScreenPositionStr; + } + + // GRAB SCREEN POSITION + static public string GenerateGrabScreenPosition( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, bool addInput = true, string customScreenPos = null ) + { + // overriding precision + precision = PrecisionType.Float; + + string screenPos = string.Empty; + if( string.IsNullOrEmpty( customScreenPos ) ) + screenPos = GenerateScreenPosition( ref dataCollector, uniqueId, precision, addInput ); + else + screenPos = customScreenPos; + + string computeBody = string.Empty; + IOUtils.AddFunctionHeader( ref computeBody, GrabFunctionHeader ); + foreach( string line in GrabFunctionBody ) + IOUtils.AddFunctionLine( ref computeBody, line ); + IOUtils.CloseFunctionBody( ref computeBody ); + string functionResult = dataCollector.AddFunctions( GrabFunctionCall, computeBody, screenPos ); + + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, GrabScreenPositionStr, functionResult ); + return GrabScreenPositionStr; + } + + // GRAB SCREEN POSITION NORMALIZED + static public string GenerateGrabScreenPositionNormalized( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, bool addInput = true, string customScreenPos = null ) + { + string stringPosVar = GenerateGrabScreenPosition( ref dataCollector, uniqueId, precision, addInput, customScreenPos ); + + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, GrabScreenPositionNormalizedStr, string.Format( NormalizedScreenPosFormat, stringPosVar ) ); + return GrabScreenPositionNormalizedStr; + } + + // SCREEN POSITION ON VERT + static public string GenerateVertexScreenPositionForValue( string customVertexPosition, string outputId, ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + // overriding precision + precision = PrecisionType.Float; + + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetScreenPosForValue( precision, customVertexPosition, outputId ); + + string screenPosVarName = ScreenPositionStr + outputId; + string value = string.Format( "ComputeScreenPos( UnityObjectToClipPos( {0} ) )", customVertexPosition ); + dataCollector.AddToVertexLocalVariables( uniqueId, precision, WirePortDataType.FLOAT4, screenPosVarName, value ); + return screenPosVarName; + } + + static public string GenerateVertexScreenPosition( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + // overriding precision + precision = PrecisionType.Float; + + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetScreenPos( precision ); + + string value = string.Format( "ComputeScreenPos( UnityObjectToClipPos( {0}.vertex ) )", Constants.VertexShaderInputStr ); + dataCollector.AddToVertexLocalVariables( uniqueId, precision, WirePortDataType.FLOAT4, ScreenPositionStr, value ); + return ScreenPositionStr; + } + + // VERTEX POSITION + static public string GenerateVertexPosition( ref MasterNodeDataCollector dataCollector, int uniqueId, WirePortDataType size ) + { + // overriding precision + var precision = PrecisionType.Float; + + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetVertexPosition( size, precision ); + + string value = Constants.VertexShaderInputStr + ".vertex"; + if( size == WirePortDataType.FLOAT3 ) + value += ".xyz"; + + if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + { + dataCollector.AddToInput( uniqueId, SurfaceInputs.WORLD_POS ); + dataCollector.AddToIncludes( uniqueId, Constants.UnityShaderVariables ); + + value = "mul( unity_WorldToObject, float4( " + Constants.InputVarStr + ".worldPos , 1 ) )"; + } + string varName = VertexPosition4Str; + if( size == WirePortDataType.FLOAT3 ) + varName = VertexPosition3Str; + + dataCollector.AddLocalVariable( uniqueId, precision, size, varName, value ); + return varName; + } + + // VERTEX NORMAL + static public string GenerateVertexNormal( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + return dataCollector.TemplateDataCollectorInstance.GetVertexNormal( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision ); + } + + string value = Constants.VertexShaderInputStr + ".normal.xyz"; + if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + { + GenerateWorldNormal( ref dataCollector, uniqueId ); + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, VertexNormalStr, "mul( unity_WorldToObject, float4( " + WorldNormalStr + ", 0 ) )" ); + //dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT3, VertexNormalStr, "mul( unity_WorldToObject, float4( " + WorldNormalStr + ", 0 ) )" ); + } + else + { + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, VertexNormalStr, value ); + } + return VertexNormalStr; + } + + // VERTEX TANGENT + static public string GenerateVertexTangent( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, WirePortDataType size ) + { + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + return dataCollector.TemplateDataCollectorInstance.GetVertexTangent( size,UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision ); + } + + if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + { + GenerateWorldTangent( ref dataCollector, uniqueId ); + dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT4, VertexTangentStr, "mul( unity_WorldToObject, float4( " + WorldTangentStr + ", 0 ) )" ); + } + else + { + string value = Constants.VertexShaderInputStr + ".tangent"; + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, VertexTangentStr, value ); + } + + return ( size == WirePortDataType.FLOAT4 ) ? VertexTangentStr : VertexTangentStr + ".xyz"; + } + + // VERTEX TANGENT SIGN + static public string GenerateVertexTangentSign( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + return dataCollector.TemplateDataCollectorInstance.GetTangentSign( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision ); + } + + string value = Constants.VertexShaderInputStr + ".tangent.w"; + if( dataCollector.IsFragmentCategory ) + { + dataCollector.AddToInput( uniqueId, VertexTangentSignStr, WirePortDataType.FLOAT, PrecisionType.Half ); + dataCollector.AddToVertexLocalVariables( uniqueId, Constants.VertexShaderOutputStr + "." + VertexTangentSignStr + " = " + Constants.VertexShaderInputStr + ".tangent.w;" ); + return Constants.InputVarStr + "." + VertexTangentSignStr; + } + else + { + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT, VertexTangentSignStr, value ); + } + return VertexTangentSignStr; + } + + // VERTEX BITANGENT + static public string GenerateVertexBitangent( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + if( dataCollector.MasterNodeCategory == AvailableShaderTypes.Template ) + { + return dataCollector.TemplateDataCollectorInstance.GetVertexBitangent( UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision ); + } + + if( dataCollector.PortCategory == MasterNodePortCategory.Fragment || dataCollector.PortCategory == MasterNodePortCategory.Debug ) + { + GenerateWorldBitangent( ref dataCollector, uniqueId ); + dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT3, VertexBitangentStr, "mul( unity_WorldToObject, float4( " + WorldBitangentStr + ", 0 ) )" ); + } + else + { + GenerateVertexNormal( ref dataCollector, uniqueId, precision ); + GenerateVertexTangent( ref dataCollector, uniqueId, precision, WirePortDataType.FLOAT3 ); + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, VertexBitangentStr, "cross( " + VertexNormalStr + ", " + VertexTangentStr + ") * " + Constants.VertexShaderInputStr + ".tangent.w * unity_WorldTransformParams.w" ); + } + return VertexBitangentStr; + } + + // VERTEX POSITION ON FRAG + static public string GenerateVertexPositionOnFrag( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + dataCollector.AddToInput( uniqueId, SurfaceInputs.WORLD_POS ); + dataCollector.AddToIncludes( uniqueId, Constants.UnityShaderVariables ); + + string value = "mul( unity_WorldToObject, float4( " + Constants.InputVarStr + ".worldPos , 1 ) )"; + + dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT4, VertexPosition4Str, value ); + return VertexPosition4Str; + } + + // CLIP POSITION ON FRAG + static public string GenerateClipPositionOnFrag( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + if( dataCollector.IsTemplate ) + return dataCollector.TemplateDataCollectorInstance.GetClipPos(); + + string vertexName = GenerateVertexPositionOnFrag( ref dataCollector, uniqueId, precision ); + string value = string.Format( "ComputeScreenPos( UnityObjectToClipPos( {0} ) )", vertexName ); + dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT4, ClipPositionStr, value ); + return ClipPositionStr; + } + + // VIEW DIRECTION + static public string GenerateViewDirection( ref MasterNodeDataCollector dataCollector, int uniqueId, ViewSpace space = ViewSpace.World ) + { + PrecisionType precision = UIUtils.CurrentWindow.CurrentGraph.CurrentPrecision; + if( dataCollector.IsTemplate ) + return ( space == ViewSpace.Tangent ) ? dataCollector.TemplateDataCollectorInstance.GetTangentViewDir( precision ) : dataCollector.TemplateDataCollectorInstance.GetViewDir(); + + string worldPos = GenerateWorldPosition( ref dataCollector, uniqueId ); + string safeNormalizeInstruction = string.Empty; + if( dataCollector.SafeNormalizeViewDir ) + { + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { + safeNormalizeInstruction = "SafeNormalize"; + } + else + { + if( dataCollector.IsTemplate ) + dataCollector.AddToIncludes( -1, Constants.UnityBRDFLib ); + safeNormalizeInstruction = "Unity_SafeNormalize"; + } + } + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, WorldViewDirectionStr, ( dataCollector.SafeNormalizeViewDir ? safeNormalizeInstruction : "normalize" ) + "( UnityWorldSpaceViewDir( " + worldPos + " ) )" ); + + if( space == ViewSpace.Tangent ) + { + string worldToTangent = GenerateWorldToTangentMatrix( ref dataCollector, uniqueId, precision ); + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, TangentViewDirectionStr, "mul( " + worldToTangent + ", " + WorldViewDirectionStr + " )" ); + return TangentViewDirectionStr; + } + else + { + return WorldViewDirectionStr; + } + } + + // VIEW POS + static public string GenerateViewPositionOnFrag( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + // overriding precision + precision = PrecisionType.Float; + + if( dataCollector.IsTemplate ) + UnityEngine.Debug.LogWarning( "View Pos not implemented on Templates" ); + + string vertexName = GenerateVertexPositionOnFrag( ref dataCollector, uniqueId, precision ); + string value = string.Format( "UnityObjectToViewPos( {0} )", vertexName ); + dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT3, ViewPositionStr, value ); + return ViewPositionStr; + } + + // SCREEN DEPTH + static public string GenerateScreenDepthOnFrag( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + // overriding precision + precision = PrecisionType.Float; + + if( dataCollector.IsTemplate ) + UnityEngine.Debug.LogWarning( "Screen Depth not implemented on Templates" ); + + string viewPos = GenerateViewPositionOnFrag( ref dataCollector, uniqueId, precision ); + string value = string.Format( "-{0}.z", viewPos ); + dataCollector.AddToLocalVariables( uniqueId, precision, WirePortDataType.FLOAT, ScreenDepthStr, value ); + return ScreenDepthStr; + } + + // LIGHT DIRECTION WORLD + static public string GenerateWorldLightDirection( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision ) + { + dataCollector.AddToIncludes( uniqueId, Constants.UnityCgLibFuncs ); + string worldPos = GeneratorUtils.GenerateWorldPosition( ref dataCollector, uniqueId ); + dataCollector.AddLocalVariable( uniqueId, "#if defined(LIGHTMAP_ON) && UNITY_VERSION < 560 //aseld" ); + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, WorldLightDirStr, "0" ); + dataCollector.AddLocalVariable( uniqueId, "#else //aseld" ); + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, WorldLightDirStr, ( dataCollector.SafeNormalizeLightDir ? "Unity_SafeNormalize" : "normalize" ) + "( UnityWorldSpaceLightDir( " + worldPos + " ) )" ); + dataCollector.AddLocalVariable( uniqueId, "#endif //aseld" ); + return WorldLightDirStr; + } + + private static readonly string[] SafeNormalizeBuiltin = + { + "inline float{0} ASESafeNormalize(float{0} inVec)\n", + "{\n", + "\tfloat dp3 = max( 0.001f , dot( inVec , inVec ) );\n", + "\treturn inVec* rsqrt( dp3);\n", + "}\n" + }; + + private static readonly string[] SafeNormalizeSRP = + { + "real{0} ASESafeNormalize(float{0} inVec)\n", + "{\n", + "\treal dp3 = max(FLT_MIN, dot(inVec, inVec));\n", + "\treturn inVec* rsqrt( dp3);\n", + "}\n", + }; + + static public string NormalizeValue( ref MasterNodeDataCollector dataCollector , bool safeNormalize , WirePortDataType dataType, string value ) + { + string normalizeInstruction = string.Empty; + if( safeNormalize ) + { + string[] finalFunction = null; + string[] funcVersion = dataCollector.IsSRP ? SafeNormalizeSRP : SafeNormalizeBuiltin; + + finalFunction = new string[ funcVersion.Length ]; + + switch( dataType ) + { + case WirePortDataType.FLOAT: + finalFunction[0] = string.Format( funcVersion[ 0 ] , string.Empty ); + break; + case WirePortDataType.FLOAT2: + finalFunction[ 0 ] = string.Format( funcVersion[ 0 ] , "2" ); + break; + case WirePortDataType.FLOAT3: + finalFunction[ 0 ] = string.Format( funcVersion[ 0 ] , "3" ); + break; + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + finalFunction[ 0 ] = string.Format( funcVersion[ 0 ] , "4" ); + break; + default: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + case WirePortDataType.INT: + case WirePortDataType.OBJECT: + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.UINT: + case WirePortDataType.UINT4: + case WirePortDataType.SAMPLER2DARRAY: + case WirePortDataType.SAMPLERSTATE:return value; + } + + for( int i = 1 ; i < funcVersion.Length ; i++ ) + { + finalFunction[ i ] = funcVersion[ i ]; + } + dataCollector.AddFunction( finalFunction[ 0 ] , finalFunction , false ); + normalizeInstruction = "ASESafeNormalize"; + } + else + { + normalizeInstruction = "normalize"; + } + + return normalizeInstruction = normalizeInstruction + "( " + value + " )"; + + } + // LIGHT DIRECTION Object + static public string GenerateObjectLightDirection( ref MasterNodeDataCollector dataCollector, int uniqueId, PrecisionType precision, string vertexPos ) + { + dataCollector.AddToIncludes( uniqueId, Constants.UnityCgLibFuncs ); + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, ObjectLightDirStr, "normalize( ObjSpaceLightDir( " + vertexPos + " ) )" ); + return ObjectLightDirStr; + } + + // UNPACK NORMALS + public static string GenerateUnpackNormalStr( ref MasterNodeDataCollector dataCollector, PrecisionType precision, int uniqueId, string outputId, string src, bool applyScale, string scale ) + { + string funcName; + if( dataCollector.IsTemplate && dataCollector.IsSRP ) + { +#if UNITY_2018_3_OR_NEWER + if( ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_7_2_1 ) + { + if( applyScale ) + { + dataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT3, "unpack" + outputId, "UnpackNormalScale( " + src + ", " + scale + " )" ); + dataCollector.AddLocalVariable( uniqueId, "unpack" + outputId + ".z = lerp( 1, unpack" + outputId + ".z, saturate(" + scale + ") );" ); + funcName = "unpack" + outputId; + } + else + { + funcName = "UnpackNormalScale( " + src + ", " + scale + " )"; + } + } + else +#endif + { + if( dataCollector.TemplateDataCollectorInstance.IsHDRP ) + funcName = "UnpackNormalmapRGorAG( " + src + ", " + scale + " )"; + else + funcName = "UnpackNormalScale( " + src + ", " + scale + " )"; + } + } + else + { + funcName = applyScale ? "UnpackScaleNormal( " + src + ", " + scale + " )" : "UnpackNormal( " + src + " )"; + } + return funcName; + } + + //MATRIX INVERSE + // 3x3 + public static string Inverse3x3Header = "Inverse3x3( {0} )"; + public static string[] Inverse3x3Function = + { + "{0}3x3 Inverse3x3({0}3x3 input)\n", + "{\n", + "\t{0}3 a = input._11_21_31;\n", + "\t{0}3 b = input._12_22_32;\n", + "\t{0}3 c = input._13_23_33;\n", + "\treturn {0}3x3(cross(b,c), cross(c,a), cross(a,b)) * (1.0 / dot(a,cross(b,c)));\n", + "}\n" + }; + + public static bool[] Inverse3x3FunctionFlags = + { + true, + false, + true, + true, + true, + true, + false + }; + + public static void Add3x3InverseFunction( ref MasterNodeDataCollector dataCollector, string precisionString ) + { + if( !dataCollector.HasFunction( Inverse3x3Header ) ) + { + //Hack to be used util indent is properly used + int currIndent = UIUtils.ShaderIndentLevel; + if( dataCollector.IsTemplate ) + { + UIUtils.ShaderIndentLevel = 0; + } + else + { + UIUtils.ShaderIndentLevel = 1; + UIUtils.ShaderIndentLevel++; + } + string finalFunction = string.Empty; + for( int i = 0; i < Inverse3x3Function.Length; i++ ) + { + finalFunction += UIUtils.ShaderIndentTabs + ( Inverse3x3FunctionFlags[ i ] ? string.Format( Inverse3x3Function[ i ], precisionString ) : Inverse3x3Function[ i ] ); + } + + + UIUtils.ShaderIndentLevel = currIndent; + + dataCollector.AddFunction( Inverse3x3Header, finalFunction ); + } + } + + public static string GenerateValueInVertex( ref MasterNodeDataCollector dataCollector, int uniqueId, WirePortDataType dataType, PrecisionType currentPrecisionType, string dataValue, string dataName, bool createInterpolator ) + { + if( !dataCollector.IsFragmentCategory ) + return dataValue; + + //TEMPLATES + if( dataCollector.IsTemplate ) + { + if( createInterpolator && dataCollector.TemplateDataCollectorInstance.HasCustomInterpolatedData( dataName ) ) + return dataName; + + MasterNodePortCategory category = dataCollector.PortCategory; + dataCollector.PortCategory = MasterNodePortCategory.Vertex; + + dataCollector.PortCategory = category; + + if( createInterpolator ) + { + dataCollector.TemplateDataCollectorInstance.RegisterCustomInterpolatedData( dataName, dataType, currentPrecisionType, dataValue ); + } + else + { + dataCollector.AddToVertexLocalVariables( -1, currentPrecisionType, dataType, dataName, dataValue ); + } + + return dataName; + } + + //SURFACE + { + if( dataCollector.TesselationActive ) + { + UIUtils.ShowMessage( "Unable to use Vertex to Frag when Tessellation is active" ); + switch( dataType ) + { + case WirePortDataType.FLOAT2: + { + return "(0).xx"; + } + case WirePortDataType.FLOAT3: + { + return "(0).xxx"; + } + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + { + return "(0).xxxx"; + } + } + return "0"; + } + + if( createInterpolator ) + dataCollector.AddToInput( uniqueId, dataName, dataType, currentPrecisionType ); + + MasterNodePortCategory portCategory = dataCollector.PortCategory; + dataCollector.PortCategory = MasterNodePortCategory.Vertex; + if( createInterpolator ) + { + dataCollector.AddLocalVariable( uniqueId, Constants.VertexShaderOutputStr + "." + dataName, dataValue + ";" ); + } + else + { + dataCollector.AddLocalVariable( uniqueId, currentPrecisionType, dataType, dataName, dataValue ); + } + dataCollector.PortCategory = portCategory; + return createInterpolator ? Constants.InputVarStr + "." + dataName : dataName; + } + } + + public static void AddCustomStandardSamplingMacros( ref MasterNodeDataCollector dataCollector, TextureType type, MipType mip ) + { + AddCustomStandardSamplingMacros( ref dataCollector, Constants.TextureToWire[ type ], mip ); + } + + public static void AddCustomStandardSamplingMacros( ref MasterNodeDataCollector dataCollector, WirePortDataType type, MipType mip ) + { + MacrosMask result = MacrosMask.NONE; + switch( mip ) + { + default: + case MipType.Auto: + result |= MacrosMask.AUTO; + break; + case MipType.MipLevel: + result |= MacrosMask.LOD; + break; + case MipType.MipBias: + result |= MacrosMask.BIAS; + break; + case MipType.Derivative: + result |= MacrosMask.GRAD; + break; + } + + switch( type ) + { + default: + case WirePortDataType.SAMPLER2D: + dataCollector.Using2DMacrosMask |= result; + break; + case WirePortDataType.SAMPLER3D: + dataCollector.Using3DMacrosMask |= result; + break; + case WirePortDataType.SAMPLERCUBE: + dataCollector.UsingCUBEMacrosMask |= result; + break; + case WirePortDataType.SAMPLER2DARRAY: + dataCollector.Using2DArrayMacrosMask |= result; + break; + } + } + + public static void AddCustom3DSRPMacros( ref MasterNodeDataCollector dataCollector ) + { + // add just once + if( dataCollector.UsingExtra3DSRPMacros ) + return; + + dataCollector.UsingExtra3DSRPMacros = true; + for( int i = 0; i < Constants.CustomSRPSamplingMacros.Length; i++ ) + dataCollector.AddToDirectives( Constants.CustomSRPSamplingMacros[ i ] ); + } + + public static void AddCustomArraySamplingMacros( ref MasterNodeDataCollector dataCollector ) + { + // add just once + if( dataCollector.UsingArrayDerivatives ) + return; + + dataCollector.UsingArrayDerivatives = true; + for( int i = 0; i < Constants.CustomArraySamplingMacros.Length; i++ ) + dataCollector.AddToDirectives( Constants.CustomArraySamplingMacros[ i ] ); + } + + /*public static void AddCustomASEMacros( ref MasterNodeDataCollector dataCollector ) + { + string varPrefix = dataCollector.IsSRP ? varPrefix = "TEXTURE" : "UNITY_DECLARE_TEX"; + + if( dataCollector.IsSRP ) + { + for( int i = 0; i < Constants.CustomASESRPArgsMacros.Length; i++ ) + { + dataCollector.AddToDirectives( Constants.CustomASESRPArgsMacros[ i ] ); + } + + for( int i = 0; i < Constants.CustomSRPSamplingMacros.Length; i++ ) + { + dataCollector.AddToDirectives( Constants.CustomSRPSamplingMacros[ i ] ); + } + } + else + { + + for( int i = 0; i < Constants.CustomASEStandardArgsMacros.Length; i++ ) + { + dataCollector.AddToDirectives( Constants.CustomASEStandardArgsMacros[ i ] ); + } + + for( int i = 0; i < Constants.CustomStandardSamplingMacros.Length; i++ ) + { + dataCollector.AddToDirectives( Constants.CustomStandardSamplingMacros[ i ] ); + } + } + + for( int i = 0; i < Constants.CustomASEDeclararionMacros.Length; i++ ) + { + string value = string.Format( Constants.CustomASEDeclararionMacros[ i ], varPrefix ); + dataCollector.AddToDirectives( value ); + } + + string samplePrefix = string.Empty; + string samplerArgs = string.Empty; + string samplerDecl = string.Empty; + + if( dataCollector.IsSRP ) + { + samplePrefix = "SAMPLE_TEXTURE"; + samplerArgs = "samplerName,"; + + for( int i = 0; i < Constants.CustomASESamplingMacros.Length; i++ ) + { + string value = string.Format( Constants.CustomASESamplingMacros[ i ], samplerArgs, samplePrefix, samplerDecl ); + dataCollector.AddToDirectives( value ); + } + } + else + { + samplePrefix = "UNITY_SAMPLE_TEX"; + samplerArgs = "samplerName,"; + samplerDecl = "_SAMPLER"; + dataCollector.AddToDirectives( Constants.CustomASEStandarSamplingMacrosHelper[ 0 ] ); + for( int i = 0; i < Constants.CustomASESamplingMacros.Length; i++ ) + { + string value = string.Format( Constants.CustomASESamplingMacros[ i ], samplerArgs, samplePrefix, samplerDecl ); + dataCollector.AddToDirectives( value ); + } + dataCollector.AddToDirectives( Constants.CustomASEStandarSamplingMacrosHelper[ 1 ] ); + samplerArgs = string.Empty; + samplerDecl = string.Empty; + for( int i = 0; i < Constants.CustomASESamplingMacros.Length; i++ ) + { + string value = string.Format( Constants.CustomASESamplingMacros[ i ], samplerArgs, samplePrefix, samplerDecl ); + dataCollector.AddToDirectives( value ); + } + dataCollector.AddToDirectives( Constants.CustomASEStandarSamplingMacrosHelper[ 2 ] ); + } + }*/ + + public static void RegisterUnity2019MatrixDefines( ref MasterNodeDataCollector dataCollector ) + { +#if UNITY_2019_1_OR_NEWER + if( dataCollector.IsSRP && dataCollector.TemplateDataCollectorInstance.IsHDRP && ASEPackageManagerHelper.CurrentHDVersion >= ASESRPVersions.ASE_SRP_5_13_0 ) + { + //dataCollector.AddToDefines( -1, "unity_CameraProjection UNITY_MATRIX_P" ); + //dataCollector.AddToDefines( -1, "unity_CameraInvProjection UNITY_MATRIX_I_P" ); + //dataCollector.AddToDefines( -1, "unity_WorldToCamera UNITY_MATRIX_V" ); + //dataCollector.AddToDefines( -1, "unity_CameraToWorld UNITY_MATRIX_I_V" ); + + dataCollector.AddToUniforms( -1, "float4x4 unity_CameraProjection;" ); + dataCollector.AddToUniforms( -1, "float4x4 unity_CameraInvProjection;" ); + dataCollector.AddToUniforms( -1, "float4x4 unity_WorldToCamera;" ); + dataCollector.AddToUniforms( -1, "float4x4 unity_CameraToWorld;" ); + } +#endif + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GeneratorUtils.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GeneratorUtils.cs.meta new file mode 100644 index 0000000..190ac10 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GeneratorUtils.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7ab31d77d200c7a4ca43f4bf159de6b3 +timeCreated: 1490798546 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GenericMessage.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GenericMessage.cs new file mode 100644 index 0000000..3a699c6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GenericMessage.cs @@ -0,0 +1,117 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public enum MessageSeverity + { + Normal, + Warning, + Error + } + public class GenericMessageData + { + public string message; + public MessageSeverity severity; + public bool console; + public GenericMessageData( string msg, MessageSeverity svrty, bool csle ) + { + message = msg; + severity = svrty; + console = csle; + } + } + + class GenericMessageUI + { + public delegate void OnMessageDisplay( string message, MessageSeverity severity, bool console ); + public event OnMessageDisplay OnMessageDisplayEvent; + + private const double MESSAGE_TIME = 2; + private double m_currentMessageStartTime; + private Queue m_messageQueue; + private bool m_displayingMessage; + + public GenericMessageUI() + { + m_messageQueue = new Queue(); + m_displayingMessage = false; + m_currentMessageStartTime = EditorApplication.timeSinceStartup; + } + + public void Destroy() + { + m_messageQueue.Clear(); + OnMessageDisplayEvent = null; + } + + public void AddToQueue( string message, MessageSeverity severity, bool console ) + { + m_messageQueue.Enqueue( new GenericMessageData( message, severity, console ) ); + } + + public void Log( string message ) + { + m_messageQueue.Enqueue( new GenericMessageData( message, MessageSeverity.Normal, true ) ); + Debug.Log( message ); + } + + public void LogError( string message ) + { + m_messageQueue.Enqueue( new GenericMessageData( message, MessageSeverity.Error, true ) ); + Debug.LogError( message ); + } + + public void LogWarning( string message ) + { + m_messageQueue.Enqueue( new GenericMessageData( message, MessageSeverity.Warning, true ) ); + Debug.LogWarning( message ); + } + + public void CheckForMessages() + { + if ( m_displayingMessage ) + { + double timeLeft = EditorApplication.timeSinceStartup - m_currentMessageStartTime; + if ( timeLeft > MESSAGE_TIME ) + { + m_displayingMessage = false; + } + } + + if ( !m_displayingMessage ) + { + if ( m_messageQueue.Count > 0 ) + { + m_displayingMessage = true; + GenericMessageData data = m_messageQueue.Dequeue(); + m_currentMessageStartTime = EditorApplication.timeSinceStartup; + + if ( OnMessageDisplayEvent != null ) + OnMessageDisplayEvent( data.message, data.severity, data.console ); + } + } + } + + public void CleanUpMessageStack() + { + m_displayingMessage = false; + m_messageQueue.Clear(); + } + + public void StartMessageCounter() + { + m_displayingMessage = true; + m_currentMessageStartTime = EditorApplication.timeSinceStartup; + } + + public bool DisplayingMessage + { + get { return ( m_displayingMessage || m_messageQueue.Count > 0 ); } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GenericMessage.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GenericMessage.cs.meta new file mode 100644 index 0000000..1385370 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/GenericMessage.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 87cfef50a69ad24479fb8b472dac6d6e +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/IOUtils.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/IOUtils.cs new file mode 100644 index 0000000..3038550 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/IOUtils.cs @@ -0,0 +1,843 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.IO; +using System.Security.Cryptography; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using System.Threading; +using UnityEditor.VersionControl; + +namespace AmplifyShaderEditor +{ + public enum ShaderLoadResult + { + LOADED, + TEMPLATE_LOADED, + FILE_NOT_FOUND, + ASE_INFO_NOT_FOUND, + UNITY_NATIVE_PATHS + } + + public class Worker + { + public static readonly object locker = new object(); + public void DoWork() + { + while ( IOUtils.ActiveThread ) + { + if ( IOUtils.SaveInThreadFlag ) + { + IOUtils.SaveInThreadFlag = false; + lock ( locker ) + { + IOUtils.SaveInThreadShaderBody = IOUtils.ShaderCopywriteMessage + IOUtils.SaveInThreadShaderBody; + // Add checksum + string checksum = IOUtils.CreateChecksum( IOUtils.SaveInThreadShaderBody ); + IOUtils.SaveInThreadShaderBody += IOUtils.CHECKSUM + IOUtils.VALUE_SEPARATOR + checksum; + + // Write to disk + StreamWriter fileWriter = new StreamWriter( IOUtils.SaveInThreadPathName ); + try + { + fileWriter.Write( IOUtils.SaveInThreadShaderBody ); + Debug.Log( "Saving complete" ); + } + catch ( Exception e ) + { + Debug.LogException( e ); + } + finally + { + fileWriter.Close(); + } + } + } + } + Debug.Log( "Thread closed" ); + } + } + + public static class IOUtils + { + public delegate void OnShaderAction( Shader shader, bool isTemplate, string type ); + public static OnShaderAction OnShaderSavedEvent; + public static OnShaderAction OnShaderTypeChangedEvent; + + public static readonly string ShaderCopywriteMessage = "// Made with Amplify Shader Editor\n// Available at the Unity Asset Store - http://u3d.as/y3X \n"; + public static readonly string GrabPassEmpty = "\t\tGrabPass{ }\n"; + public static readonly string GrabPassBegin = "\t\tGrabPass{ \""; + public static readonly string GrabPassEnd = "\" }\n"; + public static readonly string PropertiesBegin = "\tProperties\n\t{\n"; + public static readonly string PropertiesEnd = "\t}\n"; + public static readonly string PropertiesElement = "\t\t{0}\n"; + public static readonly string PropertiesElementsRaw = "{0}\n"; + + public static readonly string PragmaTargetHeader = "\t\t#pragma target {0}\n"; + public static readonly string InstancedPropertiesHeader = "multi_compile_instancing"; + public static readonly string VirtualTexturePragmaHeader = "multi_compile _ _VT_SINGLE_MODE"; + + public static readonly string InstancedPropertiesBegin = "UNITY_INSTANCING_CBUFFER_START({0})"; + public static readonly string InstancedPropertiesEnd = "UNITY_INSTANCING_CBUFFER_END"; + public static readonly string InstancedPropertiesElement = "UNITY_DEFINE_INSTANCED_PROP({0}, {1})"; + public static readonly string InstancedPropertiesData = "UNITY_ACCESS_INSTANCED_PROP({0})"; + + public static readonly string DotsInstancedPropertiesData = "\tUNITY_DOTS_INSTANCED_PROP({0}, {1})"; + public static readonly string DotsInstancedDefinesData = "#define {1} UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO({0} , Metadata_{1})"; + + public static readonly string LWSRPInstancedPropertiesBegin = "UNITY_INSTANCING_BUFFER_START({0})"; + public static readonly string LWSRPInstancedPropertiesEnd = "UNITY_INSTANCING_BUFFER_END({0})"; + public static readonly string LWSRPInstancedPropertiesElement = "UNITY_DEFINE_INSTANCED_PROP({0}, {1})"; + public static readonly string LWSRPInstancedPropertiesData = "UNITY_ACCESS_INSTANCED_PROP({0},{1})"; + + public static readonly string SRPCBufferPropertiesBegin = "CBUFFER_START( UnityPerMaterial )";//"CBUFFER_START({0})"; + public static readonly string SRPCBufferPropertiesEnd = "CBUFFER_END"; + + + public static readonly string InstancedPropertiesBeginTabs = "\t\t"+ InstancedPropertiesBegin + "\n"; + public static readonly string InstancedPropertiesEndTabs = "\t\t"+ InstancedPropertiesEnd + "\n"; + public static readonly string InstancedPropertiesElementTabs = "\t\t\t"+ InstancedPropertiesElement + "\n"; + + public static readonly string MetaBegin = "defaultTextures:"; + public static readonly string MetaEnd = "userData:"; + public static readonly string ShaderBodyBegin = "/*ASEBEGIN"; + public static readonly string ShaderBodyEnd = "ASEEND*/"; + //public static readonly float CurrentVersionFlt = 0.4f; + //public static readonly string CurrentVersionStr = "Version=" + CurrentVersionFlt; + + public static readonly string CHECKSUM = "//CHKSM"; + public static readonly string LAST_OPENED_OBJ_ID = "ASELASTOPENOBJID"; + + public static readonly string MAT_CLIPBOARD_ID = "ASEMATCLIPBRDID"; + public static readonly char FIELD_SEPARATOR = ';'; + public static readonly char VALUE_SEPARATOR = '='; + public static readonly char LINE_TERMINATOR = '\n'; + public static readonly char VECTOR_SEPARATOR = ','; + public static readonly char FLOAT_SEPARATOR = '.'; + public static readonly char CLIPBOARD_DATA_SEPARATOR = '|'; + public static readonly char MATRIX_DATA_SEPARATOR = '|'; + public readonly static string NO_TEXTURES = ""; + public static readonly string SaveShaderStr = "Please enter shader name to save"; + public static readonly string FloatifyStr = ".0"; + + // Node parameter names + public const string NodeParam = "Node"; + public const string NodePosition = "Position"; + public const string NodeId = "Id"; + public const string NodeType = "Type"; + public const string WireConnectionParam = "WireConnection"; + + public static readonly uint NodeTypeId = 1; + + public static readonly int InNodeId = 1; + public static readonly int InPortId = 2; + public static readonly int OutNodeId = 3; + public static readonly int OutPortId = 4; + + public readonly static string DefaultASEDirtyCheckName = "__dirty"; + public readonly static string DefaultASEDirtyCheckProperty = "[HideInInspector] " + DefaultASEDirtyCheckName + "( \"\", Int ) = 1"; + public readonly static string DefaultASEDirtyCheckUniform = "uniform int " + DefaultASEDirtyCheckName + " = 1;"; + + public readonly static string MaskClipValueName = "_Cutoff"; + public readonly static string MaskClipValueProperty = MaskClipValueName + "( \"{0}\", Float ) = {1}"; + public readonly static string MaskClipValueUniform = "uniform float " + MaskClipValueName + " = {0};"; + + public readonly static string ChromaticAberrationProperty = "_ChromaticAberration"; + + //public static readonly string ASEFolderGUID = "daca988099666ec40aaa2cde22bb4935"; + //public static string ASEResourcesPath = "/Plugins/EditorResources/"; + //public static string ASEFolderPath; + + //public static bool IsShaderFunctionWindow = false; + + + public static int DefaultASEDirtyCheckId; + + // this is to be used in combination with AssetDatabase.GetAssetPath, both of these include the Assets/ path so we need to remove from one of them + public static string dataPath; + + + public static string EditorResourcesGUID = "0932db7ec1402c2489679c4b72eab5eb"; + public static string GraphBgTextureGUID = "881c304491028ea48b5027ac6c62cf73"; + public static string GraphFgTextureGUID = "8c4a7fca2884fab419769ccc0355c0c1"; + public static string WireTextureGUID = "06e687f68dd96f0448c6d8217bbcf608"; + public static string MasterNodeOnTextureGUID = "26c64fcee91024a49980ea2ee9d1a2fb"; + public static string MasterNodeOffTextureGUID = "712aee08d999c16438e2d694f42428e8"; + public static string GPUInstancedOnTextureGUID = "4b0c2926cc71c5846ae2a29652d54fb6"; + public static string GPUInstancedOffTextureGUID = "486c7766baaf21b46afb63c1121ef03e"; + public static string MainSkinGUID = "57482289c346f104a8162a3a79aaff9d"; + + public static string UpdateOutdatedGUID = "cce638be049286c41bcbd0a26c356b18"; + public static string UpdateOFFGUID = "99d70ac09b4db9742b404c3f92d8564b"; + public static string UpdateUpToDatedGUID = "ce30b12fbb3223746bcfef9ea82effe3"; + public static string LiveOffGUID = "bb16faf366bcc6c4fbf0d7666b105354"; + public static string LiveOnGUID = "6a0ae1d7892333142aeb09585572202c"; + public static string LivePendingGUID = "e3182200efb67114eb5050f8955e1746"; + public static string CleanupOFFGUID = "f62c0c3a5ddcd844e905fb2632fdcb15"; + public static string CleanUpOnGUID = "615d853995cf2344d8641fd19cb09b5d"; + public static string TakeScreenshotOFFGUID = "7587de2e3bec8bf4d973109524ccc6b1"; + public static string TakeScreenshotONGUID = "7587de2e3bec8bf4d973109524ccc6b1"; + public static string ShareOFFGUID = "bc5bd469748466a459badfab23915cb0"; + public static string ShareONGUID = "bc5bd469748466a459badfab23915cb0"; + public static string OpenSourceCodeOFFGUID = "f7e8834b42791124095a8b7f2d4daac2"; + public static string OpenSourceCodeONGUID = "8b114792ff84f6546880c031eda42bc0"; + public static string FocusNodeGUID = "da673e6179c67d346abb220a6935e359"; + public static string FitViewGUID = "1def740f2314c6b4691529cadeee2e9c"; + public static string ShowInfoWindowGUID = "77af20044e9766840a6be568806dc22e"; + public static string ShowTipsWindowGUID = "066674048bbb1e64e8cdcc6c3b4abbeb"; + public static string ShowConsoleWindowGUID = "9a81d7df8e62c044a9d1cada0c8a2131"; + + + public static Dictionary NodeTypeReplacer = new Dictionary() + { + {"AmplifyShaderEditor.RotateAboutAxis", "AmplifyShaderEditor.RotateAboutAxisNode"}, + {"GlobalArrayNode", "AmplifyShaderEditor.GlobalArrayNode"}, + {"AmplifyShaderEditor.SimpleMaxOp", "AmplifyShaderEditor.SimpleMaxOpNode"}, + {"AmplifyShaderEditor.SimpleMinNode", "AmplifyShaderEditor.SimpleMinOpNode"}, + {"AmplifyShaderEditor.TFHCRemap", "AmplifyShaderEditor.TFHCRemapNode"}, + {"AmplifyShaderEditor.TFHCPixelateUV", "AmplifyShaderEditor.TFHCPixelate"}, + {"AmplifyShaderEditor.VirtualTexturePropertyNode", "AmplifyShaderEditor.VirtualTextureObject"} + }; + + private static readonly string AmplifyShaderEditorDefineSymbol = "AMPLIFY_SHADER_EDITOR"; + + ///////////////////////////////////////////////////////////////////////////// + // THREAD IO UTILS + public static bool SaveInThreadFlag = false; + public static string SaveInThreadShaderBody; + public static string SaveInThreadPathName; + public static Thread SaveInThreadMainThread; + public static bool ActiveThread = true; + private static bool UseSaveThread = false; + + private static bool Initialized = false; + + public static bool FunctionNodeChanged = false; + + public static List AllOpenedWindows = new List(); + + public static void StartSaveThread( string shaderBody, string pathName ) + { + if( Provider.enabled && Provider.isActive ) + { + Asset loadedAsset = Provider.GetAssetByPath( FileUtil.GetProjectRelativePath( pathName ) ); + if( loadedAsset != null ) + { + //Task statusTask = Provider.Status( loadedAsset ); + //statusTask.Wait(); + //if( Provider.CheckoutIsValid( statusTask.assetList[ 0 ] ) ) + { + Task checkoutTask = Provider.Checkout( loadedAsset, CheckoutMode.Both ); + checkoutTask.Wait(); + } + } + } + + if( UseSaveThread ) + { + if ( !SaveInThreadFlag ) + { + if ( SaveInThreadMainThread == null ) + { + Worker worker = new Worker(); + SaveInThreadMainThread = new Thread( worker.DoWork ); + SaveInThreadMainThread.Start(); + Debug.Log( "Thread created" ); + } + + SaveInThreadShaderBody = shaderBody; + SaveInThreadPathName = pathName; + SaveInThreadFlag = true; + } + } + else + { + SaveTextfileToDisk( shaderBody, pathName ); + } + } + + //////////////////////////////////////////////////////////////////////////// + public static void SetAmplifyDefineSymbolOnBuildTargetGroup( BuildTargetGroup targetGroup ) + { + string currData = PlayerSettings.GetScriptingDefineSymbolsForGroup( targetGroup ); + if ( !currData.Contains( AmplifyShaderEditorDefineSymbol ) ) + { + if ( string.IsNullOrEmpty( currData ) ) + { + PlayerSettings.SetScriptingDefineSymbolsForGroup( targetGroup, AmplifyShaderEditorDefineSymbol ); + } + else + { + if ( !currData[ currData.Length - 1 ].Equals( ';' ) ) + { + currData += ';'; + } + currData += AmplifyShaderEditorDefineSymbol; + PlayerSettings.SetScriptingDefineSymbolsForGroup( targetGroup, currData ); + } + } + } + + public static void RemoveAmplifyDefineSymbolOnBuildTargetGroup( BuildTargetGroup targetGroup ) + { + string currData = PlayerSettings.GetScriptingDefineSymbolsForGroup( targetGroup ); + if( currData.Contains( AmplifyShaderEditorDefineSymbol ) ) + { + currData = currData.Replace( AmplifyShaderEditorDefineSymbol + ";", "" ); + currData = currData.Replace( ";" + AmplifyShaderEditorDefineSymbol, "" ); + currData = currData.Replace( AmplifyShaderEditorDefineSymbol, "" ); + PlayerSettings.SetScriptingDefineSymbolsForGroup( targetGroup, currData ); + } + } + + public static void Init() + { + if ( !Initialized ) + { + Initialized = true; + if( EditorPrefs.GetBool( Preferences.PrefDefineSymbol, true ) ) + SetAmplifyDefineSymbolOnBuildTargetGroup( EditorUserBuildSettings.selectedBuildTargetGroup ); + //Array BuildTargetGroupValues = Enum.GetValues( typeof( BuildTargetGroup )); + //for ( int i = 0; i < BuildTargetGroupValues.Length; i++ ) + //{ + // if( i != 0 && i != 15 && i != 16 ) + // SetAmplifyDefineSymbolOnBuildTargetGroup( ( BuildTargetGroup ) BuildTargetGroupValues.GetValue( i ) ); + //} + + DefaultASEDirtyCheckId = Shader.PropertyToID( DefaultASEDirtyCheckName ); + dataPath = Application.dataPath.Remove( Application.dataPath.Length - 6 ); + + + //ASEFolderPath = AssetDatabase.GUIDToAssetPath( ASEFolderGUID ); + //ASEResourcesPath = ASEFolderPath + ASEResourcesPath; + } + } + + + public static void DumpTemplateManagers() + { + for( int i = 0; i < AllOpenedWindows.Count; i++ ) + { + if( AllOpenedWindows[ i ].TemplatesManagerInstance != null ) + { + Debug.Log( AllOpenedWindows[ i ].titleContent.text + ": " + AllOpenedWindows[ i ].TemplatesManagerInstance.GetInstanceID() ); + } + } + } + + public static TemplatesManager FirstValidTemplatesManager + { + get + { + for( int i = 0; i < AllOpenedWindows.Count; i++ ) + { + if( AllOpenedWindows[ i ].TemplatesManagerInstance != null ) + { + return AllOpenedWindows[ i ].TemplatesManagerInstance; + } + } + return null; + } + } + + public static void UpdateSFandRefreshWindows( AmplifyShaderFunction function ) + { + for( int i = 0; i < AllOpenedWindows.Count; i++ ) + { + AllOpenedWindows[ i ].LateRefreshAvailableNodes(); + if( AllOpenedWindows[ i ].IsShaderFunctionWindow ) + { + if( AllOpenedWindows[ i ].OpenedShaderFunction == function ) + { + AllOpenedWindows[ i ].UpdateTabTitle(); + } + } + } + } + + public static void UpdateIO() + { + int windowCount = AllOpenedWindows.Count; + if ( windowCount == 0 ) + { + EditorApplication.update -= IOUtils.UpdateIO; + return; + } + + for ( int i = 0; i < AllOpenedWindows.Count; i++ ) + { + if ( AllOpenedWindows[i] == EditorWindow.focusedWindow ) + { + UIUtils.CurrentWindow = AllOpenedWindows[ i ]; + } + + if( FunctionNodeChanged ) + AllOpenedWindows[ i ].CheckFunctions = true; + + if ( AllOpenedWindows[ i ] == null ) + { + AllOpenedWindows.RemoveAt( i ); + i--; + } + } + + if ( FunctionNodeChanged ) + FunctionNodeChanged = false; + } + + public static void Destroy() + { + ActiveThread = false; + if ( SaveInThreadMainThread != null ) + { + SaveInThreadMainThread.Abort(); + SaveInThreadMainThread = null; + } + } + + public static void GetShaderName( out string shaderName, out string fullPathname, string defaultName, string customDatapath ) + { + string currDatapath = String.IsNullOrEmpty( customDatapath ) ? Application.dataPath : customDatapath; + fullPathname = EditorUtility.SaveFilePanelInProject( "Select Shader to save", defaultName, "shader", SaveShaderStr, currDatapath ); + if ( !String.IsNullOrEmpty( fullPathname ) ) + { + shaderName = fullPathname.Remove( fullPathname.Length - 7 ); // -7 remove .shader extension + string[] subStr = shaderName.Split( '/' ); + if ( subStr.Length > 0 ) + { + shaderName = subStr[ subStr.Length - 1 ]; // Remove pathname + } + } + else + { + shaderName = string.Empty; + } + } + + public static void AddTypeToString( ref string myString, string typeName ) + { + myString += typeName; + } + + public static void AddFieldToString( ref string myString, string fieldName, object fieldValue ) + { + myString += FIELD_SEPARATOR + fieldName + VALUE_SEPARATOR + fieldValue; + } + + public static void AddFieldValueToString( ref string myString, object fieldValue ) + { + myString += FIELD_SEPARATOR + fieldValue.ToString(); + } + + public static void AddLineTerminator( ref string myString ) + { + myString += LINE_TERMINATOR; + } + + public static string CreateChecksum( string buffer ) + { + SHA1 sha1 = SHA1.Create(); + byte[] buf = System.Text.Encoding.UTF8.GetBytes( buffer ); + byte[] hash = sha1.ComputeHash( buf, 0, buf.Length ); + string hashstr = BitConverter.ToString( hash ).Replace( "-", "" ); + return hashstr; + } + + public static void SaveTextfileToDisk( string shaderBody, string pathName, bool addAdditionalInfo = true ) + { + + if ( addAdditionalInfo ) + { + shaderBody = ShaderCopywriteMessage + shaderBody; + // Add checksum + string checksum = CreateChecksum( shaderBody ); + shaderBody += CHECKSUM + VALUE_SEPARATOR + checksum; + } + + // Write to disk + StreamWriter fileWriter = new StreamWriter( pathName ); + try + { + fileWriter.Write( shaderBody ); + } + catch ( Exception e ) + { + Debug.LogException( e ); + } + finally + { + fileWriter.Close(); + } + } + + public static string AddAdditionalInfo( string shaderBody ) + { + shaderBody = ShaderCopywriteMessage + shaderBody; + string checksum = CreateChecksum( shaderBody ); + shaderBody += CHECKSUM + VALUE_SEPARATOR + checksum; + return shaderBody; + } + + public static string LoadTextFileFromDisk( string pathName ) + { + string result = string.Empty; + if ( !string.IsNullOrEmpty( pathName ) && File.Exists( pathName ) ) + { + + StreamReader fileReader = null; + try + { + fileReader = new StreamReader( pathName ); + result = fileReader.ReadToEnd(); + } + catch ( Exception e ) + { + Debug.LogException( e ); + } + finally + { + if( fileReader != null) + fileReader.Close(); + } + } + return result; + } + + public static bool IsASEShader( Shader shader ) + { + string datapath = AssetDatabase.GetAssetPath( shader ); + if ( UIUtils.IsUnityNativeShader( datapath ) ) + { + return false; + } + + string buffer = LoadTextFileFromDisk( datapath ); + if ( String.IsNullOrEmpty( buffer ) || !IOUtils.HasValidShaderBody( ref buffer ) ) + { + return false; + } + return true; + } + + public static bool IsShaderFunction( string functionInfo ) + { + string buffer = functionInfo; + if ( String.IsNullOrEmpty( buffer ) || !IOUtils.HasValidShaderBody( ref buffer ) ) + { + return false; + } + return true; + } + + public static bool HasValidShaderBody( ref string shaderBody ) + { + int shaderBodyBeginId = shaderBody.IndexOf( ShaderBodyBegin ); + if ( shaderBodyBeginId > -1 ) + { + int shaderBodyEndId = shaderBody.IndexOf( ShaderBodyEnd ); + return ( shaderBodyEndId > -1 && shaderBodyEndId > shaderBodyBeginId ); + } + return false; + } + + public static int[] AllIndexesOf( this string str, string substr, bool ignoreCase = false ) + { + if ( string.IsNullOrEmpty( str ) || string.IsNullOrEmpty( substr ) ) + { + throw new ArgumentException( "String or substring is not specified." ); + } + + List indexes = new List(); + int index = 0; + + while ( ( index = str.IndexOf( substr, index, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal ) ) != -1 ) + { + indexes.Add( index++ ); + } + + return indexes.ToArray(); + } + + public static void AddFunctionHeader( ref string function, string header ) + { + function += "\t\t" + header + "\n\t\t{\n"; + } + + public static void AddSingleLineFunction( ref string function, string header ) + { + function += "\t\t" + header; + } + + public static void AddFunctionLine( ref string function, string line ) + { + function += "\t\t\t" + line + "\n"; + } + + public static void CloseFunctionBody( ref string function ) + { + function += "\t\t}\n"; + } + + public static string CreateFullFunction( string header, params string[] functionLines ) + { + string result = string.Empty; + AddFunctionHeader( ref result, header ); + for ( int i = 0; i > functionLines.Length; i++ ) + { + AddFunctionLine( ref result, functionLines[ i ] ); + } + CloseFunctionBody( ref result ); + return result; + } + + public static string CreateCodeComments( bool forceForwardSlash, params string[] comments ) + { + string finalComment = string.Empty; + if ( comments.Length == 1 ) + { + finalComment = "//" + comments[ 0 ]; + } + else + { + if ( forceForwardSlash ) + { + for ( int i = 0; i < comments.Length; i++ ) + { + finalComment += "//" + comments[ i ]; + if ( i < comments.Length - 1 ) + { + finalComment += "\n\t\t\t"; + } + } + } + else + { + finalComment = "/*"; + for ( int i = 0; i < comments.Length; i++ ) + { + if ( i != 0 ) + finalComment += "\t\t\t"; + finalComment += comments[ i ]; + if ( i < comments.Length - 1 ) + finalComment += "\n"; + } + finalComment += "*/"; + } + } + return finalComment; + } + + public static string GetUVChannelDeclaration( string uvName, int channelId, int set ) + { + string uvSetStr = ( set == 0 ) ? "uv" : "uv" + Constants.AvailableUVSetsStr[ set ]; + return "float2 " + uvSetStr + uvName /*+ " : TEXCOORD" + channelId*/; + } + + public static string GetUVChannelName( string uvName, int set ) + { + string uvSetStr = ( set == 0 ) ? "uv" : "uv" + Constants.AvailableUVSetsStr[ set ]; + return uvSetStr + uvName; + } + + public static string GetVertexUVChannelName( int set ) + { + string uvSetStr = ( set == 0 ) ? "texcoord" : ( "texcoord" + set.ToString() ); + return uvSetStr; + } + + public static string Floatify( float value ) + { + return ( value % 1 ) != 0 ? value.ToString() : ( value.ToString() + FloatifyStr ); + } + + public static string Vector2ToString( Vector2 data ) + { + return data.x.ToString() + VECTOR_SEPARATOR + data.y.ToString(); + } + + public static string Vector3ToString( Vector3 data ) + { + return data.x.ToString() + VECTOR_SEPARATOR + data.y.ToString() + VECTOR_SEPARATOR + data.z.ToString(); + } + + public static string Vector4ToString( Vector4 data ) + { + return data.x.ToString() + VECTOR_SEPARATOR + data.y.ToString() + VECTOR_SEPARATOR + data.z.ToString() + VECTOR_SEPARATOR + data.w.ToString(); + } + + public static string ColorToString( Color data ) + { + return data.r.ToString() + VECTOR_SEPARATOR + data.g.ToString() + VECTOR_SEPARATOR + data.b.ToString() + VECTOR_SEPARATOR + data.a.ToString(); + } + + public static string Matrix3x3ToString( Matrix4x4 matrix ) + { + return matrix[ 0, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 0, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 0, 2 ].ToString() + IOUtils.VECTOR_SEPARATOR + + matrix[ 1, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 1, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 1, 2 ].ToString() + IOUtils.VECTOR_SEPARATOR + + matrix[ 2, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 2, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 2, 2 ].ToString(); + } + + public static string Matrix4x4ToString( Matrix4x4 matrix ) + { + return matrix[ 0, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 0, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 0, 2 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 0, 3 ].ToString() + IOUtils.VECTOR_SEPARATOR + + matrix[ 1, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 1, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 1, 2 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 1, 3 ].ToString() + IOUtils.VECTOR_SEPARATOR + + matrix[ 2, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 2, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 2, 2 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 2, 3 ].ToString() + IOUtils.VECTOR_SEPARATOR + + matrix[ 3, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 3, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 3, 2 ].ToString() + IOUtils.VECTOR_SEPARATOR + matrix[ 3, 3 ].ToString(); + } + + public static Vector2 StringToVector2( string data ) + { + string[] parsedData = data.Split( VECTOR_SEPARATOR ); + if ( parsedData.Length >= 2 ) + { + return new Vector2( Convert.ToSingle( parsedData[ 0 ] ), + Convert.ToSingle( parsedData[ 1 ] ) ); + } + return Vector2.zero; + } + + public static Vector3 StringToVector3( string data ) + { + string[] parsedData = data.Split( VECTOR_SEPARATOR ); + if ( parsedData.Length >= 3 ) + { + return new Vector3( Convert.ToSingle( parsedData[ 0 ] ), + Convert.ToSingle( parsedData[ 1 ] ), + Convert.ToSingle( parsedData[ 2 ] ) ); + } + return Vector3.zero; + } + + public static Vector4 StringToVector4( string data ) + { + string[] parsedData = data.Split( VECTOR_SEPARATOR ); + if ( parsedData.Length >= 4 ) + { + return new Vector4( Convert.ToSingle( parsedData[ 0 ] ), + Convert.ToSingle( parsedData[ 1 ] ), + Convert.ToSingle( parsedData[ 2 ] ), + Convert.ToSingle( parsedData[ 3 ] ) ); + } + return Vector4.zero; + } + + public static Color StringToColor( string data ) + { + string[] parsedData = data.Split( VECTOR_SEPARATOR ); + if ( parsedData.Length >= 4 ) + { + return new Color( Convert.ToSingle( parsedData[ 0 ] ), + Convert.ToSingle( parsedData[ 1 ] ), + Convert.ToSingle( parsedData[ 2 ] ), + Convert.ToSingle( parsedData[ 3 ] ) ); + } + return Color.white; + } + + public static Matrix4x4 StringToMatrix3x3( string data ) + { + string[] parsedData = data.Split( VECTOR_SEPARATOR ); + if ( parsedData.Length == 9 ) + { + Matrix4x4 matrix = new Matrix4x4(); + matrix[ 0, 0 ] = Convert.ToSingle( parsedData[ 0 ] ); + matrix[ 0, 1 ] = Convert.ToSingle( parsedData[ 1 ] ); + matrix[ 0, 2 ] = Convert.ToSingle( parsedData[ 2 ] ); + + matrix[ 1, 0 ] = Convert.ToSingle( parsedData[ 3 ] ); + matrix[ 1, 1 ] = Convert.ToSingle( parsedData[ 4 ] ); + matrix[ 1, 2 ] = Convert.ToSingle( parsedData[ 5 ] ); + + matrix[ 2, 0 ] = Convert.ToSingle( parsedData[ 6 ] ); + matrix[ 2, 1 ] = Convert.ToSingle( parsedData[ 7 ] ); + matrix[ 2, 2 ] = Convert.ToSingle( parsedData[ 8 ] ); + return matrix; + } + return Matrix4x4.identity; + } + + public static Matrix4x4 StringToMatrix4x4( string data ) + { + string[] parsedData = data.Split( VECTOR_SEPARATOR ); + if ( parsedData.Length == 16 ) + { + Matrix4x4 matrix = new Matrix4x4(); + matrix[ 0, 0 ] = Convert.ToSingle( parsedData[ 0 ] ); + matrix[ 0, 1 ] = Convert.ToSingle( parsedData[ 1 ] ); + matrix[ 0, 2 ] = Convert.ToSingle( parsedData[ 2 ] ); + matrix[ 0, 3 ] = Convert.ToSingle( parsedData[ 3 ] ); + + matrix[ 1, 0 ] = Convert.ToSingle( parsedData[ 4 ] ); + matrix[ 1, 1 ] = Convert.ToSingle( parsedData[ 5 ] ); + matrix[ 1, 2 ] = Convert.ToSingle( parsedData[ 6 ] ); + matrix[ 1, 3 ] = Convert.ToSingle( parsedData[ 7 ] ); + + matrix[ 2, 0 ] = Convert.ToSingle( parsedData[ 8 ] ); + matrix[ 2, 1 ] = Convert.ToSingle( parsedData[ 9 ] ); + matrix[ 2, 2 ] = Convert.ToSingle( parsedData[ 10 ] ); + matrix[ 2, 3 ] = Convert.ToSingle( parsedData[ 11 ] ); + + matrix[ 3, 0 ] = Convert.ToSingle( parsedData[ 12 ] ); + matrix[ 3, 1 ] = Convert.ToSingle( parsedData[ 13 ] ); + matrix[ 3, 2 ] = Convert.ToSingle( parsedData[ 14 ] ); + matrix[ 3, 3 ] = Convert.ToSingle( parsedData[ 15 ] ); + return matrix; + } + return Matrix4x4.identity; + } + + public static void SaveTextureToDisk( Texture2D tex, string pathname ) + { + byte[] rawData = tex.GetRawTextureData(); + Texture2D newTex = new Texture2D( tex.width, tex.height, tex.format, tex.mipmapCount > 1, false ); + newTex.LoadRawTextureData( rawData ); + newTex.Apply(); + byte[] pngData = newTex.EncodeToPNG(); + File.WriteAllBytes( pathname, pngData ); + } + + //public static void SaveObjToList( string newObj ) + //{ + // Debug.Log( UIUtils.CurrentWindow.Lastpath ); + // UIUtils.CurrentWindow.Lastpath = newObj; + // string lastOpenedObj = EditorPrefs.GetString( IOUtils.LAST_OPENED_OBJ_ID ); + // string[] allLocations = lastOpenedObj.Split( ':' ); + + // string lastLocation = allLocations[ allLocations.Length - 1 ]; + + // string resave = string.Empty; + // for ( int i = 0; i < allLocations.Length; i++ ) + // { + // if ( string.IsNullOrEmpty( allLocations[ i ] ) ) + // continue; + + // resave += allLocations[ i ]; + // resave += ":"; + // } + + // resave += newObj; + // EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, resave ); + //} + + //public static void DeleteObjFromList( string newObj ) + //{ + // string lastOpenedObj = EditorPrefs.GetString( IOUtils.LAST_OPENED_OBJ_ID ); + // string[] allLocations = lastOpenedObj.Split( ':' ); + + // string resave = string.Empty; + // for ( int i = 0; i < allLocations.Length; i++ ) + // { + // if ( string.IsNullOrEmpty( allLocations[ i ] ) || newObj.Equals( allLocations[ i ] ) ) + // continue; + + // resave += allLocations[ i ]; + // if ( i < allLocations.Length - 1 ) + // resave += ":"; + // } + + // EditorPrefs.SetString( IOUtils.LAST_OPENED_OBJ_ID, resave ); + //} + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/IOUtils.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/IOUtils.cs.meta new file mode 100644 index 0000000..08f1751 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/IOUtils.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d39b4c96fb4d7f847b3a21c377d4188d +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InlineProperty.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InlineProperty.cs new file mode 100644 index 0000000..e0d866e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InlineProperty.cs @@ -0,0 +1,322 @@ +using UnityEngine; +using UnityEditor; +using System; + +namespace AmplifyShaderEditor +{ + [System.Serializable] + public class InlineProperty + { + [SerializeField] + private float m_value = 0; + + [SerializeField] + private bool m_active = false; + + [SerializeField] + private int m_nodeId = -1; + + [SerializeField] + private string m_nodePropertyName = string.Empty; + + public InlineProperty() { } + + public InlineProperty( float val ) + { + m_value = val; + } + + public InlineProperty( int val ) + { + m_value = val; + } + + public void ResetProperty() + { + m_nodeId = -1; + m_active = false; + } + + public void CopyFrom( InlineProperty other ) + { + m_value = other.m_value; + m_active = other.m_active; + m_nodeId = other.m_nodeId; + } + + public void SetInlineByName( string propertyName ) + { + m_nodeId = UIUtils.GetNodeIdByName( propertyName ); + m_nodePropertyName = propertyName; + m_active = m_nodeId != -1; + } + + public void IntField( ref UndoParentNode owner, string content ) + { + if( !m_active ) + { + EditorGUILayout.BeginHorizontal(); + m_value = owner.EditorGUILayoutIntField( content, (int)m_value ); + if( GUILayout.Button( UIUtils.FloatIntIconON, UIUtils.FloatIntPickerONOFF, GUILayout.Width( 15 ), GUILayout.Height( 15 ) ) ) + m_active = !m_active; + EditorGUILayout.EndHorizontal(); + } + else + { + DrawPicker( ref owner, content ); + } + } + + public void IntSlider( ref UndoParentNode owner, GUIContent content, int min, int max ) + { + if( !m_active ) + { + EditorGUILayout.BeginHorizontal(); + m_value = owner.EditorGUILayoutIntSlider( content, (int)m_value, min, max ); + if( GUILayout.Button( UIUtils.FloatIntIconON, UIUtils.FloatIntPickerONOFF, GUILayout.Width( 15 ), GUILayout.Height( 15 ) ) ) + m_active = !m_active; + EditorGUILayout.EndHorizontal(); + } + else + { + DrawPicker( ref owner, content ); + } + } + + public void IntSlider( ref UndoParentNode owner, string content, int min, int max ) + { + if( !m_active ) + { + EditorGUILayout.BeginHorizontal(); + m_value = owner.EditorGUILayoutIntSlider( content, (int)m_value, min, max ); + if( GUILayout.Button( UIUtils.FloatIntIconON, UIUtils.FloatIntPickerONOFF, GUILayout.Width( 15 ), GUILayout.Height( 15 ) ) ) + m_active = !m_active; + EditorGUILayout.EndHorizontal(); + } + else + { + DrawPicker( ref owner, content ); + } + } + + public void EnumTypePopup( ref UndoParentNode owner, string content, string[] displayOptions ) + { + if( !m_active ) + { + EditorGUILayout.BeginHorizontal(); + m_value = owner.EditorGUILayoutPopup( content, (int)m_value, displayOptions ); + if( GUILayout.Button( UIUtils.FloatIntIconON, UIUtils.FloatIntPickerONOFF, GUILayout.Width( 15 ), GUILayout.Height( 15 ) ) ) + m_active = !m_active; + EditorGUILayout.EndHorizontal(); + + } + else + { + DrawPicker( ref owner, content ); + } + } + + public void FloatField( ref UndoParentNode owner, string content ) + { + if( !m_active ) + { + EditorGUILayout.BeginHorizontal(); + m_value = owner.EditorGUILayoutFloatField( content, m_value ); + if( GUILayout.Button( UIUtils.FloatIntIconON, UIUtils.FloatIntPickerONOFF, GUILayout.Width( 15 ), GUILayout.Height( 15 ) ) ) + m_active = !m_active; + EditorGUILayout.EndHorizontal(); + } + else + { + DrawPicker( ref owner, content ); + } + } + + public void SliderField( ref UndoParentNode owner, string content, float min, float max ) + { + if( !m_active ) + { + EditorGUILayout.BeginHorizontal(); + m_value = owner.EditorGUILayoutSlider( content, m_value, min, max ); + if( GUILayout.Button( UIUtils.FloatIntIconON, UIUtils.FloatIntPickerONOFF, GUILayout.Width( 15 ), GUILayout.Height( 15 ) ) ) + m_active = !m_active; + EditorGUILayout.EndHorizontal(); + } + else + { + DrawPicker( ref owner, content ); + } + } + + public void RangedFloatField( ref UndoParentNode owner, string content, float min, float max ) + { + if( !m_active ) + { + EditorGUILayout.BeginHorizontal(); + m_value = owner.EditorGUILayoutRangedFloatField( content, m_value, min, max ); + if( GUILayout.Button( UIUtils.FloatIntIconON, UIUtils.FloatIntPickerONOFF, GUILayout.Width( 15 ), GUILayout.Height( 15 ) ) ) + m_active = !m_active; + EditorGUILayout.EndHorizontal(); + } + else + { + DrawPicker( ref owner, content ); + } + } + + + public void CustomDrawer( ref UndoParentNode owner, DrawPropertySection Drawer, string content ) + { + if( !m_active ) + { + EditorGUILayout.BeginHorizontal(); + Drawer( owner ); + if( GUILayout.Button( UIUtils.FloatIntIconON, UIUtils.FloatIntPickerONOFF, GUILayout.Width( 15 ), GUILayout.Height( 15 ) ) ) + m_active = !m_active; + EditorGUILayout.EndHorizontal(); + } + else + { + DrawPicker( ref owner, content ); + } + } + + public delegate void DrawPropertySection( UndoParentNode owner ); + + private void DrawPicker( ref UndoParentNode owner, GUIContent content ) + { + DrawPicker( ref owner, content.text ); + } + + private void DrawPicker( ref UndoParentNode owner, string content ) + { + EditorGUILayout.BeginHorizontal(); + string[] intArraysNames = owner.ContainerGraph.ParentWindow.CurrentGraph.FloatIntNodes.NodesArr; + int[] intIds = owner.ContainerGraph.ParentWindow.CurrentGraph.FloatIntNodes.NodeIds; + m_nodeId = owner.EditorGUILayoutIntPopup( content, m_nodeId, intArraysNames, intIds ); + if( GUILayout.Button( UIUtils.FloatIntIconOFF, UIUtils.FloatIntPickerONOFF, GUILayout.Width( 15 ), GUILayout.Height( 15 ) ) ) + m_active = !m_active; + EditorGUILayout.EndHorizontal(); + } + + public string GetValueOrProperty( bool parentesis = true ) + { + if( m_active ) + { + PropertyNode node = GetPropertyNode(); + if( node != null ) + { + return parentesis ? "[" + node.PropertyName + "]" : node.PropertyName; + } + else + { + m_active = false; + m_nodeId = -1; + return m_value.ToString(); + } + } + else + { + return m_value.ToString(); + } + } + + public string GetValueOrProperty( string defaultValue, bool parentesis = true ) + { + if( m_active ) + { + PropertyNode node = GetPropertyNode(); + if( node != null ) + { + return parentesis ? "[" + node.PropertyName + "]" : node.PropertyName; + } + else if( !string.IsNullOrEmpty( defaultValue ) ) + { + m_active = false; + m_nodeId = -1; + return defaultValue; + } + else + { + m_active = false; + m_nodeId = -1; + return m_value.ToString(); + } + } + else + { + return defaultValue; + } + } + + public void ReadFromString( ref uint index, ref string[] nodeParams, bool isInt = true ) + { + m_value = isInt ? Convert.ToInt32( nodeParams[ index++ ] ) : Convert.ToSingle( nodeParams[ index++ ] ); + m_active = Convert.ToBoolean( nodeParams[ index++ ] ); + m_nodeId = Convert.ToInt32( nodeParams[ index++ ] ); + } + + public void ReadFromSingle( string singleLine ) + { + string[] data = singleLine.Split( IOUtils.VECTOR_SEPARATOR ); + m_value = Convert.ToSingle( data[ 0 ], System.Globalization.CultureInfo.InvariantCulture ); + m_active = Convert.ToBoolean( data[ 1 ] ); + m_nodeId = Convert.ToInt32( data[ 2 ] ); + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_value ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_active ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_nodeId ); + } + + public string WriteToSingle() + { + return m_value.ToString( System.Globalization.CultureInfo.InvariantCulture ) + IOUtils.VECTOR_SEPARATOR + m_active + IOUtils.VECTOR_SEPARATOR + m_nodeId; + } + + public void SetInlineNodeValue() + { + if( IsValid ) + { + RangedFloatNode fnode = UIUtils.GetNode( m_nodeId ) as RangedFloatNode; + if( fnode != null ) + { + fnode.Value = m_value; + fnode.SetMaterialValueFromInline( m_value ); + } + else + { + IntNode inode = UIUtils.GetNode( m_nodeId ) as IntNode; + inode.Value = (int)m_value; + inode.SetMaterialValueFromInline( (int)m_value ); + } + } + } + + public bool IsValid { get { return m_active && m_nodeId != -1; } } + + public PropertyNode GetPropertyNode() + { + if( m_nodeId >= 0 ) + return UIUtils.GetNode( m_nodeId ) as PropertyNode; + + if( m_nodeId < -1 ) + { + if(!string.IsNullOrEmpty(m_nodePropertyName)) + return UIUtils.GetInternalTemplateNode( m_nodePropertyName ); + + + return UIUtils.GetInternalTemplateNode( m_nodeId ); + } + + return null; + } + + public int IntValue { get { return (int)m_value; } set { m_value = value; } } + public float FloatValue { get { return m_value; } set { m_value = value; } } + public bool Active { get { return m_active; } set { m_active = value; } } + public int NodeId { get { return m_nodeId; } set { m_nodeId = value; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InlineProperty.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InlineProperty.cs.meta new file mode 100644 index 0000000..7c5e45d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InlineProperty.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f4f4421f529503243bfef5076ae82512 +timeCreated: 1519298230 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InvalidDataChecker.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InvalidDataChecker.cs new file mode 100644 index 0000000..b5540b2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InvalidDataChecker.cs @@ -0,0 +1,172 @@ +using UnityEditor; +using UnityEngine; +using System; +using System.Collections; +using UnityEngine.Networking; + +namespace AmplifyShaderEditor +{ + [InitializeOnLoad] + public class InvalidDataChecker + { + private static string[] m_invalidData = { "674ea7bed6b1cd94b8057074298096db", //"/Samples", + "2738539936eacef409be91f148b2a4a0", //"/Resources", + "c880e50f07f2be9499d414ac6f9f3a7a", //"/Templates", + "563f992b9989cf547ac59bf748442c17"};//"/Textures"}; + //private static string m_ASEFolderPath; + private static string m_invalidDataCollected = string.Empty; + static InvalidDataChecker() + { + bool foundInvalidData = false; + //m_ASEFolderPath = AssetDatabase.GUIDToAssetPath( IOUtils.ASEFolderGUID ); + int count = 0; + for ( int i = 0; i < m_invalidData.Length; i++ ) + { + //m_invalidData[ i ] = m_ASEFolderPath + m_invalidData[ i ]; + m_invalidData[ i ] = AssetDatabase.GUIDToAssetPath( m_invalidData[ i ] ); + if ( AssetDatabase.IsValidFolder( m_invalidData[ i ] ) ) + { + foundInvalidData = true; + m_invalidDataCollected += m_invalidData[ i ]+"\n"; + count += 1; + } + } + if ( count < 5 ) + { + for ( ; count < 5; count++ ) + { + m_invalidDataCollected += "\n"; + } + } + + if ( foundInvalidData ) + { + InvalidDataPopUp window = ( InvalidDataPopUp ) EditorWindow.GetWindow( typeof( InvalidDataPopUp ), true, "Found Invalid Data" ); + window.minSize = new Vector2( 502, 265 ); + window.maxSize = new Vector2( 502, 265 ); + window.Show(); + } + + EditorApplication.update += Update; + } + + static void Update() + { + EditorApplication.update -= Update; + + if( !EditorApplication.isPlayingOrWillChangePlaymode ) + { + Preferences.ShowOption show = Preferences.ShowOption.Never; + if( !EditorPrefs.HasKey( Preferences.PrefStartUp ) ) + { + show = Preferences.ShowOption.Always; + EditorPrefs.SetInt( Preferences.PrefStartUp, 0 ); + } + else + { + if( Time.realtimeSinceStartup < 10 ) + { + show = (Preferences.ShowOption) EditorPrefs.GetInt( Preferences.PrefStartUp, 0 ); + // check version here + if( show == Preferences.ShowOption.OnNewVersion ) + { + ASEStartScreen.StartBackgroundTask( StartRequest( ASEStartScreen.ChangelogURL, () => + { + var changeLog = ChangeLogInfo.CreateFromJSON( www.downloadHandler.text ); + if( changeLog != null ) + { + if( changeLog.Version > VersionInfo.FullNumber ) + ASEStartScreen.Init(); + } + } ) ); + } + } + } + + if( show == Preferences.ShowOption.Always ) + ASEStartScreen.Init(); + } + } + + static UnityWebRequest www; + + static IEnumerator StartRequest( string url, Action success = null ) + { + using( www = UnityWebRequest.Get( url ) ) + { +#if UNITY_2017_2_OR_NEWER + yield return www.SendWebRequest(); +#else + yield return www.Send(); +#endif + + while( www.isDone == false ) + yield return null; + + if( success != null ) + success(); + } + } + + public static void CleanInvalidData() + { + for ( int i = 0; i < m_invalidData.Length; i++ ) + { + if ( FileUtil.DeleteFileOrDirectory( m_invalidData[ i ] ) ) + { + Debug.Log( "Removed invalid " + m_invalidData[ i ] ); + if ( FileUtil.DeleteFileOrDirectory( m_invalidData[ i ] + ".meta" ) ) + { + Debug.Log( "Removed invalid " + m_invalidData[ i ] + ".meta" ); + } + } + } + AssetDatabase.Refresh(); + } + + public static string InvalidDataCollected { get { return m_invalidDataCollected; } } + } + + public class InvalidDataPopUp : EditorWindow + { + private readonly GUIContent m_buttonContent = new GUIContent( "Remove Invalid Data" ); + private Vector2 m_scrollPosition = Vector2.zero; + public void OnGUI() + { + GUILayout.BeginVertical(); + { + GUIStyle labelStyle = new GUIStyle( EditorStyles.label ); + labelStyle.alignment = TextAnchor.MiddleCenter; + labelStyle.wordWrap = true; + GUILayout.Label( "\nAmplify Shader Editor " + VersionInfo.StaticToString(), labelStyle, GUILayout.ExpandWidth( true ) ); + GUILayout.Space( 5 ); + GUILayout.Label( "Invalid/Legacy Data was found on your previous ASE folder which needs to be removed in order for it to work correctly." , labelStyle, GUILayout.ExpandWidth( true ) ); + GUILayout.Space( 5 ); + GUILayout.Label( "Below are the detected files/folders which require to be removed.", labelStyle, GUILayout.ExpandWidth( true ) ); + GUILayout.Space( 5 ); + + m_scrollPosition = GUILayout.BeginScrollView( m_scrollPosition ,GUILayout.Height(85)); + + GUILayout.TextArea( InvalidDataChecker.InvalidDataCollected ); + GUILayout.EndScrollView(); + + + GUILayout.Label( "VERY IMPORTANT: If you have assets of yours inside these folders you need to move them to another location before hitting the button below or they will be PERMANENTLY DELETED", labelStyle, GUILayout.ExpandWidth( true ) ); + GUILayout.Space( 5 ); + + GUILayout.BeginHorizontal(); + { + GUILayout.Space( 151 ); + if ( GUILayout.Button( m_buttonContent, GUILayout.Width( 200 ) ) ) + { + InvalidDataChecker.CleanInvalidData(); + Close(); + } + } + GUILayout.EndHorizontal(); + } + GUILayout.EndVertical(); + + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InvalidDataChecker.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InvalidDataChecker.cs.meta new file mode 100644 index 0000000..daaec41 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/InvalidDataChecker.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c71b815458d61e24184a60dbce19573d +timeCreated: 1481126959 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/NodeExporterUtils.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/NodeExporterUtils.cs new file mode 100644 index 0000000..0f2ca73 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/NodeExporterUtils.cs @@ -0,0 +1,284 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public enum DebugScreenShotNodeState + { + CreateNode, + FocusOnNode, + TakeScreenshot, + WaitFrame, + DeleteNode + }; + + public enum DebugUndoNodeState + { + CreateNode, + FocusOnNode, + WaitFrameCreate, + DeleteNode, + WaitFrameDelete, + UndoNode, + WaitFrameUndo, + PrepareForNext + }; + + + public class NodeExporterUtils + { + //Auto-Screenshot nodes + private RenderTexture m_screenshotRT; + private Texture2D m_screenshotTex2D; + private List m_screenshotList = new List(); + private DebugScreenShotNodeState m_screenShotState; + private bool m_takingShots = false; + + private DebugUndoNodeState m_undoState; + private bool m_testingUndo = false; + + + private AmplifyShaderEditorWindow m_window; + private ParentNode m_node; + + + private string m_pathname; + + public NodeExporterUtils( AmplifyShaderEditorWindow window ) + { + m_window = window; + Undo.undoRedoPerformed += OnUndoRedoPerformed; + } + + public void OnUndoRedoPerformed() + { + if( m_testingUndo && m_undoState == DebugUndoNodeState.WaitFrameUndo ) + { + m_undoState = DebugUndoNodeState.PrepareForNext; + } + } + + public void CalculateShaderInstructions( Shader shader ) + { + //Type shaderutilType = Type.GetType( "UnityEditor.ShaderUtil, UnityEditor" ); + //shaderutilType.InvokeMember( "OpenCompiledShader", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { shader, mode, customPlatformsMask, includeAllVariants } ); + } + + public void ActivateAutoScreenShot( string pathname, int from, int to ) + { + + m_pathname = pathname; + if( !System.IO.Directory.Exists( m_pathname ) ) + { + System.IO.Directory.CreateDirectory( m_pathname ); + } + + m_screenshotRT = new RenderTexture( (int)m_window.position.width, (int)m_window.position.height, 0 ); + m_screenshotTex2D = new Texture2D( (int)m_window.position.width, (int)m_window.position.height, TextureFormat.RGB24, false ); + + RenderTexture.active = m_screenshotRT; + m_window.CurrentPaletteWindow.FillList( ref m_screenshotList, true ); + m_window.CurrentGraph.ClearGraph(); + if( m_window.IsShaderFunctionWindow ) + { + m_window.CurrentGraph.CurrentOutputNode.Vec2Position = new Vector2( 1500, 0 ); + } + else + { + m_window.CurrentGraph.CurrentMasterNode.Vec2Position = new Vector2( 1500, 0 ); + } + m_window.ResetCameraSettings(); + + m_takingShots = true; + m_screenShotState = DebugScreenShotNodeState.CreateNode; + + } + + public void ActivateNodesURL( int from , int to ) + { + m_window.CurrentPaletteWindow.FillList( ref m_screenshotList, true ); + + if( to < 0 || to > m_screenshotList.Count ) + to = m_screenshotList.Count; + + if( from >= to ) + return; + + for( int i = from; i < to; i++ ) + { + if( m_screenshotList[ i ].NodeType != typeof( FunctionNode ) ) + { + Application.OpenURL( m_screenshotList[ i ].NodeAttributes.NodeUrl ); + } + } + } + + public void ActivateAutoUndo() + { + m_window.CurrentPaletteWindow.FillList( ref m_screenshotList, true ); + m_window.CurrentGraph.ClearGraph(); + m_window.CurrentGraph.CurrentMasterNode.Vec2Position = new Vector2( 1500, 0 ); + m_window.ResetCameraSettings(); + + m_testingUndo = true; + m_undoState = DebugUndoNodeState.CreateNode; + } + + + public void Update() + { + if( m_testingUndo ) + { + if( Event.current.type == EventType.Repaint ) + { + m_window.Focus(); + switch( m_undoState ) + { + case DebugUndoNodeState.CreateNode: + { + m_window.CurrentGraph.DeSelectAll(); + m_node = m_window.CreateNode( m_screenshotList[ 0 ].NodeType, Vector2.zero, null, true ); + m_node.RefreshExternalReferences(); + m_undoState = DebugUndoNodeState.FocusOnNode; + Debug.Log( "Created " + m_node.Attributes.Name ); + } + break; + case DebugUndoNodeState.FocusOnNode: + { + m_window.FocusOnPoint( m_node.TruePosition.center, 1, false ); + m_undoState = DebugUndoNodeState.WaitFrameCreate; + Debug.Log( "Focused " + m_node.Attributes.Name ); + } + break; + case DebugUndoNodeState.WaitFrameCreate: + { + m_undoState = DebugUndoNodeState.DeleteNode; + Debug.Log( "Waiting on Create" ); + } + break; + case DebugUndoNodeState.DeleteNode: + { + Debug.Log( "Deleting " + m_node.Attributes.Name ); + m_window.DeleteSelectedNodeWithRepaint(); + m_undoState = DebugUndoNodeState.WaitFrameDelete; + } + break; + case DebugUndoNodeState.WaitFrameDelete: + { + m_undoState = DebugUndoNodeState.UndoNode; + Debug.Log( "Waiting on Delete" ); + } + break; + case DebugUndoNodeState.UndoNode: + { + Debug.Log( "Performing Undo" ); + m_undoState = DebugUndoNodeState.WaitFrameUndo; + Undo.PerformUndo(); + } + break; + case DebugUndoNodeState.WaitFrameUndo: { } break; + case DebugUndoNodeState.PrepareForNext: + { + m_screenshotList.RemoveAt( 0 ); + Debug.Log( "Undo Performed. Nodes Left " + m_screenshotList.Count ); + m_testingUndo = m_screenshotList.Count > 0; + if( m_testingUndo ) + { + m_undoState = DebugUndoNodeState.CreateNode; + Debug.Log( "Going to next node" ); + } + else + { + Debug.Log( "Finished Undo Test" ); + } + } + break; + + } + } + } + + + if( m_takingShots ) + { + m_window.Focus(); + switch( m_screenShotState ) + { + case DebugScreenShotNodeState.CreateNode: + { + m_node = m_window.CreateNode( m_screenshotList[ 0 ].NodeType, Vector2.zero, null, false ); + m_node.RefreshExternalReferences(); + m_screenShotState = DebugScreenShotNodeState.FocusOnNode; + + + } + break; + case DebugScreenShotNodeState.FocusOnNode: + { + //m_window.FocusOnNode( m_node, 1, false ); + m_window.FocusOnPoint( m_node.TruePosition.center, 1, false ); + m_screenShotState = DebugScreenShotNodeState.TakeScreenshot; + } + break; + case DebugScreenShotNodeState.TakeScreenshot: + { + if( m_screenshotRT != null && Event.current.type == EventType.Repaint ) + { + m_screenshotTex2D.ReadPixels( new Rect( 0, 0, m_screenshotRT.width, m_screenshotRT.height ), 0, 0 ); + m_screenshotTex2D.Apply(); + + byte[] bytes = m_screenshotTex2D.EncodeToPNG(); + string pictureFilename = UIUtils.ReplaceInvalidStrings( m_screenshotList[ 0 ].Name ); + pictureFilename = UIUtils.RemoveInvalidCharacters( pictureFilename ); + + System.IO.File.WriteAllBytes( m_pathname + pictureFilename + ".png", bytes ); + m_screenShotState = DebugScreenShotNodeState.WaitFrame; + } + } + break; + case DebugScreenShotNodeState.WaitFrame: { Debug.Log( "Wait Frame" ); m_screenShotState = DebugScreenShotNodeState.DeleteNode; } break; + case DebugScreenShotNodeState.DeleteNode: + { + m_window.DestroyNode( m_node ); + m_screenshotList.RemoveAt( 0 ); + m_takingShots = m_screenshotList.Count > 0; + Debug.Log( "Destroy Node " + m_screenshotList.Count ); + + if( m_takingShots ) + { + m_screenShotState = DebugScreenShotNodeState.CreateNode; + } + else + { + RenderTexture.active = null; + m_screenshotRT.Release(); + UnityEngine.Object.DestroyImmediate( m_screenshotRT ); + m_screenshotRT = null; + UnityEngine.Object.DestroyImmediate( m_screenshotTex2D ); + m_screenshotTex2D = null; + } + } + break; + }; + } + } + + public void Destroy() + { + m_window = null; + if( m_screenshotRT != null ) + { + m_screenshotRT.Release(); + UnityEngine.Object.DestroyImmediate( m_screenshotRT ); + m_screenshotRT = null; + } + + if( m_screenshotTex2D != null ) + { + UnityEngine.Object.DestroyImmediate( m_screenshotTex2D ); + m_screenshotTex2D = null; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/NodeExporterUtils.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/NodeExporterUtils.cs.meta new file mode 100644 index 0000000..acdf759 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/NodeExporterUtils.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f9b3f6c515f0e16469de89d9e22263c5 +timeCreated: 1486374353 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/Preferences.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/Preferences.cs new file mode 100644 index 0000000..a1566cb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/Preferences.cs @@ -0,0 +1,192 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public class Preferences + { + public enum ShowOption + { + Always = 0, + OnNewVersion = 1, + Never = 2 + } + + private static readonly GUIContent StartUp = new GUIContent( "Show start screen on Unity launch", "You can set if you want to see the start screen everytime Unity launchs, only just when there's a new version available or never." ); + public static readonly string PrefStartUp = "ASELastSession" + Application.productName; + public static ShowOption GlobalStartUp = ShowOption.Always; + + private static readonly GUIContent AutoSRP = new GUIContent( "Auto import SRP shader templates", "By default Amplify Shader Editor checks for your SRP version and automatically imports the correct corresponding shader templates.\nTurn this OFF if you prefer to import them manually." ); + public static readonly string PrefAutoSRP = "ASEAutoSRP" + Application.productName; + public static bool GlobalAutoSRP = true; + + private static readonly GUIContent DefineSymbol = new GUIContent( "Add Amplify Shader Editor define symbol", "Turning it OFF will disable the automatic insertion of the define symbol and remove it from the list while turning it ON will do the opposite.\nThis is used for compatibility with other plugins, if you are not sure if you need this leave it ON." ); + public static readonly string PrefDefineSymbol = "ASEDefineSymbol" + Application.productName; + public static bool GlobalDefineSymbol = true; + + private static readonly GUIContent ClearLog = new GUIContent( "Clear Log on Update", "Clears the previously generated log each time the Update button is pressed" ); + public static readonly string PrefClearLog = "ASEClearLog" + Application.productName; + public static bool GlobalClearLog = true; + + private static readonly GUIContent UpdateOnSceneSave = new GUIContent( "Update on Scene save (Ctrl+S)" , "ASE is aware of Ctrl+S and will use it to save shader" ); + public static readonly string PrefUpdateOnSceneSave = "ASEUpdateOnSceneSave" + Application.productName; + public static bool GlobalUpdateOnSceneSave = true; + +#if UNITY_2019_4_OR_NEWER + private static readonly GUIContent ShowAsyncMsg = new GUIContent( "Show Shader Async. Compilation Message", "Shows message on ASE log if Asynchronous Shader Compilation is detected" ); + public static readonly string PrefShowAsyncMsg = "ASEShowAsync" + Application.productName; + public static bool GlobalShowAsyncMsg = true; +#endif + private static readonly GUIContent DisablePreviews = new GUIContent( "Disable Node Previews" , "Disable preview on nodes from being updated to boost up performance on large graphs" ); + public static readonly string PrefDisablePreviews = "ASEActivatePreviews" + Application.productName; + public static bool GlobalDisablePreviews = false; + + private static bool PrefsLoaded = false; + +#if UNITY_2019_1_OR_NEWER + [SettingsProvider] + public static SettingsProvider ImpostorsSettings() + { + var provider = new SettingsProvider( "Preferences/Amplify Shader Editor", SettingsScope.User ) + { + guiHandler = ( string searchContext ) => + { + PreferencesGUI(); + }, + + keywords = new HashSet( new[] { "start", "screen", "import", "shader", "templates", "macros", "macros", "define", "symbol" } ), + + }; + return provider; + } +#else + [PreferenceItem( "Amplify Shader Editor" )] +#endif + public static void PreferencesGUI() + { + if( !PrefsLoaded ) + { + LoadDefaults(); + PrefsLoaded = true; + } + + var cache = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 250; + { + EditorGUI.BeginChangeCheck(); + GlobalStartUp = (ShowOption)EditorGUILayout.EnumPopup( StartUp , GlobalStartUp ); + if( EditorGUI.EndChangeCheck() ) + { + EditorPrefs.SetInt( PrefStartUp , (int)GlobalStartUp ); + } + } + + { + EditorGUI.BeginChangeCheck(); + GlobalAutoSRP = EditorGUILayout.Toggle( AutoSRP , GlobalAutoSRP ); + if( EditorGUI.EndChangeCheck() ) + { + EditorPrefs.SetBool( PrefAutoSRP , GlobalAutoSRP ); + } + } + + { + EditorGUI.BeginChangeCheck(); + GlobalDefineSymbol = EditorGUILayout.Toggle( DefineSymbol , GlobalDefineSymbol ); + if( EditorGUI.EndChangeCheck() ) + { + EditorPrefs.SetBool( PrefDefineSymbol , GlobalDefineSymbol ); + if( GlobalDefineSymbol ) + IOUtils.SetAmplifyDefineSymbolOnBuildTargetGroup( EditorUserBuildSettings.selectedBuildTargetGroup ); + else + IOUtils.RemoveAmplifyDefineSymbolOnBuildTargetGroup( EditorUserBuildSettings.selectedBuildTargetGroup ); + } + } + + { + EditorGUI.BeginChangeCheck(); + GlobalClearLog = EditorGUILayout.Toggle( ClearLog , GlobalClearLog ); + if( EditorGUI.EndChangeCheck() ) + { + EditorPrefs.SetBool( PrefClearLog , GlobalClearLog ); + } + } + + { + EditorGUI.BeginChangeCheck(); + GlobalUpdateOnSceneSave = EditorGUILayout.Toggle( UpdateOnSceneSave , GlobalUpdateOnSceneSave ); + if( EditorGUI.EndChangeCheck() ) + { + EditorPrefs.SetBool( PrefUpdateOnSceneSave , GlobalUpdateOnSceneSave ); + } + } + + + { + EditorGUI.BeginChangeCheck(); + GlobalDisablePreviews = EditorGUILayout.Toggle( DisablePreviews , GlobalDisablePreviews ); + if( EditorGUI.EndChangeCheck() ) + { + EditorPrefs.SetBool( PrefDisablePreviews , GlobalDisablePreviews ); + UIUtils.ActivatePreviews( !GlobalDisablePreviews ); + } + } + +#if UNITY_2019_4_OR_NEWER + EditorGUI.BeginChangeCheck(); + GlobalShowAsyncMsg = EditorGUILayout.Toggle( ShowAsyncMsg, GlobalShowAsyncMsg); + if( EditorGUI.EndChangeCheck() ) + { + EditorPrefs.SetBool( PrefShowAsyncMsg, GlobalShowAsyncMsg ); + } +#endif + EditorGUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if( GUILayout.Button( "Reset and Forget All" ) ) + { + EditorPrefs.DeleteKey( PrefStartUp ); + GlobalStartUp = ShowOption.Always; + + EditorPrefs.DeleteKey( PrefAutoSRP ); + GlobalAutoSRP = true; + + EditorPrefs.DeleteKey( PrefDefineSymbol ); + GlobalDefineSymbol = true; + IOUtils.SetAmplifyDefineSymbolOnBuildTargetGroup( EditorUserBuildSettings.selectedBuildTargetGroup ); + + EditorPrefs.DeleteKey( PrefClearLog ); + GlobalClearLog = true; + + EditorPrefs.DeleteKey( PrefUpdateOnSceneSave ); + GlobalUpdateOnSceneSave = true; + + EditorPrefs.DeleteKey( PrefDisablePreviews ); + GlobalDisablePreviews = false; + +#if UNITY_2019_4_OR_NEWER + EditorPrefs.DeleteKey( PrefShowAsyncMsg ); + GlobalShowAsyncMsg = true; +#endif + } + EditorGUILayout.EndHorizontal(); + EditorGUIUtility.labelWidth = cache; + } + + public static void LoadDefaults() + { + GlobalStartUp = (ShowOption)EditorPrefs.GetInt( PrefStartUp, 0 ); + GlobalAutoSRP = EditorPrefs.GetBool( PrefAutoSRP, true ); + GlobalDefineSymbol = EditorPrefs.GetBool( PrefDefineSymbol, true ); + GlobalClearLog = EditorPrefs.GetBool( PrefClearLog, true ); + GlobalUpdateOnSceneSave = EditorPrefs.GetBool( PrefUpdateOnSceneSave , true ); + GlobalDisablePreviews = EditorPrefs.GetBool( PrefDisablePreviews , false ); +#if UNITY_2019_4_OR_NEWER + GlobalShowAsyncMsg = EditorPrefs.GetBool( PrefShowAsyncMsg, true ); +#endif + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/Preferences.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/Preferences.cs.meta new file mode 100644 index 0000000..33cf46b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/Preferences.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d036571a581792b44951e3723aef2c01 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/RectExtension.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/RectExtension.cs new file mode 100644 index 0000000..f803ac2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/RectExtension.cs @@ -0,0 +1,40 @@ +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public static class RectExtension + { + private static Rect ValidateBoundaries( this Rect thisRect ) + { + if ( thisRect.yMin > thisRect.yMax ) + { + float yMin = thisRect.yMin; + thisRect.yMin = thisRect.yMax; + thisRect.yMax = yMin; + } + + if ( thisRect.xMin > thisRect.xMax ) + { + float xMin = thisRect.xMin; + thisRect.xMin = thisRect.xMax; + thisRect.xMax = xMin; + } + return thisRect; + } + + public static bool Includes( this Rect thisRect , Rect other ) + { + thisRect = thisRect.ValidateBoundaries(); + other = other.ValidateBoundaries(); + + if ( other.xMin >= thisRect.xMin && other.xMax <= thisRect.xMax ) + { + if ( other.yMin >= thisRect.yMin && other.yMax <= thisRect.yMax ) + { + return true; + } + } + return false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/RectExtension.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/RectExtension.cs.meta new file mode 100644 index 0000000..8225869 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/RectExtension.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e5a7e5c0308e038448cd1a235bf840ca +timeCreated: 1501521591 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/SamplerStateAutoGenerator.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/SamplerStateAutoGenerator.cs new file mode 100644 index 0000000..8be253c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/SamplerStateAutoGenerator.cs @@ -0,0 +1,203 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public enum InlineSamplerFilteringMode + { + Point, + Linear, + Trilinear + }; + + public enum InlineSamplerWrapMode + { + Clamp, + Repeat, + Mirror, + MirrorOnce + }; + + public enum InlineSamplerWrapCoordinates + { + All, + U, + V, + W + }; + + [Serializable] + public class InlineSamplerWrapOptions + { + public InlineSamplerWrapMode WrapMode = InlineSamplerWrapMode.Clamp; + public InlineSamplerWrapCoordinates Coordinates = InlineSamplerWrapCoordinates.All; + public string InlineValue + { + get + { + string name = "_"+WrapMode.ToString(); + if( Coordinates != InlineSamplerWrapCoordinates.All ) + name += Coordinates.ToString(); + name += "_"; + return name; + } + } + } + + [Serializable] + public class SamplerStateAutoGenerator + { + private const int MaxCount = 3; + private const float ButtonLayoutWidth = 15; + private const string AdditionalWrapsStr = "Additional Wraps"; + private const string InlineSamplerStateStr = "Inline Sampler State"; + + [SerializeField] + private InlineSamplerFilteringMode m_filterMode = InlineSamplerFilteringMode.Point; + + [SerializeField] + private InlineSamplerWrapOptions m_mainWrapMode = new InlineSamplerWrapOptions(); + + [SerializeField] + private List m_additionalWrapOptions = new List(); + + [SerializeField] + private bool m_visibleWrapsFoldout = false; + + [SerializeField] + private bool m_visibleMainFoldout = false; + + [NonSerialized] + private UndoParentNode m_owner; + + public void Destroy() + { + m_mainWrapMode = null; + m_additionalWrapOptions.Clear(); + m_additionalWrapOptions = null; + } + + public string AddToDataCollector( ref MasterNodeDataCollector dataCollector ) + { + string inlineSampler = "sampler_"; + + inlineSampler += m_filterMode.ToString(); + inlineSampler += m_mainWrapMode.InlineValue; + + int count = m_additionalWrapOptions.Count; + for( int i = 0; i < count; i++ ) + { + inlineSampler += m_additionalWrapOptions[ i ].InlineValue; + } + return inlineSampler; + } + + void DrawAddRemoveButtons() + { + int count = m_additionalWrapOptions.Count; + if( count < MaxCount && m_owner.GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ButtonLayoutWidth ) ) ) + { + m_additionalWrapOptions.Add( new InlineSamplerWrapOptions() ); + EditorGUI.FocusTextInControl( null ); + } + + if( count > 0 && m_owner.GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ButtonLayoutWidth ) ) ) + { + m_additionalWrapOptions.RemoveAt( count - 1 ); + EditorGUI.FocusTextInControl( null ); + } + } + + public void Draw( UndoParentNode owner ) + { + m_owner = owner; + NodeUtils.DrawNestedPropertyGroup( ref m_visibleMainFoldout, InlineSamplerStateStr, DrawMain ); + } + + void DrawMain() + { + m_filterMode = (InlineSamplerFilteringMode)m_owner.EditorGUILayoutEnumPopup( m_filterMode ); + + EditorGUILayout.BeginHorizontal(); + m_mainWrapMode.WrapMode = (InlineSamplerWrapMode)m_owner.EditorGUILayoutEnumPopup( m_mainWrapMode.WrapMode ); + m_mainWrapMode.Coordinates = (InlineSamplerWrapCoordinates)m_owner.EditorGUILayoutEnumPopup( m_mainWrapMode.Coordinates ); + EditorGUILayout.EndHorizontal(); + NodeUtils.DrawNestedPropertyGroup( ref m_visibleWrapsFoldout, AdditionalWrapsStr, DrawAdditionalWrapModes, DrawAddRemoveButtons ); + } + + void DrawAdditionalWrapModes() + { + EditorGUILayout.Space(); + int count = m_additionalWrapOptions.Count; + for( int i = 0; i < count; i++ ) + { + float maxWidth = 90; + EditorGUILayout.BeginHorizontal(); + m_additionalWrapOptions[ i ].WrapMode = (InlineSamplerWrapMode)m_owner.EditorGUILayoutEnumPopup( m_additionalWrapOptions[ i ].WrapMode ,GUILayout.MaxWidth( maxWidth ) ); + m_additionalWrapOptions[ i ].Coordinates = (InlineSamplerWrapCoordinates)m_owner.EditorGUILayoutEnumPopup( m_additionalWrapOptions[ i ].Coordinates, GUILayout.MaxWidth( maxWidth ) ); + EditorGUILayout.EndHorizontal(); + } + } + + public void ReadFromString( ref uint index, ref string[] nodeParams ) + { +#if UNITY_2019_3_OR_NEWER + Enum.TryParse( nodeParams[ index++ ], out m_filterMode ); + Enum.TryParse( nodeParams[ index++ ], out m_mainWrapMode.Coordinates ); + + int count = 0; + int.TryParse( nodeParams[ index++ ], out count ); + for( int i = 0; i < count; i++ ) + { + InlineSamplerWrapOptions option = new InlineSamplerWrapOptions(); + + Enum.TryParse( nodeParams[ index++ ], out option.WrapMode ); + Enum.TryParse( nodeParams[ index++ ], out option.Coordinates ); + + m_additionalWrapOptions.Add( option ); + } +#else + m_filterMode =(InlineSamplerFilteringMode) Enum.Parse( typeof( InlineSamplerFilteringMode ), nodeParams[ index++ ] ); + m_mainWrapMode.Coordinates = (InlineSamplerWrapCoordinates)Enum.Parse( typeof( InlineSamplerWrapCoordinates ),nodeParams[ index++ ] ); + + int count = 0; + int.TryParse( nodeParams[ index++ ], out count ); + for( int i = 0; i < count; i++ ) + { + InlineSamplerWrapOptions option = new InlineSamplerWrapOptions(); + + option.WrapMode = ( InlineSamplerWrapMode)Enum.Parse(typeof( InlineSamplerWrapMode ), nodeParams[ index++ ] ); + option.Coordinates = ( InlineSamplerWrapCoordinates)Enum.Parse(typeof( InlineSamplerWrapCoordinates ), nodeParams[ index++ ] ); + + m_additionalWrapOptions.Add( option ); + } +#endif + + } + + public void WriteToString( ref string nodeInfo ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_filterMode ); + + IOUtils.AddFieldValueToString( ref nodeInfo, m_mainWrapMode.WrapMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_mainWrapMode.Coordinates ); + + int count = m_additionalWrapOptions.Count; + IOUtils.AddFieldValueToString( ref nodeInfo, count ); + if( count > 0 ) + { + for( int i = 0; i < count; i++ ) + { + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalWrapOptions[i].WrapMode ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalWrapOptions[i].Coordinates ); + } + } + + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/SamplerStateAutoGenerator.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/SamplerStateAutoGenerator.cs.meta new file mode 100644 index 0000000..896ea53 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/SamplerStateAutoGenerator.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: fe831fe9de481bc4b9df1c1142bb9aa5 +timeCreated: 1580322794 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ShortcutsManager.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ShortcutsManager.cs new file mode 100644 index 0000000..3e48aa8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ShortcutsManager.cs @@ -0,0 +1,215 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public class ShortcutItem + { + public delegate void ShortcutFunction(); + public ShortcutFunction MyKeyDownFunctionPtr; + public ShortcutFunction MyKeyUpFunctionPtr; + public string Name; + public string Description; + + public ShortcutItem( string name, string description ) + { + Name = name; + Description = description; + } + + public ShortcutItem( string name, string description, ShortcutFunction myKeyDownFunctionPtr, ShortcutFunction myKeyUpFunctionPtr = null ) + { + Name = name; + Description = description; + MyKeyDownFunctionPtr = myKeyDownFunctionPtr; + MyKeyUpFunctionPtr = myKeyUpFunctionPtr; + } + + public void Destroy() + { + MyKeyDownFunctionPtr = null; + MyKeyUpFunctionPtr = null; + } + } + + public class ShortcutsManager + { + public static readonly KeyCode ScrollUpKey = KeyCode.PageUp; + public static readonly KeyCode ScrollDownKey = KeyCode.PageDown; + + + private const string ItemWikiFormat = "*[{0}]: {1}\n"; + private Dictionary> m_editorShortcutsDict = new Dictionary>(); + private Dictionary m_editorNoModifiersShortcutsDict = new Dictionary(); + private List m_editorShortcutsList = new List(); + + private Dictionary m_nodesShortcutsDict = new Dictionary(); + private List m_nodesShortcutsList = new List(); + + public void DumpShortcutsToDisk( string pathname ) + { + if ( !System.IO.Directory.Exists( pathname ) ) + { + System.IO.Directory.CreateDirectory( pathname ); + } + + string list = "=== Full Shortcut List ===\n"; + list += "==== Editor ====\n"; + for ( int i = 0; i < m_editorShortcutsList.Count; i++ ) + { + list += string.Format( ItemWikiFormat, m_editorShortcutsList[ i ].Name, m_editorShortcutsList[ i ].Description ); + } + list += "\n"; + list += "==== Nodes ====\n"; + for ( int i = 0; i < m_nodesShortcutsList.Count; i++ ) + { + list += string.Format( ItemWikiFormat, m_nodesShortcutsList[ i ].Name, m_nodesShortcutsList[ i ].Description ); + } + + string shortcutsPathnames = pathname + "KeyboardShortcuts.txt"; + Debug.Log( " Creating shortcuts file at " + shortcutsPathnames ); + IOUtils.SaveTextfileToDisk( list, shortcutsPathnames, false ); + } + + public void RegisterNodesShortcuts( KeyCode key, string nodeName ) + { + if ( m_nodesShortcutsDict.ContainsKey( key ) ) + { + if ( DebugConsoleWindow.DeveloperMode ) + { + Debug.Log( "Attempting to register an already used node shortcut key " + key ); + } + return; + } + m_nodesShortcutsDict.Add( key, new ShortcutItem( key.ToString(), nodeName ) ); + m_nodesShortcutsList.Add( m_nodesShortcutsDict[ key ] ); + } + + public void RegisterEditorShortcut( bool showOnList, EventModifiers modifiers, KeyCode key, string description, ShortcutItem.ShortcutFunction myKeyDownFunctionPtr, ShortcutItem.ShortcutFunction myKeyUpFunctionPtr = null ) + { + if ( m_editorShortcutsDict.ContainsKey( key ) ) + { + if ( m_editorShortcutsDict[ key ].ContainsKey( modifiers ) ) + { + if ( DebugConsoleWindow.DeveloperMode ) + { + Debug.Log( "Attempting to register an already used editor shortcut key " + key ); + } + return; + } + } + else + { + m_editorShortcutsDict.Add( key, new Dictionary() ); + } + ShortcutItem item = new ShortcutItem( ( ( modifiers == EventModifiers.None || modifiers == EventModifiers.FunctionKey ) ? key.ToString() : modifiers + " + " + key ), description, myKeyDownFunctionPtr, myKeyUpFunctionPtr ); + m_editorShortcutsDict[ key ].Add( modifiers, item ); + if ( showOnList ) + m_editorShortcutsList.Add( item ); + } + + public void RegisterEditorShortcut( bool showOnList, KeyCode key, string description, ShortcutItem.ShortcutFunction myKeyDownFunctionPtr, ShortcutItem.ShortcutFunction myKeyUpFunctionPtr = null ) + { + if ( m_editorNoModifiersShortcutsDict.ContainsKey( key ) ) + { + if ( DebugConsoleWindow.DeveloperMode ) + { + Debug.Log( "Attempting to register an already used editor shortcut key " + key ); + } + return; + } + + ShortcutItem item = new ShortcutItem( key.ToString(), description, myKeyDownFunctionPtr, myKeyUpFunctionPtr ); + m_editorNoModifiersShortcutsDict.Add( key, item ); + if ( showOnList ) + m_editorShortcutsList.Add( item ); + } + + public bool ActivateShortcut( EventModifiers modifiers, KeyCode key, bool isKeyDown ) + { + if ( m_editorShortcutsDict.ContainsKey( key ) ) + { + if ( isKeyDown ) + { + if ( m_editorShortcutsDict[ key ].ContainsKey( modifiers ) ) + { + if ( m_editorShortcutsDict[ key ][ modifiers ].MyKeyDownFunctionPtr != null ) + { + m_editorShortcutsDict[ key ][ modifiers ].MyKeyDownFunctionPtr(); + return true; + } + } + } + else + { + if ( m_editorShortcutsDict[ key ].ContainsKey( modifiers ) ) + { + if ( m_editorShortcutsDict[ key ][ modifiers ].MyKeyUpFunctionPtr != null ) + { + m_editorShortcutsDict[ key ][ modifiers ].MyKeyUpFunctionPtr(); + return true; + } + } + } + } + + if ( modifiers == EventModifiers.None && m_editorNoModifiersShortcutsDict.ContainsKey( key ) ) + { + if ( isKeyDown ) + { + if ( m_editorNoModifiersShortcutsDict[ key ].MyKeyDownFunctionPtr != null ) + { + m_editorNoModifiersShortcutsDict[ key ].MyKeyDownFunctionPtr(); + return true; + } + } + else + { + if ( m_editorNoModifiersShortcutsDict[ key ].MyKeyUpFunctionPtr != null ) + { + m_editorNoModifiersShortcutsDict[ key ].MyKeyUpFunctionPtr(); + return true; + } + } + } + + return false; + } + + public void Destroy() + { + foreach ( KeyValuePair kvp in m_editorNoModifiersShortcutsDict ) + { + kvp.Value.Destroy(); + } + m_editorNoModifiersShortcutsDict.Clear(); + m_editorNoModifiersShortcutsDict = null; + + foreach ( KeyValuePair> kvpKey in m_editorShortcutsDict ) + { + foreach ( KeyValuePair kvpMod in kvpKey.Value ) + { + kvpMod.Value.Destroy(); + } + kvpKey.Value.Clear(); + } + m_editorShortcutsDict.Clear(); + m_editorShortcutsDict = null; + + m_editorShortcutsList.Clear(); + m_editorShortcutsList = null; + + m_nodesShortcutsDict.Clear(); + m_nodesShortcutsDict = null; + + m_nodesShortcutsList.Clear(); + m_nodesShortcutsList = null; + } + + public List AvailableEditorShortcutsList { get { return m_editorShortcutsList; } } + public List AvailableNodesShortcutsList { get { return m_nodesShortcutsList; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ShortcutsManager.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ShortcutsManager.cs.meta new file mode 100644 index 0000000..d08579e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ShortcutsManager.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 15917e71489c3ca4dbc5fdef9bb37433 +timeCreated: 1487952057 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TextureArrayCreatorAsset.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TextureArrayCreatorAsset.cs new file mode 100644 index 0000000..f7c2c78 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TextureArrayCreatorAsset.cs @@ -0,0 +1,75 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using System.Collections.Generic; +using UnityEngine; + +[Serializable] +public class TextureArrayCreatorAsset : ScriptableObject +{ +#pragma warning disable + [SerializeField] + private int m_selectedSize = 4; + + [SerializeField] + private bool m_lockRatio = true; + + [SerializeField] + private int m_sizeX = 512; + + [SerializeField] + private int m_sizeY = 512; + + [SerializeField] + private bool m_tex3DMode = false; + + [SerializeField] + private bool m_linearMode = false; + + [SerializeField] + private bool m_mipMaps = true; + + [SerializeField] + private TextureWrapMode m_wrapMode = TextureWrapMode.Repeat; + + [SerializeField] + private FilterMode m_filterMode = FilterMode.Bilinear; + + [SerializeField] + private int m_anisoLevel = 1; + + [SerializeField] + private TextureFormat m_selectedFormatEnum = TextureFormat.ARGB32; + + [SerializeField] + private int m_quality = 100; + + [SerializeField] + private string m_folderPath = "Assets/"; + + [SerializeField] + private string m_fileName = "NewTextureArray"; + + [SerializeField] + private bool m_filenameChanged = false; + + [SerializeField] + private List m_allTextures = new List(); + + public int SelectedSize { get { return m_selectedSize; } } + public int SizeX { get { return m_sizeX; } } + public int SizeY { get { return m_sizeY; } } + public bool Tex3DMode { get { return m_tex3DMode; } } + public bool LinearMode { get { return m_linearMode; } } + public bool MipMaps { get { return m_mipMaps; } } + public TextureWrapMode WrapMode { get { return m_wrapMode; } } + public FilterMode FilterMode { get { return m_filterMode; } } + public int AnisoLevel { get { return m_anisoLevel; } } + public TextureFormat SelectedFormatEnum { get { return m_selectedFormatEnum; } } + public int Quality { get { return m_quality; } } + public string FolderPath { get { return m_folderPath; } } + public string FileName { get { return m_fileName; } } + public List AllTextures { get { return m_allTextures; } } +#pragma warning restore +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TextureArrayCreatorAsset.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TextureArrayCreatorAsset.cs.meta new file mode 100644 index 0000000..bd40c30 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TextureArrayCreatorAsset.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 47f91343d4ad12542b3eb9511e2b310c +timeCreated: 1596799060 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TipsWindow.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TipsWindow.cs new file mode 100644 index 0000000..1d88835 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TipsWindow.cs @@ -0,0 +1,148 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System.IO; +using System.Reflection; +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class TipsWindow : MenuParent + { + private static bool m_showWindow = false; + private bool m_dontShowAtStart = false; + + private static List AllTips = new List() { + "You can press W to toggle between a flat and color coded Wires and ports.", + "You can press CTRL+W to toggle between multiline or singleline Wire connections.", + "You can press P to globally open all node Previews.", + "You can press F to Focus your selection, single tap centers the selection while double tap it to also zooms on in.", + "You can press CTRL+F to open a search bar and Find a node by it's title", + "You can press SPACE to open a context menu to add a new node and press TAB or SHIFT+TAB tocycle between the found nodes", + "You can remove a node without breaking the graph connections by pressing ALT and then dragging the node out", + "You can switch two input connections holding CTRL while dragging one input connection into the other", + }; + + int m_currentTip = 0; + + public TipsWindow( AmplifyShaderEditorWindow parentWindow ) : base( parentWindow, 0, 0, 0, 64, "Tips", MenuAnchor.TOP_LEFT, MenuAutoSize.NONE ) + { + //m_dontShowAtStart = EditorPrefs.GetBool( "DontShowTipAtStart", false ); + } + + public override void Draw( Rect parentPosition, Vector2 mousePosition, int mouseButtonId, bool hasKeyboadFocus ) + { + base.Draw( parentPosition, mousePosition, mouseButtonId, hasKeyboadFocus ); + + DrawWindow( mousePosition ); + } + + public void DrawWindow( Vector2 mousePosition ) + { + if( !m_showWindow ) + return; + + Rect windowRect = new Rect( 0, 0, Screen.width, Screen.height ); + Vector2 center = windowRect.center; + windowRect.size = new Vector2( 300, 200 ); + windowRect.center = center; + Color temp = GUI.color; + GUI.color = Color.white; + GUI.Label( windowRect, string.Empty, GUI.skin.FindStyle( "flow node 0" ) ); + + if( Event.current.type == EventType.MouseDown && !windowRect.Contains( mousePosition ) ) + m_showWindow = false; + + Rect titleRect = windowRect; + titleRect.height = 35; + GUI.Label( titleRect, "Quick Tip!", GUI.skin.FindStyle( "TL Selection H2" ) ); + Rect button = titleRect; + button.size = new Vector2( 14, 14 ); + button.y += 2; + button.x = titleRect.xMax - 16; + if( GUI.Button( button, string.Empty, GUI.skin.FindStyle( "WinBtnClose" ) ) ) + CloseWindow(); + + button.y += 100; + if( GUI.Button( button, ">" ) ) + { + m_currentTip++; + if( m_currentTip >= AllTips.Count ) + m_currentTip = 0; + } + + Rect textRect = windowRect; + textRect.yMin = titleRect.yMax; + GUI.Label( textRect, AllTips[ m_currentTip ], GUI.skin.FindStyle( "WordWrappedLabel" ) ); + + Rect footerRect = windowRect; + footerRect.yMin = footerRect.yMax - 18; + footerRect.x += 3; + GUI.Label( footerRect, (m_currentTip + 1) + " of " + AllTips.Count + " tips" ); + footerRect.x += 170; + EditorGUI.BeginChangeCheck(); + m_dontShowAtStart = GUI.Toggle( footerRect, m_dontShowAtStart, "Don't show at start" ); + if( EditorGUI.EndChangeCheck() ) + { + EditorPrefs.SetBool( "DontShowTipAtStart", m_dontShowAtStart ); + } + GUI.color = temp; + + if( Event.current.type == EventType.MouseDown && windowRect.Contains( mousePosition ) ) + { + Event.current.Use(); + ParentWindow.MouseInteracted = true; + } + } + + public override void Destroy() + { + base.Destroy(); + } + + public static void ShowWindow( bool toggle = true ) + { + if( toggle ) + m_showWindow = !m_showWindow; + else + m_showWindow = true; + + //Test(); + //ExportCompiledShaders(); + } + + //public static void Test() + //{ + // Shader shader = UIUtils.CurrentWindow.CurrentGraph.CurrentShader; + // int mode = EditorPrefs.GetInt( "ShaderInspectorPlatformMode", 1 ); + // int mask = EditorPrefs.GetInt( "ShaderInspectorPlatformMask", 524287 ); + // bool strip = EditorPrefs.GetInt( "ShaderInspectorVariantStripping", 1 ) == 0; + // ShaderUtilEx.OpenCompiledShader( shader, mode, mask, strip ); + //} + + //public static void ExportCompiledShaders() + //{ + // Shader shader = UIUtils.CurrentWindow.CurrentGraph.CurrentShader; + // string shaderPath = AssetDatabase.GetAssetPath( shader ); + // SerializedObject so = new SerializedObject( shader ); + // SerializedProperty prop = so.FindProperty( "m_Script" ); + // var compiledShaderString = prop.stringValue; + // Directory.CreateDirectory( Application.dataPath + "/../ShaderSource/" ); + // if( compiledShaderString == null ) + // return; + // var outputPath = Application.dataPath + "/../ShaderSource/" + Path.GetFileNameWithoutExtension( shaderPath ) + "_compiled.shader"; + // var sw = File.CreateText( outputPath ); + // sw.Write( compiledShaderString ); + // sw.Close(); + //} + + public static void CloseWindow() + { + m_showWindow = false; + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TipsWindow.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TipsWindow.cs.meta new file mode 100644 index 0000000..3d59829 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/TipsWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 565dc3c9725b0db49b7d5ea17d151682 +timeCreated: 1504704078 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UIUtils.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UIUtils.cs new file mode 100644 index 0000000..3ffd2e4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UIUtils.cs @@ -0,0 +1,3109 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.IO; + +using System.Globalization; +using System.Text.RegularExpressions; + +namespace AmplifyShaderEditor +{ + public enum ASEColorSpace + { + Auto, + Gamma, + Linear + } + + public enum SurfaceInputs + { + DEPTH = 0, + UV_COORDS, + UV2_COORDS, + VIEW_DIR, + COLOR, + SCREEN_POS, + WORLD_POS, + WORLD_REFL, + WORLD_NORMAL, + VFACE, + INTERNALDATA + } + + public enum CustomStyle + { + NodeWindowOff = 0, + NodeWindowOn, + NodeTitle, + NodeHeader, + CommentaryHeader, + ShaderLibraryTitle, + ShaderLibraryAddToList, + ShaderLibraryRemoveFromList, + ShaderLibraryOpenListed, + ShaderLibrarySelectionAsTemplate, + ShaderLibraryItem, + CommentaryTitle, + PortEmptyIcon, + PortFullIcon, + InputPortlabel, + OutputPortLabel, + CommentaryResizeButton, + CommentaryResizeButtonInv, + CommentaryBackground, + MinimizeButton, + MaximizeButton, + NodePropertiesTitle, + ShaderModeTitle, + MaterialModeTitle, + ShaderNoMaterialModeTitle, + PropertyValuesTitle, + ShaderModeNoShader, + MainCanvasTitle, + ShaderBorder, + MaterialBorder, + SamplerTextureRef, + SamplerTextureIcon, + CustomExpressionAddItem, + CustomExpressionRemoveItem, + CustomExpressionSmallAddItem, + CustomExpressionSmallRemoveItem, + ResetToDefaultInspectorButton, + SliderStyle, + ObjectPicker, + NodePropertyPicker, + NodePreviewExpander, + NodePreviewCollapser, + SamplerButton, + SamplerFrame, + CommentarySuperTitle, + MiniButtonTopLeft, + MiniButtonTopMid, + MiniButtonTopRight, + ShaderFunctionBorder, + ShaderFunctionMode, + RightShaderMode, + FlatBackground, + DocumentationLink, + GraphButtonIcon, + GraphButton, + NodeWindowOffSquare, + NodeHeaderSquare, + NodeWindowOnSquare, + ConsoleLogMessage, + ConsoleLogCircle + } + + public enum MasterNodePortCategory + { + Vertex = 1 << 0, + Fragment = 1 << 1, + Tessellation = 1 << 2, + Debug = 1 << 3 + } + + public enum PortGenType + { + NonCustomLighting, + //Normal = 1 << 1, + //Emission = 1 << 2, + //Metallic = 1 << 3, + //Specular = 1 << 4, + CustomLighting + } + + public struct NodeData + { + public MasterNodePortCategory Category; + public int OrderIndex; + public int GraphDepth; + public NodeData( MasterNodePortCategory category ) + { + Category = category; + OrderIndex = 0; + GraphDepth = -1; + } + } + + public struct NodeCastInfo + { + public int NodeId; + public int PortId; + public NodeCastInfo( int nodeId, int portId ) + { + NodeId = nodeId; + PortId = portId; + } + public override string ToString() + { + return NodeId.ToString() + PortId.ToString(); + } + }; + + public struct ButtonClickId + { + public const int LeftMouseButton = 0; + public const int RightMouseButton = 1; + public const int MiddleMouseButton = 2; + } + + public enum ASESelectionMode + { + Shader = 0, + Material, + ShaderFunction + } + + public enum DrawOrder + { + Background, + Default + } + + public enum NodeConnectionStatus + { + Not_Connected = 0, + Connected, + Error, + Island + } + + public enum InteractionMode + { + Target, + Other, + Both + } + + public enum FunctionNodeCategories + { + Custom, + CameraAndScreen, + ConstantsAndProperties, + Functions, + ImageEffects, + Light, + LogicalOperators, + MathOperators, + MatrixOperators, + Miscellaneous, + ObjectTransform, + SurfaceData, + Textures, + Time, + TrigonometryOperators, + UVCoordinates, + VectorOperators, + VertexData + } + + public enum TransformSpaceFrom + { + Object = 0, + World, + View, + Tangent + } + + public enum TransformSpaceTo + { + Object = 0, + World, + View, + Tangent, + Clip + } + + public class UIUtils + { + public static string NewTemplateGUID; + public static int SerializeHelperCounter = 0; + public static bool IgnoreDeselectAll = false; + + public static bool DirtyMask = true; + public static bool Initialized = false; + public static float HeaderMaxHeight; + public static float CurrentHeaderHeight; + public static GUISkin MainSkin = null; + public static GUIStyle PlusStyle; + public static GUIStyle MinusStyle; + public static GUIStyle RangedFloatSliderStyle; + public static GUIStyle RangedFloatSliderThumbStyle; + public static GUIStyle SwitchNodePopUp; + public static GUIStyle PropertyPopUp; + public static GUIStyle ObjectField; + public static GUIStyle PreviewExpander; + public static GUIStyle PreviewCollapser; + public static GUIStyle ObjectFieldThumb; + public static GUIStyle ObjectFieldThumbOverlay; + public static GUIStyle InspectorPopdropdownStyle; + public static GUIStyle InspectorPopdropdownFallback; + public static GUIStyle BoldErrorStyle; + public static GUIStyle BoldWarningStyle; + public static GUIStyle BoldInfoStyle; + public static GUIStyle Separator; + public static GUIStyle ToolbarMainTitle; + public static GUIStyle ToolbarSearchTextfield; + public static GUIStyle ToolbarSearchCancelButton; + public static GUIStyle MiniButtonTopLeft; + public static GUIStyle MiniButtonTopMid; + public static GUIStyle MiniButtonTopRight; + + public static GUIStyle CommentaryTitle; + public static GUIStyle StickyNoteText; + public static GUIStyle InputPortLabel; + public static GUIStyle OutputPortLabel; + + public static GUIStyle MiniObjectFieldThumbOverlay; + public static GUIStyle MiniSamplerButton; + + public static GUIStyle NodeWindowOffSquare; + public static GUIStyle NodeHeaderSquare; + public static GUIStyle NodeWindowOnSquare; + public static GUIStyle InternalDataOnPort; + public static GUIStyle InternalDataBackground; + + public static GUIStyle GraphButtonIcon; + public static GUIStyle GraphButton; + public static GUIStyle GraphDropDown; + + public static GUIStyle EmptyStyle = new GUIStyle(); + + public static GUIStyle ConsoleLogLabel; + public static GUIStyle ConsoleLogMessage; + public static GUIStyle ConsoleLogCircle; + + public static GUIStyle TooltipBox; + public static GUIStyle Box; + public static GUIStyle Button; + public static GUIStyle TextArea; + public static GUIStyle Label; + public static GUIStyle Toggle; + public static GUIStyle Textfield; + + public static GUIStyle UnZoomedNodeTitleStyle; + public static GUIStyle UnZoomedPropertyValuesTitleStyle; + public static GUIStyle UnZoomedInputPortStyle; + public static GUIStyle UnZoomedOutputPortPortStyle; + + // Node Property Menu items + public static GUIStyle MenuItemToggleStyle; + public static GUIStyle MenuItemEnableStyle; + public static GUIStyle MenuItemBackgroundStyle; + public static GUIStyle MenuItemToolbarStyle; + public static GUIStyle MenuItemInspectorDropdownStyle; + + public static GUIStyle FloatIntPickerONOFF; + + public static bool UsingProSkin = false; + + public static Texture ShaderIcon { get { return EditorGUIUtility.IconContent( "Shader Icon" ).image; } } + public static Texture MaterialIcon { get { return EditorGUIUtility.IconContent( "Material Icon" ).image; } } + + //50be8291f9514914aa55c66c49da67cf + public static Texture ShaderFunctionIcon { get { return AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "50be8291f9514914aa55c66c49da67cf" ) ); } } + + public static Texture2D WireNodeSelection = null; + public static Texture2D SliderButton = null; + + public static Texture2D SmallErrorIcon = null; + public static Texture2D SmallWarningIcon = null; + public static Texture2D SmallInfoIcon = null; + + public static Texture2D CheckmarkIcon = null; + public static Texture2D PopupIcon = null; + + public static Texture2D MasterNodeOnTexture = null; + public static Texture2D MasterNodeOffTexture = null; + + public static Texture2D GPUInstancedOnTexture = null; + public static Texture2D GPUInstancedOffTexture = null; + + public static GUIContent LockIconOpen = null; + public static GUIContent LockIconClosed = null; + + public static GUIContent FloatIntIconON = null; + public static GUIContent FloatIntIconOFF = null; + + public static bool ShowContextOnPick = true; + + private static AmplifyShaderEditorWindow m_currentWindow = null; + public static AmplifyShaderEditorWindow CurrentWindow + { + get + { + if( m_currentWindow == null ) + { + for( int i = 0 ; i < IOUtils.AllOpenedWindows.Count ; i++ ) + { + if( IOUtils.AllOpenedWindows[ i ] != null ) + { + m_currentWindow = IOUtils.AllOpenedWindows[ i ]; + } + else + { + //Debug.Log("No Window Found!"); + } + } + } + return m_currentWindow; + } + set { m_currentWindow = value; } + } + + public static Vector2 PortsSize; + public static Vector3 PortsDelta; + public static Vector3 ScaledPortsDelta; + + public static RectOffset RectOffsetZero; + public static RectOffset RectOffsetOne; + public static RectOffset RectOffsetTwo; + public static RectOffset RectOffsetThree; + public static RectOffset RectOffsetFour; + public static RectOffset RectOffsetFive; + public static RectOffset RectOffsetSix; + + public static Material LinearMaterial = null; + public static Shader IntShader = null; + public static Shader FloatShader = null; + public static Shader Vector2Shader = null; + public static Shader Vector3Shader = null; + public static Shader Vector4Shader = null; + public static Shader ColorShader = null; + public static Shader Texture2DShader = null; + public static Shader MaskingShader = null; + + public static bool InhibitMessages = false; + + + private static int m_shaderIndentLevel = 0; + private static string m_shaderIndentTabs = string.Empty; + + //Label Vars + + private static TextAnchor m_alignment; + private static TextClipping m_clipping; + private static bool m_wordWrap; + private static int m_fontSize; + private static Color m_fontColor; + private static FontStyle m_fontStyle; + + + private static string NumericNamePattern = @"^\d"; + private static System.Globalization.TextInfo m_textInfo; + private static string m_latestOpenedFolder = string.Empty; + private static Dictionary m_undoHelper = new Dictionary(); + + private static Dictionary AvailableKeywordsDict = new Dictionary(); + public static readonly string[] AvailableKeywords = + { + "Custom", + "ETC1_EXTERNAL_ALPHA", + "PIXELSNAP_ON", + "UNITY_PASS_FORWARDBASE", + "UNITY_PASS_FORWARDADD", + "UNITY_PASS_DEFERRED", + "UNITY_PASS_SHADOWCASTER", + "UNITY_INSTANCING_ENABLED", + "DIRECTIONAL_COOKIE" + + }; + + private static Dictionary AvailableURPKeywordsDict = new Dictionary(); + public static readonly string[] AvailableURPKeywords = + { + "Custom", + "ETC1_EXTERNAL_ALPHA", + "PIXELSNAP_ON", + "SHADERPASS_EXTRA_PREPASS", + "SHADERPASS_FORWARD", + "SHADERPASS_SHADOWCASTER", + "SHADERPASS_DEPTHONLY", + "SHADERPASS_META", + "SHADERPASS_2D", + "UNITY_INSTANCING_ENABLED", + "DIRECTIONAL_COOKIE" + }; + + //private static Dictionary URPToBultinKeywordsDict = new Dictionary() + //{ + // {"SHADERPASS_FORWARD","UNITY_PASS_FORWARDBASE"}, + // {"SHADERPASS_SHADOWCASTER","UNITY_PASS_SHADOWCASTER"} + //}; + + //private static Dictionary BultinToURPKeywordsDict = new Dictionary() + //{ + // {"UNITY_PASS_FORWARDBASE","SHADERPASS_FORWARD"}, + // {"UNITY_PASS_SHADOWCASTER","SHADERPASS_SHADOWCASTER"} + //}; + + public static readonly string[] CategoryPresets = + { + "", + "Camera And Screen", + "Constants And Properties", + "Functions", + "Image Effects", + "Light", + "Logical Operators", + "Math Operators", + "Matrix Operators", + "Miscellaneous", + "Object Transform", + "Surface Data", + "Textures", + "Time", + "Trigonometry Operators", + "UV Coordinates", + "Vector Operators", + "Vertex Data" + }; + + private static Dictionary m_portCategoryToArrayIdx = new Dictionary + { + { MasterNodePortCategory.Vertex,0}, + { MasterNodePortCategory.Tessellation,0}, + { MasterNodePortCategory.Fragment,1}, + { MasterNodePortCategory.Debug,1} + }; + + private static Dictionary m_reservedPropertyNames = new Dictionary + { + { "UNITY_MATRIX_MVP", string.Empty}, + { "UNITY_MATRIX_MV", string.Empty}, + { "UNITY_MATRIX_V", string.Empty}, + { "UNITY_MATRIX_P", string.Empty}, + { "UNITY_MATRIX_VP", string.Empty}, + { "UNITY_MATRIX_T_MV", string.Empty}, + { "UNITY_MATRIX_IT_MV", string.Empty}, + { "UNITY_MATRIX_TEXTURE0", string.Empty}, + { "UNITY_MATRIX_TEXTURE1", string.Empty}, + { "UNITY_MATRIX_TEXTURE2", string.Empty}, + { "UNITY_MATRIX_TEXTURE3", string.Empty}, + { "_Object2World", string.Empty}, + { "_WorldSpaceCameraPos", string.Empty}, + { "unity_Scale", string.Empty}, + { "_ModelLightColor", string.Empty}, + { "_SpecularLightColor", string.Empty}, + { "_ObjectSpaceLightPos", string.Empty}, + { "_Light2World", string.Empty}, + { "_World2Light", string.Empty}, + { "_Object2Light", string.Empty}, + { "_Time", string.Empty}, + { "_SinTime", string.Empty}, + { "_CosTime", string.Empty}, + { "unity_DeltaTime", string.Empty}, + { "_ProjectionParams", string.Empty}, + { "_ScreenParams", string.Empty} + }; + + private static Dictionary m_exampleMaterialIDs = new Dictionary() + { + //Community + {"2Sided", "8ebbbf2c99a544ca780a2573ef1450fc" }, + {"DissolveBurn", "f144f2d7ff3daf349a2b7f0fd81ec8ac" }, + {"MourEnvironmentGradient", "b64adae401bc073408ac7bff0993c107" }, + {"ForceShield", "0119aa6226e2a4cfdb6c9a5ba9df7820" }, + {"HighlightAnimated", "3d232e7526f6e426cab994cbec1fc287" }, + {"Hologram", "b422c600f1c3941b8bc7e95db33476ad" }, + {"LowPolyWater", "0557703d3791a4286a62f8ee709d5bef"}, + //Official + {"AnimatedFire", "63ea5eae6d954a14292033589d0d4275" }, + {"AnimatedFire-ShaderFunction", "9c6c9fcb82afe874a825a9e680e694b2" }, + {"BurnEffect", "0b019675a8064414b97862a02f644166" }, + {"CubemapReflections", "2c299f827334e9c459a60931aea62260" }, + {"DitheringFade", "610507217b7dcad4d97e6e03e9844171" }, + {"DoubleLayerCustomSurface", "846aec4914103104d99e9e31a217b548" }, + {"NormalExtrusion", "70a5800fbba039f46b438a2055bc6c71" }, + {"MatcapSample", "da8aaaf01fe8f2b46b2fbcb803bd7af4" }, + {"ParallaxMappingIterations", "a0cea9c3f318ac74d89cd09134aad000" }, + {"SandPOM", "905481dc696211145b88dc4bac2545f3" }, + {"ParallaxWindow", "63ad0e7afb1717b4e95adda8904ab0c3" }, + {"LocalPosCutoff", "fed8c9d33a691084c801573feeed5a62" }, + {"ImprovedReadFromAtlasTiled", "941b31b251ea8e74f9198d788a604c9b" }, + {"ReadFromAtlasTiled", "2d5537aa702f24645a1446dc3be92bbf" }, + {"ReflectRefractSoapBubble", "a844987c9f2e7334abaa34f12feda3b9" }, + {"RimLight", "e2d3a4d723cf1dc4eab1d919f3324dbc" }, + {"RefractedShadows", "11818aa28edbeb04098f3b395a5bfc1d" }, + {"TextureArray", "0f572993ab788a346aea45f2f797b7fa" }, + {"ObjectNormalRefraction", "f1a0a645876302547b608ce881c94e6d" }, + {"ShaderBallInterior", "e47ee174f55b6144b9c1a942bb23d82a" }, + {"ScreenSpaceCurvature", "2e794cb9b3900b043a37ba28cdc2f907" }, + {"ScreenSpaceDetail", "3a0163d12fede4d47a1f818a66a115de" }, + {"SimpleNoise", "cc167bc6c2063a14f84a5a77be541194" }, + {"SimpleBlur", "1d283ff911af20e429180bb15d023661" }, + {"SimpleGPUInstancing", "9d609a7c8d00c7c4c9bdcdcdba154b81" }, + {"SimpleLambert", "54b29030f7d7ffe4b84f2f215dede5ac" }, + {"SimpleRefraction", "58c94d2f48acdc049a53b4ca53d6d98a" }, + {"SimpleTexture", "9661085a7d249a54c95078ac8e7ff004" }, + {"SnowAccum", "e3bd639f50ae1a247823079047a8dc01" }, + {"StencilDiffuse01", "9f47f529fdeddd948a2d2722f73e6ac4" }, + {"StencilMask01", "6f870834077d59b44ac421c36f619d59" }, + {"StencilDiffuse02", "11cdb862d5ba68c4eae526765099305b" }, + {"StencilMask02", "344696733b065c646b18c1aa2eacfdb7" }, + {"StencilDiffuse03", "75e851f6c686a5f42ab900222b29355b" }, + {"StencilMask03", "c7b3018ad495c6b479f2e3f8564aa6dc" }, + {"SubstanceExample", "a515e243b476d7e4bb37eb9f82c87a12" }, + {"AnimatedRefraction", "e414af1524d258047bb6b82b8860062c" }, + {"Tessellation", "efb669a245f17384c88824d769d0087c" }, + {"Translucency", "842ba3dcdd461ea48bdcfcea316cbcc4" }, + {"Transmission", "1b21506b7afef734facfc42c596caa7b" }, + {"Transparency", "e323a62068140c2408d5601877e8de2c" }, + {"TriplanarProjection", "663d512de06d4e24db5205c679f394cb" }, + {"TwoSideWithFace", "c953c4b601ba78e4f870d24d038b67f6" }, + {"Ground", "48df9bdf7b922d94bb3167e6db39c943" }, + {"WaterSample", "288137d67ce790e41903020c572ab4d7" }, + {"WorldPosSlices", "013cc03f77f3d034692f902db8928787" } + }; + + private static Dictionary m_textureTypeToCgType = new Dictionary() + { + {TextureType.Texture1D, "sampler1D" }, + {TextureType.Texture2D, "sampler2D" }, + {TextureType.Texture3D, "sampler3D" }, + {TextureType.Cube , "samplerCUBE"}, + {TextureType.Texture2DArray, "sampler2DArray" }, + {TextureType.ProceduralTexture, "sampler2D" } + }; + + + private static Dictionary m_nodeCategoryToColor = new Dictionary() + { + { "Master", new Color( 0.6f, 0.52f, 0.43f, 1.0f )}, + { "Default", new Color( 0.26f, 0.35f, 0.44f, 1.0f )}, + { "Vertex Data", new Color( 0.8f, 0.07f, 0.18f, 1.0f)},//new Color( 0.75f, 0.10f, 0.30f, 1.0f )}, + { "Math Operators", new Color( 0.26f, 0.35f, 0.44f, 1.0f )},//new Color( 0.10f, 0.27f, 0.45f, 1.0f) }, + { "Logical Operators", new Color( 0.0f, 0.55f, 0.45f, 1.0f)},//new Color( 0.11f, 0.28f, 0.47f, 1.0f) }, + { "Trigonometry Operators", new Color( 0.1f, 0.20f, 0.35f, 1.0f)},//new Color( 0.8f, 0.07f, 0.18f, 1.0f)}, + { "Image Effects", new Color( 0.5f, 0.2f, 0.90f, 1.0f)},//new Color( 0.12f, 0.47f, 0.88f, 1.0f)}, + { "Miscellaneous", new Color( 0.49f, 0.32f, 0.60f, 1.0f)}, + { "Camera And Screen", new Color( 0.75f, 0.10f, 0.30f, 1.0f )},//new Color( 0.17f, 0.22f, 0.07f, 1.0f) }, + { "Constants And Properties", new Color( 0.42f, 0.70f, 0.22f, 1.0f) }, + { "Surface Data", new Color( 0.92f, 0.73f, 0.03f, 1.0f)}, + { "Matrix Transform", new Color( 0.09f, 0.43f, 0.2f, 1.0f) }, + { "Time", new Color( 0.25f, 0.25f, 0.25f, 1.0f)},//new Color( 0.89f, 0.59f, 0.0f, 1.0f) }, + { "Functions", new Color( 1.00f, 0.4f, 0.0f, 1.0f) }, + { "Vector Operators", new Color( 0.22f, 0.20f, 0.45f, 1.0f)}, + { "Matrix Operators", new Color( 0.45f, 0.9f, 0.20f, 1.0f) }, + { "Light", new Color( 1.0f, 0.9f, 0.0f, 1.0f) }, + { "Textures", new Color( 0.15f, 0.40f, 0.8f, 1.0f)}, + { "Commentary", new Color( 0.7f, 0.7f, 0.7f, 1.0f)}, + { "UV Coordinates", new Color( 0.89f, 0.59f, 0.0f, 1.0f) }, + { "Object Transform", new Color( 0.15f, 0.4f, 0.49f, 1.0f)}, + { "Vertex Transform", new Color( 0.15f, 0.4f, 0.49f, 1.0f)} + }; + + private static Dictionary> m_toolButtonTooltips = new Dictionary> + { + { ToolButtonType.New, new List() { "Create new shader." } }, + { ToolButtonType.Open, new List() { "Open existing shader." } }, + { ToolButtonType.Save, new List() { "No changes to save.", "Save current changes." } }, + { ToolButtonType.Library, new List() { "Lists custom shader selection." } }, + { ToolButtonType.Options, new List() { "Open Options menu." } }, + { ToolButtonType.Update, new List() { "Open or create a new shader first.", "Click to enable to update current shader.", "Shader up-to-date." } }, + { ToolButtonType.Live, new List() { "Open or create a new shader first.", "Click to enable live shader preview", "Click to enable live shader and material preview." , "Live preview active, click to disable." } }, + { ToolButtonType.TakeScreenshot, new List() { "Take screenshot", "Take screenshot" }}, + { ToolButtonType.Share, new List() { "Share selection", "Share selection" }}, + { ToolButtonType.CleanUnusedNodes, new List() { "No unconnected nodes to clean.", "Remove all nodes not connected( directly or indirectly) to the master node." }}, + { ToolButtonType.Help, new List() { "Show help window." } }, + { ToolButtonType.FocusOnMasterNode,new List() { "Focus on active master node." } }, + { ToolButtonType.FocusOnSelection, new List() { "Focus on selection fit to screen ( if none selected )." } } + }; + + private static Color[] m_dataTypeToColorMonoMode = { new Color( 0.5f , 0.5f , 0.5f , 1.0f ) , Color.white }; + private static Dictionary m_dataTypeToColor = new Dictionary( new WirePortDataTypeComparer() ) + { + { WirePortDataType.OBJECT, Color.white}, + { WirePortDataType.SAMPLERSTATE,Color.white}, + { WirePortDataType.FLOAT, Color.gray}, + { WirePortDataType.FLOAT2, new Color(1f,1f,0f,1f)}, + { WirePortDataType.FLOAT3, new Color(0.5f,0.5f,1f,1f)}, + { WirePortDataType.FLOAT4, new Color(1f,0,1f,1f)}, + { WirePortDataType.FLOAT3x3, new Color(0.5f,1f,0.5f,1f)}, + { WirePortDataType.FLOAT4x4, new Color(0.5f,1f,0.5f,1f)}, + { WirePortDataType.COLOR, new Color(1f,0,1f,1f)}, + { WirePortDataType.INT, Color.white}, + { WirePortDataType.SAMPLER1D, new Color(1f,0.5f,0f,1f)}, + { WirePortDataType.SAMPLER2D, new Color(1f,0.5f,0f,1f)}, + { WirePortDataType.SAMPLER3D, new Color(1f,0.5f,0f,1f)}, + { WirePortDataType.SAMPLERCUBE, new Color(1f,0.5f,0f,1f)}, + { WirePortDataType.SAMPLER2DARRAY, new Color(1f,0.5f,0f,1f)} + }; + + private static Dictionary m_dataTypeToName = new Dictionary() + { + { WirePortDataType.OBJECT, "Generic Object"}, + { WirePortDataType.FLOAT, "Float"}, + { WirePortDataType.FLOAT2, "Vector2"}, + { WirePortDataType.FLOAT3, "Vector3"}, + { WirePortDataType.FLOAT4, "Vector4"}, + { WirePortDataType.FLOAT3x3, "3x3 Matrix"}, + { WirePortDataType.FLOAT4x4, "4x4 Matrix"}, + { WirePortDataType.COLOR, "Color"}, + { WirePortDataType.INT, "Int"}, + { WirePortDataType.SAMPLER1D, "Sampler1D"}, + { WirePortDataType.SAMPLER2D, "Sampler2D"}, + { WirePortDataType.SAMPLER3D, "Sampler3D"}, + { WirePortDataType.SAMPLERCUBE, "SamplerCUBE"}, + { WirePortDataType.SAMPLER2DARRAY, "Sampler2DArray"}, + { WirePortDataType.SAMPLERSTATE,"Sampler State"}, + }; + + private static Dictionary m_inputTypeDeclaration = new Dictionary() + { + { SurfaceInputs.DEPTH, "{0} Depth : SV_Depth"}, + { SurfaceInputs.UV_COORDS, "{0}2 uv"},// texture uv must have uv or uv2 followed by the texture name + { SurfaceInputs.UV2_COORDS, "{0}2 uv2"}, + { SurfaceInputs.VIEW_DIR, "{0}3 viewDir"}, + { SurfaceInputs.COLOR, Constants.ColorInput}, + { SurfaceInputs.SCREEN_POS, "{0}4 screenPos"}, + { SurfaceInputs.WORLD_POS, "{0}3 worldPos"}, + { SurfaceInputs.WORLD_REFL, "{0}3 worldRefl"}, + { SurfaceInputs.WORLD_NORMAL,"{0}3 worldNormal"}, + { SurfaceInputs.VFACE, Constants.VFaceInput}, + { SurfaceInputs.INTERNALDATA, Constants.InternalData} + }; + + private static Dictionary m_inputTypeName = new Dictionary() + { + { SurfaceInputs.DEPTH, "Depth"}, + { SurfaceInputs.UV_COORDS, "uv"},// texture uv must have uv or uv2 followed by the texture name + { SurfaceInputs.UV2_COORDS, "uv2"}, + { SurfaceInputs.VIEW_DIR, "viewDir"}, + { SurfaceInputs.COLOR, Constants.ColorVariable}, + { SurfaceInputs.SCREEN_POS, "screenPos"}, + { SurfaceInputs.WORLD_POS, "worldPos"}, + { SurfaceInputs.WORLD_REFL, "worldRefl"}, + { SurfaceInputs.WORLD_NORMAL, "worldNormal"}, + { SurfaceInputs.VFACE, Constants.VFaceVariable}, + }; + + private static Dictionary m_precisionTypeToCg = new Dictionary() + { + {PrecisionType.Float, "float"}, + {PrecisionType.Half, "half"}, + {PrecisionType.Inherit, "float"} + }; + + private static Dictionary m_qualifierToCg = new Dictionary() + { + { VariableQualifiers.In, string.Empty}, + {VariableQualifiers.Out, "out"}, + {VariableQualifiers.InOut, "inout"} + }; + + private static Dictionary m_precisionWirePortToCgType = new Dictionary() + { + {WirePortDataType.FLOAT, "{0}"}, + {WirePortDataType.FLOAT2, "{0}2"}, + {WirePortDataType.FLOAT3, "{0}3"}, + {WirePortDataType.FLOAT4, "{0}4"}, + {WirePortDataType.FLOAT3x3, "{0}3x3"}, + {WirePortDataType.FLOAT4x4, "{0}4x4"}, + {WirePortDataType.COLOR, "{0}4"}, + {WirePortDataType.INT, "int"}, + {WirePortDataType.SAMPLER1D, "sampler1D"}, + {WirePortDataType.SAMPLER2D, "sampler2D"}, + {WirePortDataType.SAMPLER3D, "sampler3D"}, + {WirePortDataType.SAMPLERCUBE, "samplerCUBE"}, + {WirePortDataType.SAMPLER2DARRAY, "sampler2DArray"}, + {WirePortDataType.SAMPLERSTATE, "SamplerState"} + }; + + private static Dictionary m_precisionWirePortToStandardMacroType = new Dictionary() + { + {WirePortDataType.FLOAT, "{0}"}, + {WirePortDataType.FLOAT2, "{0}2"}, + {WirePortDataType.FLOAT3, "{0}3"}, + {WirePortDataType.FLOAT4, "{0}4"}, + {WirePortDataType.FLOAT3x3, "{0}3x3"}, + {WirePortDataType.FLOAT4x4, "{0}4x4"}, + {WirePortDataType.COLOR, "{0}4"}, + {WirePortDataType.INT, "int"}, + {WirePortDataType.SAMPLER1D, "sampler1D"}, + {WirePortDataType.SAMPLER2D, "UNITY_DECLARE_TEX2D_NOSAMPLER("}, + {WirePortDataType.SAMPLER3D, "UNITY_DECLARE_TEX3D_NOSAMPLER("}, + {WirePortDataType.SAMPLERCUBE, "UNITY_DECLARE_TEXCUBE_NOSAMPLER("}, + {WirePortDataType.SAMPLER2DARRAY, "UNITY_DECLARE_TEX2DARRAY_NOSAMPLER("}, + {WirePortDataType.SAMPLERSTATE, "SamplerState"} + }; + + private static Dictionary m_precisionWirePortToSRPMacroType = new Dictionary() + { + {WirePortDataType.FLOAT, "{0}"}, + {WirePortDataType.FLOAT2, "{0}2"}, + {WirePortDataType.FLOAT3, "{0}3"}, + {WirePortDataType.FLOAT4, "{0}4"}, + {WirePortDataType.FLOAT3x3, "{0}3x3"}, + {WirePortDataType.FLOAT4x4, "{0}4x4"}, + {WirePortDataType.COLOR, "{0}4"}, + {WirePortDataType.INT, "int"}, + {WirePortDataType.SAMPLER1D, "sampler1D"}, + {WirePortDataType.SAMPLER2D, "TEXTURE2D("}, + {WirePortDataType.SAMPLER3D, "TEXTURE3D("}, + {WirePortDataType.SAMPLERCUBE, "TEXTURECUBE("}, + {WirePortDataType.SAMPLER2DARRAY, "TEXTURE2D_ARRAY("}, + {WirePortDataType.SAMPLERSTATE, "SamplerState"} + }; + + private static Dictionary m_wirePortToCgType = new Dictionary() + { + { WirePortDataType.FLOAT, "float"}, + {WirePortDataType.FLOAT2, "float2"}, + {WirePortDataType.FLOAT3, "float3"}, + {WirePortDataType.FLOAT4, "float4"}, + {WirePortDataType.FLOAT3x3, "float3x3"}, + {WirePortDataType.FLOAT4x4, "float4x4"}, + {WirePortDataType.COLOR, "float4"}, + {WirePortDataType.INT, "int"}, + {WirePortDataType.SAMPLER1D, "sampler1D"}, + {WirePortDataType.SAMPLER2D, "sampler2D"}, + {WirePortDataType.SAMPLER3D, "sampler3D"}, + {WirePortDataType.SAMPLERCUBE, "samplerCUBE"}, + {WirePortDataType.SAMPLER2DARRAY, "sampler2DArray"}, + {WirePortDataType.UINT, "uint"}, + {WirePortDataType.UINT4, "uint4"}, + {WirePortDataType.SAMPLERSTATE, "SamplerState"} + }; + + private static Dictionary m_keycodeToString = new Dictionary() + { + {KeyCode.Alpha0,"0" }, + {KeyCode.Alpha1,"1" }, + {KeyCode.Alpha2,"2" }, + {KeyCode.Alpha3,"3" }, + {KeyCode.Alpha4,"4" }, + {KeyCode.Alpha5,"5" }, + {KeyCode.Alpha6,"6" }, + {KeyCode.Alpha7,"7" }, + {KeyCode.Alpha8,"8" }, + {KeyCode.Alpha9,"9" } + }; + + private static Dictionary m_wireStatusToColor = new Dictionary() + { + { WireStatus.Default,new Color(0.7f,0.7f,0.7f,1.0f) }, + {WireStatus.Highlighted,Color.yellow }, + {WireStatus.Selected,Color.white} + }; + + private static Dictionary m_autoSwizzle = new Dictionary() + { + {WirePortDataType.FLOAT, ".x"}, + {WirePortDataType.FLOAT2, ".xy"}, + {WirePortDataType.FLOAT3, ".xyz"}, + {WirePortDataType.FLOAT4, ".xyzw"} + }; + + private static Dictionary m_unityNativeShaderPaths = new Dictionary + { + { "Resources/unity_builtin_extra", true }, + { "Library/unity default resources", true } + }; + + private static Dictionary m_portPriority = new Dictionary() + { + {WirePortDataType.OBJECT, 0}, + {WirePortDataType.SAMPLERSTATE, 0}, + {WirePortDataType.SAMPLER1D, 0}, + {WirePortDataType.SAMPLER2D, 0}, + {WirePortDataType.SAMPLER3D, 0}, + {WirePortDataType.SAMPLERCUBE, 0}, + {WirePortDataType.SAMPLER2DARRAY, 0}, + {WirePortDataType.FLOAT3x3, 1}, + {WirePortDataType.FLOAT4x4, 2}, + {WirePortDataType.INT, 3}, + {WirePortDataType.UINT, 3}, + {WirePortDataType.FLOAT, 4}, + {WirePortDataType.FLOAT2, 5}, + {WirePortDataType.FLOAT3, 6}, + {WirePortDataType.FLOAT4, 7}, + {WirePortDataType.COLOR, 7} + }; + + private static readonly string IncorrectInputConnectionErrorMsg = "Input Port {0} from node {1} has type {2}\nwhich is incompatible with connection of type {3} from port {4} on node {5}"; + private static readonly string IncorrectOutputConnectionErrorMsg = "Output Port {0} from node {1} has type {2}\nwhich is incompatible with connection of type {3} from port {4} on node {5}"; + private static readonly string NoVertexModeNodeWarning = "{0} is unable to generate code in vertex function"; + + private static float SwitchFixedHeight; + private static float SwitchFontSize; + private static RectOffset SwitchNodeBorder; + private static RectOffset SwitchNodeMargin; + private static RectOffset SwitchNodeOverflow; + private static RectOffset SwitchNodePadding; + + private static RenderTexture m_dummyPreviewRT; + public static void ForceExampleShaderCompilation() + { + CurrentWindow.ForceMaterialsToUpdate( ref m_exampleMaterialIDs ); + + } + + public static void Destroy() + { + if( IOUtils.AllOpenedWindows != null && IOUtils.AllOpenedWindows.Count > 0 ) + { + return; + } + else + { + IOUtils.AllOpenedWindows.Clear(); + } + + Initialized = false; + + if( m_dummyPreviewRT != null ) + m_dummyPreviewRT.Release(); + + ScriptableObject.DestroyImmediate( m_dummyPreviewRT ); + + m_dummyPreviewRT = null; + PlusStyle = null; + MinusStyle = null; + m_textInfo = null; + RangedFloatSliderStyle = null; + RangedFloatSliderThumbStyle = null; + PropertyPopUp = null; + ObjectField = null; + PreviewExpander = null; + PreviewCollapser = null; + MenuItemToggleStyle = null; + MenuItemEnableStyle = null; + MenuItemBackgroundStyle = null; + MenuItemToolbarStyle = null; + MenuItemInspectorDropdownStyle = null; + ObjectFieldThumb = null; + ObjectFieldThumbOverlay = null; + InspectorPopdropdownStyle = null; + InspectorPopdropdownFallback = null; + TooltipBox = null; + UnZoomedNodeTitleStyle = null; + UnZoomedPropertyValuesTitleStyle = null; + UnZoomedInputPortStyle = null; + UnZoomedOutputPortPortStyle = null; + ToolbarSearchTextfield = null; + ToolbarSearchCancelButton = null; + FloatIntPickerONOFF = null; + Box = null; + Button = null; + TextArea = null; + Label = null; + Toggle = null; + Textfield = null; + + CommentaryTitle = null; + StickyNoteText = null; + InputPortLabel = null; + OutputPortLabel = null; + + IntShader = null; + FloatShader = null; + Vector2Shader = null; + Vector3Shader = null; + Vector4Shader = null; + ColorShader = null; + Texture2DShader = null; + + MaskingShader = null; + + BoldErrorStyle = null; + BoldWarningStyle = null; + BoldInfoStyle = null; + Separator = null; + ToolbarMainTitle = null; + + GraphButtonIcon = null; + GraphButton = null; + GraphDropDown = null; + + ConsoleLogLabel = null; + ConsoleLogMessage = null; + ConsoleLogCircle = null; + + MiniButtonTopLeft = null; + MiniButtonTopMid = null; + MiniButtonTopRight = null; + + NodeWindowOffSquare = null; + NodeHeaderSquare = null; + NodeWindowOnSquare = null; + InternalDataOnPort = null; + InternalDataBackground = null; + + MiniObjectFieldThumbOverlay = null; + MiniSamplerButton = null; + + Resources.UnloadAsset( SmallErrorIcon ); + SmallErrorIcon = null; + + Resources.UnloadAsset( SmallWarningIcon ); + SmallWarningIcon = null; + + Resources.UnloadAsset( SmallInfoIcon ); + SmallInfoIcon = null; + + LockIconOpen = null; + LockIconClosed = null; + + FloatIntIconON = null; + FloatIntIconOFF = null; + + Resources.UnloadAsset( CheckmarkIcon ); + CheckmarkIcon = null; + + Resources.UnloadAsset( PopupIcon ); + PopupIcon = null; + + Resources.UnloadAsset( MasterNodeOnTexture ); + MasterNodeOnTexture = null; + + Resources.UnloadAsset( MasterNodeOffTexture ); + MasterNodeOffTexture = null; + + Resources.UnloadAsset( GPUInstancedOnTexture ); + GPUInstancedOnTexture = null; + + Resources.UnloadAsset( GPUInstancedOffTexture ); + GPUInstancedOffTexture = null; + + MainSkin = null; + + if( LinearMaterial != null ) + GameObject.DestroyImmediate( LinearMaterial ); + + LinearMaterial = null; + + if( m_undoHelper == null ) + { + m_undoHelper.Clear(); + m_undoHelper = null; + } + ASEMaterialInspector.Instance = null; + } + + public static void ResetMainSkin() + { + if( (object)MainSkin != null ) + { + CurrentHeaderHeight = HeaderMaxHeight; + ScaledPortsDelta = PortsDelta; + MainSkin.textField.fontSize = (int)( Constants.TextFieldFontSize ); + MainSkin.label.fontSize = (int)( Constants.DefaultFontSize ); + MainSkin.customStyles[ (int)CustomStyle.NodeTitle ].fontSize = (int)( Constants.DefaultTitleFontSize ); + + InputPortLabel.fontSize = (int)( Constants.DefaultFontSize ); + OutputPortLabel.fontSize = (int)( Constants.DefaultFontSize ); + CommentaryTitle.fontSize = (int)( Constants.DefaultFontSize ); + StickyNoteText.fontSize = (int)( Constants.DefaultFontSize ); + } + } + + public static void InitMainSkin() + { + MainSkin = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( IOUtils.MainSkinGUID ) , typeof( GUISkin ) ) as GUISkin; + Initialized = true; + Texture2D portTex = GetCustomStyle( CustomStyle.PortEmptyIcon ).normal.background; + PortsSize = new Vector2( portTex.width , portTex.height ); + PortsDelta = new Vector3( 0.5f * PortsSize.x , 0.5f * PortsSize.y ); + HeaderMaxHeight = MainSkin.customStyles[ (int)CustomStyle.NodeHeader ].normal.background.height; + + RectOffsetZero = new RectOffset( 0 , 0 , 0 , 0 ); + RectOffsetOne = new RectOffset( 1 , 1 , 1 , 1 ); + RectOffsetTwo = new RectOffset( 2 , 2 , 2 , 2 ); + RectOffsetThree = new RectOffset( 3 , 3 , 3 , 3 ); + RectOffsetFour = new RectOffset( 4 , 4 , 4 , 4 ); + RectOffsetFive = new RectOffset( 5 , 5 , 5 , 5 ); + RectOffsetSix = new RectOffset( 6 , 6 , 6 , 6 ); + + PropertyPopUp = GetCustomStyle( CustomStyle.NodePropertyPicker ); + ObjectField = new GUIStyle( (GUIStyle)"ObjectField" ); + PreviewExpander = GetCustomStyle( CustomStyle.NodePreviewExpander ); + PreviewCollapser = GetCustomStyle( CustomStyle.NodePreviewCollapser ); + + WireNodeSelection = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "bfe0b03d5d60cea4f9d4b2d1d121e592" ) , typeof( Texture2D ) ) as Texture2D; + SliderButton = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "dd563e33152bb6443b099b4139ceecb9" ) , typeof( Texture2D ) ) as Texture2D; + + SmallErrorIcon = EditorGUIUtility.Load( "icons/d_console.erroricon.sml.png" ) as Texture2D; + SmallWarningIcon = EditorGUIUtility.Load( "icons/d_console.warnicon.sml.png" ) as Texture2D; + SmallInfoIcon = EditorGUIUtility.Load( "icons/d_console.infoicon.sml.png" ) as Texture2D; + + LockIconOpen = new GUIContent( EditorGUIUtility.IconContent( "LockIcon-On" ) ); + LockIconOpen.tooltip = "Click to unlock and customize the variable name"; + LockIconClosed = new GUIContent( EditorGUIUtility.IconContent( "LockIcon" ) ); + LockIconClosed.tooltip = "Click to lock and auto-generate the variable name"; + + if( UsingProSkin ) + { + FloatIntIconON = new GUIContent( EditorGUIUtility.IconContent( "CircularToggle_ON" ) ); + FloatIntIconOFF = new GUIContent( EditorGUIUtility.IconContent( "CircularToggle_OFF" ) ); + } + else + { + FloatIntIconON = new GUIContent( ( AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "ac0860a6a77e29d4091ba790a17daa0f" ) , typeof( Texture2D ) ) as Texture2D ) ); + FloatIntIconOFF = new GUIContent( ( AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "1aaca50d084b0bb43854f075ce2f302b" ) , typeof( Texture2D ) ) as Texture2D ) ); + } + + CommentaryTitle = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.CommentaryTitle ] ); + StickyNoteText = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.CommentaryTitle ] ); + StickyNoteText.wordWrap = true; + StickyNoteText.alignment = TextAnchor.UpperLeft; + InputPortLabel = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.InputPortlabel ] ); + OutputPortLabel = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.OutputPortLabel ] ); + + CheckmarkIcon = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "e9c4642eaa083a54ab91406d8449e6ac" ) , typeof( Texture2D ) ) as Texture2D; + PopupIcon = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "d2384a227b4ac4943b73c8151393e502" ) , typeof( Texture2D ) ) as Texture2D; + + BoldErrorStyle = new GUIStyle( (GUIStyle)"BoldLabel" ); + BoldErrorStyle.normal.textColor = Color.red; + BoldErrorStyle.alignment = TextAnchor.MiddleCenter; + BoldWarningStyle = new GUIStyle( (GUIStyle)"BoldLabel" ); + BoldWarningStyle.normal.textColor = Color.yellow; + BoldWarningStyle.alignment = TextAnchor.MiddleCenter; + BoldInfoStyle = new GUIStyle( (GUIStyle)"BoldLabel" ); + BoldInfoStyle.normal.textColor = Color.white; + BoldInfoStyle.alignment = TextAnchor.MiddleCenter; + + ToolbarMainTitle = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.MainCanvasTitle ] ); + Separator = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.FlatBackground ] ); + MiniButtonTopLeft = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.MiniButtonTopLeft ] ); + MiniButtonTopMid = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.MiniButtonTopMid ] ); + MiniButtonTopRight = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.MiniButtonTopRight ] ); + + InternalDataOnPort = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.NodeTitle ] ); + InternalDataOnPort.fontSize = 8; + InternalDataOnPort.fontStyle = FontStyle.BoldAndItalic; + InternalDataBackground = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.NodeWindowOffSquare ] ); + InternalDataBackground.normal.background = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "330fd0c8f074a3c4f8042114a61a73d9" ) , typeof( Texture2D ) ) as Texture2D; + InternalDataBackground.overflow = RectOffsetOne; + + MiniObjectFieldThumbOverlay = new GUIStyle( (GUIStyle)"ObjectFieldThumbOverlay" ); + MiniSamplerButton = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.SamplerButton ] ); + + m_textInfo = new System.Globalization.CultureInfo( "en-US" , false ).TextInfo; + RangedFloatSliderStyle = new GUIStyle( GUI.skin.horizontalSlider ); + RangedFloatSliderThumbStyle = new GUIStyle( GUI.skin.horizontalSliderThumb ); + RangedFloatSliderThumbStyle.normal.background = SliderButton; + RangedFloatSliderThumbStyle.active.background = null; + RangedFloatSliderThumbStyle.hover.background = null; + RangedFloatSliderThumbStyle.focused.background = null; + RangedFloatSliderThumbStyle.overflow = new RectOffset( 1 , 1 , -4 , 4 ); + RangedFloatSliderThumbStyle.margin = RectOffsetZero; + + SwitchNodePopUp = new GUIStyle( (GUIStyle)"Popup" ); + // RectOffset cannot be initiliazed on constructor + SwitchNodeBorder = new RectOffset( 4 , 15 , 3 , 3 ); + SwitchNodeMargin = new RectOffset( 4 , 4 , 3 , 3 ); + SwitchNodeOverflow = new RectOffset( 0 , 0 , -1 , 2 ); + SwitchNodePadding = new RectOffset( 6 , 14 , 2 , 3 ); + SwitchFixedHeight = 18; + SwitchFontSize = 10; + + GraphButtonIcon = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.GraphButtonIcon ] ); + GraphButton = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.GraphButton ] ); + GraphDropDown = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.GraphButton ] ); + GraphDropDown.padding.right = 20; + + Box = new GUIStyle( MainSkin.box ); + Button = new GUIStyle( GUI.skin.button ); + TextArea = new GUIStyle( GUI.skin.textArea ); + Label = new GUIStyle( GUI.skin.label ); + Toggle = new GUIStyle( GUI.skin.toggle ); + Textfield = new GUIStyle( GUI.skin.textField ); + //ShaderIcon = EditorGUIUtility.IconContent( "Shader Icon" ).image; + //MaterialIcon = EditorGUIUtility.IconContent( "Material Icon" ).image; + + ConsoleLogLabel = new GUIStyle( GUI.skin.label ); + ConsoleLogMessage = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.ConsoleLogMessage ] ); + ConsoleLogCircle = new GUIStyle( MainSkin.customStyles[ (int)CustomStyle.ConsoleLogCircle ] ); + + NodeWindowOffSquare = GetCustomStyle( CustomStyle.NodeWindowOffSquare ); + NodeHeaderSquare = GetCustomStyle( CustomStyle.NodeHeaderSquare ); + NodeWindowOnSquare = GetCustomStyle( CustomStyle.NodeWindowOnSquare ); + + UnZoomedNodeTitleStyle = new GUIStyle( GetCustomStyle( CustomStyle.NodeTitle ) ); + UnZoomedNodeTitleStyle.fontSize = 13; + + UnZoomedPropertyValuesTitleStyle = new GUIStyle( GetCustomStyle( CustomStyle.PropertyValuesTitle ) ); + UnZoomedPropertyValuesTitleStyle.fontSize = 11; + + UnZoomedInputPortStyle = new GUIStyle( InputPortLabel ); + UnZoomedInputPortStyle.fontSize = (int)Constants.DefaultFontSize; + + UnZoomedOutputPortPortStyle = new GUIStyle( OutputPortLabel ); + UnZoomedOutputPortPortStyle.fontSize = (int)Constants.DefaultFontSize; + + ObjectFieldThumb = new GUIStyle( (GUIStyle)"ObjectFieldThumb" ); + ObjectFieldThumbOverlay = new GUIStyle( (GUIStyle)"ObjectFieldThumbOverlay" ); + + FloatIntPickerONOFF = new GUIStyle( "metimelabel" ); + FloatIntPickerONOFF.padding.left = -2; + FloatIntPickerONOFF.margin = new RectOffset( 0 , 2 , 2 , 2 ); + + TooltipBox = new GUIStyle( (GUIStyle)"Tooltip" ); + TooltipBox.richText = true; + + MasterNodeOnTexture = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( IOUtils.MasterNodeOnTextureGUID ) ); + MasterNodeOffTexture = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( IOUtils.MasterNodeOnTextureGUID ) ); + + GPUInstancedOnTexture = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( IOUtils.GPUInstancedOnTextureGUID ) ); + GPUInstancedOffTexture = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( IOUtils.GPUInstancedOffTextureGUID ) ); + + CheckNullMaterials(); + + UsingProSkin = EditorGUIUtility.isProSkin; + FetchMenuItemStyles(); + } + + public static bool IsLoading + { + get { return CurrentWindow.OutsideGraph.IsLoading; } + } + + public static void CheckNullMaterials() + { + if( LinearMaterial == null ) + { + Shader linearShader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "e90ef6ea05743b84baf9549874c52e47" ) ); //linear previews + LinearMaterial = new Material( linearShader ); + } + + if( IntShader == null ) + IntShader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "0f64d695b6ffacc469f2dd31432a232a" ) ); //int + if( FloatShader == null ) + FloatShader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "d9ca47581ac157145bff6f72ac5dd73e" ) ); //ranged float + if( Vector2Shader == null ) + Vector2Shader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "88b4191eb06084d4da85d1dd2f984085" ) ); //vector2 + if( Vector3Shader == null ) + Vector3Shader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "8a44d38f06246bf48944b3f314bc7920" ) ); //vector3 + if( Vector4Shader == null ) + Vector4Shader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "aac241d0e47a5a84fbd2edcd640788dc" ) ); //vector4 + if( ColorShader == null ) + ColorShader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "6cf365ccc7ae776488ae8960d6d134c3" ) ); //color node + if( MaskingShader == null ) + MaskingShader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "9c34f18ebe2be3e48b201b748c73dec0" ) ); //masking shader + if( Texture2DShader == null ) + Texture2DShader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "13bd295c44d04e1419f20f792d331e33" ) ); //texture2d shader + } + + private static void FetchMenuItemStyles() + { + ObjectFieldThumb = new GUIStyle( (GUIStyle)"ObjectFieldThumb" ); + ObjectFieldThumbOverlay = new GUIStyle( (GUIStyle)"ObjectFieldThumbOverlay" ); + MenuItemToggleStyle = new GUIStyle( (GUIStyle)"foldout" ); + MenuItemEnableStyle = UsingProSkin ? new GUIStyle( (GUIStyle)"OL ToggleWhite" ) : new GUIStyle( (GUIStyle)"OL Toggle" ); + MenuItemBackgroundStyle = new GUIStyle( (GUIStyle)"TE NodeBackground" ); + MenuItemToolbarStyle = new GUIStyle( (GUIStyle)"toolbarbutton" ) { fixedHeight = 20 }; + MenuItemInspectorDropdownStyle = new GUIStyle( (GUIStyle)"toolbardropdown" ) { fixedHeight = 20 }; + MenuItemInspectorDropdownStyle.margin.bottom = 2; + + + InspectorPopdropdownStyle = new GUIStyle( GUI.skin.GetStyle( "PopupCurveDropdown" ) ); + InspectorPopdropdownStyle.alignment = TextAnchor.MiddleRight; + InspectorPopdropdownStyle.border.bottom = 16; + + InspectorPopdropdownFallback = new GUIStyle( InspectorPopdropdownStyle ); + InspectorPopdropdownFallback.overflow = new RectOffset( 0 , -5 , 0 , 0 ); + + PlusStyle = ( EditorGUIUtility.isProSkin ) ? new GUIStyle( GetCustomStyle( CustomStyle.CustomExpressionAddItem ) ) : new GUIStyle( (GUIStyle)"OL Plus" ); + PlusStyle.imagePosition = ImagePosition.ImageOnly; + PlusStyle.overflow = new RectOffset( -2 , 0 , -4 , 0 ); + + MinusStyle = ( EditorGUIUtility.isProSkin ) ? new GUIStyle( GetCustomStyle( CustomStyle.CustomExpressionRemoveItem ) ) : new GUIStyle( (GUIStyle)"OL Minus" ); + MinusStyle.contentOffset = Vector2.zero; + MinusStyle.imagePosition = ImagePosition.ImageOnly; + MinusStyle.overflow = new RectOffset( -2 , 0 , -4 , 0 ); + + ToolbarSearchTextfield = new GUIStyle( (GUIStyle)"ToolbarSeachTextField" ); + ToolbarSearchCancelButton = new GUIStyle( (GUIStyle)"ToolbarSeachCancelButton" ); + } + + public static void UpdateMainSkin( DrawInfo drawInfo ) + { + CurrentHeaderHeight = HeaderMaxHeight * drawInfo.InvertedZoom; + ScaledPortsDelta = drawInfo.InvertedZoom * PortsDelta; + MainSkin.textField.fontSize = (int)( Constants.TextFieldFontSize * drawInfo.InvertedZoom ); + MainSkin.label.fontSize = (int)( Constants.DefaultFontSize * drawInfo.InvertedZoom ); + + MainSkin.customStyles[ (int)CustomStyle.NodeTitle ].fontSize = (int)( Constants.DefaultTitleFontSize * drawInfo.InvertedZoom ); + MainSkin.customStyles[ (int)CustomStyle.PropertyValuesTitle ].fontSize = (int)( Constants.PropertiesTitleFontSize * drawInfo.InvertedZoom ); + + InputPortLabel.fontSize = (int)( Constants.DefaultFontSize * drawInfo.InvertedZoom ); + OutputPortLabel.fontSize = (int)( Constants.DefaultFontSize * drawInfo.InvertedZoom ); + CommentaryTitle.fontSize = (int)( Constants.DefaultFontSize * drawInfo.InvertedZoom ); + StickyNoteText.fontSize = (int)( Constants.DefaultFontSize * drawInfo.InvertedZoom ); + + RangedFloatSliderStyle.fixedHeight = 18 * drawInfo.InvertedZoom; + RangedFloatSliderThumbStyle.fixedHeight = 12 * drawInfo.InvertedZoom; + RangedFloatSliderThumbStyle.fixedWidth = 10 * drawInfo.InvertedZoom; + RangedFloatSliderThumbStyle.overflow.left = (int)( 1 * drawInfo.InvertedZoom ); + RangedFloatSliderThumbStyle.overflow.right = (int)( 1 * drawInfo.InvertedZoom ); + RangedFloatSliderThumbStyle.overflow.top = (int)( -4 * drawInfo.InvertedZoom ); + RangedFloatSliderThumbStyle.overflow.bottom = (int)( 4 * drawInfo.InvertedZoom ); + + SwitchNodePopUp.fixedHeight = SwitchFixedHeight * drawInfo.InvertedZoom; + + SwitchNodePopUp.border.left = (int)( SwitchNodeBorder.left * drawInfo.InvertedZoom ); + SwitchNodePopUp.border.right = (int)( SwitchNodeBorder.right * drawInfo.InvertedZoom ); + SwitchNodePopUp.border.top = (int)( SwitchNodeBorder.top * drawInfo.InvertedZoom ); + SwitchNodePopUp.border.bottom = (int)( SwitchNodeBorder.bottom * drawInfo.InvertedZoom ); + + SwitchNodePopUp.margin.left = (int)( SwitchNodeMargin.left * drawInfo.InvertedZoom ); + SwitchNodePopUp.margin.right = (int)( SwitchNodeMargin.right * drawInfo.InvertedZoom ); + SwitchNodePopUp.margin.top = (int)( SwitchNodeMargin.top * drawInfo.InvertedZoom ); + SwitchNodePopUp.margin.bottom = (int)( SwitchNodeMargin.bottom * drawInfo.InvertedZoom ); + + SwitchNodePopUp.overflow.left = (int)( SwitchNodeOverflow.left * drawInfo.InvertedZoom ); + SwitchNodePopUp.overflow.right = (int)( SwitchNodeOverflow.right * drawInfo.InvertedZoom ); + SwitchNodePopUp.overflow.top = (int)( SwitchNodeOverflow.top * drawInfo.InvertedZoom ); + SwitchNodePopUp.overflow.bottom = (int)( SwitchNodeOverflow.bottom * drawInfo.InvertedZoom ); + + SwitchNodePopUp.padding.left = (int)( SwitchNodePadding.left * drawInfo.InvertedZoom ); + SwitchNodePopUp.padding.right = (int)( SwitchNodePadding.right * drawInfo.InvertedZoom ); + SwitchNodePopUp.padding.top = (int)( SwitchNodePadding.top * drawInfo.InvertedZoom ); + SwitchNodePopUp.padding.bottom = (int)( SwitchNodePadding.bottom * drawInfo.InvertedZoom ); + + SwitchNodePopUp.fontSize = (int)( SwitchFontSize * drawInfo.InvertedZoom ); + + BoldErrorStyle.fontSize = (int)( 12 * drawInfo.InvertedZoom ); + BoldWarningStyle.fontSize = (int)( 12 * drawInfo.InvertedZoom ); + BoldInfoStyle.fontSize = (int)( 12 * drawInfo.InvertedZoom ); + + PropertyPopUp.fixedHeight = Constants.PropertyPickerHeight * drawInfo.InvertedZoom; + PropertyPopUp.fixedWidth = Constants.PropertyPickerWidth * drawInfo.InvertedZoom; + if( UsingProSkin != EditorGUIUtility.isProSkin ) + { + UsingProSkin = EditorGUIUtility.isProSkin; + FetchMenuItemStyles(); + } + + GraphDropDown.padding.left = (int)( 2 * drawInfo.InvertedZoom + 2 ); + GraphDropDown.padding.right = (int)( 20 * drawInfo.InvertedZoom ); + GraphDropDown.fontSize = (int)( 10 * drawInfo.InvertedZoom ); + + PreviewExpander.fixedHeight = Constants.PreviewExpanderHeight * drawInfo.InvertedZoom; + PreviewExpander.fixedWidth = Constants.PreviewExpanderWidth * drawInfo.InvertedZoom; + + PreviewCollapser.fixedHeight = Constants.PreviewExpanderHeight * drawInfo.InvertedZoom; + PreviewCollapser.fixedWidth = Constants.PreviewExpanderWidth * drawInfo.InvertedZoom; + + MainSkin.customStyles[ (int)CustomStyle.SamplerButton ].fontSize = (int)( 9 * drawInfo.InvertedZoom ); + ObjectFieldThumbOverlay.fontSize = (int)( 9 * drawInfo.InvertedZoom ); + MiniButtonTopLeft.fontSize = (int)( 9 * drawInfo.InvertedZoom ); + MiniButtonTopMid.fontSize = (int)( 9 * drawInfo.InvertedZoom ); + MiniButtonTopRight.fontSize = (int)( 9 * drawInfo.InvertedZoom ); + + MiniObjectFieldThumbOverlay.fontSize = (int)( 7 * drawInfo.InvertedZoom ); + MiniSamplerButton.fontSize = (int)( 8 * drawInfo.InvertedZoom ); + + InternalDataOnPort.fontSize = (int)( 8 * drawInfo.InvertedZoom ); + ToolbarMainTitle.padding.left = 0; + ToolbarMainTitle.padding.right = 0; + + CheckNullMaterials(); + } + + public static void CacheLabelVars() + { + m_alignment = GUI.skin.label.alignment; + m_clipping = GUI.skin.label.clipping; + m_wordWrap = GUI.skin.label.wordWrap; + m_fontSize = GUI.skin.label.fontSize; + m_fontStyle = GUI.skin.label.fontStyle; + m_fontColor = GUI.skin.label.normal.textColor; + } + + public static void RestoreLabelVars() + { + GUI.skin.label.alignment = m_alignment; + GUI.skin.label.clipping = m_clipping; + GUI.skin.label.wordWrap = m_wordWrap; + GUI.skin.label.fontSize = m_fontSize; + GUI.skin.label.fontStyle = m_fontStyle; + GUI.skin.label.normal.textColor = m_fontColor; + } + + public static string GetTooltipForToolButton( ToolButtonType toolButtonType , int state ) { return m_toolButtonTooltips[ toolButtonType ][ state ]; } + + public static string KeyCodeToString( KeyCode keyCode ) + { + if( m_keycodeToString.ContainsKey( keyCode ) ) + return m_keycodeToString[ keyCode ]; + + return keyCode.ToString(); + } + + public static string TextureTypeToCgType( TextureType type ) { return m_textureTypeToCgType[ type ]; } + + public static string QualifierToCg( VariableQualifiers qualifier ) + { + return m_qualifierToCg[ qualifier ]; + } + + public static string WirePortToCgType( WirePortDataType type ) + { + if( type == WirePortDataType.OBJECT ) + return string.Empty; + + return m_wirePortToCgType[ type ]; + } + + public static string FinalPrecisionWirePortToCgType( PrecisionType precisionType , WirePortDataType type ) + { + return PrecisionWirePortToCgType( precisionType , type ); + } + + public static string PrecisionWirePortToCgType( PrecisionType precisionType , WirePortDataType type ) + { + if( type == WirePortDataType.OBJECT ) + return string.Empty; + + if( type == WirePortDataType.INT ) + return m_wirePortToCgType[ type ]; + + if( type == WirePortDataType.UINT ) + return m_wirePortToCgType[ type ]; + + if( type == WirePortDataType.UINT4 ) + return m_wirePortToCgType[ type ]; + + return string.Format( m_precisionWirePortToCgType[ type ] , m_precisionTypeToCg[ precisionType ] ); + } + + public static string PrecisionWirePortToTypeValue( PrecisionType precisionType , WirePortDataType type , string varName/*, bool isSRP, bool samplingMacro*/ ) + { + string result = string.Empty; + string varType = string.Empty; + if( type == WirePortDataType.OBJECT ) + varType = string.Empty; + + if( type == WirePortDataType.INT ) + varType = m_wirePortToCgType[ type ]; + + if( type == WirePortDataType.UINT ) + varType = m_wirePortToCgType[ type ]; + + switch( type ) + { + default: + case WirePortDataType.OBJECT: + case WirePortDataType.SAMPLERSTATE: + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + case WirePortDataType.COLOR: + case WirePortDataType.UINT: + case WirePortDataType.INT: + case WirePortDataType.SAMPLER1D: + varType = string.Format( m_precisionWirePortToCgType[ type ] , m_precisionTypeToCg[ precisionType ] ); + result = varType + " " + varName; + break; + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + ParentGraph outsideGraph = UIUtils.CurrentWindow.OutsideGraph; + if( outsideGraph.SamplingMacros /*&& !outsideGraph.IsStandardSurface*/ ) + { + if( outsideGraph.IsSRP ) + varType = string.Format( m_precisionWirePortToSRPMacroType[ type ] , m_precisionTypeToCg[ precisionType ] ); + else + varType = string.Format( m_precisionWirePortToStandardMacroType[ type ] , m_precisionTypeToCg[ precisionType ] ); + result = varType + varName + ")"; + } + else + { + varType = string.Format( m_precisionWirePortToCgType[ type ] , m_precisionTypeToCg[ precisionType ] ); + result = varType + " " + varName; + } + break; + } + + return result; + } + + public static string GetAutoSwizzle( WirePortDataType type ) + { + return m_autoSwizzle[ type ]; + } + + public static Color GetColorForDataType( WirePortDataType dataType , bool monochromeMode = true , bool isInput = true ) + { + if( monochromeMode ) + { + return isInput ? m_dataTypeToColorMonoMode[ 0 ] : m_dataTypeToColorMonoMode[ 1 ]; + } + else + { + if( m_dataTypeToColor.ContainsKey( dataType ) ) + return m_dataTypeToColor[ dataType ]; + } + return m_dataTypeToColor[ WirePortDataType.OBJECT ]; + } + + public static bool IsValidType( WirePortDataType type ) + { + switch( type ) + { + case WirePortDataType.OBJECT: + case WirePortDataType.SAMPLERSTATE: + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + case WirePortDataType.COLOR: + case WirePortDataType.INT: + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + return true; + } + return false; + } + public static string GetNameForDataType( WirePortDataType dataType ) { return m_dataTypeToName[ dataType ]; } + + public static string GetInputDeclarationFromType( PrecisionType precision , SurfaceInputs inputType ) + { + string precisionStr = m_precisionTypeToCg[ precision ]; + return string.Format( m_inputTypeDeclaration[ inputType ] , precisionStr ); + } + + public static string GetInputValueFromType( SurfaceInputs inputType ) { return m_inputTypeName[ inputType ]; } + private static string CreateLocalValueName( PrecisionType precision , WirePortDataType dataType , string localOutputValue , string value ) { return string.Format( Constants.LocalValueDecWithoutIdent , PrecisionWirePortToCgType( precision , dataType ) , localOutputValue , value ); } + + public static string CastPortType( ref MasterNodeDataCollector dataCollector , PrecisionType nodePrecision , NodeCastInfo castInfo , object value , WirePortDataType oldType , WirePortDataType newType , string parameterName = null ) + { + if( oldType == newType || newType == WirePortDataType.OBJECT ) + { + return ( parameterName != null ) ? parameterName : value.ToString(); + } + + PrecisionType currentPrecision = nodePrecision; + string precisionStr = m_precisionTypeToCg[ currentPrecision ]; + string newTypeStr = m_wirePortToCgType[ newType ]; + newTypeStr = m_textInfo.ToTitleCase( newTypeStr ); + int castId = ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation ) ? dataCollector.AvailableVertexTempId : dataCollector.AvailableFragTempId; + string localVarName = "temp_cast_" + castId;//m_wirePortToCgType[ oldType ] + "To" + newTypeStr + "_" + castInfo.ToString(); + string result = string.Empty; + bool useRealValue = ( parameterName == null ); + + switch( oldType ) + { + case WirePortDataType.FLOAT: + { + switch( newType ) + { + case WirePortDataType.OBJECT: result = useRealValue ? value.ToString() : parameterName; break; + case WirePortDataType.FLOAT2: + { + string localVal = CreateLocalValueName( currentPrecision , newType , localVarName , string.Format( Constants.CastHelper , ( ( useRealValue ) ? value.ToString() : parameterName ) , "xx" ) ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory , -1 , localVal ); + result = localVarName; + } + break; + case WirePortDataType.FLOAT3: + { + string localVal = CreateLocalValueName( currentPrecision , newType , localVarName , string.Format( Constants.CastHelper , ( ( useRealValue ) ? value.ToString() : parameterName ) , "xxx" ) ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory , -1 , localVal ); + result = localVarName; + } + break; + case WirePortDataType.COLOR: + { + string localVal = CreateLocalValueName( currentPrecision , newType , localVarName , string.Format( Constants.CastHelper , ( ( useRealValue ) ? value.ToString() : parameterName ) , "xxxx" ) ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory , -1 , localVal ); + result = localVarName; + } + break; + case WirePortDataType.FLOAT4: + { + string localVal = CreateLocalValueName( currentPrecision , newType , localVarName , string.Format( Constants.CastHelper , ( ( useRealValue ) ? value.ToString() : parameterName ) , "xxxx" ) ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory , -1 , localVal ); + result = localVarName; + } + break; + case WirePortDataType.FLOAT3x3: + { + string localVal = CreateLocalValueName( currentPrecision , newType , localVarName , ( ( useRealValue ) ? value.ToString() : parameterName ) ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory , -1 , localVal ); + result = localVarName; + } + break; + case WirePortDataType.FLOAT4x4: + { + string localVal = CreateLocalValueName( currentPrecision , newType , localVarName , ( ( useRealValue ) ? value.ToString() : parameterName ) ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory , -1 , localVal ); + result = localVarName; + } + break; + case WirePortDataType.INT: + { + result = ( useRealValue ) ? ( (int)value ).ToString() : "(int)" + parameterName; + } + break; + case WirePortDataType.UINT: + { + result = ( useRealValue ) ? ( (int)value ).ToString() : "(uint)" + parameterName; + } + break; + } + } + break; + case WirePortDataType.FLOAT2: + { + Vector2 vecVal = useRealValue ? (Vector2)value : Vector2.zero; + switch( newType ) + { + case WirePortDataType.OBJECT: result = useRealValue ? precisionStr + "2( " + vecVal.x + " , " + vecVal.y + " )" : parameterName; break; + case WirePortDataType.FLOAT: + { + result = ( useRealValue ) ? vecVal.x.ToString() : parameterName + ".x"; + } + break; + case WirePortDataType.FLOAT3: + { + result = ( useRealValue ) ? precisionStr + "3( " + vecVal.x + " , " + vecVal.y + " , " + " 0.0 )" : precisionStr + "3( " + parameterName + " , 0.0 )"; + } + break; + case WirePortDataType.COLOR: + case WirePortDataType.FLOAT4: + { + result = ( useRealValue ) ? precisionStr + "4( " + vecVal.x + " , " + vecVal.y + " , " + " 0.0 , 0.0 )" : precisionStr + "4( " + parameterName + ", 0.0 , 0.0 )"; + } + break; + } + } + break; + case WirePortDataType.FLOAT3: + { + Vector3 vecVal = useRealValue ? (Vector3)value : Vector3.zero; + switch( newType ) + { + case WirePortDataType.OBJECT: result = useRealValue ? precisionStr + "3( " + vecVal.x + " , " + vecVal.y + " , " + vecVal.z + " )" : parameterName; break; + case WirePortDataType.FLOAT: + { + result = ( useRealValue ) ? vecVal.x.ToString() : parameterName + ".x"; + } + break; + case WirePortDataType.FLOAT2: + { + result = ( useRealValue ) ? precisionStr + "2( " + vecVal.x + " , " + vecVal.y + " )" : parameterName + ".xy"; + } + break; + case WirePortDataType.COLOR: + case WirePortDataType.FLOAT4: + { + result = ( useRealValue ) ? precisionStr + "4( " + vecVal.x + " , " + vecVal.y + " , " + vecVal.z + " , 0.0 )" : precisionStr + "4( " + parameterName + " , 0.0 )"; + } + break; + //case WirePortDataType.FLOAT3x3: + //{ + // if ( useRealValue ) + // { + // result = precisionStr + "3x3( " + vecVal.x + " , " + vecVal.y + " , " + vecVal.z + " , " + + // vecVal.x + " , " + vecVal.y + " , " + vecVal.z + " , " + + // vecVal.x + " , " + vecVal.y + " , " + vecVal.z + " )"; + // } + // else + // { + // string localVal = CreateLocalValueName( currentPrecision, newType, localVarName, parameterName ); + // CurrentDataCollector.AddToLocalVariables( portCategory, -1, localVal ); + // result = precisionStr + "3x3( " + localVarName + ".x , " + localVarName + ".y , " + localVarName + ".x , " + + // localVarName + ".x , " + localVarName + ".y , " + localVarName + ".y , " + + // localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z )"; + // } + //} + //break; + //case WirePortDataType.FLOAT4x4: + //{ + // if ( useRealValue ) + // { + // result = precisionStr + "4x4( " + vecVal + ".x , " + vecVal + ".y , " + vecVal + ".z , 0 , " + + // vecVal + ".x , " + vecVal + ".y , " + vecVal + ".z , 0 , " + + // vecVal + ".x , " + vecVal + ".y , " + vecVal + ".z , 0 , " + + // vecVal + ".x , " + vecVal + ".y , " + vecVal + ".z , 0 )"; + // } + // else + // { + // string localVal = CreateLocalValueName( currentPrecision, newType, localVarName, parameterName ); + // CurrentDataCollector.AddToLocalVariables( portCategory, -1, localVal ); + // result = precisionStr + "4x4( " + localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z , 0 , " + + // localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z , 0 , " + + // localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z , 0 , " + + // localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z , 0 )"; + // } + //} + //break; + } + } + break; + case WirePortDataType.FLOAT4: + { + Vector4 vecVal = useRealValue ? (Vector4)value : Vector4.zero; + switch( newType ) + { + case WirePortDataType.OBJECT: result = useRealValue ? precisionStr + "4( " + vecVal.x + " , " + vecVal.y + " , " + vecVal.z + " , " + vecVal.w + " )" : parameterName; break; + case WirePortDataType.FLOAT: + { + result = ( useRealValue ) ? vecVal.x.ToString() : parameterName + ".x"; + } + break; + case WirePortDataType.FLOAT2: + { + result = ( useRealValue ) ? precisionStr + "2( " + vecVal.x + " , " + vecVal.y + " )" : parameterName + ".xy"; + } + break; + case WirePortDataType.FLOAT3: + { + result = ( useRealValue ) ? precisionStr + "3( " + vecVal.x + " , " + vecVal.y + " , " + vecVal.z + " )" : parameterName + ".xyz"; + } + break; + //case WirePortDataType.FLOAT4x4: + //{ + // if ( useRealValue ) + // { + // result = precisionStr + "4x4( " + vecVal + ".x , " + vecVal + ".y , " + vecVal + ".z , " + vecVal + ".w , " + + // vecVal + ".x , " + vecVal + ".y , " + vecVal + ".z , " + vecVal + ".w , " + + // vecVal + ".x , " + vecVal + ".y , " + vecVal + ".z , " + vecVal + ".w , " + + // vecVal + ".x , " + vecVal + ".y , " + vecVal + ".z , " + vecVal + ".w )"; + // } + // else + // { + // string localVal = CreateLocalValueName( currentPrecision, newType, localVarName, parameterName ); + // CurrentDataCollector.AddToLocalVariables( portCategory, -1, localVal ); + // result = precisionStr + "4x4( " + localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z , " + localVarName + ".w , " + + // localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z , " + localVarName + ".w , " + + // localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z , " + localVarName + ".w , " + + // localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z , " + localVarName + ".w )"; + // } + //} + //break; + case WirePortDataType.COLOR: + { + result = useRealValue ? precisionStr + "4( " + vecVal.x + " , " + vecVal.y + " , " + vecVal.z + " , " + vecVal.w + " )" : parameterName; + } + break; + } + } + break; + case WirePortDataType.FLOAT3x3: + { + //Matrix4x4 matrixVal = useRealValue ? ( Matrix4x4 ) value : Matrix4x4.identity; + //switch ( newType ) + //{ + // case WirePortDataType.OBJECT: + // case WirePortDataType.FLOAT4x4: + // { + // result = ( useRealValue ) ? precisionStr + "4x4(" + matrixVal.m00 + " , " + matrixVal.m01 + " , " + matrixVal.m02 + " , " + matrixVal.m03 + " , " + + // matrixVal.m10 + " , " + matrixVal.m11 + " , " + matrixVal.m12 + " , " + matrixVal.m10 + " , " + + // matrixVal.m20 + " , " + matrixVal.m21 + " , " + matrixVal.m22 + " , " + matrixVal.m20 + " , " + + // matrixVal.m30 + " , " + matrixVal.m31 + " , " + matrixVal.m32 + " , " + matrixVal.m30 + " )" : precisionStr + "4x4(" + parameterName + ")"; + // } + // break; + //} + } + break; + case WirePortDataType.FLOAT4x4: + { + Matrix4x4 matrixVal = useRealValue ? (Matrix4x4)value : Matrix4x4.identity; + switch( newType ) + { + case WirePortDataType.OBJECT: + { + result = ( useRealValue ) ? precisionStr + "4x4(" + matrixVal.m00 + " , " + matrixVal.m01 + " , " + matrixVal.m02 + " , " + matrixVal.m03 + " , " + + matrixVal.m10 + " , " + matrixVal.m11 + " , " + matrixVal.m12 + " , " + matrixVal.m10 + " , " + + matrixVal.m20 + " , " + matrixVal.m21 + " , " + matrixVal.m22 + " , " + matrixVal.m20 + " , " + + matrixVal.m30 + " , " + matrixVal.m31 + " , " + matrixVal.m32 + " , " + matrixVal.m30 + " )" : parameterName; + } + break; + } + } + break; + case WirePortDataType.COLOR: + { + Color colorValue = ( useRealValue ) ? (Color)value : Color.black; + switch( newType ) + { + case WirePortDataType.OBJECT: result = useRealValue ? precisionStr + "4( " + colorValue.r + " , " + colorValue.g + " , " + colorValue.b + " , " + colorValue.a + " )" : parameterName; break; + case WirePortDataType.FLOAT: + { + result = ( useRealValue ) ? colorValue.r.ToString() : parameterName + ".r"; + } + break; + case WirePortDataType.FLOAT2: + { + result = ( useRealValue ) ? precisionStr + "2( " + colorValue.r + " , " + colorValue.g + " )" : parameterName + ".rg"; + } + break; + case WirePortDataType.FLOAT3: + { + result = ( useRealValue ) ? precisionStr + "3( " + colorValue.r + " , " + colorValue.g + " , " + colorValue.b + " )" : parameterName + ".rgb"; + } + break; + case WirePortDataType.FLOAT4: + { + result = useRealValue ? precisionStr + "4( " + colorValue.r + " , " + colorValue.g + " , " + colorValue.b + " , " + colorValue.a + " )" : parameterName; + } + break; + //case WirePortDataType.FLOAT4x4: + //{ + // if ( useRealValue ) + // { + // result = precisionStr + "4x4( " + colorValue.r + " , " + colorValue.g + " , " + colorValue.b + " , " + colorValue.a + " , " + + // colorValue.r + " , " + colorValue.g + " , " + colorValue.b + " , " + colorValue.a + " , " + + // colorValue.r + " , " + colorValue.g + " , " + colorValue.b + " , " + colorValue.a + " , " + + // colorValue.r + " , " + colorValue.g + " , " + colorValue.b + " , " + colorValue.a + " )"; + // } + // else + // { + // string localVal = CreateLocalValueName( currentPrecision, newType, localVarName, parameterName ); + // CurrentDataCollector.AddToLocalVariables( portCategory, -1, localVal ); + + // result = precisionStr + "4x4( " + localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z , " + localVarName + ".w , " + + // localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z , " + localVarName + ".w , " + + // localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z , " + localVarName + ".w , " + + // localVarName + ".x , " + localVarName + ".y , " + localVarName + ".z , " + localVarName + ".w )"; + // } + //} + //break; + } + } + break; + case WirePortDataType.INT: + { + switch( newType ) + { + case WirePortDataType.OBJECT: result = useRealValue ? value.ToString() : parameterName; break; + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.COLOR: + case WirePortDataType.FLOAT4: + { + string localVal = CreateLocalValueName( currentPrecision , newType , localVarName , ( ( useRealValue ) ? value.ToString() : parameterName ) ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory , -1 , localVal ); + result = localVarName; + } + break; + case WirePortDataType.FLOAT3x3: + { + string localVal = CreateLocalValueName( currentPrecision , oldType , localVarName , ( ( useRealValue ) ? value.ToString() : parameterName ) ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory , -1 , localVal ); + result = localVarName; + } + break; + case WirePortDataType.FLOAT4x4: + { + string localVal = CreateLocalValueName( currentPrecision , oldType , localVarName , ( ( useRealValue ) ? value.ToString() : parameterName ) ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory , -1 , localVal ); + result = localVarName; + } + break; + case WirePortDataType.FLOAT: + { + result = ( useRealValue ) ? ( (int)value ).ToString() : "(float)" + parameterName; + } + break; + case WirePortDataType.UINT: + { + result = ( useRealValue ) ? ( (int)value ).ToString() : "(uint)" + parameterName; + } + break; + } + } + break; + case WirePortDataType.UINT: + { + switch( newType ) + { + case WirePortDataType.OBJECT: result = useRealValue ? value.ToString() : parameterName; break; + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.COLOR: + case WirePortDataType.FLOAT4: + { + string localVal = CreateLocalValueName( currentPrecision , newType , localVarName , ( ( useRealValue ) ? value.ToString() : parameterName ) ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory , -1 , localVal ); + result = localVarName; + } + break; + case WirePortDataType.FLOAT3x3: + { + string localVal = CreateLocalValueName( currentPrecision , oldType , localVarName , ( ( useRealValue ) ? value.ToString() : parameterName ) ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory , -1 , localVal ); + result = localVarName; + } + break; + case WirePortDataType.FLOAT4x4: + { + string localVal = CreateLocalValueName( currentPrecision , oldType , localVarName , ( ( useRealValue ) ? value.ToString() : parameterName ) ); + dataCollector.AddToLocalVariables( dataCollector.PortCategory , -1 , localVal ); + result = localVarName; + } + break; + case WirePortDataType.FLOAT: + { + result = ( useRealValue ) ? ( (int)value ).ToString() : "(float)" + parameterName; + } + break; + case WirePortDataType.INT: + { + result = ( useRealValue ) ? ( (int)value ).ToString() : "(int)" + parameterName; + } + break; + } + } + break; + } + if( result.Equals( string.Empty ) ) + { + result = "0"; + string warningStr = string.Format( "Unable to cast from {0} to {1}. Generating dummy data ( {2} )" , oldType , newType , result ); + + if( oldType == WirePortDataType.SAMPLER1D || oldType == WirePortDataType.SAMPLER2D || oldType == WirePortDataType.SAMPLER3D || oldType == WirePortDataType.SAMPLERCUBE || oldType == WirePortDataType.SAMPLER2DARRAY ) + { + warningStr = string.Format( "Unable to cast from {0} to {1}. You might want to use a Texture Sample node and connect it to the 'Tex' port. Generating dummy data ( {2} )" , oldType , newType , result ); + } + ShowMessage( warningStr , MessageSeverity.Warning ); + } + return result; + } + + public static bool CanCast( WirePortDataType from , WirePortDataType to ) + { + if( from == WirePortDataType.OBJECT || to == WirePortDataType.OBJECT || from == to ) + return true; + + switch( from ) + { + case WirePortDataType.FLOAT: + { + if( to == WirePortDataType.INT ) + return true; + } + break; + case WirePortDataType.FLOAT2: + { + return false; + } + case WirePortDataType.FLOAT3: + { + if( to == WirePortDataType.COLOR || + to == WirePortDataType.FLOAT4 ) + return true; + } + break; + case WirePortDataType.FLOAT4: + { + if( to == WirePortDataType.FLOAT3 || + to == WirePortDataType.COLOR ) + return true; + } + break; + case WirePortDataType.FLOAT3x3: + { + if( to == WirePortDataType.FLOAT4x4 ) + return true; + } + break; + case WirePortDataType.FLOAT4x4: + { + if( to == WirePortDataType.FLOAT3x3 ) + return true; + } + break; + case WirePortDataType.COLOR: + { + if( to == WirePortDataType.FLOAT3 || + to == WirePortDataType.FLOAT4 ) + return true; + + } + break; + case WirePortDataType.INT: + { + if( to == WirePortDataType.FLOAT ) + return true; + } + break; + } + + return false; + } + + public static int GetChannelsAmount( WirePortDataType type ) + { + switch( type ) + { + case WirePortDataType.OBJECT: return 0; + case WirePortDataType.FLOAT: return 1; + case WirePortDataType.FLOAT2: return 2; + case WirePortDataType.FLOAT3: return 3; + case WirePortDataType.FLOAT4: return 4; + case WirePortDataType.FLOAT3x3: return 9; + case WirePortDataType.FLOAT4x4: return 16; + case WirePortDataType.COLOR: return 4; + case WirePortDataType.INT: return 1; + case WirePortDataType.UINT: return 1; + } + return 0; + } + + public static WirePortDataType GetWireTypeForChannelAmount( int channelAmount ) + { + switch( channelAmount ) + { + case 1: return WirePortDataType.FLOAT; + case 2: return WirePortDataType.FLOAT2; + case 3: return WirePortDataType.FLOAT3; + case 4: return WirePortDataType.FLOAT4; + case 9: return WirePortDataType.FLOAT3x3; + case 16: return WirePortDataType.FLOAT4x4; + } + return WirePortDataType.FLOAT; + } + + public static string GenerateUniformName( bool excludeUniformKeyword , WirePortDataType dataType , string dataName ) + { + return GenerateUniformName( excludeUniformKeyword , WirePortToCgType( dataType ) , dataName ); + } + + public static string GenerateUniformName( bool excludeUniformKeyword , string dataType , string dataName ) + { + int index = excludeUniformKeyword ? 1 : 0; + return string.Format( Constants.UniformDec[ index ] , dataType , dataName ); + } + + public static string GeneratePropertyName( string name , PropertyType propertyType , bool forceUnderscore = false ) + { + if( string.IsNullOrEmpty( name ) ) + return name; + + name = RemoveInvalidCharacters( name ); + if( propertyType != PropertyType.Global || forceUnderscore ) + { + if( name[ 0 ] != '_' ) + { + name = '_' + name; + } + } + + return name; + } + + public static string UrlReplaceInvalidStrings( string originalString ) + { + for( int i = 0 ; i < Constants.UrlReplacementStringValuesLen ; i++ ) + { + originalString = originalString.Replace( Constants.UrlReplacementStringValues[ i , 0 ] , Constants.UrlReplacementStringValues[ i , 1 ] ); + } + return originalString; + } + + public static string ReplaceInvalidStrings( string originalString ) + { + for( int i = 0 ; i < Constants.ReplacementStringValuesLen ; i++ ) + { + originalString = originalString.Replace( Constants.ReplacementStringValues[ i , 0 ] , Constants.ReplacementStringValues[ i , 1 ] ); + } + return originalString; + } + + public static string RemoveWikiInvalidCharacters( string originalString ) + { + for( int i = 0 ; i < Constants.WikiInvalidChars.Length ; i++ ) + { + originalString = originalString.Replace( Constants.WikiInvalidChars[ i ] , string.Empty ); + } + return originalString; + } + + public static string RemoveInvalidEnumCharacters( string originalString ) + { + for( int i = 0 ; i < Constants.EnumInvalidChars.Length ; i++ ) + { + originalString = originalString.Replace( Constants.EnumInvalidChars[ i ] , string.Empty ); + } + return originalString; + } + + public static string RemoveInvalidAttrCharacters( string originalString ) + { + for( int i = 0 ; i < Constants.AttrInvalidChars.Length ; i++ ) + { + originalString = originalString.Replace( Constants.AttrInvalidChars[ i ] , string.Empty ); + } + return originalString; + } + + public static string RemoveHeaderAttrCharacters( string originalString ) + { + for( int i = 0 ; i < Constants.AttrInvalidChars.Length ; i++ ) + { + originalString = originalString.Replace( Constants.HeaderInvalidChars[ i ] , string.Empty ); + } + return originalString; + } + + public static string RemoveInvalidCharacters( string originalString ) + { + for( int i = 0 ; i < Constants.OverallInvalidChars.Length ; i++ ) + { + originalString = originalString.Replace( Constants.OverallInvalidChars[ i ] , string.Empty ); + } + return originalString; + } + + public static string RemoveShaderInvalidCharacters( string originalString ) + { + originalString = originalString.Replace( '\\' , '/' ); + for( int i = 0 ; i < Constants.ShaderInvalidChars.Length ; i++ ) + { + originalString = originalString.Replace( Constants.ShaderInvalidChars[ i ] , string.Empty ); + } + return originalString; + } + + public static bool IsUnityNativeShader( Shader shader ) + { + string pathName = AssetDatabase.GetAssetPath( shader ); + + if( pathName.Contains( "unity_builtin_extra" ) || + pathName.Contains( "unity default resources" ) ) + return true; + + return false; + } + public static bool IsUnityNativeShader( string path ) { return m_unityNativeShaderPaths.ContainsKey( path ); } + + public static string GetComponentForPosition( int pos , WirePortDataType type , bool addDot = false ) + { + string result = addDot ? "." : string.Empty; + switch( pos ) + { + case 0: + { + return ( ( type == WirePortDataType.COLOR ) ? ( result + "r" ) : ( result + "x" ) ); + } + case 1: + { + return ( ( type == WirePortDataType.COLOR ) ? ( result + "g" ) : ( result + "y" ) ); + } + case 2: + { + return ( ( type == WirePortDataType.COLOR ) ? ( result + "b" ) : ( result + "z" ) ); + } + case 3: + { + return ( ( type == WirePortDataType.COLOR ) ? ( result + "a" ) : ( result + "w" ) ); + } + } + return string.Empty; + } + + public static string InvalidParameter( ParentNode node ) + { + ShowMessage( node.UniqueId , "Invalid entrance type on node" + node , MessageSeverity.Error ); + return "0"; + } + + public static string NoConnection( ParentNode node ) + { + ShowMessage( node.UniqueId , "No Input connection on node" + node , MessageSeverity.Error ); + return "0"; + } + + public static string UnknownError( ParentNode node ) + { + ShowMessage( node.UniqueId , "Unknown error on node" + node , MessageSeverity.Error ); + return "0"; + } + + public static string GetTex2DProperty( string name , TexturePropertyValues defaultValue ) { return name + "(\"" + name + "\", 2D) = \"" + defaultValue + "\" {}"; } + public static string AddBrackets( string value ) { return "( " + value + " )"; } + public static Color GetColorFromWireStatus( WireStatus status ) { return m_wireStatusToColor[ status ]; } + public static bool HasColorCategory( string category ) { return m_nodeCategoryToColor.ContainsKey( category ); } + public static void AddColorCategory( string category , Color color ) + { + m_nodeCategoryToColor.Add( category , color ); + } + + public static Color AddColorCategory( string category , string hexColor ) + { + try + { + Color color = new Color(); + ColorUtility.TryParseHtmlString( hexColor , out color ); + m_nodeCategoryToColor.Add( category , color ); + return color; + } + catch( System.Exception e ) + { + Debug.LogException( e ); + } + return m_nodeCategoryToColor[ "Default" ]; + } + + public static Color GetColorFromCategory( string category ) + { + if( m_nodeCategoryToColor.ContainsKey( category ) ) + return m_nodeCategoryToColor[ category ]; + + + if( DebugConsoleWindow.DeveloperMode ) + Debug.LogWarning( category + " category does not contain an associated color" ); + + return m_nodeCategoryToColor[ "Default" ]; + } + + public static string LatestOpenedFolder + { + get { return m_latestOpenedFolder; } + set { m_latestOpenedFolder = value; } + } + + public static void ActivatePreviews( bool value ) + { + int count = IOUtils.AllOpenedWindows.Count; + for( int i = 0 ; i < count ; i++ ) + { + IOUtils.AllOpenedWindows[ i ].ActivatePreviews( value ); + } + } + + public static Shader CreateNewUnlit() + { + if( CurrentWindow == null ) + return null; + + string shaderName; + string pathName; + Shader newShader = null; + IOUtils.GetShaderName( out shaderName , out pathName , "MyUnlitShader" , m_latestOpenedFolder ); + if( !System.String.IsNullOrEmpty( shaderName ) && !System.String.IsNullOrEmpty( pathName ) ) + { + CurrentWindow.CreateNewGraph( shaderName ); + CurrentWindow.PreMadeShadersInstance.FlatColorSequence.Execute(); + + CurrentWindow.CurrentGraph.CurrentMasterNode.SetName( shaderName ); + newShader = CurrentWindow.CurrentGraph.FireMasterNode( pathName , true ); + AssetDatabase.Refresh(); + } + return newShader; + } + + public static Shader CreateNewEmpty( string customPath = null , string customShaderName = null ) + { + if( CurrentWindow == null ) + return null; + + string shaderName; + string pathName; + Shader newShader = null; + + + string path = AssetDatabase.GetAssetPath( Selection.activeObject ); + if( path == "" ) + { + path = "Assets"; + } + else if( System.IO.Path.GetExtension( path ) != "" ) + { + path = path.Replace( System.IO.Path.GetFileName( AssetDatabase.GetAssetPath( Selection.activeObject ) ) , "" ); + } + + + if( string.IsNullOrEmpty( customPath ) ) + { + IOUtils.GetShaderName( out shaderName , out pathName , Constants.DefaultShaderName , m_latestOpenedFolder ); + } + else + { + pathName = customPath; + if( string.IsNullOrEmpty( customShaderName ) ) + { + shaderName = Constants.DefaultShaderName; + int indexOfAssets = pathName.IndexOf( "Assets" ); + string uniquePath = ( indexOfAssets > 0 ) ? pathName.Remove( 0 , indexOfAssets ) : pathName; + string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath( uniquePath + shaderName + ".shader" ); + pathName = assetPathAndName; + shaderName = assetPathAndName.Remove( 0 , assetPathAndName.IndexOf( shaderName ) ); + } + else + { + shaderName = customShaderName; + } + shaderName = shaderName.Remove( shaderName.Length - 7 ); + } + if( !System.String.IsNullOrEmpty( shaderName ) && !System.String.IsNullOrEmpty( pathName ) ) + { + m_latestOpenedFolder = pathName; + + CurrentWindow.titleContent.text = AmplifyShaderEditorWindow.GenerateTabTitle( shaderName ); + CurrentWindow.titleContent.image = ShaderIcon; + CurrentWindow.CreateNewGraph( shaderName ); + CurrentWindow.LastOpenedLocation = pathName; + CurrentWindow.CurrentGraph.CurrentMasterNode.SetName( shaderName ); + newShader = CurrentWindow.CurrentGraph.FireMasterNode( pathName , true ); + AssetDatabase.Refresh(); + } + + return newShader; + } + + + public static Shader CreateNewEmptyTemplate( string templateGUID , string customPath = null , string customShaderName = null ) + { + if( CurrentWindow == null ) + return null; + + string shaderName; + string pathName; + Shader newShader = null; + + + string path = AssetDatabase.GetAssetPath( Selection.activeObject ); + if( path == "" ) + { + path = "Assets"; + } + else if( System.IO.Path.GetExtension( path ) != "" ) + { + path = path.Replace( System.IO.Path.GetFileName( AssetDatabase.GetAssetPath( Selection.activeObject ) ) , "" ); + } + + + if( string.IsNullOrEmpty( customPath ) ) + { + IOUtils.GetShaderName( out shaderName , out pathName , Constants.DefaultShaderName , m_latestOpenedFolder ); + } + else + { + pathName = customPath; + if( string.IsNullOrEmpty( customShaderName ) ) + { + shaderName = Constants.DefaultShaderName; + int indexOfAssets = pathName.IndexOf( "Assets" ); + string uniquePath = ( indexOfAssets > 0 ) ? pathName.Remove( 0 , indexOfAssets ) : pathName; + string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath( uniquePath + shaderName + ".shader" ); + pathName = assetPathAndName; + shaderName = assetPathAndName.Remove( 0 , assetPathAndName.IndexOf( shaderName ) ); + } + else + { + shaderName = customShaderName; + } + shaderName = shaderName.Remove( shaderName.Length - 7 ); + } + if( !System.String.IsNullOrEmpty( shaderName ) && !System.String.IsNullOrEmpty( pathName ) ) + { + m_latestOpenedFolder = pathName; + + CurrentWindow.titleContent.text = AmplifyShaderEditorWindow.GenerateTabTitle( shaderName ); + CurrentWindow.titleContent.image = UIUtils.ShaderIcon; + CurrentWindow.CreateNewTemplateGraph( templateGUID ); + CurrentWindow.CurrentGraph.CurrentMasterNode.SetName( shaderName ); + newShader = CurrentWindow.CurrentGraph.FireMasterNode( pathName , true ); + AssetDatabase.Refresh(); + } + + return newShader; + } + + + public static void SetDelayedMaterialMode( Material material ) + { + if( CurrentWindow == null ) + return; + CurrentWindow.SetDelayedMaterialMode( material ); + } + + public static void CreateEmptyFromInvalid( Shader shader ) + { + if( CurrentWindow == null ) + return; + + CurrentWindow.CreateNewGraph( shader ); + CurrentWindow.ForceRepaint(); + } + + public static void CreateEmptyFunction( AmplifyShaderFunction shaderFunction ) + { + if( CurrentWindow == null ) + return; + + CurrentWindow.CreateNewFunctionGraph( shaderFunction ); + CurrentWindow.SaveToDisk( false ); + CurrentWindow.ForceRepaint(); + } + + public static void DrawFloat( UndoParentNode owner , ref Rect propertyDrawPos , ref float value , float newLabelWidth = 8 ) + { + float labelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = newLabelWidth; + value = owner.EditorGUIFloatField( propertyDrawPos , " " , value , UIUtils.MainSkin.textField ); + EditorGUIUtility.labelWidth = labelWidth; + } + + public static GUIStyle GetCustomStyle( CustomStyle style ) + { + return ( Initialized ) ? MainSkin.customStyles[ (int)style ] : null; + } + + public static void SetCustomStyle( CustomStyle style , GUIStyle guiStyle ) + { + if( MainSkin != null ) + MainSkin.customStyles[ (int)style ] = new GUIStyle( guiStyle ); + } + + public static void OpenFile() + { + if( CurrentWindow == null ) + return; + string newShader = EditorUtility.OpenFilePanel( "Select Shader to open" , m_latestOpenedFolder , "shader" ); + if( !System.String.IsNullOrEmpty( newShader ) ) + { + m_latestOpenedFolder = newShader.Substring( 0 , newShader.LastIndexOf( '/' ) + 1 ); + int relFilenameId = newShader.IndexOf( Application.dataPath ); + if( relFilenameId > -1 ) + { + string relFilename = newShader.Substring( relFilenameId + Application.dataPath.Length - 6 );// -6 need to also copy the assets/ part + CurrentWindow.LoadFromDisk( relFilename ); + } + else + { + ShowMessage( "Can only load shaders\nfrom inside the projects folder" , MessageSeverity.Error ); + } + } + } + + public static bool DetectNodeLoopsFrom( ParentNode node , Dictionary currentNodes ) + { + for( int i = 0 ; i < node.InputPorts.Count ; i++ ) + { + if( node.InputPorts[ i ].IsConnected ) + { + ParentNode newNode = node.InputPorts[ i ].GetOutputNode(); + if( !currentNodes.ContainsKey( newNode.UniqueId ) ) + RecursiveNodeFill( newNode , currentNodes ); + } + } + + bool found = currentNodes.ContainsKey( node.UniqueId ); + currentNodes.Clear(); + currentNodes = null; + + return found; + } + + private static void RecursiveNodeFill( ParentNode node , Dictionary currentNodes ) + { + if( !currentNodes.ContainsKey( node.UniqueId ) ) + currentNodes.Add( node.UniqueId , 1 ); + + for( int i = 0 ; i < node.InputPorts.Count ; i++ ) + { + if( node.InputPorts[ i ].IsConnected ) + { + ParentNode newNode = node.InputPorts[ i ].GetOutputNode(); + if( !currentNodes.ContainsKey( newNode.UniqueId ) ) + RecursiveNodeFill( newNode , currentNodes ); + } + } + } + + public static ParentNode CreateNode( System.Type type , bool registerUndo , Vector2 pos , int nodeId = -1 , bool addLast = true ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.CurrentGraph.CreateNode( type , registerUndo , pos , nodeId , addLast ); + } + return null; + } + + public static void DestroyNode( int nodeId ) + { + if( CurrentWindow != null ) + { + CurrentWindow.CurrentGraph.DestroyNode( nodeId ); + } + } + + public static void ShowMessage( int ownerId , string message , MessageSeverity severity = MessageSeverity.Normal , bool registerTimestamp = true ) + { + if( CurrentWindow != null ) + { + CurrentWindow.ShowMessage( ownerId , message , severity , registerTimestamp ); + } + } + + public static void ShowMessage( string message , MessageSeverity severity = MessageSeverity.Normal , bool registerTimestamp = true ) + { + if( CurrentWindow != null ) + { + CurrentWindow.ShowMessage( message , severity , registerTimestamp ); + } + } + + public static ParentNode GetNode( int nodeId ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.CurrentGraph.GetNode( nodeId ); + } + return null; + } + + public static PropertyNode GetInternalTemplateNode( int nodeId ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.CurrentGraph.GetInternalTemplateNode( nodeId ); + } + return null; + } + + public static PropertyNode GetInternalTemplateNode( string propertyName ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.CurrentGraph.GetInternalTemplateNode( propertyName ); + } + return null; + } + + + public static void DeleteConnection( bool isInput , int nodeId , int portId , bool registerOnLog , bool propagateCallback ) + { + if( CurrentWindow != null ) + { + CurrentWindow.DeleteConnection( isInput , nodeId , portId , registerOnLog , propagateCallback ); + } + } + + public static void ConnectInputToOutput( int inNodeId , int inPortId , int outNodeId , int outPortId ) + { + if( CurrentWindow != null ) + { + CurrentWindow.ConnectInputToOutput( inNodeId , inPortId , outNodeId , outPortId ); + } + } + + public static Shader CreateNewGraph( string name ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.CreateNewGraph( name ); + } + return null; + } + public static void SetConnection( int InNodeId , int InPortId , int OutNodeId , int OutPortId ) + { + if( CurrentWindow != null ) + { + CurrentWindow.CurrentGraph.SetConnection( InNodeId , InPortId , OutNodeId , OutPortId ); + } + } + + public static bool IsChannelAvailable( int channelId ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.DuplicatePrevBufferInstance.IsChannelAvailable( channelId ); + } + return false; + } + + public static bool ReleaseUVChannel( int nodeId , int channelId ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.DuplicatePrevBufferInstance.ReleaseUVChannel( nodeId , channelId ); + } + return false; + } + + public static bool RegisterUVChannel( int nodeId , int channelId , string name ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.DuplicatePrevBufferInstance.RegisterUVChannel( nodeId , channelId , name ); + } + return false; + } + + public static void GetFirstAvailableName( int nodeId , WirePortDataType type , out string outProperty , out string outInspector , bool useCustomPrefix = false , string customPrefix = null ) + { + outProperty = string.Empty; + outInspector = string.Empty; + if( CurrentWindow != null ) + { + CurrentWindow.DuplicatePrevBufferInstance.GetFirstAvailableName( nodeId , type , out outProperty , out outInspector , useCustomPrefix , customPrefix ); + } + } + + + public static bool IsNumericName( string name ) + { + Match match = Regex.Match( name , NumericNamePattern ); + if( match != null && match.Success ) + return true; + return false; + } + + public static bool CheckInvalidUniformName( string name ) + { + if( m_reservedPropertyNames.ContainsKey( name ) ) + { + ShowMessage( string.Format( Constants.ReservedPropertyNameStr , name ) ); + return true; + } + + if( IsNumericName( name ) ) + { + ShowMessage( string.Format( Constants.NumericPropertyNameStr , name ) ); + return true; + } + + return false; + } + + public static bool RegisterUniformName( int nodeId , string name ) + { + if( CheckInvalidUniformName( name ) ) + { + return false; + } + + if( CurrentWindow != null ) + { + return CurrentWindow.DuplicatePrevBufferInstance.RegisterUniformName( nodeId , name ); + } + return false; + } + + public static bool ReleaseUniformName( int nodeId , string name ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.DuplicatePrevBufferInstance.ReleaseUniformName( nodeId , name ); + } + return false; + } + + public static bool IsUniformNameAvailable( string name ) + { + if( CheckInvalidUniformName( name ) ) + { + return false; + } + + if( CurrentWindow != null ) + { + return CurrentWindow.DuplicatePrevBufferInstance.IsUniformNameAvailable( name ); + } + return false; + } + + public static int CheckUniformNameOwner( string name ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.DuplicatePrevBufferInstance.CheckUniformNameOwner( name ); + } + return -1; + } + + public static string GetUniqueUniformName( string name ) + { + int num = 0; + Regex reg = new Regex( @"([0-9]+)$" ); + Match match = reg.Match( name ); + if( match.Success ) + { + string s = match.Groups[ 1 ].Captures[ 0 ].Value; + num = int.Parse( s ); + name = name.Replace( s , "" ); + } + + for( int i = num + 1 ; i < 1000 ; i++ ) + { + string testName = name + i; + + if( CheckInvalidUniformName( testName ) ) + { + continue; + } + + if( CurrentWindow != null ) + { + if( CurrentWindow.DuplicatePrevBufferInstance.IsUniformNameAvailable( testName ) ) + { + return testName; + } + } + } + return name; + } + + public static bool RegisterLocalVariableName( int nodeId , string name ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.DuplicatePrevBufferInstance.RegisterLocalVariableName( nodeId , name ); + } + return false; + } + + public static bool ReleaseLocalVariableName( int nodeId , string name ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.DuplicatePrevBufferInstance.ReleaseLocalVariableName( nodeId , name ); + } + return false; + } + + public static bool IsLocalvariableNameAvailable( string name ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.DuplicatePrevBufferInstance.IsLocalvariableNameAvailable( name ); + } + return false; + } + + public static string GetChannelName( int channelId ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.DuplicatePrevBufferInstance.GetChannelName( channelId ); + } + return string.Empty; + } + + public static void SetChannelName( int channelId , string name ) + { + if( CurrentWindow != null ) + { + CurrentWindow.DuplicatePrevBufferInstance.SetChannelName( channelId , name ); + } + } + + public static int RegisterFirstAvailableChannel( int nodeId , string name ) + { + if( CurrentWindow != null ) + { + return CurrentWindow.DuplicatePrevBufferInstance.RegisterFirstAvailableChannel( nodeId , name ); + } + return -1; + } + + public static int PortCategorytoAttayIdx( MasterNodePortCategory category ) + { + if( m_portCategoryToArrayIdx.ContainsKey( category ) ) + return m_portCategoryToArrayIdx[ category ]; + + return m_portCategoryToArrayIdx[ MasterNodePortCategory.Fragment ]; + } + + public static bool DisplayDialog( string shaderPath ) + { + string value = System.String.Format( "Save changes to the shader {0} before closing?" , shaderPath ); + return EditorUtility.DisplayDialog( "Load selected" , value , "Yes" , "No" ); + } + + public static void ForceUpdateFromMaterial() + { + if( CurrentWindow != null ) + { + // CurrentWindow.Focus(); + CurrentWindow.ForceUpdateFromMaterial(); + } + } + + public static void MarkToRepaint() { if( CurrentWindow != null ) CurrentWindow.MarkToRepaint(); } + public static void RequestSave() { if( CurrentWindow != null ) CurrentWindow.RequestSave(); } + public static string FloatToString( float value ) + { + string floatStr = value.ToString(); + if( value % 1 == 0 ) + { + floatStr += ".0"; + } + return floatStr; + } + + public static int CurrentShaderVersion() + { + if( CurrentWindow != null ) + { + return CurrentWindow.CurrentGraph.LoadedShaderVersion; + } + return -1; + } + + public static bool IsProperty( PropertyType type ) { return ( type == PropertyType.Property || type == PropertyType.InstancedProperty ); } + + public static MasterNode CurrentMasterNode() + { + if( CurrentWindow != null ) + { + return CurrentWindow.CurrentGraph.CurrentMasterNode; + } + return null; + } + + public static void AddVirtualTextureCount() { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.AddVirtualTextureCount(); } } + + public static bool HasVirtualTexture() + { + if( CurrentWindow != null ) + { + return CurrentWindow.CurrentGraph.HasVirtualTexture; + } + return false; + } + + public static void RemoveVirtualTextureCount() { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.RemoveVirtualTextureCount(); } } + + //public static void AddInstancePropertyCount() { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.AddInstancePropertyCount(); } } + + public static bool IsInstancedShader() + { + if( CurrentWindow != null ) + { + return CurrentWindow.CurrentGraph.IsInstancedShader; + } + return false; + } + + //public static void RemoveInstancePropertyCount() { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.RemoveInstancePropertyCount(); } } + //public static void AddNormalDependentCount() { if ( CurrentWindow != null ) { CurrentWindow.CurrentGraph.AddNormalDependentCount(); } } + //public static void RemoveNormalDependentCount() { if ( CurrentWindow != null ) { CurrentWindow.CurrentGraph.RemoveNormalDependentCount(); } } + //public static bool IsNormalDependent() + //{ + // if ( CurrentWindow != null ) + // { + // return CurrentWindow.CurrentGraph.IsNormalDependent; + // } + // return false; + //} + + public static void CopyValuesFromMaterial( Material mat ) + { + if( CurrentWindow != null && CurrentWindow.CurrentMaterial == mat ) + { + CurrentWindow.CurrentGraph.CopyValuesFromMaterial( mat ); + } + else + { + int aseWindowCount = IOUtils.AllOpenedWindows.Count; + for( int i = 0 ; i < aseWindowCount ; i++ ) + { + if( IOUtils.AllOpenedWindows[ i ] != m_currentWindow && IOUtils.AllOpenedWindows[ i ].CurrentMaterial == mat ) + { + IOUtils.AllOpenedWindows[ i ].CurrentGraph.CopyValuesFromMaterial( mat ); + break; + } + } + } + } + + // Sampler Node + public static void RegisterSamplerNode( SamplerNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.SamplerNodes.AddNode( node ); } } + public static void UnregisterSamplerNode( SamplerNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.SamplerNodes.RemoveNode( node ); } } + public static string[] SamplerNodeArr() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.SamplerNodes.NodesArr; } return null; } + public static SamplerNode GetSamplerNode( int idx ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.SamplerNodes.GetNode( idx ); } return null; } + public static void UpdateSamplerDataNode( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.SamplerNodes.UpdateDataOnNode( uniqueId , data ); } } + public static int GetSamplerNodeRegisterId( int uniqueId ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.SamplerNodes.GetNodeRegisterIdx( uniqueId ); } return -1; } + public static int GetSamplerNodeAmount() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.SamplerNodes.NodesList.Count; } return -1; } + + // Float Node + public static void RegisterFloatIntNode( PropertyNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FloatIntNodes.AddNode( node ); } } + public static void UnregisterFloatIntNode( PropertyNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FloatIntNodes.RemoveNode( node ); } } + public static string[] FloatIntNodeArr() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FloatIntNodes.NodesArr; } return null; } + public static int[] FloatIntNodeIds() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FloatIntNodes.NodeIds; } return null; } + public static PropertyNode GetFloatIntNode( int idx ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FloatIntNodes.GetNode( idx ); } return null; } + public static void UpdateFloatIntDataNode( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FloatIntNodes.UpdateDataOnNode( uniqueId , data ); } } + public static int GetFloatIntNodeRegisterId( int uniqueId ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FloatIntNodes.GetNodeRegisterIdx( uniqueId ); } return -1; } + public static int GetNodeIdByName( string name ) + { + if( CurrentWindow != null ) + { + UsageListFloatIntNodes list = CurrentWindow.CurrentGraph.FloatIntNodes; + int count = list.Count; + for( int i = 0 ; i < count ; i++ ) + { + if( list.NodesList[ i ].PropertyName.Equals( name ) ) + return list.NodesList[ i ].UniqueId; + } + } + return -1; + } + public static PropertyNode GetFloatIntNodeByUniqueId( int uniqueId ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FloatIntNodes.GetNodeByUniqueId( uniqueId ); } return null; } + //public static int GetFloatNodeAmount() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FloatNodes.NodesList.Count; } return -1; } + + // Texture Property + public static void RegisterTexturePropertyNode( TexturePropertyNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.TexturePropertyNodes.AddNode( node ); } } + public static void UnregisterTexturePropertyNode( TexturePropertyNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.TexturePropertyNodes.RemoveNode( node ); } } + public static string[] TexturePropertyNodeArr() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.TexturePropertyNodes.NodesArr; } return null; } + public static TexturePropertyNode GetTexturePropertyNode( int idx ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.TexturePropertyNodes.GetNode( idx ); } return null; } + public static void UpdateTexturePropertyDataNode( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.TexturePropertyNodes.UpdateDataOnNode( uniqueId , data ); } } + public static int GetTexturePropertyNodeRegisterId( int uniqueId ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.TexturePropertyNodes.GetNodeRegisterIdx( uniqueId ); } return -1; } + public static int GetTexturePropertyNodeAmount() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.TexturePropertyNodes.NodesList.Count; } return -1; } + + // Texture Array + public static void RegisterTextureArrayNode( TextureArrayNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.TextureArrayNodes.AddNode( node ); } } + public static void UnregisterTextureArrayNode( TextureArrayNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.TextureArrayNodes.RemoveNode( node ); } } + public static string[] TextureArrayNodeArr() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.TextureArrayNodes.NodesArr; } return null; } + public static TextureArrayNode GetTextureArrayNode( int idx ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.TextureArrayNodes.GetNode( idx ); } return null; } + public static void UpdateTextureArrayDataNode( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.TextureArrayNodes.UpdateDataOnNode( uniqueId , data ); } } + public static int GetTextureArrayNodeRegisterId( int uniqueId ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.TextureArrayNodes.GetNodeRegisterIdx( uniqueId ); } return -1; } + public static int GetTextureArrayNodeAmount() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.TextureArrayNodes.NodesList.Count; } return -1; } + + // Raw Property Node + public static void RegisterRawPropertyNode( PropertyNode node ) { if( CurrentWindow != null ) { CurrentWindow.OutsideGraph.RawPropertyNodes.AddNode( node ); } } + public static void UnregisterRawPropertyNode( PropertyNode node ) { if( CurrentWindow != null ) { CurrentWindow.OutsideGraph.RawPropertyNodes.RemoveNode( node ); } } + + // Property Node + public static void RegisterPropertyNode( PropertyNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.PropertyNodes.AddNode( node ); } } + public static void UnregisterPropertyNode( PropertyNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.PropertyNodes.RemoveNode( node ); } } + public static string[] PropertyNodeNodeArr() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.PropertyNodes.NodesArr; } return null; } + public static PropertyNode GetPropertyNode( int idx ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.PropertyNodes.GetNode( idx ); } return null; } + public static PropertyNode GetPropertyNodeByUniqueId( int uniqueId ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.PropertyNodes.GetNodeByUniqueId( uniqueId ); } return null; } + public static void UpdatePropertyDataNode( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.PropertyNodes.UpdateDataOnNode( uniqueId , data ); } } + public static int GetPropertyNodeRegisterId( int uniqueId ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.PropertyNodes.GetNodeRegisterIdx( uniqueId ); } return -1; } + public static List PropertyNodesList() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.PropertyNodes.NodesList; } return null; } + public static int GetPropertyNodeAmount() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.PropertyNodes.NodesList.Count; } return -1; } + + // Function Inputs + public static void RegisterFunctionInputNode( FunctionInput node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionInputNodes.AddNode( node ); } } + public static void UnregisterFunctionInputNode( FunctionInput node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionInputNodes.RemoveNode( node ); } } + public static void UpdateFunctionInputData( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionInputNodes.UpdateDataOnNode( uniqueId , data ); } } + public static List FunctionInputList() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FunctionInputNodes.NodesList; } return null; } + + // Function Nodes + public static void RegisterFunctionNode( FunctionNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionNodes.AddNode( node ); } } + public static void UnregisterFunctionNode( FunctionNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionNodes.RemoveNode( node ); } } + public static void UpdateFunctionData( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionNodes.UpdateDataOnNode( uniqueId , data ); } } + public static List FunctionList() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FunctionNodes.NodesList; } return null; } + + // Function Outputs + public static void RegisterFunctionOutputNode( FunctionOutput node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionOutputNodes.AddNode( node ); } } + public static void UnregisterFunctionOutputNode( FunctionOutput node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionOutputNodes.RemoveNode( node ); } } + public static void UpdateFunctionOutputData( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionOutputNodes.UpdateDataOnNode( uniqueId , data ); } } + public static List FunctionOutputList() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FunctionOutputNodes.NodesList; } return null; } + + // Function Switches Copy + public static void RegisterFunctionSwitchCopyNode( FunctionSwitch node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionSwitchCopyNodes.AddNode( node ); } } + public static void UnregisterFunctionSwitchCopyNode( FunctionSwitch node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionSwitchCopyNodes.RemoveNode( node ); } } + public static void UpdateFunctionSwitchCopyData( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionSwitchCopyNodes.UpdateDataOnNode( uniqueId , data ); } } + public static List FunctionSwitchCopyList() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FunctionSwitchCopyNodes.NodesList; } return null; } + + // Function Switches + public static void RegisterFunctionSwitchNode( FunctionSwitch node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionSwitchNodes.AddNode( node ); } } + public static void UnregisterFunctionSwitchNode( FunctionSwitch node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionSwitchNodes.RemoveNode( node ); } } + public static void UpdateFunctionSwitchData( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionSwitchNodes.UpdateDataOnNode( uniqueId , data ); } } + public static List FunctionSwitchList() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FunctionSwitchNodes.NodesList; } return null; } + public static void UpdateFunctionSwitchArr() { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.FunctionSwitchNodes.UpdateNodeArr(); } } + public static string[] FunctionSwitchesNodeArr() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FunctionSwitchNodes.NodesArr; } return null; } + public static FunctionSwitch GetFunctionSwitchNode( int idx ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FunctionSwitchNodes.GetNode( idx ); } return null; } + public static int GetFunctionSwitchNodeIndex( int uniqueId ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.FunctionSwitchNodes.GetNodeRegisterIdx( uniqueId ); } return -1; } + + // Screen Color Node + public static void RegisterScreenColorNode( ScreenColorNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.ScreenColorNodes.AddNode( node ); } } + public static void UnregisterScreenColorNode( ScreenColorNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.ScreenColorNodes.RemoveNode( node ); } } + public static string[] ScreenColorNodeArr() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.ScreenColorNodes.NodesArr; } return null; } + public static ScreenColorNode GetScreenColorNode( int idx ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.ScreenColorNodes.GetNode( idx ); } return null; } + public static int GetScreenColorNodeRegisterId( int uniqueId ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.ScreenColorNodes.GetNodeRegisterIdx( uniqueId ); } return -1; } + public static void UpdateScreenColorDataNode( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.ScreenColorNodes.UpdateDataOnNode( uniqueId , data ); } } + public static int GetScreenColorNodeAmount() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.ScreenColorNodes.NodesList.Count; } return -1; } + + // Local Var Node + public static int RegisterLocalVarNode( RegisterLocalVarNode node ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.LocalVarNodes.AddNode( node ); } return -1; } + public static void UnregisterLocalVarNode( RegisterLocalVarNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.LocalVarNodes.RemoveNode( node ); } } + public static string[] LocalVarNodeArr() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.LocalVarNodes.NodesArr; } return null; } + public static int LocalVarNodeAmount() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.LocalVarNodes.NodesList.Count; } return 0; } + public static int GetLocalVarNodeRegisterId( int uniqueId ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.LocalVarNodes.GetNodeRegisterIdx( uniqueId ); } return -1; } + public static RegisterLocalVarNode GetLocalVarNode( int idx ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.LocalVarNodes.GetNode( idx ); } return null; } + public static void UpdateLocalVarDataNode( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.LocalVarNodes.UpdateDataOnNode( uniqueId , data ); } } + + //Global Array + public static void RegisterGlobalArrayNode( GlobalArrayNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.GlobalArrayNodes.AddNode( node ); } } + public static void UnregisterGlobalArrayNode( GlobalArrayNode node ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.GlobalArrayNodes.RemoveNode( node ); } } + public static string[] GlobalArrayNodeArr() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.GlobalArrayNodes.NodesArr; } return null; } + public static GlobalArrayNode GetGlobalArrayNode( int idx ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.GlobalArrayNodes.GetNode( idx ); } return null; } + public static int GetGlobalArrayNodeRegisterId( int uniqueId ) { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.GlobalArrayNodes.GetNodeRegisterIdx( uniqueId ); } return -1; } + public static void UpdateGlobalArrayDataNode( int uniqueId , string data ) { if( CurrentWindow != null ) { CurrentWindow.CurrentGraph.GlobalArrayNodes.UpdateDataOnNode( uniqueId , data ); } } + public static int GetGlobalArrayNodeAmount() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.GlobalArrayNodes.NodesList.Count; } return -1; } + + + public static void FocusOnNode( ParentNode node , float zoom , bool selectNode ) { if( CurrentWindow != null ) { CurrentWindow.FocusOnNode( node , zoom , selectNode ); } } + public static PrecisionType CurrentPrecision() { if( CurrentWindow != null ) { return CurrentWindow.CurrentGraph.CurrentPrecision; } return PrecisionType.Float; } + public static string CurrentPrecisionCg() { if( CurrentWindow != null ) { return m_precisionTypeToCg[ CurrentWindow.CurrentGraph.CurrentPrecision ]; } return m_precisionTypeToCg[ PrecisionType.Float ]; } + + public static PrecisionType GetFinalPrecision( PrecisionType precision ) + { + if( CurrentWindow != null && CurrentWindow.CurrentGraph != null ) + { + PrecisionType mainPrecision = CurrentWindow.CurrentGraph.CurrentPrecision; + if( (int)mainPrecision > (int)precision ) + return mainPrecision; + } + return precision; + } + + public static bool GetNodeAvailabilityInBitArray( int bitArray , NodeAvailability availability ) { return ( bitArray & (int)availability ) != 0; } + public static bool GetCategoryInBitArray( int bitArray , MasterNodePortCategory category ) { return ( bitArray & (int)category ) != 0; } + public static void SetCategoryInBitArray( ref int bitArray , MasterNodePortCategory category ) { bitArray = bitArray | (int)category; } + + public static int GetPriority( WirePortDataType type ) { return m_portPriority[ type ]; } + + public static void ShowIncompatiblePortMessage( bool fromInput , ParentNode inNode , WirePort inPort , ParentNode outNode , WirePort outPort ) + { + string inPortName = inPort.Name.Equals( Constants.EmptyPortValue ) ? inPort.PortId.ToString() : inPort.Name; + string outPortName = outPort.Name.Equals( Constants.EmptyPortValue ) ? outPort.PortId.ToString() : outPort.Name; + ShowMessage( outNode.UniqueId , string.Format( ( fromInput ? IncorrectInputConnectionErrorMsg : IncorrectOutputConnectionErrorMsg ) , inPortName , inNode.Attributes.Name , inPort.DataType , outPort.DataType , outPortName , outNode.Attributes.Name ) ); + } + + public static void ShowNoVertexModeNodeMessage( ParentNode node ) + { + ShowMessage( node.UniqueId , string.Format( NoVertexModeNodeWarning , node.Attributes.Name ) , MessageSeverity.Warning ); + } + + public static int TotalExampleMaterials { get { return m_exampleMaterialIDs.Count; } } + + public static int ShaderIndentLevel + { + get { return m_shaderIndentLevel; } + set + { + m_shaderIndentLevel = Mathf.Max( value , 0 ); + m_shaderIndentTabs = string.Empty; + for( int i = 0 ; i < m_shaderIndentLevel ; i++ ) { m_shaderIndentTabs += "\t"; } + } + } + + public static string ShaderIndentTabs { get { return m_shaderIndentTabs; } } + public static void AddLineToShaderBody( ref string ShaderBody , string line ) { ShaderBody += m_shaderIndentTabs + line; } + public static void AddMultiLineToShaderBody( ref string ShaderBody , string[] lines ) + { + for( int i = 0 ; i < lines.Length ; i++ ) + { + ShaderBody += m_shaderIndentTabs + lines[ i ]; + } + } + + public static void ClearUndoHelper() + { + m_undoHelper.Clear(); + } + + public static bool CheckUndoNode( ParentNode node ) + { + if( node == null ) + return false; + if( m_undoHelper.ContainsKey( node.UniqueId ) ) + { + return false; + } + + m_undoHelper.Add( node.UniqueId , node ); + EditorUtility.SetDirty( node ); + return true; + } + + public static void MarkUndoAction() + { + SerializeHelperCounter = 2; + } + + public static bool SerializeFromUndo() + { + if( SerializeHelperCounter > 0 ) + { + SerializeHelperCounter--; + return true; + } + return false; + } + + public static int GetKeywordId( string keyword , TemplateSRPType type = TemplateSRPType.BuiltIn ) + { + switch( type ) + { + default: + case TemplateSRPType.BuiltIn: + { + if( AvailableKeywordsDict.Count != AvailableKeywords.Length ) + { + AvailableKeywordsDict.Clear(); + for( int i = 1 ; i < AvailableKeywords.Length ; i++ ) + { + AvailableKeywordsDict.Add( AvailableKeywords[ i ] , i ); + } + } + + if( AvailableKeywordsDict.ContainsKey( keyword ) ) + { + return AvailableKeywordsDict[ keyword ]; + } + } + break; + case TemplateSRPType.HD: + case TemplateSRPType.Lightweight: + { + if( AvailableURPKeywordsDict.Count != AvailableURPKeywords.Length ) + { + AvailableURPKeywordsDict.Clear(); + for( int i = 1 ; i < AvailableURPKeywords.Length ; i++ ) + { + AvailableURPKeywordsDict.Add( AvailableURPKeywords[ i ] , i ); + } + } + + if( AvailableURPKeywordsDict.ContainsKey( keyword ) ) + { + return AvailableURPKeywordsDict[ keyword ]; + } + } + break; + } + + + return 0; + } + public static string ForceLFLineEnding( string body ) + { + body = body.Replace( "\r\n" , "\n" ); + body = body.Replace( "\r" , "\n" ); + return body; + } + + public static RenderTexture DummyRT + { + get + { + if( m_dummyPreviewRT == null ) + { + m_dummyPreviewRT = new RenderTexture( 128 , 128 , 0 , RenderTextureFormat.ARGB32 ); + RenderTexture temp = RenderTexture.active; + RenderTexture.active = m_dummyPreviewRT; + Graphics.Blit( Texture2D.blackTexture , m_dummyPreviewRT ); + RenderTexture.active = temp; + } + return m_dummyPreviewRT; + } + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UIUtils.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UIUtils.cs.meta new file mode 100644 index 0000000..9185851 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UIUtils.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 23e0210afe076544ca92d761094a9119 +timeCreated: 1481126954 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UndoUtils.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UndoUtils.cs new file mode 100644 index 0000000..d7b35d3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UndoUtils.cs @@ -0,0 +1,12 @@ +using UnityEditor; +using UnityEngine; +using UnityEngine.Internal; +using System; + +namespace AmplifyShaderEditor +{ + public class UndoUtils + { + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UndoUtils.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UndoUtils.cs.meta new file mode 100644 index 0000000..e4ad8c0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UndoUtils.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 89dee7566d97f1847b9fe114e1c9a1a2 +timeCreated: 1489603190 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UpperLeftWidgetHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UpperLeftWidgetHelper.cs new file mode 100644 index 0000000..9e92fe2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UpperLeftWidgetHelper.cs @@ -0,0 +1,91 @@ +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public class UpperLeftWidgetHelper + { + public int DrawWidget( ParentNode owner, int selectedIndex, GUIContent[] displayedOptions ) + { + if( owner.DropdownEditing ) + { + int newValue = owner.EditorGUIPopup( owner.DropdownRect, selectedIndex, displayedOptions, UIUtils.PropertyPopUp ); + if( newValue != selectedIndex ) + { + owner.DropdownEditing = false; + } + return newValue; + } + return selectedIndex; + } + + public int DrawWidget( ParentNode owner, int selectedIndex, string[] displayedOptions ) + { + if( owner.DropdownEditing ) + { + int newValue = owner.EditorGUIPopup( owner.DropdownRect, selectedIndex, displayedOptions, UIUtils.PropertyPopUp ); + if( newValue != selectedIndex ) + { + owner.DropdownEditing = false; + } + return newValue; + } + return selectedIndex; + } + + public int DrawWidget( ParentNode owner, int selectedIndex, string[] displayedOptions, int[] optionValues ) + { + if( owner.DropdownEditing ) + { + int newValue = owner.EditorGUIIntPopup( owner.DropdownRect, selectedIndex, displayedOptions, optionValues, UIUtils.PropertyPopUp ); + if( newValue != selectedIndex ) + { + owner.DropdownEditing = false; + } + return newValue; + } + return selectedIndex; + } + + // GC free version + public void DrawWidget( ref TEnum selectedIndex, ParentNode owner, Action callback ) where TEnum : struct + { + if( owner.DropdownEditing ) + { + Enum asEnumType = selectedIndex as Enum; + if( asEnumType != null ) + { + EditorGUI.BeginChangeCheck(); + selectedIndex = ( owner.EditorGUIEnumPopup( owner.DropdownRect, asEnumType, UIUtils.PropertyPopUp ) as TEnum? ).Value; + if( EditorGUI.EndChangeCheck() ) + { + owner.DropdownEditing = false; + if( callback != null ) + callback( owner ); + } + } + } + } + + /* + * USE THIS OVERRIDE IN CASE THE NODE DOESN'T HAVE PREVIEW + */ + //public override void AfterCommonInit() + //{ + // base.AfterCommonInit(); + // if( PaddingTitleLeft == 0 ) + // { + // PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + // if( PaddingTitleRight == 0 ) + // PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin; + // } + //} + + + /* + * USE THE SOURCE CODE BELOW INTO THE NODE YOU WANT THE WIDGET TO SHOW + */ + //private UpperLeftWidgetHelper m_upperLeftWidget = new UpperLeftWidgetHelper(); + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UpperLeftWidgetHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UpperLeftWidgetHelper.cs.meta new file mode 100644 index 0000000..6e11052 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/UpperLeftWidgetHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 32dbececad3a67a4fbde694ae50ce82c +timeCreated: 1504080603 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowHelper.cs new file mode 100644 index 0000000..3ae6481 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowHelper.cs @@ -0,0 +1,260 @@ +#if UNITY_EDITOR +using System; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +public static class WindowHelper +{ + private class R_EditorWindow + { + private EditorWindow m_instance; + private System.Type m_type; + + public R_EditorWindow( EditorWindow instance ) + { + m_instance = instance; + m_type = instance.GetType(); + } + + public object Parent + { + get + { + var field = m_type.GetField( "m_Parent", BindingFlags.Instance | BindingFlags.NonPublic ); + return field.GetValue( m_instance ); + } + } + + public object Docked + { + get + { + var property = m_type.GetProperty( "docked", BindingFlags.Instance | BindingFlags.NonPublic ); + return property.GetValue( m_instance, null ); + } + } + } + + private class R_DockArea + { + private object m_instance; + private System.Type m_type; + + public R_DockArea( object instance ) + { + m_instance = instance; + m_type = instance.GetType(); + } + + public object Window + { + get + { + var property = m_type.GetProperty( "window", BindingFlags.Instance | BindingFlags.Public ); + return property.GetValue( m_instance, null ); + } + } + + public object ActualView + { + get + { + var field = m_type.GetField( "m_ActualView", BindingFlags.Instance | BindingFlags.NonPublic ); + return field.GetValue( m_instance ); + } + } + + public object OriginalDragSource + { + set + { + var field = m_type.GetField( "s_OriginalDragSource", BindingFlags.Static | BindingFlags.NonPublic ); + field.SetValue( null, value ); + } + } + + + public void AddTab( EditorWindow pane ) + { +#if UNITY_2018_3_OR_NEWER + var method = m_type.GetMethod( "AddTab", BindingFlags.Instance | BindingFlags.Public, null, new System.Type[] { typeof( EditorWindow ), typeof( bool ) }, null ); + if( method != null ) + method.Invoke( m_instance, new object[] { pane, true } ); +#else + var method = m_type.GetMethod( "AddTab", BindingFlags.Instance | BindingFlags.Public, null, new System.Type[] { typeof( EditorWindow ) }, null ); + if( method != null ) + method.Invoke( m_instance, new object[] { pane } ); +#endif + } + + public void RemoveTab( EditorWindow pane ) + { + if( !pane.maximized ) + { + var method = m_type.GetMethod( "RemoveTab", BindingFlags.Instance | BindingFlags.Public, null, new System.Type[] { typeof( EditorWindow ) }, null ); + if( method != null ) + method.Invoke( m_instance, new object[] { pane } ); + } + } + } + + private class R_ContainerWindow + { + private object m_instance; + private System.Type m_type; + + public R_ContainerWindow( object instance ) + { + m_instance = instance; + m_type = instance.GetType(); + } + + public object RootSplitView + { + get + { + var property = m_type.GetProperty( "rootSplitView", BindingFlags.Instance | BindingFlags.Public ); + return property.GetValue( m_instance, null ); + } + } + + public object RootView + { + get + { + var property = m_type.GetProperty( "rootView", BindingFlags.Instance | BindingFlags.Public ); + return property.GetValue( m_instance, null ); + } + } + + public object WindowPtr + { + get + { + var all = m_type.GetNestedTypes(); + foreach( var item in all ) + { + Debug.Log( item.Name ); + } + var property = m_type.GetField( "m_WindowPtr", BindingFlags.Instance | BindingFlags.NonPublic ); + return property.GetValue( m_instance ); + } + } + } + + private class R_SplitView + { + private object m_instance; + private System.Type m_type; + + public R_SplitView( object instance ) + { + m_instance = instance; + m_type = instance.GetType(); + } + + public object DragOver( EditorWindow child, Vector2 screenPoint ) + { + var method = m_type.GetMethod( "DragOver", BindingFlags.Instance | BindingFlags.Public ); + return method.Invoke( m_instance, new object[] { child, screenPoint } ); + } + + public void PerformDrop( EditorWindow child, object dropInfo, Vector2 screenPoint ) + { + var method = m_type.GetMethod( "PerformDrop", BindingFlags.Instance | BindingFlags.Public ); + method.Invoke( m_instance, new object[] { child, dropInfo, screenPoint } ); + } + } + + public enum DockPosition + { + Left, + Top, + Right, + Bottom + } + + public static bool IsDocked( this EditorWindow wnd ) + { +#if UNITY_2020_2_OR_NEWER + return wnd.docked; +#else + var parent = new R_EditorWindow( wnd ); + return (bool)parent.Docked; +#endif + } + + public static void Undock( this EditorWindow wnd ) + { + var parent = new R_EditorWindow( wnd ); + var dockArea = new R_DockArea( parent.Parent ); + dockArea.RemoveTab( wnd ); + wnd.Show( true ); + } + + public static void RemoveTab( this EditorWindow wnd ) + { + var parent = new R_EditorWindow( wnd ); + var dockArea = new R_DockArea( parent.Parent ); + dockArea.RemoveTab( wnd ); + } + + /// + /// Docks the second window to the first window at the given position + /// + public static void Dock( this EditorWindow wnd, EditorWindow other, DockPosition position ) + { + var mousePosition = GetFakeMousePosition( wnd, position ); + + var parent = new R_EditorWindow( wnd ); + var child = new R_EditorWindow( other ); + var dockArea = new R_DockArea( parent.Parent ); + var containerWindow = new R_ContainerWindow( dockArea.Window ); + var splitView = new R_SplitView( containerWindow.RootSplitView ); + var dropInfo = splitView.DragOver( other, mousePosition ); + dockArea.OriginalDragSource = child.Parent; + splitView.PerformDrop( other, dropInfo, mousePosition ); + } + + + /// + /// Adds the the second window as a tab at the end of the first window tab list + /// + /// + /// + public static void AddTab( this EditorWindow existingWindow, EditorWindow newWindow ) + { + var parent = new R_EditorWindow( existingWindow ); + var child = new R_EditorWindow( newWindow ); + var dockArea = new R_DockArea( parent.Parent ); + dockArea.OriginalDragSource = child.Parent; + dockArea.AddTab( newWindow ); + } + + private static Vector2 GetFakeMousePosition( EditorWindow wnd, DockPosition position ) + { + Vector2 mousePosition = Vector2.zero; + + // The 20 is required to make the docking work. + // Smaller values might not work when faking the mouse position. + switch ( position ) + { + case DockPosition.Left: + mousePosition = new Vector2( 20, wnd.position.size.y / 2 ); + break; + case DockPosition.Top: + mousePosition = new Vector2( wnd.position.size.x / 2, 20 ); + break; + case DockPosition.Right: + mousePosition = new Vector2( wnd.position.size.x - 20, wnd.position.size.y / 2 ); + break; + case DockPosition.Bottom: + mousePosition = new Vector2( wnd.position.size.x / 2, wnd.position.size.y - 20 ); + break; + } + + return GUIUtility.GUIToScreenPoint( mousePosition ); + } +} +#endif diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowHelper.cs.meta new file mode 100644 index 0000000..4b58919 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ad6ef05d39dc39e42b8bfe0bdb826b7a +timeCreated: 1494336778 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowsUtil.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowsUtil.cs new file mode 100644 index 0000000..3a57b9b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowsUtil.cs @@ -0,0 +1,148 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +#if UNITY_EDITOR_WIN + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +public class WindowsUtil +{ + public const int GWL_STYLE = -16; //hex constant for style changing + public const int WS_BORDER = 0x00800000; //window with border + public const int WS_CAPTION = 0x00C00000; //window with a title bar with border + public const int WS_SYSMENU = 0x00080000; //window with no borders etc. + public const int WS_MAXIMIZE = 0x01000000; + public const int WS_MAXIMIZEBOX = 0x00010000; + public const int WS_MINIMIZE = 0x20000000; + public const int WS_MINIMIZEBOX = 0x00020000; + public const int WS_SIZEBOX = 0x00040000; + public const int WS_VISIBLE = 0x10000000; + public const int WS_TABSTOP = 0x00010000; + public const int WS_CLIPCHILDREN = 0x02000000; + public const int WS_CLIPSIBLINGS = 0x04000000; + + [DllImport( "user32.dll", EntryPoint = "SetWindowPos" )] + public static extern bool SetWindowPos( System.IntPtr hwnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags ); + + public delegate bool EnumWindowsProc( System.IntPtr hWnd, System.IntPtr lParam ); + + [DllImport( "user32.dll", CharSet = CharSet.Auto, ExactSpelling = true )] + public static extern IntPtr GetDesktopWindow(); + + [DllImport( "user32.dll" )] + public static extern int SetWindowLong( IntPtr hWnd, int nIndex, int dwNewLong ); + + [DllImport( "user32.dll" )] + public static extern int GetWindowLong( IntPtr hWnd, int nIndex ); + + [DllImport( "user32.dll", ExactSpelling = true, SetLastError = true )] + internal static extern int MapWindowPoints( IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref Rect rect, [MarshalAs( UnmanagedType.U4 )] int cPoints ); + + [DllImport( "user32.dll" )] + public static extern bool EnumWindows( EnumWindowsProc enumProc, System.IntPtr lParam ); + + [DllImport( "user32" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool EnumChildWindows( IntPtr window, EnumWindowProc callback, IntPtr lParam ); + + public delegate bool EnumWindowProc( IntPtr hwnd, IntPtr lParam ); + + [DllImport( "user32.dll", SetLastError = true )] + public static extern bool MoveWindow( IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint ); + + [DllImport( "user32.dll", CharSet = CharSet.Auto, SetLastError = true )] + public static extern int GetWindowThreadProcessId( System.IntPtr handle, out int processId ); + + [DllImport( "user32.dll", SetLastError = true )] + public static extern IntPtr FindWindowEx( string lpClassName, string lpWindowName ); + + // Find window by Caption only. Note you must pass IntPtr.Zero as the first parameter. + [DllImport( "user32.dll", EntryPoint = "FindWindow", SetLastError = true )] + public static extern IntPtr FindWindowByCaptionEx( IntPtr ZeroOnly, string lpWindowName ); + + [DllImport( "user32.dll", SetLastError = true, CharSet = CharSet.Auto )] + public static extern int GetClassName( IntPtr hWnd, StringBuilder lpClassName, int nMaxCount ); + + [DllImport( "user32.dll" )] + public static extern int GetWindowText( System.IntPtr hWnd, StringBuilder text, int nMaxCount ); + + [DllImport( "user32.dll" )] + public static extern int GetWindowTextLength( System.IntPtr hWnd ); + + [DllImport( "user32.dll" )] + public static extern IntPtr FindWindowEx( IntPtr parentWindow, IntPtr previousChildWindow, string windowClass, string windowTitle ); + + [DllImport( "user32.dll" )] + public static extern IntPtr GetActiveWindow(); + + [DllImport( "user32.dll" )] + public static extern bool GetWindowRect( System.IntPtr hwnd, ref Rect rectangle ); + + static public IntPtr[] GetProcessWindows( int processId ) + { + List output = new List(); + IntPtr winPtr = IntPtr.Zero; + do + { + winPtr = FindWindowEx( IntPtr.Zero, winPtr, null, null ); + int id; + GetWindowThreadProcessId( winPtr, out id ); + if( id == processId ) + output.Add( winPtr ); + } while( winPtr != IntPtr.Zero ); + + return output.ToArray(); + } + + public struct Rect + { + public int Left { get; set; } + public int Top { get; set; } + public int Right { get; set; } + public int Bottom { get; set; } + public int Width { get { return Right - Left; } } + public int Height { get { return Bottom - Top; } } + + public override string ToString() + { + return "(l: " + Left + ", r: " + Right + ", t: " + Top + ", b: " + Bottom + ")"; + } + } + + public static bool GetProcessRect( System.Diagnostics.Process process, ref Rect rect ) + { + IntPtr[] winPtrs = WindowsUtil.GetProcessWindows( process.Id ); + + for( int i = 0; i < winPtrs.Length; i++ ) + { + bool gotRect = WindowsUtil.GetWindowRect( winPtrs[ i ], ref rect ); + if( gotRect && ( rect.Left != 0 && rect.Top != 0 ) ) + return true; + } + return false; + } + + public static void SetWindowPosition( int x, int y, int sizeX = 0, int sizeY = 0 ) + { + System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess(); + process.Refresh(); + + EnumWindows( delegate ( System.IntPtr wnd, System.IntPtr param ) + { + int id; + GetWindowThreadProcessId( wnd, out id ); + if( id == process.Id ) + { + SetWindowPos( wnd, 0, x, y, sizeX, sizeY, sizeX * sizeY == 0 ? 1 : 0 ); + return false; + } + + return true; + }, System.IntPtr.Zero ); + } +} + +#endif \ No newline at end of file diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowsUtil.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowsUtil.cs.meta new file mode 100644 index 0000000..8200f79 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/WindowsUtil.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 84d9a18b60b810c4c894886264a89da0 +timeCreated: 1559138384 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Version.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Version.meta new file mode 100644 index 0000000..c5ba7b8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Version.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6072f991722ef6c44b167cf204724a52 +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Version/About.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Version/About.cs new file mode 100644 index 0000000..a147751 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Version/About.cs @@ -0,0 +1,66 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + public class About : EditorWindow + { + private const string AboutImageGUID = "8aba6bb20faf8824d9d81946542f1ce1"; + private Vector2 m_scrollPosition = Vector2.zero; + private Texture2D m_aboutImage; + + [MenuItem( "Window/Amplify Shader Editor/About...", false, 2001 )] + static void Init() + { + About window = (About)GetWindow( typeof( About ), true, "About Amplify Shader Editor" ); + window.minSize = new Vector2( 502, 290 ); + window.maxSize = new Vector2( 502, 290 ); + window.Show(); + } + + [MenuItem( "Window/Amplify Shader Editor/Manual", false, 2000 )] + static void OpenManual() + { + Application.OpenURL( "http://wiki.amplify.pt/index.php?title=Unity_Products:Amplify_Shader_Editor/Manual" ); + } + + private void OnEnable() + { + m_aboutImage = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( AboutImageGUID ) ); + } + + public void OnGUI() + { + m_scrollPosition = GUILayout.BeginScrollView( m_scrollPosition ); + + GUILayout.BeginVertical(); + + GUILayout.Space( 10 ); + + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + GUILayout.Box( m_aboutImage, GUIStyle.none ); + + if( Event.current.type == EventType.MouseUp && GUILayoutUtility.GetLastRect().Contains( Event.current.mousePosition ) ) + Application.OpenURL( "http://www.amplify.pt" ); + + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + + GUIStyle labelStyle = new GUIStyle( EditorStyles.label ); + labelStyle.alignment = TextAnchor.MiddleCenter; + labelStyle.wordWrap = true; + + GUILayout.Label( "\nAmplify Shader Editor " + VersionInfo.StaticToString(), labelStyle, GUILayout.ExpandWidth( true ) ); + + GUILayout.Label( "\nCopyright (c) Amplify Creations, Lda. All rights reserved.\n", labelStyle, GUILayout.ExpandWidth( true ) ); + + GUILayout.EndVertical(); + + GUILayout.EndScrollView(); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Version/About.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Version/About.cs.meta new file mode 100644 index 0000000..1f8de1d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Version/About.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b52649079e4f9ef488724bd3c72449ed +timeCreated: 1481126958 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Version/VersionInfo.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Version/VersionInfo.cs new file mode 100644 index 0000000..df0a7fa --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Version/VersionInfo.cs @@ -0,0 +1,31 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; + +namespace AmplifyShaderEditor +{ + [Serializable] + public class VersionInfo + { + public const byte Major = 1; + public const byte Minor = 8; + public const byte Release = 9; + public static byte Revision = 12; + + //private static string StageSuffix = "_dev0"+Revision; + + //public static string StaticToString() + //{ + // return string.Format( "{0}.{1}.{2}", Major, Minor, Release ) + StageSuffix; + //} + + public static string StaticToString() + { + return string.Format( "{0}.{1}.{2}", Major, Minor, Release ) + ( Revision > 0 ? "r" + Revision.ToString() : "" ); + } + + public static int FullNumber { get { return Major * 10000 + Minor * 1000 + Release * 100 + Revision; } } + public static string FullLabel { get { return "Version=" + FullNumber; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Version/VersionInfo.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Version/VersionInfo.cs.meta new file mode 100644 index 0000000..f5edff8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Version/VersionInfo.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 581602482686da34180d35b169cd357a +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires.meta new file mode 100644 index 0000000..04d01cf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 81b7f9ca313139248a5500a6da3c8a12 +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/GLDraw.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/GLDraw.cs new file mode 100644 index 0000000..ab8011f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/GLDraw.cs @@ -0,0 +1,156 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public class GLDraw + { + /* + * Clipping code: http://forum.unity3d.com/threads/17066-How-to-draw-a-GUI-2D-quot-line-quot?p=230386#post230386 + * Thick line drawing code: http://unifycommunity.com/wiki/index.php?title=VectorLine + */ + public static Material LineMaterial = null; + public static bool MultiLine = false; + private static Shader LineShader = null; + private static Rect BoundBox = new Rect(); + private static Vector3[] Allv3Points = new Vector3[] { }; + private static Vector2[] AllPerpendiculars = new Vector2[] { }; + private static Color[] AllColors = new Color[] { }; + private static Vector2 StartPt = Vector2.zero; + private static Vector2 EndPt = Vector2.zero; + + private static Vector3 Up = new Vector3( 0, 1, 0 ); + private static Vector3 Zero = new Vector3( 0, 0, 0 ); + + private static Vector2 Aux1Vec2 = Vector2.zero; + + private static int HigherBoundArray = 0; + + public static void CreateMaterial() + { + if( (object)LineMaterial != null && (object)LineShader != null ) + return; + + LineShader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "50fc796413bac8b40aff70fb5a886273" ) ); + LineMaterial = new Material( LineShader ); + + LineMaterial.hideFlags = HideFlags.HideAndDontSave; + } + + public static void DrawCurve( Vector3[] allPoints, Vector2[] allNormals, Color[] allColors, int pointCount ) + { + CreateMaterial(); + LineMaterial.SetPass( ( MultiLine ? 1 : 0 ) ); + + GL.Begin( GL.TRIANGLE_STRIP ); + for( int i = 0; i < pointCount; i++ ) + { + GL.Color( allColors[ i ] ); + GL.TexCoord( Zero ); + GL.Vertex3( allPoints[ i ].x - allNormals[ i ].x, allPoints[ i ].y - allNormals[ i ].y, 0 ); + GL.TexCoord( Up ); + GL.Vertex3( allPoints[ i ].x + allNormals[ i ].x, allPoints[ i ].y + allNormals[ i ].y, 0 ); + } + GL.End(); + + } + + public static Rect DrawBezier( Vector2 start, Vector2 startTangent, Vector2 end, Vector2 endTangent, Color color, float width, int type = 1 ) + { + int segments = Mathf.FloorToInt( ( start - end ).magnitude / 20 ) * 3; // Three segments per distance of 20 + return DrawBezier( start, startTangent, end, endTangent, color, width, segments, type ); + } + + public static Rect DrawBezier( Vector2 start, Vector2 startTangent, Vector2 end, Vector2 endTangent, Color color, float width, int segments, int type = 1 ) + { + return DrawBezier( start, startTangent, end, endTangent, color, color, width, segments, type ); + } + + public static Rect DrawBezier( Vector2 start, Vector2 startTangent, Vector2 end, Vector2 endTangent, Color startColor, Color endColor, float width, int segments, int type = 1 ) + { + int pointsCount = segments + 1; + int linesCount = segments; + + HigherBoundArray = HigherBoundArray > pointsCount ? HigherBoundArray : pointsCount; + + Allv3Points = Handles.MakeBezierPoints( start, end, startTangent, endTangent, pointsCount ); + if( AllColors.Length < HigherBoundArray ) + { + AllColors = new Color[ HigherBoundArray ]; + AllPerpendiculars = new Vector2[ HigherBoundArray ]; + } + + startColor.a = ( type * 0.25f ); + endColor.a = ( type * 0.25f ); + + float minX = Allv3Points[ 0 ].x; + float minY = Allv3Points[ 0 ].y; + float maxX = Allv3Points[ 0 ].x; + float maxY = Allv3Points[ 0 ].y; + + float amount = 1 / (float)linesCount; + for( int i = 0; i < pointsCount; i++ ) + { + if( i == 0 ) + { + AllColors[ 0 ] = startColor; + StartPt.Set( startTangent.y, start.x ); + EndPt.Set( start.y, startTangent.x ); + } + else if( i == pointsCount - 1 ) + { + AllColors[ pointsCount - 1 ] = endColor; + StartPt.Set( end.y, endTangent.x ); + EndPt.Set( endTangent.y, end.x ); + } + else + { + AllColors[ i ] = Color.LerpUnclamped( startColor, endColor, amount * i ); + + minX = ( Allv3Points[ i ].x < minX ) ? Allv3Points[ i ].x : minX; + minY = ( Allv3Points[ i ].y < minY ) ? Allv3Points[ i ].y : minY; + maxX = ( Allv3Points[ i ].x > maxX ) ? Allv3Points[ i ].x : maxX; + maxY = ( Allv3Points[ i ].y > maxY ) ? Allv3Points[ i ].y : maxY; + StartPt.Set( Allv3Points[ i + 1 ].y, Allv3Points[ i - 1 ].x ); + EndPt.Set( Allv3Points[ i - 1 ].y, Allv3Points[ i + 1 ].x ); + } + Aux1Vec2.Set( StartPt.x - EndPt.x, StartPt.y - EndPt.y ); + FastNormalized( ref Aux1Vec2 ); + //aux1Vec2.FastNormalized(); + Aux1Vec2.Set( Aux1Vec2.x * width, Aux1Vec2.y * width ); + AllPerpendiculars[ i ] = Aux1Vec2; + } + + BoundBox.Set( minX, minY, ( maxX - minX ), ( maxY - minY ) ); + + DrawCurve( Allv3Points, AllPerpendiculars, AllColors, pointsCount ); + return BoundBox; + } + + private static void FastNormalized( ref Vector2 v ) + { + float len = Mathf.Sqrt( v.x * v.x + v.y * v.y ); + v.Set( v.x / len, v.y / len ); + } + + public static void Destroy() + { + GameObject.DestroyImmediate( LineMaterial ); + LineMaterial = null; + + Resources.UnloadAsset( LineShader ); + LineShader = null; + } + } + + //public static class VectorEx + //{ + // public static void FastNormalized( this Vector2 v ) + // { + // float len = Mathf.Sqrt( v.x * v.x + v.y * v.y ); + // v.Set( v.x / len, v.y / len ); + // } + //} +} + diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/GLDraw.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/GLDraw.cs.meta new file mode 100644 index 0000000..0f466ab --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/GLDraw.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7647d2525992b7748a587740fd596977 +timeCreated: 1481126956 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/InputPort.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/InputPort.cs new file mode 100644 index 0000000..0e2131e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/InputPort.cs @@ -0,0 +1,1527 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; +using UnityEditor; + +namespace AmplifyShaderEditor +{ + [Serializable] + public sealed class InputPort : WirePort + { + private const string InputDefaultNameStr = "Input"; + [SerializeField] + private int m_externalNodeLink = -1; + + [SerializeField] + private int m_externalPortLink = -1; + + [SerializeField] + private string m_externalLinkId = string.Empty; + + [SerializeField] + private bool m_typeLocked; + + [SerializeField] + private string m_internalData = string.Empty; + + [SerializeField] + private string m_internalDataWrapper = string.Empty; + + [SerializeField] + private string m_dataName = string.Empty; + + [SerializeField] + private string m_internalDataPropertyLabel = string.Empty; + + // this will only is important on master node + [SerializeField] + private MasterNodePortCategory m_category = MasterNodePortCategory.Fragment; + + [SerializeField] + private PortGenType m_genType; + + private string m_propertyName = string.Empty; + private int m_cachedPropertyId = -1; + + private int m_cachedIntShaderID = -1; + private int m_cachedFloatShaderID = -1; + private int m_cachedVectorShaderID = -1; + private int m_cachedColorShaderID = -1; + private int m_cached2DShaderID = -1; + private int m_cachedDefaultTexShaderID = -1; + + [SerializeField] + private bool m_drawInternalData = false; + + //[SerializeField] + //private RenderTexture m_inputPreview = null; + //[SerializeField] + private RenderTexture m_inputPreviewTexture = null; + private Material m_inputPreviewMaterial = null; + private Shader m_inputPreviewShader = null; + + [SerializeField] + private int m_previewInternalInt = 0; + [SerializeField] + private float m_previewInternalFloat = 0; + [SerializeField] + private Vector2 m_previewInternalVec2 = Vector2.zero; + [SerializeField] + private Vector3 m_previewInternalVec3 = Vector3.zero; + [SerializeField] + private Vector4 m_previewInternalVec4 = Vector4.zero; + [SerializeField] + private Color m_previewInternalColor = Color.clear; + [SerializeField] + private Matrix4x4 m_previewInternalMatrix4x4 = Matrix4x4.identity; + + private int m_propertyNameInt = 0; + private ParentNode m_node = null; + + public InputPort() : base( -1, -1, WirePortDataType.FLOAT, string.Empty ) { m_typeLocked = true; } + public InputPort( int nodeId, int portId, WirePortDataType dataType, string name, bool typeLocked, int orderId = -1, MasterNodePortCategory category = MasterNodePortCategory.Fragment, PortGenType genType = PortGenType.NonCustomLighting ) : base( nodeId, portId, dataType, name, orderId ) + { + m_dataName = name; + m_internalDataPropertyLabel = ( string.IsNullOrEmpty( name ) || name.Equals( Constants.EmptyPortValue ) ) ? InputDefaultNameStr : name; + m_typeLocked = typeLocked; + m_category = category; + m_genType = genType; + } + + public InputPort( int nodeId, int portId, WirePortDataType dataType, string name, string dataName, bool typeLocked, int orderId = -1, MasterNodePortCategory category = MasterNodePortCategory.Fragment, PortGenType genType = PortGenType.NonCustomLighting ) : base( nodeId, portId, dataType, name, orderId ) + { + m_dataName = dataName; + m_internalDataPropertyLabel = ( string.IsNullOrEmpty( name ) || name.Equals( Constants.EmptyPortValue ) ) ? InputDefaultNameStr : name; + m_typeLocked = typeLocked; + m_category = category; + m_genType = genType; + } + + public void SetExternalLink( int nodeId, int portId ) + { + m_externalNodeLink = nodeId; + m_externalPortLink = portId; + } + + public override bool CheckValidType( WirePortDataType dataType ) + { + if( m_typeLocked ) + return ( dataType == m_dataType ); + + return base.CheckValidType( dataType ); + } + + public override void FullDeleteConnections() + { + UIUtils.DeleteConnection( true, m_nodeId, m_portId, true, true ); + } + + public override void NotifyExternalRefencesOnChange() + { + for( int i = 0; i < m_externalReferences.Count; i++ ) + { + ParentNode node = UIUtils.GetNode( m_externalReferences[ i ].NodeId ); + if( node ) + { + OutputPort port = node.GetOutputPortByUniqueId( m_externalReferences[ i ].PortId ); + port.UpdateInfoOnExternalConn( m_nodeId, m_portId, m_dataType ); + node.OnConnectedInputNodeChanges( m_externalReferences[ i ].PortId, m_nodeId, m_portId, m_name, m_dataType ); + } + } + } + + public void UpdatePreviewInternalData() + { + switch( m_dataType ) + { + case WirePortDataType.INT: m_previewInternalInt = IntInternalData; break; + case WirePortDataType.FLOAT: m_previewInternalFloat = FloatInternalData; break; + case WirePortDataType.FLOAT2: m_previewInternalVec2 = Vector2InternalData; break; + case WirePortDataType.FLOAT3: m_previewInternalVec3 = Vector3InternalData; break; + case WirePortDataType.FLOAT4: m_previewInternalVec4 = Vector4InternalData; break; + case WirePortDataType.COLOR: m_previewInternalColor = ColorInternalData; break; + } + } + + void UpdateVariablesFromInternalData() + { + string[] data = String.IsNullOrEmpty( m_internalData ) ? null : m_internalData.Split( IOUtils.VECTOR_SEPARATOR ); + bool reset = ( data == null || data.Length == 0 ); + m_internalDataUpdated = false; + try + { + switch( m_dataType ) + { + case WirePortDataType.OBJECT:break; + case WirePortDataType.FLOAT: m_previewInternalFloat = reset ? 0 : Convert.ToSingle( data[ 0 ] ); break; + case WirePortDataType.INT: + { + if( reset ) + { + m_previewInternalInt = 0; + } + else + { + if( data[ 0 ].Contains( "." ) ) + { + m_previewInternalInt = (int)Convert.ToSingle( data[ 0 ] ); + } + else + { + m_previewInternalInt = Convert.ToInt32( data[ 0 ] ); + } + } + } + break; + case WirePortDataType.FLOAT2: + { + if( reset ) + { + m_previewInternalVec2 = Vector2.zero; + } + else + { + if( data.Length < 2 ) + { + m_previewInternalVec2.x = Convert.ToSingle( data[ 0 ] ); + m_previewInternalVec2.y = 0; + } + else + { + m_previewInternalVec2.x = Convert.ToSingle( data[ 0 ] ); + m_previewInternalVec2.y = Convert.ToSingle( data[ 1 ] ); + } + } + } + break; + case WirePortDataType.FLOAT3: + { + if( reset ) + { + m_previewInternalVec3 = Vector3.zero; + } + else + { + int count = Mathf.Min( data.Length, 3 ); + for( int i = 0; i < count; i++ ) + { + m_previewInternalVec3[ i ] = Convert.ToSingle( data[ i ] ); + } + if( count < 3 ) + { + for( int i = count; i < 3; i++ ) + { + m_previewInternalVec3[ i ] = 0; + } + } + } + + } + break; + case WirePortDataType.FLOAT4: + { + if( reset ) + { + m_previewInternalVec4 = Vector4.zero; + } + else + { + int count = Mathf.Min( data.Length, 4 ); + for( int i = 0; i < count; i++ ) + { + m_previewInternalVec4[ i ] = Convert.ToSingle( data[ i ] ); + } + if( count < 4 ) + { + for( int i = count; i < 4; i++ ) + { + m_previewInternalVec4[ i ] = 0; + } + } + } + } + break; + case WirePortDataType.COLOR: + { + if( reset ) + { + m_previewInternalColor = Color.black; + } + else + { + int count = Mathf.Min( data.Length, 4 ); + for( int i = 0; i < count; i++ ) + { + m_previewInternalColor[ i ] = Convert.ToSingle( data[ i ] ); + } + if( count < 4 ) + { + for( int i = count; i < 4; i++ ) + { + m_previewInternalColor[ i ] = 0; + } + } + } + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + if( reset ) + { + m_previewInternalMatrix4x4 = Matrix4x4.identity; + } + else + { + int count = Mathf.Min( data.Length, 16 ); + int overallIdx = 0; + for( int i = 0; i < 4; i++ ) + { + for( int j = 0; j < 4; j++ ) + { + if( overallIdx < count ) + { + m_previewInternalMatrix4x4[ i, j ] = Convert.ToSingle( data[ overallIdx ] ); + } + else + { + m_previewInternalMatrix4x4[ i, j ] = ( ( i == j ) ? 1 : 0 ); + } + overallIdx++; + } + } + } + } + break; + } + } + catch( Exception e ) + { + if( DebugConsoleWindow.DeveloperMode ) + Debug.LogException( e ); + } + } + + void UpdateInternalDataFromVariables( bool forceDecimal = false ) + { + switch( m_dataType ) + { + case WirePortDataType.OBJECT:break; + case WirePortDataType.FLOAT: + { + if( forceDecimal && m_previewInternalFloat == (int)m_previewInternalFloat ) + m_internalData = m_previewInternalFloat.ToString("0.0##############"); // to make sure integer values like 0 or 1 are generated as 0.0 and 1.0 + else + m_internalData = m_previewInternalFloat.ToString(); + m_internalDataWrapper = string.Empty; + } + break; + case WirePortDataType.INT: + { + m_internalData = m_previewInternalInt.ToString(); + m_internalDataWrapper = string.Empty; + } + break; + case WirePortDataType.FLOAT2: + { + m_internalData = m_previewInternalVec2.x.ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalVec2.y.ToString(); + m_internalDataWrapper = "float2( {0} )"; + } + break; + case WirePortDataType.FLOAT3: + { + m_internalData = m_previewInternalVec3.x.ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalVec3.y.ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalVec3.z.ToString(); + m_internalDataWrapper = "float3( {0} )"; + } + break; + case WirePortDataType.FLOAT4: + { + m_internalData = m_previewInternalVec4.x.ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalVec4.y.ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalVec4.z.ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalVec4.w.ToString(); + + m_internalDataWrapper = "float4( {0} )"; + } + break; + case WirePortDataType.COLOR: + { + m_internalData = m_previewInternalColor.r.ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalColor.g.ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalColor.b.ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalColor.a.ToString(); + + m_internalDataWrapper = "float4( {0} )"; + } + break; + case WirePortDataType.FLOAT3x3: + { + m_internalData = m_previewInternalMatrix4x4[ 0, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 0, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 0, 2 ].ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalMatrix4x4[ 1, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 1, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 1, 2 ].ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalMatrix4x4[ 2, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 2, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 2, 2 ].ToString(); + + m_internalDataWrapper = "float3x3( {0} )"; + + } + break; + case WirePortDataType.FLOAT4x4: + { + m_internalData = m_previewInternalMatrix4x4[ 0, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 0, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 0, 2 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 0, 3 ].ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalMatrix4x4[ 1, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 1, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 1, 2 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 1, 3 ].ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalMatrix4x4[ 2, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 2, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 2, 2 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 2, 3 ].ToString() + IOUtils.VECTOR_SEPARATOR + + m_previewInternalMatrix4x4[ 3, 0 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 3, 1 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 3, 2 ].ToString() + IOUtils.VECTOR_SEPARATOR + m_previewInternalMatrix4x4[ 3, 3 ].ToString(); + + m_internalDataWrapper = "float4x4( {0} )"; + } + break; + } + } + + //This gets the 3x3 matrix inside of the 4x4 + private string Matrix3x3WrappedData() + { + string tempInternal = string.Empty; + + string[] data = String.IsNullOrEmpty( m_internalData ) ? null : m_internalData.Split( IOUtils.VECTOR_SEPARATOR ); + if( data.Length == 16 ) + { + int o = 0; + for( int i = 0; i < 8; i++ ) + { + if( i == 3 || i == 6 ) + o++; + tempInternal += data[ i + o ] + IOUtils.VECTOR_SEPARATOR; + } + + tempInternal += data[ 10 ]; + + return String.Format( m_internalDataWrapper, tempInternal ); + } + else + { + return String.Format( m_internalDataWrapper, m_internalData ); + } + } + + private string SamplerWrappedData( ref MasterNodeDataCollector dataCollector ) + { + m_internalData = "_Sampler" + PortId + UIUtils.GetNode( m_nodeId ).OutputId; + + dataCollector.AddToUniforms( m_nodeId, GeneratorUtils.GetPropertyDeclaraction( m_internalData, TextureType.Texture2D, ";" ) ); + + return m_internalData; + } + + //TODO: Replace GenerateShaderForOutput(...) calls to this one + // This is a new similar method to GenerateShaderForOutput(...) which always autocasts + public string GeneratePortInstructions( ref MasterNodeDataCollector dataCollector ) + { + InputPort linkPort = ExternalLink; + if( linkPort != null ) + { + return linkPort.GeneratePortInstructions( ref dataCollector ); + } + + string result = string.Empty; + if( m_externalReferences.Count > 0 && !m_locked ) + { + result = UIUtils.GetNode( m_externalReferences[ 0 ].NodeId ).GenerateShaderForOutput( m_externalReferences[ 0 ].PortId, ref dataCollector, false ); + if( m_externalReferences[ 0 ].DataType != m_dataType ) + { + result = UIUtils.CastPortType( ref dataCollector, UIUtils.GetNode( m_nodeId ).CurrentPrecisionType, new NodeCastInfo( m_externalReferences[ 0 ].NodeId, m_externalReferences[ 0 ].PortId ), null, m_externalReferences[ 0 ].DataType, m_dataType, result ); + } + } + else + { + UpdateInternalDataFromVariables( true ); + if( DataType == WirePortDataType.FLOAT3x3 ) + result = Matrix3x3WrappedData(); + else if( DataType == WirePortDataType.SAMPLER2D ) + result = SamplerWrappedData( ref dataCollector ); + else + result = !String.IsNullOrEmpty( m_internalDataWrapper ) ? String.Format( m_internalDataWrapper, m_internalData ) : m_internalData; + } + return result; + } + + public string GenerateShaderForOutput( ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar ) + { + InputPort linkPort = ExternalLink; + if( linkPort != null ) + { + return linkPort.GenerateShaderForOutput( ref dataCollector, ignoreLocalVar ); + } + + string result = string.Empty; + if( m_externalReferences.Count > 0 && !m_locked ) + { + result = UIUtils.GetNode( m_externalReferences[ 0 ].NodeId ).GenerateShaderForOutput( m_externalReferences[ 0 ].PortId, ref dataCollector, ignoreLocalVar ); + } + else + { + UpdateInternalDataFromVariables( true ); + if( !String.IsNullOrEmpty( m_internalDataWrapper ) ) + { + if( DataType == WirePortDataType.FLOAT3x3 ) + result = Matrix3x3WrappedData(); + else + result = String.Format( m_internalDataWrapper, m_internalData ); + } + else + { + result = m_internalData; + } + } + return result; + } + + public string GenerateShaderForOutput( ref MasterNodeDataCollector dataCollector, WirePortDataType inputPortType, bool ignoreLocalVar, bool autoCast = false ) + { + InputPort linkPort = ExternalLink; + if( linkPort != null ) + { + return linkPort.GenerateShaderForOutput( ref dataCollector, inputPortType, ignoreLocalVar, autoCast ); + } + + string result = string.Empty; + if( m_externalReferences.Count > 0 && !m_locked ) + { + result = UIUtils.GetNode( m_externalReferences[ 0 ].NodeId ).GenerateShaderForOutput( m_externalReferences[ 0 ].PortId, ref dataCollector, ignoreLocalVar ); + if( autoCast && m_externalReferences[ 0 ].DataType != inputPortType ) + { + result = UIUtils.CastPortType( ref dataCollector, UIUtils.GetNode( m_nodeId ).CurrentPrecisionType, new NodeCastInfo( m_externalReferences[ 0 ].NodeId, m_externalReferences[ 0 ].PortId ), null, m_externalReferences[ 0 ].DataType, inputPortType, result ); + } + } + else + { + UpdateInternalDataFromVariables( true ); + if( !String.IsNullOrEmpty( m_internalDataWrapper ) ) + { + if( DataType == WirePortDataType.FLOAT3x3 ) + result = Matrix3x3WrappedData(); + else + result = String.Format( m_internalDataWrapper, m_internalData ); + } + else + { + result = m_internalData; + } + } + + return result; + } + + public OutputPort GetOutputConnection( int connID = 0 ) + { + if( connID < m_externalReferences.Count ) + { + return UIUtils.GetNode( m_externalReferences[ connID ].NodeId ).GetOutputPortByUniqueId( m_externalReferences[ connID ].PortId ); + } + return null; + } + + public ParentNode GetOutputNodeWhichIsNotRelay( int connID = 0 ) + { + if( connID < m_externalReferences.Count ) + { + ParentNode node = UIUtils.GetNode( m_externalReferences[ connID ].NodeId ); + if( node is WireNode || node is RelayNode || node is FunctionInput ) + { + return node.InputPorts[ 0 ].GetOutputNodeWhichIsNotRelay( connID ); + } + + return node; + } + return null; + } + + public ParentNode GetOutputNode( int connID = 0 ) + { + if( connID < m_externalReferences.Count ) + { + return UIUtils.GetNode( m_externalReferences[ connID ].NodeId ); + } + return null; + } + + public bool TypeLocked + { + get { return m_typeLocked; } + } + + public void WriteToString( ref string myString ) + { + if( m_externalReferences.Count != 1 || m_isDummy ) + { + return; + } + + IOUtils.AddTypeToString( ref myString, IOUtils.WireConnectionParam ); + IOUtils.AddFieldValueToString( ref myString, m_nodeId ); + IOUtils.AddFieldValueToString( ref myString, m_portId ); + IOUtils.AddFieldValueToString( ref myString, m_externalReferences[ 0 ].NodeId ); + IOUtils.AddFieldValueToString( ref myString, m_externalReferences[ 0 ].PortId ); + IOUtils.AddLineTerminator( ref myString ); + } + + public void ShowInternalData( Rect rect, UndoParentNode owner, bool useCustomLabel = false, string customLabel = null ) + { + string label = ( useCustomLabel == true && customLabel != null ) ? customLabel : m_internalDataPropertyLabel; + switch( m_dataType ) + { + case WirePortDataType.OBJECT: + { + InternalData = owner.EditorGUITextField( rect, label, InternalData ); + } + break; + case WirePortDataType.FLOAT: + { + FloatInternalData = owner.EditorGUIFloatField( rect, label, FloatInternalData ); + } + break; + case WirePortDataType.FLOAT2: + { + Vector2InternalData = owner.EditorGUIVector2Field( rect, label, Vector2InternalData ); + } + break; + case WirePortDataType.FLOAT3: + { + Vector3InternalData = owner.EditorGUIVector3Field( rect, label, Vector3InternalData ); + } + break; + case WirePortDataType.FLOAT4: + { + Vector4InternalData = owner.EditorGUIVector4Field( rect, label, Vector4InternalData ); + } + break; + case WirePortDataType.FLOAT3x3: + { + Matrix4x4 matrix = Matrix4x4InternalData; + Vector3 currVec3 = Vector3.zero; + for( int i = 0; i < 3; i++ ) + { + Vector4 currVec = matrix.GetRow( i ); + currVec3.Set( currVec.x, currVec.y, currVec.z ); + EditorGUI.BeginChangeCheck(); + currVec3 = owner.EditorGUIVector3Field( rect, label + "[ " + i + " ]", currVec3 ); + rect.y += 2*EditorGUIUtility.singleLineHeight; + if( EditorGUI.EndChangeCheck() ) + { + currVec.Set( currVec3.x, currVec3.y, currVec3.z, currVec.w ); + matrix.SetRow( i, currVec ); + } + } + Matrix4x4InternalData = matrix; + } + break; + case WirePortDataType.FLOAT4x4: + { + Matrix4x4 matrix = Matrix4x4InternalData; + for( int i = 0; i < 4; i++ ) + { + Vector4 currVec = matrix.GetRow( i ); + EditorGUI.BeginChangeCheck(); + currVec = owner.EditorGUIVector4Field( rect, label + "[ " + i + " ]", currVec ); + rect.y += 2*EditorGUIUtility.singleLineHeight; + if( EditorGUI.EndChangeCheck() ) + { + matrix.SetRow( i, currVec ); + } + } + Matrix4x4InternalData = matrix; + } + break; + case WirePortDataType.COLOR: + { + ColorInternalData = owner.EditorGUIColorField( rect, label, ColorInternalData ); + } + break; + case WirePortDataType.INT: + { + IntInternalData = owner.EditorGUIIntField( rect, label, IntInternalData ); + } + break; + } + } + + public void ShowInternalData( UndoParentNode owner, bool useCustomLabel = false, string customLabel = null ) + { + string label = ( useCustomLabel == true && customLabel != null ) ? customLabel : m_internalDataPropertyLabel; + switch( m_dataType ) + { + case WirePortDataType.OBJECT: + case WirePortDataType.FLOAT: + { + FloatInternalData = owner.EditorGUILayoutFloatField( label, FloatInternalData ); + } + break; + case WirePortDataType.FLOAT2: + { + Vector2InternalData = owner.EditorGUILayoutVector2Field( label, Vector2InternalData ); + } + break; + case WirePortDataType.FLOAT3: + { + Vector3InternalData = owner.EditorGUILayoutVector3Field( label, Vector3InternalData ); + } + break; + case WirePortDataType.FLOAT4: + { + Vector4InternalData = owner.EditorGUILayoutVector4Field( label, Vector4InternalData ); + } + break; + case WirePortDataType.FLOAT3x3: + { + Matrix4x4 matrix = Matrix4x4InternalData; + Vector3 currVec3 = Vector3.zero; + for( int i = 0; i < 3; i++ ) + { + Vector4 currVec = matrix.GetRow( i ); + currVec3.Set( currVec.x, currVec.y, currVec.z ); + EditorGUI.BeginChangeCheck(); + currVec3 = owner.EditorGUILayoutVector3Field( label + "[ " + i + " ]", currVec3 ); + if( EditorGUI.EndChangeCheck() ) + { + currVec.Set( currVec3.x, currVec3.y, currVec3.z, currVec.w ); + matrix.SetRow( i, currVec ); + } + } + Matrix4x4InternalData = matrix; + } + break; + case WirePortDataType.FLOAT4x4: + { + Matrix4x4 matrix = Matrix4x4InternalData; + for( int i = 0; i < 4; i++ ) + { + Vector4 currVec = matrix.GetRow( i ); + EditorGUI.BeginChangeCheck(); + currVec = owner.EditorGUILayoutVector4Field( label + "[ " + i + " ]", currVec ); + if( EditorGUI.EndChangeCheck() ) + { + matrix.SetRow( i, currVec ); + } + } + Matrix4x4InternalData = matrix; + } + break; + case WirePortDataType.COLOR: + { + ColorInternalData = owner.EditorGUILayoutColorField( label, ColorInternalData ); + } + break; + case WirePortDataType.INT: + { + IntInternalData = owner.EditorGUILayoutIntField( label, IntInternalData ); + } + break; + } + } + public bool IsZeroInternalData + { + get + { + switch( m_dataType ) + { + + case WirePortDataType.FLOAT: return Mathf.Abs(m_previewInternalFloat) < 0.001f; + case WirePortDataType.UINT: + case WirePortDataType.INT: return m_previewInternalInt == 0; + case WirePortDataType.FLOAT2: + return (Mathf.Abs( m_previewInternalVec2.x ) < 0.001f && + Mathf.Abs( m_previewInternalVec2.y ) < 0.001f); + case WirePortDataType.FLOAT3: + return (Mathf.Abs( m_previewInternalVec3.x ) < 0.001f && + Mathf.Abs( m_previewInternalVec3.y ) < 0.001f && + Mathf.Abs( m_previewInternalVec3.z ) < 0.001f ); + case WirePortDataType.UINT4: + case WirePortDataType.FLOAT4: + return (Mathf.Abs( m_previewInternalVec4.x ) < 0.001f && + Mathf.Abs( m_previewInternalVec4.y ) < 0.001f && + Mathf.Abs( m_previewInternalVec4.z ) < 0.001f && + Mathf.Abs( m_previewInternalVec4.w ) < 0.001f ); + case WirePortDataType.COLOR: + return (Mathf.Abs( m_previewInternalColor.r ) < 0.001f && + Mathf.Abs( m_previewInternalColor.g ) < 0.001f && + Mathf.Abs( m_previewInternalColor.b ) < 0.001f && + Mathf.Abs( m_previewInternalColor.a ) < 0.001f); + + } + return true; + } + } + public float FloatInternalData + { + set { m_previewInternalFloat = value; m_internalDataUpdated = false; } + get { return m_previewInternalFloat; } + } + + public int IntInternalData + { + set { m_previewInternalInt = value; m_internalDataUpdated = false; } + get { return m_previewInternalInt; } + } + + public Vector2 Vector2InternalData + { + set { m_previewInternalVec2 = value; m_internalDataUpdated = false; } + get { return m_previewInternalVec2; } + } + + public Vector3 Vector3InternalData + { + set { m_previewInternalVec3 = value; m_internalDataUpdated = false; } + get { return m_previewInternalVec3; } + } + + public Vector4 Vector4InternalData + { + set { m_previewInternalVec4 = value; m_internalDataUpdated = false; } + get { return m_previewInternalVec4; } + } + + public Color ColorInternalData + { + set { m_previewInternalColor = value; m_internalDataUpdated = false; } + get { return m_previewInternalColor; } + } + + public Matrix4x4 Matrix4x4InternalData + { + set { m_previewInternalMatrix4x4 = value; m_internalDataUpdated = false; } + get { return m_previewInternalMatrix4x4; } + } + + public string SamplerInternalData + { + set { InternalData = UIUtils.RemoveInvalidCharacters( value ); m_internalDataUpdated = false; } + get { return m_internalData; } + } + + public override void ForceClearConnection() + { + UIUtils.DeleteConnection( true, m_nodeId, m_portId, false, true ); + } + + private bool m_internalDataUpdated = false; + private string m_displayInternalData = string.Empty; + public string DisplayInternalData + { + get + { + if( !m_internalDataUpdated ) + { + UpdateInternalDataFromVariables(); + m_internalDataUpdated = true; + m_displayInternalData = "( "+ m_internalData + " )"; + } + return m_displayInternalData; + } + } + + public string InternalData + { + get + { + UpdateInternalDataFromVariables(); + return m_internalData; + } + set + { + m_internalData = value; + UpdateVariablesFromInternalData(); + } + } + + public string WrappedInternalData + { + get + { + UpdateInternalDataFromVariables(); + return string.IsNullOrEmpty( m_internalDataWrapper ) ? m_internalData : String.Format( m_internalDataWrapper, m_internalData ); + } + } + + public override WirePortDataType DataType + { + get { return base.DataType; } + // must be set to update internal data. do not delete + set + { + m_internalDataUpdated = false; + switch( DataType ) + { + case WirePortDataType.FLOAT: + { + switch( value ) + { + case WirePortDataType.FLOAT2: m_previewInternalVec2.x = m_previewInternalFloat; break; + case WirePortDataType.FLOAT3: m_previewInternalVec3.x = m_previewInternalFloat; break; + case WirePortDataType.FLOAT4: m_previewInternalVec4.x = m_previewInternalFloat; break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: m_previewInternalMatrix4x4[ 0 ] = m_previewInternalFloat; break; + case WirePortDataType.COLOR: m_previewInternalColor.r = m_previewInternalFloat; break; + case WirePortDataType.INT: m_previewInternalInt = (int)m_previewInternalFloat; break; + } + } + break; + case WirePortDataType.FLOAT2: + { + switch( value ) + { + case WirePortDataType.FLOAT: m_previewInternalFloat = m_previewInternalVec2.x; break; + case WirePortDataType.FLOAT3: + { + m_previewInternalVec3.x = m_previewInternalVec2.x; + m_previewInternalVec3.y = m_previewInternalVec2.y; + } + break; + case WirePortDataType.FLOAT4: + { + m_previewInternalVec4.x = m_previewInternalVec2.x; + m_previewInternalVec4.y = m_previewInternalVec2.y; + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + m_previewInternalMatrix4x4[ 0 ] = m_previewInternalVec2.x; + m_previewInternalMatrix4x4[ 1 ] = m_previewInternalVec2.y; + } + break; + case WirePortDataType.COLOR: + { + m_previewInternalColor.r = m_previewInternalVec2.x; + m_previewInternalColor.g = m_previewInternalVec2.y; + } + break; + case WirePortDataType.INT: m_previewInternalInt = (int)m_previewInternalVec2.x; break; + } + } + break; + case WirePortDataType.FLOAT3: + { + switch( value ) + { + case WirePortDataType.FLOAT: m_previewInternalFloat = m_previewInternalVec3.x; break; + case WirePortDataType.FLOAT2: + { + m_previewInternalVec2.x = m_previewInternalVec3.x; + m_previewInternalVec2.y = m_previewInternalVec3.y; + } + break; + case WirePortDataType.FLOAT4: + { + m_previewInternalVec4.x = m_previewInternalVec3.x; + m_previewInternalVec4.y = m_previewInternalVec3.y; + m_previewInternalVec4.z = m_previewInternalVec3.z; + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + m_previewInternalMatrix4x4[ 0 ] = m_previewInternalVec3.x; + m_previewInternalMatrix4x4[ 1 ] = m_previewInternalVec3.y; + m_previewInternalMatrix4x4[ 2 ] = m_previewInternalVec3.z; + } + break; + case WirePortDataType.COLOR: + { + m_previewInternalColor.r = m_previewInternalVec3.x; + m_previewInternalColor.g = m_previewInternalVec3.y; + m_previewInternalColor.b = m_previewInternalVec3.z; + } + break; + case WirePortDataType.INT: m_previewInternalInt = (int)m_previewInternalVec3.x; break; + } + } + break; + case WirePortDataType.FLOAT4: + { + switch( value ) + { + case WirePortDataType.FLOAT: m_previewInternalFloat = m_previewInternalVec4.x; break; + case WirePortDataType.FLOAT2: + { + m_previewInternalVec2.x = m_previewInternalVec4.x; + m_previewInternalVec2.y = m_previewInternalVec4.y; + } + break; + case WirePortDataType.FLOAT3: + { + m_previewInternalVec3.x = m_previewInternalVec4.x; + m_previewInternalVec3.y = m_previewInternalVec4.y; + m_previewInternalVec3.z = m_previewInternalVec4.z; + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + m_previewInternalMatrix4x4[ 0 ] = m_previewInternalVec4.x; + m_previewInternalMatrix4x4[ 1 ] = m_previewInternalVec4.y; + m_previewInternalMatrix4x4[ 2 ] = m_previewInternalVec4.z; + m_previewInternalMatrix4x4[ 3 ] = m_previewInternalVec4.w; + } + break; + case WirePortDataType.COLOR: + { + m_previewInternalColor.r = m_previewInternalVec4.x; + m_previewInternalColor.g = m_previewInternalVec4.y; + m_previewInternalColor.b = m_previewInternalVec4.z; + m_previewInternalColor.a = m_previewInternalVec4.w; + } + break; + case WirePortDataType.INT: m_previewInternalInt = (int)m_previewInternalVec4.x; break; + } + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + switch( value ) + { + case WirePortDataType.FLOAT: m_previewInternalFloat = m_previewInternalMatrix4x4[ 0 ]; break; + case WirePortDataType.FLOAT2: + { + m_previewInternalVec2.x = m_previewInternalMatrix4x4[ 0 ]; + m_previewInternalVec2.y = m_previewInternalMatrix4x4[ 1 ]; + } + break; + case WirePortDataType.FLOAT3: + { + m_previewInternalVec3.x = m_previewInternalMatrix4x4[ 0 ]; + m_previewInternalVec3.y = m_previewInternalMatrix4x4[ 1 ]; + m_previewInternalVec3.z = m_previewInternalMatrix4x4[ 2 ]; + } + break; + case WirePortDataType.FLOAT4: + { + m_previewInternalVec4.x = m_previewInternalMatrix4x4[ 0 ]; + m_previewInternalVec4.y = m_previewInternalMatrix4x4[ 1 ]; + m_previewInternalVec4.z = m_previewInternalMatrix4x4[ 2 ]; + m_previewInternalVec4.w = m_previewInternalMatrix4x4[ 3 ]; + } + break; + case WirePortDataType.COLOR: + { + m_previewInternalColor.r = m_previewInternalMatrix4x4[ 0 ]; + m_previewInternalColor.g = m_previewInternalMatrix4x4[ 1 ]; + m_previewInternalColor.b = m_previewInternalMatrix4x4[ 2 ]; + m_previewInternalColor.a = m_previewInternalMatrix4x4[ 3 ]; + } + break; + case WirePortDataType.INT: m_previewInternalInt = (int)m_previewInternalMatrix4x4[ 0 ]; break; + } + } + break; + case WirePortDataType.COLOR: + { + switch( value ) + { + case WirePortDataType.FLOAT: m_previewInternalFloat = m_previewInternalColor.r; break; + case WirePortDataType.FLOAT2: + { + m_previewInternalVec2.x = m_previewInternalColor.r; + m_previewInternalVec2.y = m_previewInternalColor.g; + } + break; + case WirePortDataType.FLOAT3: + { + m_previewInternalVec3.x = m_previewInternalColor.r; + m_previewInternalVec3.y = m_previewInternalColor.g; + m_previewInternalVec3.z = m_previewInternalColor.b; + } + break; + case WirePortDataType.FLOAT4: + { + m_previewInternalVec4.x = m_previewInternalColor.r; + m_previewInternalVec4.y = m_previewInternalColor.g; + m_previewInternalVec4.z = m_previewInternalColor.b; + m_previewInternalVec4.w = m_previewInternalColor.a; + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + m_previewInternalMatrix4x4[ 0 ] = m_previewInternalColor.r; + m_previewInternalMatrix4x4[ 1 ] = m_previewInternalColor.g; + m_previewInternalMatrix4x4[ 2 ] = m_previewInternalColor.b; + m_previewInternalMatrix4x4[ 3 ] = m_previewInternalColor.a; + } + break; + case WirePortDataType.INT: m_previewInternalInt = (int)m_previewInternalColor.r; break; + } + } + break; + case WirePortDataType.INT: + { + switch( value ) + { + case WirePortDataType.FLOAT: m_previewInternalFloat = m_previewInternalInt; break; + case WirePortDataType.FLOAT2: m_previewInternalVec2.x = m_previewInternalInt; break; + case WirePortDataType.FLOAT3: m_previewInternalVec3.x = m_previewInternalInt; break; + case WirePortDataType.FLOAT4: m_previewInternalVec4.x = m_previewInternalInt; break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: m_previewInternalMatrix4x4[ 0 ] = m_previewInternalInt; break; + case WirePortDataType.COLOR: m_previewInternalColor.r = m_previewInternalInt; break; + } + } + break; + } + base.DataType = value; + } + } + + public string DataName + { + get { return m_dataName; } + set { m_dataName = value; } + } + + public bool IsFragment { get { return m_category == MasterNodePortCategory.Fragment || m_category == MasterNodePortCategory.Debug; } } + public MasterNodePortCategory Category + { + set { m_category = value; } + get { return m_category; } + } + + private int CachedIntPropertyID + { + get + { + if( m_cachedIntShaderID == -1 ) + m_cachedIntShaderID = Shader.PropertyToID( "_InputInt" ); + return m_cachedIntShaderID; + } + } + + private int CachedFloatPropertyID + { + get + { + if( m_cachedFloatShaderID == -1 ) + m_cachedFloatShaderID = Shader.PropertyToID( "_InputFloat" ); + return m_cachedFloatShaderID; + } + } + + private int CachedVectorPropertyID + { + get + { + if( m_cachedVectorShaderID == -1 ) + m_cachedVectorShaderID = Shader.PropertyToID( "_InputVector" ); + return m_cachedVectorShaderID; + } + } + + private int CachedColorPropertyID + { + get + { + if( m_cachedColorShaderID == -1 ) + m_cachedColorShaderID = Shader.PropertyToID( "_InputColor" ); + return m_cachedColorShaderID; + } + } + + private int CachedDefaultTexPropertyID + { + get + { + if( m_cachedDefaultTexShaderID == -1 ) + m_cachedDefaultTexShaderID = Shader.PropertyToID( "_Default" ); + return m_cachedDefaultTexShaderID; + } + } + + private int Cached2DPropertyID + { + get + { + if( m_cached2DShaderID == -1 ) + m_cached2DShaderID = Shader.PropertyToID( "_Input2D" ); + return m_cached2DShaderID; + } + } + + public int CachedPropertyId + { + get { return m_cachedPropertyId; } + } + + public bool InputNodeHasPreview( ParentGraph container ) + { + ParentNode node = null; + if( m_externalReferences.Count > 0) + { + node = container.GetNode( m_externalReferences[ 0 ].NodeId ); + } + + if( node != null ) + return node.HasPreviewShader; + + return false; + } + + public void PreparePortCacheID() + { + if( m_propertyNameInt != PortId || string.IsNullOrEmpty( m_propertyName ) ) + { + m_propertyNameInt = PortId; + m_propertyName = "_" + Convert.ToChar( PortId + 65 ); + m_cachedPropertyId = Shader.PropertyToID( m_propertyName ); + } + + if( m_cachedPropertyId == -1 ) + m_cachedPropertyId = Shader.PropertyToID( m_propertyName ); + } + + public void SetPreviewInputTexture( ParentGraph container ) + { + PreparePortCacheID(); + + if( (object)m_node == null ) + { + m_node = container.GetNode( NodeId ); + //m_node = UIUtils.GetNode( NodeId ); + } + + if( ExternalReferences.Count>0 ) + { + m_node.PreviewMaterial.SetTexture( m_cachedPropertyId, container.GetNode( ExternalReferences[ 0 ].NodeId ).GetOutputPortByUniqueId( ExternalReferences[ 0 ].PortId ).OutputPreviewTexture ); + } + //m_node.PreviewMaterial.SetTexture( m_cachedPropertyId, GetOutputConnection( 0 ).OutputPreviewTexture ); + } + + private void SetPortPreviewShader( Shader portShader ) + { + if( m_inputPreviewShader != portShader ) + { + m_inputPreviewShader = portShader; + InputPreviewMaterial.shader = portShader; + } + } + + public void SetPreviewInputValue( ParentGraph container ) + { + if( m_inputPreviewTexture == null ) + { + m_inputPreviewTexture = new RenderTexture( Constants.PreviewSize , Constants.PreviewSize , 0, Constants.PreviewFormat , RenderTextureReadWrite.Linear ); + m_inputPreviewTexture.wrapMode = TextureWrapMode.Repeat; + } + + switch( DataType ) + { + case WirePortDataType.INT: + { + SetPortPreviewShader( UIUtils.IntShader ); + + InputPreviewMaterial.SetInt( CachedIntPropertyID, m_previewInternalInt ); + } + break; + case WirePortDataType.FLOAT: + { + SetPortPreviewShader( UIUtils.FloatShader ); + //Debug.Log( m_previewInternalFloat ); + InputPreviewMaterial.SetFloat( CachedFloatPropertyID, m_previewInternalFloat ); + } + break; + case WirePortDataType.FLOAT2: + { + SetPortPreviewShader( UIUtils.Vector2Shader ); + + Vector2 v2 = m_previewInternalVec2;// Vector2InternalData; + InputPreviewMaterial.SetVector( CachedVectorPropertyID, new Vector4( v2.x, v2.y, 0, 0 ) ); + } + break; + case WirePortDataType.FLOAT3: + { + SetPortPreviewShader( UIUtils.Vector3Shader ); + + Vector3 v3 = m_previewInternalVec3;// Vector3InternalData; + InputPreviewMaterial.SetVector( CachedVectorPropertyID, new Vector4( v3.x, v3.y, v3.z, 0 ) ); + } + break; + case WirePortDataType.FLOAT4: + { + SetPortPreviewShader( UIUtils.Vector4Shader ); + + InputPreviewMaterial.SetVector( CachedVectorPropertyID, m_previewInternalVec4 ); + } + break; + case WirePortDataType.COLOR: + { + SetPortPreviewShader( UIUtils.ColorShader ); + + InputPreviewMaterial.SetColor( CachedColorPropertyID, m_previewInternalColor ); + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + SetPortPreviewShader( UIUtils.FloatShader ); + + InputPreviewMaterial.SetFloat( CachedFloatPropertyID, 1 ); + } + break; + case WirePortDataType.SAMPLER2D: + { + SetPortPreviewShader( UIUtils.Texture2DShader ); + } + break; + default: + { + SetPortPreviewShader( UIUtils.FloatShader ); + + InputPreviewMaterial.SetFloat( CachedFloatPropertyID, 0 ); + } + break; + } + + RenderTexture temp = RenderTexture.active; + RenderTexture.active = m_inputPreviewTexture; + Graphics.Blit( null, m_inputPreviewTexture, InputPreviewMaterial ); + RenderTexture.active = temp; + + PreparePortCacheID(); + + //if( (object)m_node == null ) + // m_node = UIUtils.GetNode( NodeId ); + + if( (object)m_node == null ) + { + m_node = container.GetNode( NodeId ); + //m_node = UIUtils.GetNode( NodeId ); + } + //m_propertyName = "_A"; + //Debug.Log( m_propertyName ); + m_node.PreviewMaterial.SetTexture( m_propertyName, m_inputPreviewTexture ); + } + + public override void ChangePortId( int newPortId ) + { + if( IsConnected ) + { + int count = ExternalReferences.Count; + for( int connIdx = 0; connIdx < count; connIdx++ ) + { + int nodeId = ExternalReferences[ connIdx ].NodeId; + int portId = ExternalReferences[ connIdx ].PortId; + ParentNode node = UIUtils.GetNode( nodeId ); + if( node != null ) + { + OutputPort outputPort = node.GetOutputPortByUniqueId( portId ); + int outputCount = outputPort.ExternalReferences.Count; + for( int j = 0; j < outputCount; j++ ) + { + if( outputPort.ExternalReferences[ j ].NodeId == NodeId && + outputPort.ExternalReferences[ j ].PortId == PortId ) + { + outputPort.ExternalReferences[ j ].PortId = newPortId; + } + } + } + } + } + + PortId = newPortId; + } + + public override void Destroy() + { + base.Destroy(); + //if ( m_inputPreview != null ) + // UnityEngine.ScriptableObject.DestroyImmediate( m_inputPreview ); + //m_inputPreview = null; + + if( m_inputPreviewTexture != null ) + { + m_inputPreviewTexture.Release(); + UnityEngine.ScriptableObject.DestroyImmediate( m_inputPreviewTexture ); + } + m_inputPreviewTexture = null; + + if( m_inputPreviewMaterial != null ) + UnityEngine.ScriptableObject.DestroyImmediate( m_inputPreviewMaterial ); + m_inputPreviewMaterial = null; + + m_inputPreviewShader = null; + + m_node = null; + } + + public Shader InputPreviewShader + { + get + { + if( m_inputPreviewShader == null ) + m_inputPreviewShader = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "d9ca47581ac157145bff6f72ac5dd73e" ) ); //ranged float + + if( m_inputPreviewShader == null ) + m_inputPreviewShader = Shader.Find( "Unlit/Colored Transparent" ); + + return m_inputPreviewShader; + } + set + { + m_inputPreviewShader = value; + } + } + + public Material InputPreviewMaterial + { + get + { + if( m_inputPreviewMaterial == null ) + m_inputPreviewMaterial = new Material( InputPreviewShader ); + + return m_inputPreviewMaterial; + } + //set + //{ + // m_inputPreviewMaterial = value; + //} + } + + public override string Name + { + get { return m_name; } + set + { + m_name = value; + m_internalDataPropertyLabel = ( string.IsNullOrEmpty( value ) || value.Equals( Constants.EmptyPortValue ) ) ? InputDefaultNameStr : value; + m_dirtyLabelSize = true; + } + } + + public string InternalDataName + { + get { return m_internalDataPropertyLabel; } + set { m_internalDataPropertyLabel = value; } + } + + public bool AutoDrawInternalData + { + get { return m_drawInternalData; } + set { m_drawInternalData = value; } + } + + public PortGenType GenType + { + get { return m_genType; } + set { m_genType = value; } + } + + public bool ValidInternalData + { + get + { + switch( m_dataType ) + { + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + case WirePortDataType.COLOR: + case WirePortDataType.INT: return true; + case WirePortDataType.OBJECT: + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + case WirePortDataType.SAMPLER2DARRAY: + case WirePortDataType.SAMPLERSTATE: + default: return false; + } + } + } + + //public RenderTexture InputPreviewTexture + //{ + // get + // { + // if( IsConnected ) + // return GetOutputConnection( 0 ).OutputPreviewTexture; + // else + // return m_inputPreviewTexture; + // } + //} + + public RenderTexture InputPreviewTexture( ParentGraph container ) + { + if( IsConnected ) + { + if( m_externalReferences.Count > 0 ) + return container.GetNode( m_externalReferences[ 0 ].NodeId ).GetOutputPortByUniqueId( m_externalReferences[ 0 ].PortId ).OutputPreviewTexture; + else + return null; + } + else + { + return m_inputPreviewTexture; + } + } + + public string ExternalLinkId + { + get { return m_externalLinkId; } + set + { + m_externalLinkId = value; + if( string.IsNullOrEmpty( value ) ) + { + m_externalNodeLink = -1; + m_externalPortLink = -1; + } + } + } + + public bool HasOwnOrLinkConnection { get { return IsConnected || HasConnectedExternalLink; } } + public bool HasExternalLink { get { return m_externalNodeLink > -1 && m_externalPortLink > -1; } } + + public bool HasConnectedExternalLink + { + get + { + InputPort link = ExternalLink; + return ( link != null && link.IsConnected ); + } + } + + public InputPort ExternalLink + { + get + { + if( HasExternalLink ) + { + ParentNode linkNode = UIUtils.GetNode( m_externalNodeLink ); + if( linkNode != null ) + { + return linkNode.GetInputPortByUniqueId( m_externalPortLink ); + } + } + return null; + } + } + + public ParentNode ExternalLinkNode + { + get + { + if( HasExternalLink ) + { + return UIUtils.GetNode( m_externalNodeLink ); + } + return null; + } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/InputPort.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/InputPort.cs.meta new file mode 100644 index 0000000..421ab30 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/InputPort.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e8199169aaf7f404492a0f2353fb52f9 +timeCreated: 1481126960 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/OutputPort.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/OutputPort.cs new file mode 100644 index 0000000..2dc729d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/OutputPort.cs @@ -0,0 +1,314 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEditor; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [System.Serializable] + public sealed class OutputPort : WirePort + { + public delegate void OnNewPreviewRTCreated(); + public OnNewPreviewRTCreated OnNewPreviewRTCreatedEvent; + + [SerializeField] + private bool m_connectedToMasterNode; + + [SerializeField] + private bool[] m_isLocalValue = { false, false}; + + [SerializeField] + private string[] m_localOutputValue = { string.Empty,string.Empty}; + + //[SerializeField] + //private int m_isLocalWithPortType = 0; + + private RenderTexture m_outputPreview = null; + private Material m_outputMaskMaterial = null; + + private int m_indexPreviewOffset = 0; + + public OutputPort( ParentNode owner, int nodeId, int portId, WirePortDataType dataType, string name ) : base( nodeId, portId, dataType, name ) + { + LabelSize = Vector2.zero; + OnNewPreviewRTCreatedEvent += owner.SetPreviewDirtyFromOutputs; + } + + public string ErrorValue + { + get + { + string value = string.Empty; + switch( m_dataType ) + { + default: + case WirePortDataType.OBJECT: + case WirePortDataType.INT: + case WirePortDataType.FLOAT: value = "(0)"; break; + case WirePortDataType.FLOAT2: value = "half2(0,0)"; break; + case WirePortDataType.FLOAT3: value = "half3(0,0,0)"; break; + case WirePortDataType.COLOR: + case WirePortDataType.FLOAT4: value = "half4(0,0,0,0)"; break; + case WirePortDataType.FLOAT3x3: value = "half3x3(0,0,0,0,0,0,0,0,0)"; break; + case WirePortDataType.FLOAT4x4: value = "half4x4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)"; break; + } + return value; + } + } + + public bool ConnectedToMasterNode + { + get { return m_connectedToMasterNode; } + set { m_connectedToMasterNode = value; } + } + + public override void FullDeleteConnections() + { + UIUtils.DeleteConnection( false, m_nodeId, m_portId, true, true ); + } + + public bool HasConnectedNode + { + get + { + int count = m_externalReferences.Count; + for( int i = 0; i < count; i++ ) + { + if( UIUtils.GetNode( m_externalReferences[ i ].NodeId ).IsConnected ) + return true; + } + return false; + } + } + public InputPort GetInputConnection( int connID = 0 ) + { + if( connID < m_externalReferences.Count ) + { + return UIUtils.GetNode( m_externalReferences[ connID ].NodeId ).GetInputPortByUniqueId( m_externalReferences[ connID ].PortId ); + } + return null; + } + + public ParentNode GetInputNode( int connID = 0 ) + { + if( connID < m_externalReferences.Count ) + { + return UIUtils.GetNode( m_externalReferences[ connID ].NodeId ); + } + return null; + } + + public override void NotifyExternalRefencesOnChange() + { + for( int i = 0; i < m_externalReferences.Count; i++ ) + { + ParentNode node = UIUtils.GetNode( m_externalReferences[ i ].NodeId ); + if( node ) + { + node.CheckSpherePreview(); + InputPort port = node.GetInputPortByUniqueId( m_externalReferences[ i ].PortId ); + port.UpdateInfoOnExternalConn( m_nodeId, m_portId, m_dataType ); + node.OnConnectedOutputNodeChanges( m_externalReferences[ i ].PortId, m_nodeId, m_portId, m_name, m_dataType ); + } + } + } + + public void ChangeTypeWithRestrictions( WirePortDataType newType, int restrictions ) + { + if( m_dataType != newType ) + { + DataType = newType; + for( int i = 0; i < m_externalReferences.Count; i++ ) + { + ParentNode inNode = UIUtils.GetNode( m_externalReferences[ i ].NodeId ); + InputPort inputPort = inNode.GetInputPortByUniqueId( m_externalReferences[ i ].PortId ); + + bool valid = false; + if( restrictions == 0 ) + { + valid = true; + } + else + { + valid = ( restrictions & (int)inputPort.DataType ) != 0; + } + + if( valid ) + { + inNode.CheckSpherePreview(); + inputPort.UpdateInfoOnExternalConn( m_nodeId, m_portId, m_dataType ); + inNode.OnConnectedOutputNodeChanges( m_externalReferences[ i ].PortId, m_nodeId, m_portId, m_name, m_dataType ); + } + else + { + InvalidateConnection( m_externalReferences[ i ].NodeId, m_externalReferences[ i ].PortId ); + inputPort.InvalidateConnection( NodeId, PortId ); + i--; + } + } + } + } + + public override void ChangePortId( int newPortId ) + { + if( IsConnected ) + { + int count = ExternalReferences.Count; + for( int connIdx = 0; connIdx < count; connIdx++ ) + { + int nodeId = ExternalReferences[ connIdx ].NodeId; + int portId = ExternalReferences[ connIdx ].PortId; + ParentNode node = UIUtils.GetNode( nodeId ); + if( node != null ) + { + InputPort inputPort = node.GetInputPortByUniqueId( portId ); + int inputCount = inputPort.ExternalReferences.Count; + for( int j = 0; j < inputCount; j++ ) + { + if( inputPort.ExternalReferences[ j ].NodeId == NodeId && + inputPort.ExternalReferences[ j ].PortId == PortId ) + { + inputPort.ExternalReferences[ j ].PortId = newPortId; + } + } + } + } + } + + PortId = newPortId; + } + + public string ConfigOutputLocalValue( PrecisionType precisionType, string value, string customName, MasterNodePortCategory category ) + { + int idx = UIUtils.PortCategorytoAttayIdx( category ); + ParentGraph currentGraph = UIUtils.GetNode( NodeId ).ContainerGraph; + string autoGraphId = currentGraph.GraphId > 0 ? "_g" + currentGraph.GraphId : string.Empty; + m_localOutputValue[idx] = string.IsNullOrEmpty( customName ) ? ( "temp_output_" + m_nodeId + "_" + PortId + autoGraphId ) : customName; + m_isLocalValue[idx] = true; + //m_isLocalWithPortType |= (int)category; + return string.Format( Constants.LocalValueDecWithoutIdent, UIUtils.PrecisionWirePortToCgType( precisionType, DataType ), m_localOutputValue[idx], value ); + } + + public void SetLocalValue( string value, MasterNodePortCategory category ) + { + int idx = UIUtils.PortCategorytoAttayIdx( category ); + m_isLocalValue[idx] = true; + m_localOutputValue[ idx ] = value; + //m_isLocalWithPortType |= (int)category; + } + + public void ResetLocalValue() + { + for( int i = 0; i < m_localOutputValue.Length; i++ ) + { + m_localOutputValue[ i ] = string.Empty; + m_isLocalValue[i] = false; + } + //m_isLocalWithPortType = 0; + } + + public void ResetLocalValueIfNot( MasterNodePortCategory category ) + { + int idx = UIUtils.PortCategorytoAttayIdx( category ); + for( int i = 0; i < m_localOutputValue.Length; i++ ) + { + if( i != idx ) + { + m_localOutputValue[ i ] = string.Empty; + m_isLocalValue[ i ] = false; + } + } + } + + public void ResetLocalValueOnCategory( MasterNodePortCategory category ) + { + int idx = UIUtils.PortCategorytoAttayIdx( category ); + m_localOutputValue[ idx ] = string.Empty; + m_isLocalValue[ idx ] = false; + } + + public bool IsLocalOnCategory( MasterNodePortCategory category ) + { + int idx = UIUtils.PortCategorytoAttayIdx( category ); + return m_isLocalValue[ idx ]; + //return ( m_isLocalWithPortType & (int)category ) != 0; ; + } + + public override void ForceClearConnection() + { + UIUtils.DeleteConnection( false, m_nodeId, m_portId, false, true ); + } + + public bool IsLocalValue( MasterNodePortCategory category ) + { + int idx = UIUtils.PortCategorytoAttayIdx( category ); + return m_isLocalValue[ idx ]; + } + + public string LocalValue(MasterNodePortCategory category) + { + int idx = UIUtils.PortCategorytoAttayIdx( category ); + return m_localOutputValue[idx]; + } + + public RenderTexture OutputPreviewTexture + { + get + { + if( Preferences.GlobalDisablePreviews ) + { + return UIUtils.DummyRT; + } + + if( m_outputPreview == null ) + { + m_outputPreview = new RenderTexture( Constants.PreviewSize , Constants.PreviewSize , 0 , Constants.PreviewFormat , RenderTextureReadWrite.Linear ); + m_outputPreview.wrapMode = TextureWrapMode.Repeat; + if( OnNewPreviewRTCreatedEvent != null ) + OnNewPreviewRTCreatedEvent(); + } + + return m_outputPreview; + } + set { m_outputPreview = value; } + } + + public int IndexPreviewOffset + { + get { return m_indexPreviewOffset; } + set { m_indexPreviewOffset = value; } + } + + public override void Destroy() + { + base.Destroy(); + if( m_outputPreview != null ) + { + m_outputPreview.Release(); + UnityEngine.ScriptableObject.DestroyImmediate( m_outputPreview ); + } + m_outputPreview = null; + + if( m_outputMaskMaterial != null ) + UnityEngine.ScriptableObject.DestroyImmediate( m_outputMaskMaterial ); + m_outputMaskMaterial = null; + + OnNewPreviewRTCreatedEvent = null; + } + + public Material MaskingMaterial + { + get + { + if( m_outputMaskMaterial == null ) + { + //m_outputMaskMaterial = new Material( AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( "9c34f18ebe2be3e48b201b748c73dec0" ) ) ); + m_outputMaskMaterial = new Material( UIUtils.MaskingShader ); + } + return m_outputMaskMaterial; + } + //set { m_outputMaskMaterial = value; } + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/OutputPort.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/OutputPort.cs.meta new file mode 100644 index 0000000..9825de1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/OutputPort.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 82722ce1ba0df314490a9362e503727c +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireBezierReference.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireBezierReference.cs new file mode 100644 index 0000000..6753ff0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireBezierReference.cs @@ -0,0 +1,58 @@ +using UnityEngine; + +namespace AmplifyShaderEditor +{ + [System.Serializable] + public class WireBezierReference + { + private Rect m_boundingBox; + private int m_inNodeId; + private int m_inPortId; + private int m_outNodeId; + private int m_outPortId; + + public WireBezierReference() + { + m_boundingBox = new Rect(); + m_inNodeId = -1; + m_inPortId = -1; + m_outNodeId = -1; + m_outPortId = -1; + } + + public WireBezierReference( ref Rect area, int inNodeId, int inPortId, int outNodeId, int outPortId ) + { + UpdateInfo( ref area, inNodeId, inPortId, outNodeId, outPortId ); + } + + public void UpdateInfo( ref Rect area, int inNodeId, int inPortId, int outNodeId, int outPortId ) + { + m_boundingBox = area; + m_inNodeId = inNodeId; + m_inPortId = inPortId; + m_outNodeId = outNodeId; + m_outPortId = outPortId; + } + + public bool Contains( Vector2 position ) + { + return m_boundingBox.Contains( position ); + } + + public void DebugDraw() + { + GUI.Label( m_boundingBox, string.Empty, UIUtils.GetCustomStyle( CustomStyle.MainCanvasTitle )); + } + + public override string ToString() + { + return string.Format( "In node: {0} port: {1} -> Out node: {2} port: {3}", m_inNodeId, m_inPortId, m_outNodeId, m_outPortId ); + } + + public Rect BoundingBox { get { return m_boundingBox; } } + public int InNodeId { get { return m_inNodeId; } } + public int InPortId { get { return m_inPortId; } } + public int OutNodeId { get { return m_outNodeId; } } + public int OutPortId { get { return m_outPortId; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireBezierReference.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireBezierReference.cs.meta new file mode 100644 index 0000000..df5640c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireBezierReference.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 499682ec40529f44480d58747ad7ab44 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WirePort.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WirePort.cs new file mode 100644 index 0000000..24986d7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WirePort.cs @@ -0,0 +1,606 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using UnityEngine; +using UnityEditor; + +using System.Collections.Generic; + +namespace AmplifyShaderEditor +{ + public enum WirePortDataType + { + OBJECT = 1 << 1, + FLOAT = 1 << 2, + FLOAT2 = 1 << 3, + FLOAT3 = 1 << 4, + FLOAT4 = 1 << 5, + FLOAT3x3 = 1 << 6, + FLOAT4x4 = 1 << 7, + COLOR = 1 << 8, + INT = 1 << 9, + SAMPLER1D = 1 << 10, + SAMPLER2D = 1 << 11, + SAMPLER3D = 1 << 12, + SAMPLERCUBE = 1 << 13, + UINT = 1 << 14, + SAMPLER2DARRAY = 1 << 15, + SAMPLERSTATE = 1 << 16, + UINT4 = 1 << 17 + } + + public enum VariableQualifiers + { + In = 0, + Out, + InOut + } + + public struct WirePortDataTypeComparer : IEqualityComparer + { + public bool Equals( WirePortDataType x, WirePortDataType y ) + { + return x == y; + } + + public int GetHashCode( WirePortDataType obj ) + { + // you need to do some thinking here, + return (int)obj; + } + } + + [System.Serializable] + public class WirePort + { + private const double PortClickTime = 0.2; + + private double m_lastTimeClicked = -1; + + private Vector2 m_labelSize; + private Vector2 m_unscaledLabelSize; + protected bool m_dirtyLabelSize = true; + + private bool m_isEditable = false; + private bool m_editingName = false; + + protected int m_portRestrictions = 0; + + private bool m_repeatButtonState = false; + + [SerializeField] + private Rect m_position; + + [SerializeField] + private Rect m_labelPosition; + + [SerializeField] + protected int m_nodeId = -1; + + [SerializeField] + protected int m_portId = -1; + + [SerializeField] + protected int m_orderId = -1; + + [SerializeField] + protected WirePortDataType m_dataType = WirePortDataType.FLOAT; + + [SerializeField] + protected string m_name; + + [SerializeField] + protected List m_externalReferences; + + [SerializeField] + protected bool m_locked = false; + + [SerializeField] + protected bool m_visible = true; + + [SerializeField] + protected bool m_isDummy = false; + + [SerializeField] + protected bool m_hasCustomColor = false; + + [SerializeField] + protected Color m_customColor = Color.white; + + [SerializeField] + protected Rect m_activePortArea; + + public WirePort( int nodeId, int portId, WirePortDataType dataType, string name, int orderId = -1 ) + { + m_nodeId = nodeId; + m_portId = portId; + m_orderId = orderId; + m_dataType = dataType; + m_name = name; + m_externalReferences = new List(); + } + + public virtual void Destroy() + { + m_externalReferences.Clear(); + m_externalReferences = null; + } + + public void SetFreeForAll() + { + m_portRestrictions = -1; + } + + public void AddPortForbiddenTypes( params WirePortDataType[] forbiddenTypes ) + { + if( forbiddenTypes != null ) + { + if( m_portRestrictions == 0 ) + { + //if no previous restrictions are detected then we set up the bit array so we can set is bit correctly + m_portRestrictions = int.MaxValue; + } + + for( int i = 0; i < forbiddenTypes.Length; i++ ) + { + m_portRestrictions = m_portRestrictions & ( int.MaxValue - (int)forbiddenTypes[ i ] ); + } + } + } + + public void AddPortRestrictions( params WirePortDataType[] validTypes ) + { + if( validTypes != null ) + { + for( int i = 0; i < validTypes.Length; i++ ) + { + m_portRestrictions = m_portRestrictions | (int)validTypes[ i ]; + } + } + } + + public void CreatePortRestrictions( params WirePortDataType[] validTypes ) + { + m_portRestrictions = 0; + if( validTypes != null ) + { + for( int i = 0; i < validTypes.Length; i++ ) + { + m_portRestrictions = m_portRestrictions | (int)validTypes[ i ]; + } + } + } + + public virtual bool CheckValidType( WirePortDataType dataType ) + { + if( m_portRestrictions == 0 ) + { + return true; + } + + return ( m_portRestrictions & (int)dataType ) != 0; + } + + public bool ConnectTo( WireReference port ) + { + if( m_locked ) + return false; + + if( m_externalReferences.Contains( port ) ) + return false; + + m_externalReferences.Add( port ); + return true; + } + + public bool ConnectTo( int nodeId, int portId ) + { + if( m_locked ) + return false; + + + foreach( WireReference reference in m_externalReferences ) + { + if( reference.NodeId == nodeId && reference.PortId == portId ) + { + return false; + } + } + m_externalReferences.Add( new WireReference( nodeId, portId, m_dataType, false ) ); + return true; + } + + public bool ConnectTo( int nodeId, int portId, WirePortDataType dataType, bool typeLocked ) + { + if( m_locked ) + return false; + + foreach( WireReference reference in m_externalReferences ) + { + if( reference.NodeId == nodeId && reference.PortId == portId ) + { + return false; + } + } + m_externalReferences.Add( new WireReference( nodeId, portId, dataType, typeLocked ) ); + return true; + } + + public void DummyAdd( int nodeId, int portId ) + { + m_externalReferences.Insert( 0, new WireReference( nodeId, portId, WirePortDataType.OBJECT, false ) ); + m_isDummy = true; + } + + public void DummyRemove() + { + m_externalReferences.RemoveAt( 0 ); + m_isDummy = false; + } + + public void DummyClear() + { + m_externalReferences.Clear(); + m_isDummy = false; + } + + public WireReference GetConnection( int connID = 0 ) + { + if( connID < m_externalReferences.Count ) + return m_externalReferences[ connID ]; + return null; + } + + public void ChangeProperties( string newName, WirePortDataType newType, bool invalidateConnections ) + { + Name = newName; + ChangeType( newType, invalidateConnections ); + //if ( m_dataType != newType ) + //{ + // DataType = newType; + // if ( invalidateConnections ) + // { + // InvalidateAllConnections(); + // } + // else + // { + // NotifyExternalRefencesOnChange(); + // } + //} + } + + public void ChangeType( WirePortDataType newType, bool invalidateConnections ) + { + if( m_dataType != newType ) + { + //ParentNode node = UIUtils.GetNode( m_nodeId ); + //if ( node ) + //{ + // Undo.RegisterCompleteObjectUndo( node.ContainerGraph.ParentWindow, Constants.UndoChangeTypeNodesId ); + // Undo.RecordObject( node, Constants.UndoChangeTypeNodesId ); + //} + DataType = newType; + if( invalidateConnections ) + { + InvalidateAllConnections(); + } + else + { + NotifyExternalRefencesOnChange(); + } + } + } + + public virtual void ChangePortId( int newId ) { } + public virtual void NotifyExternalRefencesOnChange() { } + + public void UpdateInfoOnExternalConn( int nodeId, int portId, WirePortDataType type ) + { + for( int i = 0; i < m_externalReferences.Count; i++ ) + { + if( m_externalReferences[ i ].NodeId == nodeId && m_externalReferences[ i ].PortId == portId ) + { + m_externalReferences[ i ].DataType = type; + } + } + } + + public void InvalidateConnection( int nodeId, int portId ) + { + int id = -1; + for( int i = 0; i < m_externalReferences.Count; i++ ) + { + if( m_externalReferences[ i ].NodeId == nodeId && m_externalReferences[ i ].PortId == portId ) + { + id = i; + break; + } + } + + if( id > -1 ) + m_externalReferences.RemoveAt( id ); + } + + public void RemoveInvalidConnections() + { + Debug.Log( "Cleaning invalid connections" ); + List validConnections = new List(); + for( int i = 0; i < m_externalReferences.Count; i++ ) + { + if( m_externalReferences[ i ].IsValid ) + { + validConnections.Add( m_externalReferences[ i ] ); + } + else + { + Debug.Log( "Detected invalid connection on node " + m_nodeId + " port " + m_portId ); + } + } + m_externalReferences.Clear(); + m_externalReferences = validConnections; + } + + public void InvalidateAllConnections() + { + m_externalReferences.Clear(); + } + + public virtual void FullDeleteConnections() { } + + public bool IsConnectedTo( int nodeId, int portId ) + { + if( m_locked ) + return false; + + for( int i = 0; i < m_externalReferences.Count; i++ ) + { + if( m_externalReferences[ i ].NodeId == nodeId && m_externalReferences[ i ].PortId == portId ) + return true; + } + return false; + } + + public WirePortDataType ConnectionType( int id = 0 ) + { + return ( id < m_externalReferences.Count ) ? m_externalReferences[ id ].DataType : DataType; + } + + public bool CheckMatchConnectionType( int id = 0 ) + { + if( id < m_externalReferences.Count ) + return m_externalReferences[ id ].DataType == DataType; + + return false; + } + + public void MatchPortToConnection( int id = 0 ) + { + if( id < m_externalReferences.Count ) + { + DataType = m_externalReferences[ id ].DataType; + } + } + + public void ResetWireReferenceStatus() + { + for( int i = 0; i < m_externalReferences.Count; i++ ) + { + m_externalReferences[ i ].WireStatus = WireStatus.Default; + } + } + + public bool InsideActiveArea( Vector2 pos ) + { + return m_activePortArea.Contains( pos ); + } + + public void Click() + { + if( m_isEditable ) + { + if( ( EditorApplication.timeSinceStartup - m_lastTimeClicked ) < PortClickTime ) + { + m_editingName = true; + GUI.FocusControl( "port" + m_nodeId.ToString() + m_portId.ToString() ); + TextEditor te = (TextEditor)GUIUtility.GetStateObject( typeof( TextEditor ), GUIUtility.keyboardControl ); + if( te != null ) + { + te.SelectAll(); + } + } + + m_lastTimeClicked = EditorApplication.timeSinceStartup; + } + } + + public bool Draw( Rect textPos, GUIStyle style ) + { + bool changeFlag = false; + if( m_isEditable && m_editingName ) + { + textPos.width = m_labelSize.x; + EditorGUI.BeginChangeCheck(); + GUI.SetNextControlName( "port" + m_nodeId.ToString() + m_portId.ToString() ); + m_name = GUI.TextField( textPos, m_name, style ); + if( EditorGUI.EndChangeCheck() ) + { + m_dirtyLabelSize = true; + changeFlag = true; + } + + if( Event.current.isKey && ( Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter ) ) + { + m_editingName = false; + GUIUtility.keyboardControl = 0; + } + } + else + { + GUI.Label( textPos, m_name, style ); + } + //GUI.Label( textPos, string.Empty ); + return changeFlag; + } + + public void ResetEditing() + { + m_editingName = false; + } + + public virtual void ForceClearConnection() { } + + public bool IsConnected + { + get { return ( m_externalReferences.Count > 0 && !m_locked ); } + } + + public List ExternalReferences + { + get { return m_externalReferences; } + } + + public int ConnectionCount + { + get { return m_externalReferences.Count; } + } + + public Rect Position + { + get { return m_position; } + set { m_position = value; } + } + + public Rect LabelPosition + { + get { return m_labelPosition; } + set { m_labelPosition = value; } + } + + public int PortId + { + get { return m_portId; } + set { m_portId = value; } + } + + public int OrderId + { + get { return m_orderId; } + set { m_orderId = value; } + } + + + public int NodeId + { + get { return m_nodeId; } + set { m_nodeId = value; } + } + + public virtual WirePortDataType DataType + { + get { return m_dataType; } + set { m_dataType = value; } + } + + public bool Visible + { + get { return m_visible; } + set + { + m_visible = value; + if( !m_visible && IsConnected ) + { + ForceClearConnection(); + } + } + } + + public bool Locked + { + get { return m_locked; } + set + { + //if ( m_locked && IsConnected ) + //{ + // ForceClearConnection(); + //} + m_locked = value; + } + } + + public virtual string Name + { + get { return m_name; } + set { m_name = value; m_dirtyLabelSize = true; } + } + + public bool DirtyLabelSize + { + get { return m_dirtyLabelSize; } + set { m_dirtyLabelSize = value; } + } + + public bool HasCustomColor + { + get { return m_hasCustomColor; } + } + + public Color CustomColor + { + get { return m_customColor; } + set + { + m_hasCustomColor = true; + m_customColor = value; + } + } + + public Rect ActivePortArea + { + get { return m_activePortArea; } + set { m_activePortArea = value; } + } + + public Vector2 LabelSize + { + get { return m_labelSize; } + set { m_labelSize = value; } + } + + public Vector2 UnscaledLabelSize + { + get { return m_unscaledLabelSize; } + set { m_unscaledLabelSize = value; } + } + + public bool IsEditable + { + get { return m_isEditable; } + set { m_isEditable = value; } + } + + public bool Available { get { return m_visible && !m_locked; } } + public override string ToString() + { + string dump = ""; + dump += "Order: " + m_orderId + "\n"; + dump += "Name: " + m_name + "\n"; + dump += " Type: " + m_dataType; + dump += " NodeId : " + m_nodeId; + dump += " PortId : " + m_portId; + dump += "\nConnections:\n"; + foreach( WireReference wirePort in m_externalReferences ) + { + dump += wirePort + "\n"; + } + return dump; + } + + public bool RepeatButtonState + { + get { return m_repeatButtonState; } + set { m_repeatButtonState = value; } + } + public bool IsDummy { get { return m_isDummy; } } + public bool NotFreeForAllTypes { get { return m_portRestrictions != -1; } } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WirePort.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WirePort.cs.meta new file mode 100644 index 0000000..d70ad88 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WirePort.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4709687a4844c9545a254c2ddbf3ca63 +timeCreated: 1481126955 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireReference.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireReference.cs new file mode 100644 index 0000000..fb2b347 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireReference.cs @@ -0,0 +1,126 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda + +using System; +using UnityEngine; + +namespace AmplifyShaderEditor +{ + public enum WireStatus + { + Default = 0, + Highlighted, + Selected + } + + [Serializable] + public sealed class WireReference + { + private WireStatus m_status = WireStatus.Default; + + + + [SerializeField] + private int m_nodeId = -1; + [SerializeField] + private int m_portId = -1; + [SerializeField] + private WirePortDataType m_dataType = WirePortDataType.FLOAT; + [SerializeField] + private bool m_typeLocked = false; + + + + public WireReference() + { + m_nodeId = -1; + m_portId = -1; + m_dataType = WirePortDataType.FLOAT; + m_typeLocked = false; + m_status = WireStatus.Default; + } + + public WireReference( int nodeId, int portId, WirePortDataType dataType, bool typeLocked ) + { + m_portId = portId; + m_nodeId = nodeId; + m_dataType = dataType; + m_typeLocked = typeLocked; + m_status = WireStatus.Default; + } + + public void Invalidate() + { + m_nodeId = -1; + m_portId = -1; + m_typeLocked = false; + m_status = WireStatus.Default; + } + + public void SetReference( int nodeId, int portId, WirePortDataType dataType, bool typeLocked ) + { + m_nodeId = nodeId; + m_portId = portId; + m_dataType = dataType; + m_typeLocked = typeLocked; + } + + public void SetReference( WirePort port ) + { + m_nodeId = port.NodeId; + m_portId = port.PortId; + m_dataType = port.DataType; + } + + public bool IsValid + { + get { return ( m_nodeId != -1 && m_portId != -1 ); } + } + + public int NodeId + { + get { return m_nodeId; } + } + + public int PortId + { + get { return m_portId; } + set { m_portId = value; } + } + + public WirePortDataType DataType + { + get { return m_dataType; } + set { m_dataType = value; } + } + + public bool TypeLocked + { + get { return m_typeLocked; } + } + + public WireStatus WireStatus + { + get { return m_status; } + set { m_status = value; } + } + + public override string ToString() + { + string dump = ""; + dump += "* Wire Reference *\n"; + dump += "NodeId : " + m_nodeId + "\n"; + dump += "PortId : " + m_portId + "\n"; + dump += "DataType " + m_dataType + "\n"; ; + return dump; + } + + public void WriteToString( ref string myString ) + { + IOUtils.AddFieldToString( ref myString, "PortId", m_portId ); + IOUtils.AddFieldToString( ref myString, "NodeID", m_nodeId ); + IOUtils.AddFieldToString( ref myString, "DataType", m_dataType ); + IOUtils.AddFieldToString( ref myString, "TypeLocked", m_typeLocked ); + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireReference.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireReference.cs.meta new file mode 100644 index 0000000..dee7f4d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Wires/WireReference.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 99fb607e60678c44da002d6b694400dc +timeCreated: 1481126957 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources.meta new file mode 100644 index 0000000..82d54d7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0932db7ec1402c2489679c4b72eab5eb +folderAsset: yes +timeCreated: 1481126943 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/GUISkins.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/GUISkins.meta new file mode 100644 index 0000000..18ce2da --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/GUISkins.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0ecdc2c57c073bd4796f1ae8da7f851f +folderAsset: yes +timeCreated: 1481126943 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/GUISkins/MainSkin.guiskin b/Assets/AmplifyShaderEditor/Plugins/EditorResources/GUISkins/MainSkin.guiskin new file mode 100644 index 0000000..58289c6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/GUISkins/MainSkin.guiskin @@ -0,0 +1,5340 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12001, guid: 0000000000000000e000000000000000, type: 0} + m_Name: MainSkin + m_EditorClassIdentifier: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_box: + m_Name: box + m_Normal: + m_Background: {fileID: 2800000, guid: a702c1245d15ddb48b8fba73bf951a65, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.79999995, g: 0.79999995, b: 0.79999995, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 1 + m_Right: 1 + m_Top: 1 + m_Bottom: 1 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 1 + m_Right: 1 + m_Top: 1 + m_Bottom: 1 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_button: + m_Name: button + m_Normal: + m_Background: {fileID: 2800000, guid: 87629cdfe03457046b57a25b1ea3096d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: 87629cdfe03457046b57a25b1ea3096d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 87629cdfe03457046b57a25b1ea3096d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: 87629cdfe03457046b57a25b1ea3096d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 6c0712566778b3f4383fc3bb16edc880, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 6c0712566778b3f4383fc3bb16edc880, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 6c0712566778b3f4383fc3bb16edc880, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_toggle: + m_Name: toggle + m_Normal: + m_Background: {fileID: 11018, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.89112896, g: 0.89112896, b: 0.89112896, a: 1} + m_Hover: + m_Background: {fileID: 11014, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 11013, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 11016, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.8901961, g: 0.8901961, b: 0.8901961, a: 1} + m_OnHover: + m_Background: {fileID: 11015, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 11017, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 14 + m_Right: 0 + m_Top: 14 + m_Bottom: 0 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 15 + m_Right: 0 + m_Top: 3 + m_Bottom: 0 + m_Overflow: + m_Left: -1 + m_Right: 0 + m_Top: -4 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_label: + m_Name: label + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 15 + m_FontStyle: 0 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + m_textField: + m_Name: textfield + m_Normal: + m_Background: {fileID: 11024, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.79999995, g: 0.79999995, b: 0.79999995, a: 1} + m_Hover: + m_Background: {fileID: 11026, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.9, g: 0.9, b: 0.9, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 11026, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 11025, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 3 + m_Right: 3 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 11 + m_FontStyle: 0 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 3 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_textArea: + m_Name: textarea + m_Normal: + m_Background: {fileID: 11024, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.9019608, g: 0.9019608, b: 0.9019608, a: 1} + m_Hover: + m_Background: {fileID: 11026, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.79999995, g: 0.79999995, b: 0.79999995, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 11025, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 3 + m_Right: 3 + m_Top: 3 + m_Bottom: 3 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 1 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_window: + m_Name: window + m_Normal: + m_Background: {fileID: 2800000, guid: bd8a303795331fe48b05eee287c0b3e5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: bd8a303795331fe48b05eee287c0b3e5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 4fdd9ad2fb20f14438637f9b085fbe81, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: bd8a303795331fe48b05eee287c0b3e5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: bd8a303795331fe48b05eee287c0b3e5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: bd8a303795331fe48b05eee287c0b3e5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 4fdd9ad2fb20f14438637f9b085fbe81, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: bd8a303795331fe48b05eee287c0b3e5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 7 + m_Right: 7 + m_Top: 37 + m_Bottom: 7 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 25 + m_Bottom: 10 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 10 + m_FontStyle: 1 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: -18} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_horizontalSlider: + m_Name: horizontalslider + m_Normal: + m_Background: {fileID: 11009, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 3 + m_Right: 3 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: -1 + m_Right: -1 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: -2 + m_Bottom: -3 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 12 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_horizontalSliderThumb: + m_Name: horizontalsliderthumb + m_Normal: + m_Background: {fileID: 11011, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 11012, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 11010, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 4 + m_Right: 4 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 7 + m_Right: 7 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: -1 + m_Right: -1 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 12 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_verticalSlider: + m_Name: verticalslider + m_Normal: + m_Background: {fileID: 11021, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 3 + m_Bottom: 3 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: -1 + m_Bottom: -1 + m_Overflow: + m_Left: -2 + m_Right: -3 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 12 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 1 + m_verticalSliderThumb: + m_Name: verticalsliderthumb + m_Normal: + m_Background: {fileID: 11011, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 11012, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 11010, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 7 + m_Bottom: 7 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: -1 + m_Bottom: -1 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 12 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 1 + m_horizontalScrollbar: + m_Name: horizontalscrollbar + m_Normal: + m_Background: {fileID: 11008, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 9 + m_Right: 9 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 1 + m_Bottom: 4 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 15 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_horizontalScrollbarThumb: + m_Name: horizontalscrollbarthumb + m_Normal: + m_Background: {fileID: 11007, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 6 + m_Right: 6 + m_Top: 6 + m_Bottom: 6 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 6 + m_Right: 6 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: -1 + m_Bottom: 1 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 13 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_horizontalScrollbarLeftButton: + m_Name: horizontalscrollbarleftbutton + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_horizontalScrollbarRightButton: + m_Name: horizontalscrollbarrightbutton + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_verticalScrollbar: + m_Name: verticalscrollbar + m_Normal: + m_Background: {fileID: 11020, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 9 + m_Bottom: 9 + m_Margin: + m_Left: 1 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 1 + m_Bottom: 1 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 15 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_verticalScrollbarThumb: + m_Name: verticalscrollbarthumb + m_Normal: + m_Background: {fileID: 11019, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 6 + m_Right: 6 + m_Top: 6 + m_Bottom: 6 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 6 + m_Bottom: 6 + m_Overflow: + m_Left: -1 + m_Right: -1 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 15 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 1 + m_verticalScrollbarUpButton: + m_Name: verticalscrollbarupbutton + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_verticalScrollbarDownButton: + m_Name: verticalscrollbardownbutton + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_ScrollView: + m_Name: scrollview + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_CustomStyles: + - m_Name: NodeWindowOff + m_Normal: + m_Background: {fileID: 2800000, guid: 60c283ffa9a758646ab70a2fe7ff5f71, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 6 + m_Right: 6 + m_Top: 6 + m_Bottom: 6 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 1 + m_Right: 1 + m_Top: 1 + m_Bottom: 1 + m_Font: {fileID: 0} + m_FontSize: 13 + m_FontStyle: 1 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: -18} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: NodeWindowOn + m_Normal: + m_Background: {fileID: 2800000, guid: 24fb767323009c143a4e744a2025a27e, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: 24fb767323009c143a4e744a2025a27e, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 24fb767323009c143a4e744a2025a27e, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: 24fb767323009c143a4e744a2025a27e, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 24fb767323009c143a4e744a2025a27e, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 24fb767323009c143a4e744a2025a27e, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 24fb767323009c143a4e744a2025a27e, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 24fb767323009c143a4e744a2025a27e, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 6 + m_Right: 6 + m_Top: 6 + m_Bottom: 6 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 2 + m_Right: 2 + m_Top: 2 + m_Bottom: 2 + m_Font: {fileID: 0} + m_FontSize: 6 + m_FontStyle: 1 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: NodeTitle + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 13 + m_FontStyle: 1 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 3 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 1 + - m_Name: NodeHeader + m_Normal: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 6 + m_Right: 6 + m_Top: 6 + m_Bottom: 4 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 1 + m_Right: 1 + m_Top: 1 + m_Bottom: 1 + m_Font: {fileID: 0} + m_FontSize: 13 + m_FontStyle: 1 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: CommentaryHeader + m_Normal: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 9e88b336bd16b1e4b99de75f486126c1, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 7 + m_Right: 7 + m_Top: 7 + m_Bottom: 7 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 1 + m_Right: 1 + m_Top: 1 + m_Bottom: 1 + m_Font: {fileID: 0} + m_FontSize: 15 + m_FontStyle: 1 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 1 + m_ContentOffset: {x: 8, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: ShaderLibraryTitle + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 7 + m_Right: 7 + m_Top: 7 + m_Bottom: 7 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 23 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 20 + m_FontStyle: 1 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: ShaderLibraryAddToList + m_Normal: + m_Background: {fileID: 2800000, guid: cccc116a6334dc1428687697c5a11d58, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: cccc116a6334dc1428687697c5a11d58, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: cccc116a6334dc1428687697c5a11d58, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: cccc116a6334dc1428687697c5a11d58, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: cccc116a6334dc1428687697c5a11d58, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: cccc116a6334dc1428687697c5a11d58, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: cccc116a6334dc1428687697c5a11d58, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: cccc116a6334dc1428687697c5a11d58, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 20 + m_FontStyle: 0 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 23 + m_FixedHeight: 21 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: ShaderLibraryRemoveFromList + m_Normal: + m_Background: {fileID: 2800000, guid: 75f68506ba820564ea85b2620d78c097, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: 75f68506ba820564ea85b2620d78c097, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 75f68506ba820564ea85b2620d78c097, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: 75f68506ba820564ea85b2620d78c097, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 75f68506ba820564ea85b2620d78c097, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 75f68506ba820564ea85b2620d78c097, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 75f68506ba820564ea85b2620d78c097, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 75f68506ba820564ea85b2620d78c097, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 20 + m_FontStyle: 1 + m_Alignment: 2 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 23 + m_FixedHeight: 21 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: ShaderLibraryOpenListed + m_Normal: + m_Background: {fileID: 2800000, guid: a66917730dccde947a01140dc04b9e59, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: a66917730dccde947a01140dc04b9e59, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: a66917730dccde947a01140dc04b9e59, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: a66917730dccde947a01140dc04b9e59, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: a66917730dccde947a01140dc04b9e59, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: a66917730dccde947a01140dc04b9e59, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: a66917730dccde947a01140dc04b9e59, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: a66917730dccde947a01140dc04b9e59, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 20 + m_FontStyle: 1 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 23 + m_FixedHeight: 21 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: ShaderLibrarySelectionAsTemplate + m_Normal: + m_Background: {fileID: 2800000, guid: 8148796947da07d49906f1201f417a60, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: 8148796947da07d49906f1201f417a60, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 8148796947da07d49906f1201f417a60, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: 8148796947da07d49906f1201f417a60, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 8148796947da07d49906f1201f417a60, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 8148796947da07d49906f1201f417a60, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 8148796947da07d49906f1201f417a60, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 8148796947da07d49906f1201f417a60, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 20 + m_FontStyle: 1 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 23 + m_FixedHeight: 21 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: ShaderLibraryItem + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 10 + m_Right: 10 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 15 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: CommentaryTitle + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 10 + m_Right: 10 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 15 + m_FontStyle: 1 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: PortEmptyIcon + m_Normal: + m_Background: {fileID: 2800000, guid: 56277f370fb77a448a152bcd2e3a9077, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: 56277f370fb77a448a152bcd2e3a9077, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 56277f370fb77a448a152bcd2e3a9077, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: 56277f370fb77a448a152bcd2e3a9077, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 56277f370fb77a448a152bcd2e3a9077, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 56277f370fb77a448a152bcd2e3a9077, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 56277f370fb77a448a152bcd2e3a9077, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 56277f370fb77a448a152bcd2e3a9077, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: PortFullIcon + m_Normal: + m_Background: {fileID: 2800000, guid: 8113366f9f7cec647878e3af2fb98922, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: 8113366f9f7cec647878e3af2fb98922, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 8113366f9f7cec647878e3af2fb98922, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: 8113366f9f7cec647878e3af2fb98922, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 8113366f9f7cec647878e3af2fb98922, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 8113366f9f7cec647878e3af2fb98922, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 8113366f9f7cec647878e3af2fb98922, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 8113366f9f7cec647878e3af2fb98922, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: InputPortLabel + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 10 + m_Right: 10 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 15 + m_FontStyle: 0 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 3 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 1 + - m_Name: OutputPortLabel + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 15 + m_FontStyle: 0 + m_Alignment: 5 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: CommentaryResizeButton + m_Normal: + m_Background: {fileID: 2800000, guid: 5321bd2b79632764286f28503db80815, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: 5321bd2b79632764286f28503db80815, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 5321bd2b79632764286f28503db80815, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: 5321bd2b79632764286f28503db80815, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 5321bd2b79632764286f28503db80815, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 5321bd2b79632764286f28503db80815, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 5321bd2b79632764286f28503db80815, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 5321bd2b79632764286f28503db80815, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 15 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: CommentaryResizeButtonInv + m_Normal: + m_Background: {fileID: 2800000, guid: b52bc320a2ff91446978a893ec738134, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: b52bc320a2ff91446978a893ec738134, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: b52bc320a2ff91446978a893ec738134, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: b52bc320a2ff91446978a893ec738134, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: b52bc320a2ff91446978a893ec738134, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: b52bc320a2ff91446978a893ec738134, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: b52bc320a2ff91446978a893ec738134, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: b52bc320a2ff91446978a893ec738134, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 15 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: CommentaryBackground + m_Normal: + m_Background: {fileID: 2800000, guid: b2be9c55e7e7ba447967677c82b2cb23, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: b2be9c55e7e7ba447967677c82b2cb23, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: b2be9c55e7e7ba447967677c82b2cb23, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: b2be9c55e7e7ba447967677c82b2cb23, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: b2be9c55e7e7ba447967677c82b2cb23, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: b2be9c55e7e7ba447967677c82b2cb23, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: b2be9c55e7e7ba447967677c82b2cb23, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: b2be9c55e7e7ba447967677c82b2cb23, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 6 + m_Right: 6 + m_Top: 6 + m_Bottom: 6 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 1 + m_Right: 1 + m_Top: 1 + m_Bottom: 1 + m_Font: {fileID: 0} + m_FontSize: 15 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: -18} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: MinimizeButton + m_Normal: + m_Background: {fileID: 2800000, guid: 2aae9a02747d74d46bf98a15ac5c9b21, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: 2aae9a02747d74d46bf98a15ac5c9b21, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 2aae9a02747d74d46bf98a15ac5c9b21, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: 2aae9a02747d74d46bf98a15ac5c9b21, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 2aae9a02747d74d46bf98a15ac5c9b21, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 2aae9a02747d74d46bf98a15ac5c9b21, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 2aae9a02747d74d46bf98a15ac5c9b21, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 2aae9a02747d74d46bf98a15ac5c9b21, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 15 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: MaximizeButton + m_Normal: + m_Background: {fileID: 2800000, guid: 7a1fd3f5fef75b64385591e1890d1842, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: 7a1fd3f5fef75b64385591e1890d1842, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 7a1fd3f5fef75b64385591e1890d1842, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: 7a1fd3f5fef75b64385591e1890d1842, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 7a1fd3f5fef75b64385591e1890d1842, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 7a1fd3f5fef75b64385591e1890d1842, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 7a1fd3f5fef75b64385591e1890d1842, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 7a1fd3f5fef75b64385591e1890d1842, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 15 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: NodePropertiesTitle + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 15 + m_FontStyle: 1 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: ShaderModeTitle + m_Normal: + m_Background: {fileID: 2800000, guid: f4ca92d9e50d06049b7ccec2c438754d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Hover: + m_Background: {fileID: 2800000, guid: f4ca92d9e50d06049b7ccec2c438754d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Active: + m_Background: {fileID: 2800000, guid: f4ca92d9e50d06049b7ccec2c438754d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Focused: + m_Background: {fileID: 2800000, guid: f4ca92d9e50d06049b7ccec2c438754d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnNormal: + m_Background: {fileID: 2800000, guid: f4ca92d9e50d06049b7ccec2c438754d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnHover: + m_Background: {fileID: 2800000, guid: f4ca92d9e50d06049b7ccec2c438754d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnActive: + m_Background: {fileID: 2800000, guid: f4ca92d9e50d06049b7ccec2c438754d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnFocused: + m_Background: {fileID: 2800000, guid: f4ca92d9e50d06049b7ccec2c438754d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Border: + m_Left: 30 + m_Right: 0 + m_Top: 0 + m_Bottom: 38 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 14 + m_FontStyle: 1 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 34, y: -1} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 1 + - m_Name: MaterialModeTitle + m_Normal: + m_Background: {fileID: 2800000, guid: 5725fa8ee04e1be449af059f5735cd81, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Hover: + m_Background: {fileID: 2800000, guid: 5725fa8ee04e1be449af059f5735cd81, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Focused: + m_Background: {fileID: 2800000, guid: 5725fa8ee04e1be449af059f5735cd81, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 5725fa8ee04e1be449af059f5735cd81, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnHover: + m_Background: {fileID: 2800000, guid: 5725fa8ee04e1be449af059f5735cd81, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 5725fa8ee04e1be449af059f5735cd81, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Border: + m_Left: 0 + m_Right: 40 + m_Top: 0 + m_Bottom: 38 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 14 + m_FontStyle: 1 + m_Alignment: 5 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: -44, y: -1} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 1 + - m_Name: ShaderNoMaterialModeTitle + m_Normal: + m_Background: {fileID: 2800000, guid: 7040748e1c49b9648aeeefef41c8a3d5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Hover: + m_Background: {fileID: 2800000, guid: 7040748e1c49b9648aeeefef41c8a3d5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Focused: + m_Background: {fileID: 2800000, guid: 7040748e1c49b9648aeeefef41c8a3d5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 7040748e1c49b9648aeeefef41c8a3d5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnHover: + m_Background: {fileID: 2800000, guid: 7040748e1c49b9648aeeefef41c8a3d5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnActive: + m_Background: {fileID: 2800000, guid: 7040748e1c49b9648aeeefef41c8a3d5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 7040748e1c49b9648aeeefef41c8a3d5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 14 + m_FontStyle: 1 + m_Alignment: 5 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: -44, y: 9} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: PropertyValuesTitle + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5882353} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 11 + m_FontStyle: 3 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 3 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 1 + - m_Name: ShaderModeNoShader + m_Normal: + m_Background: {fileID: 2800000, guid: df81b9531d8ef704f96072ce6910db68, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Border: + m_Left: 30 + m_Right: 0 + m_Top: 0 + m_Bottom: 38 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 14 + m_FontStyle: 1 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 34, y: -1} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 1 + - m_Name: MainCanvasTitle + m_Normal: + m_Background: {fileID: 2800000, guid: bdb42c87b8801e94e886c5c0d60b3014, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.41911763, g: 0.41911763, b: 0.41911763, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 6 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 17 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 1 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: ShaderBorder + m_Normal: + m_Background: {fileID: 2800000, guid: 555b6a287b4121b479d412e6ea92bb2e, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 10 + m_Right: 10 + m_Top: 10 + m_Bottom: 10 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 17 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: MaterialBorder + m_Normal: + m_Background: {fileID: 2800000, guid: 157b94751c138d84bbe1768c672b5168, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 10 + m_Right: 10 + m_Top: 10 + m_Bottom: 10 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 17 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: SamplerTextureRef + m_Normal: + m_Background: {fileID: 2800000, guid: f9bd85ea2601b824c87556c13e852933, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 13 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 1 + - m_Name: SamplerTextureIcon + m_Normal: + m_Background: {fileID: 2800000, guid: 7cabe27e9427ef346a6b6557106353fd, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 7cabe27e9427ef346a6b6557106353fd, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 13 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: CustomExpressionAddItem + m_Normal: + m_Background: {fileID: 2800000, guid: 7eb057fdbf020504fb6c9c3c78031e5e, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 52bbe770f45f531419e44a69be67ccba, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Border: + m_Left: 12 + m_Right: 0 + m_Top: 12 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 15 + m_Right: 3 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: -2 + m_Right: 0 + m_Top: -4 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 17 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: CustomExpressionRemoveItem + m_Normal: + m_Background: {fileID: 2800000, guid: 839cb1530f95ad14ab58762161a9cb06, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 1ba096552f9cbbb418ee2286856bb352, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Border: + m_Left: 12 + m_Right: 0 + m_Top: 12 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 15 + m_Right: 3 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: -2 + m_Right: 0 + m_Top: -4 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 17 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: CustomExpressionSmallAddItem + m_Normal: + m_Background: {fileID: 2800000, guid: 1bd93c39ca74ac041b79ae289e9b9f08, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 1bd93c39ca74ac041b79ae289e9b9f08, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 13 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 1 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 20 + m_FixedHeight: 18 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: CustomExpressionSmallRemoveItem + m_Normal: + m_Background: {fileID: 2800000, guid: f4d31aa109c919d4595094f627510932, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: f4d31aa109c919d4595094f627510932, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 13 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 1 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 25 + m_FixedHeight: 18 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: ResetToDefaultInspectorButton + m_Normal: + m_Background: {fileID: 2800000, guid: a51794475a883744db8d524cee84e5fc, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: a51794475a883744db8d524cee84e5fc, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 2 + m_Top: 6 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: -2 + m_Right: 2 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 13 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 10 + m_FixedHeight: 9 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: SliderStyle + m_Normal: + m_Background: {fileID: 2800000, guid: 4cabb2d6785b8aa4db0c0a34e1e00f04, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 3 + m_Right: 3 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: ObjectPicker + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: 0} + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 8 + m_Right: 31 + m_Top: 0 + m_Bottom: 16 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 0 + m_Right: 3 + m_Top: 0 + m_Bottom: 1 + m_Overflow: + m_Left: -24 + m_Right: -1 + m_Top: 0 + m_Bottom: -1 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 8 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 3 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: NodePropertyPicker + m_Normal: + m_Background: {fileID: 2800000, guid: 94816692c85001f4dab01ec3666943c0, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 16 + m_FixedHeight: 16 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: NodePreviewExpander + m_Normal: + m_Background: {fileID: 2800000, guid: 1f3a46793c375864ab816c0d78061e4e, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 16 + m_FixedHeight: 16 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: NodePreviewCollapser + m_Normal: + m_Background: {fileID: 2800000, guid: dae54b5aa457b474e8a1599de1073d26, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 16 + m_FixedHeight: 16 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: SamplerButton + m_Normal: + m_Background: {fileID: 2800000, guid: b57dd36838fb19c449fd4559efe3f800, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Border: + m_Left: 2 + m_Right: 0 + m_Top: 2 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 1 + m_Top: 0 + m_Bottom: -1 + m_Overflow: + m_Left: 0 + m_Right: 1 + m_Top: 0 + m_Bottom: 1 + m_Font: {fileID: 3021071571035331536, guid: 0000000000000000d000000000000000, + type: 0} + m_FontSize: 9 + m_FontStyle: 0 + m_Alignment: 5 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 3 + m_ContentOffset: {x: 0, y: 1} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: SamplerFrame + m_Normal: + m_Background: {fileID: 2800000, guid: c1912a55d2f211d468ddeb7b1386dd41, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Border: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 3 + m_Right: 3 + m_Top: 3 + m_Bottom: 3 + m_Overflow: + m_Left: 1 + m_Right: 1 + m_Top: 1 + m_Bottom: 1 + m_Font: {fileID: 3021071571035331536, guid: 0000000000000000d000000000000000, + type: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: CommentarySuperTitle + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5882353} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_Border: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 3 + m_Right: 3 + m_Top: 3 + m_Bottom: 3 + m_Overflow: + m_Left: 1 + m_Right: 1 + m_Top: 1 + m_Bottom: 1 + m_Font: {fileID: 3021071571035331536, guid: 0000000000000000d000000000000000, + type: 0} + m_FontSize: 18 + m_FontStyle: 2 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 3 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: MiniButtonBotLeft + m_Normal: + m_Background: {fileID: 2800000, guid: 9f2d5e61dd9821b44a410f36519781d7, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Hover: + m_Background: {fileID: 2800000, guid: 6f3901bfd2342774ba74e117e43d6db7, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 4c872bb553406fe44a9d0046a0ef9bc5, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 7ef06ce40d713d34790e78278ee82dea, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Border: + m_Left: 1 + m_Right: 2 + m_Top: 2 + m_Bottom: 1 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 1 + m_Right: 0 + m_Top: 1 + m_Bottom: 0 + m_Font: {fileID: 3021071571035331536, guid: 0000000000000000d000000000000000, + type: 0} + m_FontSize: 9 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: MiniButtonBotMid + m_Normal: + m_Background: {fileID: 2800000, guid: eaf512a569994074b9b268ff098b0f03, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Hover: + m_Background: {fileID: 2800000, guid: c86cb249299fb7249b5ee7fb27ef1951, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 133e79bed45185d408f4c5410f89dded, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: 542d7546736ddd244a145ef7103678fb, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Border: + m_Left: 1 + m_Right: 1 + m_Top: 2 + m_Bottom: 1 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 1 + m_Bottom: 0 + m_Font: {fileID: 3021071571035331536, guid: 0000000000000000d000000000000000, + type: 0} + m_FontSize: 9 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: MiniButtonBotRight + m_Normal: + m_Background: {fileID: 2800000, guid: bfcecef29876cc54db85363cf2feebb2, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Hover: + m_Background: {fileID: 2800000, guid: df6fb8448a382c743bd124cc0da55113, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnNormal: + m_Background: {fileID: 2800000, guid: 3821e905373e9fb4aac56ad254ba5769, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 2800000, guid: d3098ebd60a35494e9977bd96b923298, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Border: + m_Left: 1 + m_Right: 2 + m_Top: 2 + m_Bottom: 1 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 1 + m_Top: 1 + m_Bottom: 0 + m_Font: {fileID: 3021071571035331536, guid: 0000000000000000d000000000000000, + type: 0} + m_FontSize: 9 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: ShaderFunctionBorder + m_Normal: + m_Background: {fileID: 2800000, guid: 94cd628d3d8e07d40a85d82b3fdad15d, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: -3646434626659933611, guid: 0000000000000000d000000000000000, type: 0} + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: -3080321147634112521, guid: 0000000000000000d000000000000000, type: 0} + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: -3976217546018649614, guid: 0000000000000000d000000000000000, type: 0} + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Border: + m_Left: 10 + m_Right: 10 + m_Top: 10 + m_Bottom: 10 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 17 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: ShaderFunctionMode + m_Normal: + m_Background: {fileID: 2800000, guid: 68897d376b60748438e0ae3474ebe558, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: -3646434626659933611, guid: 0000000000000000d000000000000000, type: 0} + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: -3080321147634112521, guid: 0000000000000000d000000000000000, type: 0} + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: -3976217546018649614, guid: 0000000000000000d000000000000000, type: 0} + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Border: + m_Left: 30 + m_Right: 0 + m_Top: 0 + m_Bottom: 38 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 14 + m_FontStyle: 1 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 34, y: -1} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 1 + - m_Name: RightShaderMode + m_Normal: + m_Background: {fileID: 2800000, guid: 5725fa8ee04e1be449af059f5735cd81, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: -3646434626659933611, guid: 0000000000000000d000000000000000, type: 0} + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: -3080321147634112521, guid: 0000000000000000d000000000000000, type: 0} + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: -3976217546018649614, guid: 0000000000000000d000000000000000, type: 0} + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Border: + m_Left: 0 + m_Right: 40 + m_Top: 0 + m_Bottom: 38 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 14 + m_FontStyle: 1 + m_Alignment: 5 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 3 + m_ContentOffset: {x: -44, y: -1} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 1 + - m_Name: FlatBackground + m_Normal: + m_Background: {fileID: 2800000, guid: 44efd0011d6a9bc4fb0b3a82753dac4e, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.4} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: -3646434626659933611, guid: 0000000000000000d000000000000000, type: 0} + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: -3080321147634112521, guid: 0000000000000000d000000000000000, type: 0} + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: + - {fileID: -3976217546018649614, guid: 0000000000000000d000000000000000, type: 0} + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 11 + m_FontStyle: 1 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 3 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: DocumentationLink + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.29803923, g: 0.49019608, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: 1004d06b4b28f5943abdf2313a22790a, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 1004d06b4b28f5943abdf2313a22790a, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.7019608, g: 0.7019608, b: 0.7019608, a: 1} + m_Focused: + m_Background: {fileID: 2800000, guid: 1004d06b4b28f5943abdf2313a22790a, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.2985075, g: 0.4923412, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.705, g: 0.705, b: 0.705, a: 1} + m_OnActive: + m_Background: {fileID: 2800000, guid: 1004d06b4b28f5943abdf2313a22790a, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.2985075, g: 0.4923412, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 2800000, guid: 1004d06b4b28f5943abdf2313a22790a, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.2985075, g: 0.4923412, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 2 + m_Bottom: 2 + m_Padding: + m_Left: 2 + m_Right: 2 + m_Top: 1 + m_Bottom: 2 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 9 + m_FontStyle: 0 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: GraphButtonIcon + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.7058824, g: 0.7058824, b: 0.7058824, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.7058824, g: 0.7058824, b: 0.7058824, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 2 + m_Right: 2 + m_Top: 2 + m_Bottom: 2 + m_Overflow: + m_Left: 2 + m_Right: 2 + m_Top: 2 + m_Bottom: 2 + m_Font: {fileID: 0} + m_FontSize: 10 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: GraphButton + m_Normal: + m_Background: {fileID: 2800000, guid: 2b3b7485f95e8a44dab3fa9610f56cbb, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.7058824, g: 0.7058824, b: 0.7058824, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: dd3411e8d9927d3429d5872dbdbd752b, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.7058824, g: 0.7058824, b: 0.7058824, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 3 + m_Right: 3 + m_Top: 3 + m_Bottom: 3 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 4 + m_Right: 4 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 1 + m_Right: 1 + m_Top: 1 + m_Bottom: 1 + m_Font: {fileID: 0} + m_FontSize: 10 + m_FontStyle: 0 + m_Alignment: 3 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: NodeWindowOffSquare + m_Normal: + m_Background: {fileID: 2800000, guid: d179c8744f837da49ab92aae04d1ae1c, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 1 + m_Right: 1 + m_Top: 1 + m_Bottom: 1 + m_Font: {fileID: 0} + m_FontSize: 13 + m_FontStyle: 1 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: -18} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: NodeHeaderSquare + m_Normal: + m_Background: {fileID: 2800000, guid: b16188b8a3dee8146bd9cb0bde234a24, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 1 + m_Right: 1 + m_Top: 1 + m_Bottom: 1 + m_Font: {fileID: 0} + m_FontSize: 13 + m_FontStyle: 1 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: NodeWindowOnSquare + m_Normal: + m_Background: {fileID: 2800000, guid: 080a030f87555fe419ecc1fb9f509118, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 6 + m_Right: 6 + m_Top: 6 + m_Bottom: 6 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 2 + m_Right: 2 + m_Top: 2 + m_Bottom: 2 + m_Font: {fileID: 0} + m_FontSize: 6 + m_FontStyle: 1 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + - m_Name: ConsoleLogMessage + m_Normal: + m_Background: {fileID: 2800000, guid: c560c5d8ca4c353409caf2ec204f3a19, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 8 + m_Right: 8 + m_Top: 8 + m_Bottom: 8 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 10 + m_FontStyle: 0 + m_Alignment: 8 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + - m_Name: ConsoleLogCircle + m_Normal: + m_Background: {fileID: 2800000, guid: c560c5d8ca4c353409caf2ec204f3a19, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_Hover: + m_Background: {fileID: 2800000, guid: c560c5d8ca4c353409caf2ec204f3a19, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 0.5019608} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Border: + m_Left: 8 + m_Right: 8 + m_Top: 8 + m_Bottom: 8 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 10 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 0 + m_Settings: + m_DoubleClickSelectsWord: 0 + m_TripleClickSelectsLine: 0 + m_CursorColor: {r: 1, g: 1, b: 1, a: 1} + m_CursorFlashSpeed: -1 + m_SelectionColor: {r: 1, g: 0.38403907, b: 0, a: 0.7} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/GUISkins/MainSkin.guiskin.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/GUISkins/MainSkin.guiskin.meta new file mode 100644 index 0000000..1601885 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/GUISkins/MainSkin.guiskin.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 57482289c346f104a8162a3a79aaff9d +timeCreated: 1481127067 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes.meta new file mode 100644 index 0000000..09c8ef6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 74a246631cfb81b4eb720dba241ad84c +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/Bezier1X2AA.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/Bezier1X2AA.png new file mode 100644 index 0000000000000000000000000000000000000000..ca6e05cf40e8048529082af6a8e59c826f9aefc5 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^j6lr9!3HE}Hf~b~Qfx`y?k+$Y2!1;6t_M<_1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~Cx?KV*5l~qZa^W~%#er@=ltB<)VvZPmw~~#C^fMp zHASI3vm`^o-P1Q9MK6^dC@$pb;uyklJ^9D~|NraRK!8E^4f9{+<9{xIw0XMvxvXKPsC5 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/Bezier1X2AA.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/Bezier1X2AA.png.meta new file mode 100644 index 0000000..c2e4d98 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/Bezier1X2AA.png.meta @@ -0,0 +1,59 @@ +fileFormatVersion: 2 +guid: 06e687f68dd96f0448c6d8217bbcf608 +timeCreated: 1481126972 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: 2 + aniso: 16 + mipBias: -1 + wrapMode: 0 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + 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 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 5 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconOFF.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconOFF.png new file mode 100644 index 0000000000000000000000000000000000000000..b97bfdb5c05e3abf186d8b4562a7ef59a15ed7c8 GIT binary patch literal 19742 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 S1&h(2nQ*jSWm90~yW`&@ZWjvx literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconOFF.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconOFF.png.meta new file mode 100644 index 0000000..5d712f1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconOFF.png.meta @@ -0,0 +1,58 @@ +fileFormatVersion: 2 +guid: 486c7766baaf21b46afb63c1121ef03e +timeCreated: 1481126990 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 1 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: 1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconON.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconON.png new file mode 100644 index 0000000000000000000000000000000000000000..0d8878a22697d7dca2383f18589e838c0ef8efbe GIT binary patch literal 20254 zcmeI43p7;g`^Ptla!VzW)VNfVxnGzuMvUAgx6su#vu8}q3^S8U7g3Qer;?(GqdHP4 zC8dPYjc!P#3q=>@bW!KHq?7R5L$NEJ>G%Jg|L?#4Yt5|1Jl_30-*@lN`@HY_>}{>R ze$H%14b=&%003w>JK1}|-!tGJ-4V+0?`_Wub>Od&VNL;J08kq%{ZRnYc8>=DRSzDM zIcH9=P$Cou3&T*(OeQK!B;@cyApnS~%kbvWX98s}-QzCrcAN|WK<&1?20Zn)OBOb%P6Q;DI1}l;zaZ$$EqK+n>70Inu<&1Pns|@<5W$;0Id-PY(sIk zu>$ZRhEAVhRHkwkP>8y%HUcPfPcOqwT-Q75mEEod3bAVy$|Omat|MZ#ftkxT+wBKt zIw-_u?40TiWGMlG*I7Z&fH`O&aN4RDw}IG<54)Bt0Q0vSj#J1=0#IY2M0+6E3OHOn zcf%~e9|vf2TrW|9`)B~??8k8ej-3L^s}e+e zv=$4`-!UCAEH-$}lj_LccQ)OQSyO;mj`Ox~09a&ig7LXlU{f&y0PM5k%#PXWx1S$x zUZyf@c(t8rLgg_7vq0>fnFgdX&)|gQFip$_ z-_x4bVWU2RBQnpMmc)%zvb{25ENEDls1UTl-+1!~-Cgk?49`0$joD~|x|*o%Y2=zj zcEWpY@Im=H8MIo96shYLIGjncx&jbZe@ZBE#BYx~?rD8T{Uo#KfW?Hh4tv#ZvL*Pm zEjn50H$^8VSZ|{2X}*~oJgROBgIR$q`+d9$@lq%bQ-0Ad-_m?!GV6N2(P8!6@(IW0 z9v)V_zJpbrAE`7ZZdTbyic+K<3Y=u?>>BZsZ^yfDou`GD(* zsb@z2b!mJM0l&`Q$=vwvm@Q+mTFVoemn=-itY;FY6>U{?&i~El)|gukw*+3sFU=38 zlbj|PCts~&ha6X-ZZ}8GxDwx#(R8ti*reZN*g9V|BWPy$Zy&s$ntEMZ;-dFl>pAJU zGPILm>$@+_>(PNdKBLK7=Gh(DQ|NWnbKQZlq@`)p$~8L9uGvTS?zlZ6SU0$ncl3A3 znbD7SOq!i~)9=>xmyW-u{ywZdQe7iq+?t9+uBl%7c$M*7y~y!Lce?G@yS-7b!Ut!8 zf4#GL*Qi}WUw^YgvlZi#uBq;D*)es8z8Ti%;GzA88V;%Xw)tN7*>Z4^_sTp6U!wQ3 zgCp;xcF}~+yg=%o8Mvry4NcQTy(qW!TilLD}V8`l5&(9ORpfx z+%QBVH(_ZU`O?(<$_FbV%!+q*8x(J}K6G#ol}U6V`W1M!ZRgmiJlh%mVYg)V$Y#@= z)V7!n4chOfKb@|>pX64AhZck!N=Z%e&vnZ6%yoQSO37=<$=F{yt2m%5PSdu+W!i#i zj@&I(!!w$_A9z2?QO(hDx2AREVGf04>+dPHk31*HdAl?7?4sCAH(^dgbZPU)i7T<) zKHdC}IUSDb{>laFCd&2dRpaTG$>Bn}0k)$4PfzB;i!+(o;0`eL$=al%8v4FkhhH2< zZQ_+LcxLj9U(PSzH&uD6;Z#@mSMG1qyxfcSPv39lX6056KlEWBEH@RZ)M=l7NC^9uQeD?x6MF89>syo+y>OOscgS@}!1wTi~N2b#GC z^9*9dCq&w`xwM9~s@-pGR$gvTd5PuvS8G+@Cq642dwu#PUWRx2ZAY#yw@AFEEpg*| z*VWfCsSHfIe)*#-rA;o9j_`#~mfh;eNH0jg&~l*u=v&HL-rIE#f4xEab$Vt1QGD~_ z73O2l=QTEJzwW?=G#-xeV0y%HPc|E4S=c1MBlnJ-%8oqL3BJ>1yl04hea3i3w`d?V z1T4N`QFiLesp}pWg_(=v8=0$&d)d9qdTW53*eMF!Ve8{;p`*FWdGese~MDa+#QI{=8`I zw1Znq+%()CrPDHX(jriNf;Fuazh+y~)^NK+hVIFQ+*jNeoQUg(q4?uHmjxS7VJGcS zxf)Wi_3-cjv}&Q<{@;D(ncg!~InIUrIOi(YU!$hvX3nT=xlwSfeyhdqcfaEY4!s?Wv^pOG+E`7r(ThC(xbtw(N)Uus@V>C|QJA#sb& zUt4|tq(aDRHDA@|@he|Hyw|eO!yg;acoO`WkfF~Qw|+yOcD-)uxK;N}A4WabUnjhF zZr8)@Cl2ObDq>f2ZgF0|Xh3Jq*GxH-`XW_Rpz)yYghu1s6D=L@XVqgRwtKjQi z%c+IBoVyA-ZSvM1dif!xi@)&5Y<_r4#jsn$x>bxd3-1-(sWrG|?c=rO?u^%tniZ4J z_GG+^L~Bqqe1F+p{?s_kKDy~;=g7v+NgA}eh)v56KT)|oIl_QzfL&sj)|%#!?w!^( zKWP3Lj~k4dyRRCSeR8ayJZd+I9uV!)=5v)-_j2{^WNvHqri>jKD`PN!Jq)bhTe!TL zRn@p;l)?IbI_(9~f zw?|4mN*1@zY_Wa7e6+6CW`57Z`|lpET2dC7)mHP+u~RvIO?6LF$Cgpd;ahfXxt^er z@H*3yL8U&m5p}=(l*6oMS5M8TT_$I@mFMbzbbpJ zceK9zLiwb#SEGpdMeTFDTFys4j5K(+uW^(|(+boo)862}@;kh5=5!_NB`5bP4cpoF ziA6-$1Ay&mo{zu8-`$PI67n%1TNngkqWEEOAqoI=o2W356#_|6K@gWGur_*Ee9j2P zV_O^fk==3bVN58P=d?@&c`uvo!&(-?qOy%_7^?Ir8Z5wvBp@n^A1V;jqO6VjbZM|H zZN?g*`dlO-)<(9{4pIK@b5Km72ttuD6f_Hu$D=H$7(CgMNFbY|2sk_$i=$%kI5ZAV z!{cZK9P0DOh@lEwbP=0F^RjpN+#URvwNbD{5=O&fBO@a*kwlD8#Kq#NR4Nunz!C^( z*aIz&7D&J-v_Nd!FY-ml9ul)eyf6t*C_qVd!64yMiM5fDw4;H~=j-B!4Rj;8i)y7Dhlm8H8u+ig+hEtAQ8iH_#xw9r0(tmp+k1Z=MNbvmduKP zui!J0AtS{;(P0qQ3la;LidfLB2>48lhdOz�wgP`x8>I`;bCmUv6cFKCgkpKg1~E zaeiUu)Px7A!xINHhv)No137WV9vTf{MoDAqtubvI%IAMc_~^aX}!5!tUb^ zcZ3l8t|Jc-4_*qvP=t^4TG()BAelzvTw2ThQhyY{c<3b*SBbefg&*^ozvDvUncdyDmSo*Nn`rf z1{%ncE_V!;G|?fL!dI<>r!^4yIgI!HaQ+;EetksvkNb!Wh6H~%QTnC&ynZYq7IGw! zpa`<%!Wr^2bGTpi>#%R-=~(IZ5X$>s7zi;K@t+L?+X7@mRDuPX0O24sg-T+hsbmTc z&F0`Cf(4lsM7AV+8Rq}-Fd$c&|GQxr%wkqBDBwbD2KLL9eQEeFjvPxUh=4@@&Lo1T zDhL-vkVwqnh=hC;7#0@FV}a5MiH#7jKUWn4>ljKRL?IU2e(ng3|Khc>ArbH2$y3Bx z4q!t4KfC7tcxL|Ge%C*&@|oGcD#SY|t-TLJKysr*j$Ki+|IS3E$YD5wh>aXMAqJxOG zWRpk`nZOR>kjS#O<{wB?*lbH2hhQm{CjYb2>>xJP5(25x>eKRv)#u+A6n!9I2;QCCkQ?~v{--Z*CR;B{@nN@(u64t6^h)2Y=}WbMh`Y4Qg2Wk{twuk{(pcm z#9oeeDCb#B3Z6=#pa~c}QU>9N(2?FF(%=#tE(iN|S_T~RUE8<*{?bx9bZK9yY(c=m zANY|3{P`S;Jp65Fz~6@=4}Tjv80jnENf>b1)_0=cG$W#XX~d=-c|@HwzQWe|^8`X+yWEBpWles+W% zczE>Py3oHF{KLNoujn5ZM#{-MLDGgmjSOLeh|F%W=s>gmjSOLeh|F%W=s> zgmjSOLeh|F%W=s>gmjSOLeh|F%W=s>gmjSOLeh|F%W=s>gmjSOLeh|F%W=s>gmjSO zLeh|F%W=s>gmjSOLeh|F%W=s>gmjSOLeh|F%W=s>gmjSOLeh|F%W=s>gmjSOLeh|F z%W=s>gmjSOLeh|F%W=s>gmjSOLeh|F%W=s>gmjSOLeh|F%W=s>gmjSOLeh|F%W=s> zgmjSOLeh|F%W=s>gmjSOLeh|F%W=s>gmjSOLeh|F%W=s>gmjSOLeh|F|1B=n!PhZB z0{9&ak?_kF&U?I=0>7vM#d7j;2Y_X;9lHhq{_2IlUjo2V900ru1OVDj_#I=yZHq5E z0Dxk=v%RfPRNW;%_mDd?$Hz2W4K2)mH0rlUEg02BpN3CT>X@rl(mCw|mcG2!ChKWs z$e&N0w+4CImTYhuHSX%%`fCxD$KP;>M^y@1LL)faLgSU}rV0r}kId+X=8T)orRm2e zu5Hz%42Lwg`Y1XP;!>!#Ue0f-;v(=}HhTLNA6wQg3QSSIXU^d{XEpi9%+3%`23aX0 zV83G4)fx|#>=Pkre5YaQO0laK^^PywqVAv+8vD`s9k8evsASJ6LJ z(b-D3J+HX-et5p+B*)s@jTcJ=Inh?Gg!45Iddhd4~Rg85BU-}34j@~bOGfZ3_uL_LMT2uK;9VXU=uwTG>qnMs;O}V_P zX99iB24O~s{mqJq+@2NhOT7M^`Xp?H@#fl#?PV@C%YmcnO8J!iZ>#+z4v=9 z8k->AJvKot`BrNT+CaIoPFvN!D{zs*lZ{6r*5q?e|9aFu^yPdY^vsD$UV%|5FETeA zYrsu#G3Tb32)ElE2%$i>_yUNmw-nf*yHPR49T#!A{>VpfpgJ^TpXvLRja@nwuad56 zcwH_lN^?f`=wK13hD+Aj=&v=- zY0=m@x%$VT literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconON.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconON.png.meta new file mode 100644 index 0000000..a752056 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/GPUInstancingIconON.png.meta @@ -0,0 +1,58 @@ +fileFormatVersion: 2 +guid: 4b0c2926cc71c5846ae2a29652d54fb6 +timeCreated: 1481126990 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: 1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/LinkIcon.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/LinkIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..fa98d7989eeaca2988dd8087c2923f6349593a71 GIT binary patch literal 18334 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 D=1lBE literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/MasterNodeIconOFF.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/MasterNodeIconOFF.png.meta new file mode 100644 index 0000000..50b756f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/MasterNodeIconOFF.png.meta @@ -0,0 +1,58 @@ +fileFormatVersion: 2 +guid: 712aee08d999c16438e2d694f42428e8 +timeCreated: 1481126996 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: 1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/MasterNodeIconON.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/MasterNodeIconON.png new file mode 100644 index 0000000000000000000000000000000000000000..7dc8d1573ef0f1637b2c15bc04ec345e3fd5775d GIT binary patch literal 23337 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 S)NjzH0C2EbWL;|M7xy1G2@Qq- literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/MasterNodeIconON.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/MasterNodeIconON.png.meta new file mode 100644 index 0000000..8d64d38 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/MasterNodeIconON.png.meta @@ -0,0 +1,58 @@ +fileFormatVersion: 2 +guid: 26c64fcee91024a49980ea2ee9d1a2fb +timeCreated: 1481126983 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: 1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/TextureReferenceBg.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Nodes/TextureReferenceBg.png new file mode 100644 index 0000000000000000000000000000000000000000..573cc11790dfc445c02ea64d870b4d7cca8c5a6a GIT binary patch literal 788 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 $i) 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%0DI^6|2CBS2sFX&TjAM`UsV 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/IndirectSpecularPreview.exr.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/IndirectSpecularPreview.exr.meta new file mode 100644 index 0000000..fd58550 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/IndirectSpecularPreview.exr.meta @@ -0,0 +1,69 @@ +fileFormatVersion: 2 +guid: ef7513b54a0670140b9b967af7620563 +timeCreated: 1512052044 +licenseType: Store +TextureImporter: + fileIDToRecycleName: + 8900000: generatedCubemap + 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: 1 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + filterMode: 2 + aniso: 0 + mipBias: 0 + 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: 2 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 100 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/LinearPreviews.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/LinearPreviews.shader new file mode 100644 index 0000000..077ef3a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/LinearPreviews.shader @@ -0,0 +1,232 @@ +Shader "Hidden/LinearMaterial" +{ + Properties + { + _MainTex( "Texture", any ) = "" {} + _BackGround( "Back", 2D) = "white" {} + } + + SubShader + { + Lighting Off + Blend SrcAlpha OneMinusSrcAlpha + Cull Off + ZWrite Off + ZTest Always + + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 2.0 + + #include "UnityCG.cginc" + + sampler2D _MainTex; + uniform float4 _MainTex_ST; + float4 _Mask; + + uniform float4x4 unity_GUIClipTextureMatrix; + sampler2D _GUIClipTexture; + + struct appdata_t { + float4 vertex : POSITION; + float2 texcoord : TEXCOORD0; + }; + + struct v2f { + float4 vertex : SV_POSITION; + float2 texcoord : TEXCOORD0; + float2 clipUV : TEXCOORD1; + }; + + v2f vert( appdata_t v ) + { + v2f o; + o.vertex = UnityObjectToClipPos( v.vertex ); + o.texcoord = TRANSFORM_TEX( v.texcoord.xy, _MainTex ); + float3 eyePos = UnityObjectToViewPos( v.vertex ); + o.clipUV = mul( unity_GUIClipTextureMatrix, float4( eyePos.xy, 0, 1.0 ) ); + return o; + } + + fixed4 frag( v2f i ) : SV_Target + { + float4 c = tex2D( _MainTex, i.texcoord ); + c.rgb *= _Mask.rgb; + + c.a = tex2D( _GUIClipTexture, i.clipUV ).a; + return c; + } + ENDCG + } + + Pass { // sphere preview = true, alpha mask = false + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 2.0 + + #include "UnityCG.cginc" + + sampler2D _MainTex; + uniform float4 _MainTex_ST; + float _InvertedZoom; + float4 _Mask; + + uniform float4x4 unity_GUIClipTextureMatrix; + sampler2D _GUIClipTexture; + + struct appdata_t { + float4 vertex : POSITION; + float2 texcoord : TEXCOORD0; + }; + + struct v2f { + float4 vertex : SV_POSITION; + float2 texcoord : TEXCOORD0; + float2 clipUV : TEXCOORD1; + }; + + v2f vert( appdata_t v ) + { + v2f o; + o.vertex = UnityObjectToClipPos( v.vertex ); + o.texcoord = TRANSFORM_TEX( v.texcoord.xy, _MainTex ); + float3 eyePos = UnityObjectToViewPos( v.vertex ); + o.clipUV = mul( unity_GUIClipTextureMatrix, float4( eyePos.xy, 0, 1.0 ) ); + return o; + } + + fixed4 frag( v2f i ) : SV_Target + { + float2 p = 2 * i.texcoord - 1; + float r = sqrt( dot( p,p ) ); + + float alpha = saturate( ( 1 - r )*( 45 * _InvertedZoom + 5 ) ); + + float4 c = tex2D( _MainTex, i.texcoord ); + c.rgb *= _Mask.rgb; + + c.rgb *= alpha; + + c.a = tex2D( _GUIClipTexture, i.clipUV ).a; + return c; + } + ENDCG + } + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 2.0 + + #include "UnityCG.cginc" + + sampler2D _MainTex; + sampler2D _BackGround; + uniform float4 _MainTex_ST; + uniform float4 _BackGround_ST; + float _InvertedZoom; + float4 _Mask; + + uniform float4x4 unity_GUIClipTextureMatrix; + sampler2D _GUIClipTexture; + + struct appdata_t { + float4 vertex : POSITION; + float2 texcoord : TEXCOORD0; + }; + + struct v2f { + float4 vertex : SV_POSITION; + float2 texcoord : TEXCOORD0; + float2 clipUV : TEXCOORD1; + }; + + v2f vert( appdata_t v ) + { + v2f o; + o.vertex = UnityObjectToClipPos( v.vertex ); + o.texcoord = TRANSFORM_TEX( v.texcoord.xy, _MainTex ); + float3 eyePos = UnityObjectToViewPos( v.vertex ); + o.clipUV = mul( unity_GUIClipTextureMatrix, float4( eyePos.xy, 0, 1.0 ) ); + return o; + } + + fixed4 frag( v2f i ) : SV_Target + { + float3 back = tex2D( _BackGround, ( i.texcoord * 2 - 1 ) * _InvertedZoom).b; + + float4 c = tex2D( _MainTex, i.texcoord ); + c.rgb *= _Mask.rgb; + c.rgb = lerp( back, c.rgb, c.a ); + + c.a = tex2D( _GUIClipTexture, i.clipUV ).a; + return c; + } + ENDCG + } + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 2.0 + + #include "UnityCG.cginc" + + sampler2D _MainTex; + sampler2D _BackGround; + uniform float4 _MainTex_ST; + uniform float4 _BackGround_ST; + float _InvertedZoom; + float4 _Mask; + + uniform float4x4 unity_GUIClipTextureMatrix; + sampler2D _GUIClipTexture; + + struct appdata_t { + float4 vertex : POSITION; + float2 texcoord : TEXCOORD0; + }; + + struct v2f { + float4 vertex : SV_POSITION; + float2 texcoord : TEXCOORD0; + float2 clipUV : TEXCOORD1; + }; + + v2f vert( appdata_t v ) + { + v2f o; + o.vertex = UnityObjectToClipPos( v.vertex ); + o.texcoord = TRANSFORM_TEX( v.texcoord.xy, _MainTex ); + float3 eyePos = UnityObjectToViewPos( v.vertex ); + o.clipUV = mul( unity_GUIClipTextureMatrix, float4( eyePos.xy, 0, 1.0 ) ); + return o; + } + + fixed4 frag( v2f i ) : SV_Target + { + float2 p = 2 * i.texcoord - 1; + float3 back = tex2D( _BackGround, p * _InvertedZoom).b; + float r = sqrt( dot( p,p ) ); + + float alpha = saturate( ( 1 - r )*( 45 * _InvertedZoom + 5 ) ); + + float4 c = 0; + c = tex2D( _MainTex, i.texcoord ); + c.rgb *= _Mask.rgb; + c.rgb = lerp( back, c.rgb, c.a * alpha); + + c.a = tex2D( _GUIClipTexture, i.clipUV ).a; + return c; + } + ENDCG + } + } + Fallback Off +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/LinearPreviews.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/LinearPreviews.shader.meta new file mode 100644 index 0000000..03bf6e5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/LinearPreviews.shader.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e90ef6ea05743b84baf9549874c52e47 +timeCreated: 1489078120 +licenseType: Store +ShaderImporter: + defaultTextures: + - _MainTex: {instanceID: 0} + - _BackGround: {fileID: 2800000, guid: 750b1bd7ba8bd28489650de6d0a95cc5, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ACosOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ACosOpNode.shader new file mode 100644 index 0000000..a06859d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ACosOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/ACosOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return acos(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ACosOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ACosOpNode.shader.meta new file mode 100644 index 0000000..8cb6d6a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ACosOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 710f3c0bbd7ba0c4aada6d7dfadd49c2 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ASinOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ASinOpNode.shader new file mode 100644 index 0000000..8273b04 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ASinOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/ASinOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return asin(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ASinOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ASinOpNode.shader.meta new file mode 100644 index 0000000..69d34ba --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ASinOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2b016c135284add4cb3364d4a0bd0638 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATan2OpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATan2OpNode.shader new file mode 100644 index 0000000..f15dbcd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATan2OpNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/ATan2OpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return atan2(a, b); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATan2OpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATan2OpNode.shader.meta new file mode 100644 index 0000000..fc57c1a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATan2OpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 02e3ff61784e38840af6313936b6a730 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATanOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATanOpNode.shader new file mode 100644 index 0000000..acc5cdb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATanOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/ATanOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return atan(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATanOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATanOpNode.shader.meta new file mode 100644 index 0000000..178006a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ATanOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7d7f3331a98831241b017364e80625ea +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AbsOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AbsOpNode.shader new file mode 100644 index 0000000..ecff53d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AbsOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/AbsOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return abs(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AbsOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AbsOpNode.shader.meta new file mode 100644 index 0000000..43b7595 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AbsOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: cd6d6dfa3df214a479f68a490e177db6 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AppendNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AppendNode.shader new file mode 100644 index 0000000..f91228b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AppendNode.shader @@ -0,0 +1,36 @@ +Shader "Hidden/AppendNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_C", 2D) = "white" {} + _D ("_D", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + + float4 frag(v2f_img i) : SV_Target + { + float x = tex2D(_A, i.uv).x; + float y = tex2D(_B, i.uv).y; + float z = tex2D(_C, i.uv).z; + float w = tex2D(_D, i.uv).w; + + return float4(x,y,z,w); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AppendNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AppendNode.shader.meta new file mode 100644 index 0000000..fc3d21e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_AppendNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: d80ac81aabf643848a4eaa76f2f88d65 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendNormalsNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendNormalsNode.shader new file mode 100644 index 0000000..cbb2419 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendNormalsNode.shader @@ -0,0 +1,82 @@ +Shader "Hidden/BlendNormalsNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_C", 2D) = "white" {} + } + SubShader + { + CGINCLUDE + #pragma vertex vert_img + #pragma fragment frag + #pragma target 3.0 + #include "UnityCG.cginc" + #include "UnityStandardUtils.cginc" + + float3 BlendNormalWorldspaceRNM(float3 n1, float3 n2, float3 vtxNormal) + { + float4 q = float4(cross(vtxNormal, n2), dot(vtxNormal, n2) + 1.0) / sqrt(2.0 * (dot(vtxNormal, n2) + 1)); + return n1 * (q.w * q.w - dot(q.xyz, q.xyz)) + 2 * q.xyz * dot(q.xyz, n1) + 2 * q.w * cross(q.xyz, n1); + } + + float3 BlendNormalRNM(float3 n1, float3 n2) + { + float3 t = n1.xyz + float3(0.0, 0.0, 1.0); + float3 u = n2.xyz * float3(-1.0, -1.0, 1.0); + float3 r = (t / t.z) * dot(t, u) - u; + return r; + } + ENDCG + Pass + { + CGPROGRAM + + sampler2D _A; + sampler2D _B; + + float4 frag(v2f_img i) : SV_Target + { + float3 a = tex2D( _A, i.uv ).rgb; + float3 b = tex2D( _B, i.uv ).rgb; + return float4(BlendNormals(a, b), 0); + } + ENDCG + } + + Pass + { + CGPROGRAM + + sampler2D _A; + sampler2D _B; + + float4 frag(v2f_img i) : SV_Target + { + float3 a = tex2D(_A, i.uv).rgb; + float3 b = tex2D(_B, i.uv).rgb; + return float4(BlendNormalRNM(a, b), 0); + } + ENDCG + } + + Pass + { + CGPROGRAM + + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag(v2f_img i) : SV_Target + { + float3 a = tex2D(_A, i.uv).rgb; + float3 b = tex2D(_B, i.uv).rgb; + float3 c = tex2D(_C, i.uv).rgb; + return float4(BlendNormalWorldspaceRNM(a,b,c), 0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendNormalsNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendNormalsNode.shader.meta new file mode 100644 index 0000000..fac57de --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendNormalsNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: bcdf750ff5f70444f98b8a3efa50dc6f +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendOpsNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendOpsNode.shader new file mode 100644 index 0000000..8066511 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendOpsNode.shader @@ -0,0 +1,601 @@ +Shader "Hidden/BlendOpsNode" +{ + Properties + { + _A ("_Source", 2D) = "white" {} + _B ("_Destiny", 2D) = "white" {} + _C ("_Alpha", 2D) = "white" {} + } + SubShader + { + Pass //colorburn + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( 1.0 - ( ( 1.0 - des) / max( src,0.00001)) ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp(des, c, alpha); + } + + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //colordodge + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( des/ max( 1.0 - src,0.00001 ) ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //darken + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( min( src , des ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //divide + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( des / max( src,0.00001) ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //difference + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( abs( src - des ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //exclusion + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( 0.5 - 2.0 * ( src - 0.5 ) * ( des - 0.5 ) ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //softlight + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( 2.0f*src*des + des*des*(1.0f - 2.0f*src) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //hardlight + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( src > 0.5 ? ( 1.0 - ( 1.0 - 2.0 * ( src - 0.5 ) ) * ( 1.0 - des ) ) : ( 2.0 * src * des ) ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //hardmix + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( round( 0.5 * ( src + des ) ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //lighten + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( max( src, des ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //linearburn + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( src + des - 1.0 ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //lineardodge + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( src + des ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //linearlight + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( src > 0.5 ? ( des + 2.0 * src - 1.0 ) : ( des + 2.0 * ( src - 0.5 ) ) ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //multiply + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( src * des ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //overlay + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( des > 0.5 ? ( 1.0 - 2.0 * ( 1.0 - des ) * ( 1.0 - src ) ) : ( 2.0 * des * src ) ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //pinlight + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( src > 0.5 ? max( des, 2.0 * ( src - 0.5 ) ) : min( des, 2.0 * src ) ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //subtract + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( des - src ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //screen + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( 1.0 - ( 1.0 - src ) * ( 1.0 - des ) ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + + Pass //vividlight + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + int _Sat; + int _Lerp; + + float4 frag(v2f_img i) : SV_Target + { + float4 src = tex2D( _A, i.uv ); + float4 des = tex2D( _B, i.uv ); + + float4 c = ( ( src > 0.5 ? ( des / max( ( 1.0 - src ) * 2.0 ,0.00001) ) : ( 1.0 - ( ( ( 1.0 - des ) * 0.5 ) / max(src,0.00001) ) ) ) ); + if (_Lerp == 1) + { + float alpha = tex2D (_C, i.uv).r; + c = lerp (des, c, alpha); + } + if( _Sat == 1 ) + c = saturate( c ); + return c; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendOpsNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendOpsNode.shader.meta new file mode 100644 index 0000000..37d0722 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BlendOpsNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6d6b3518705b3ba49acdc6e18e480257 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BreakToComponentsNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BreakToComponentsNode.shader new file mode 100644 index 0000000..e6306b5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BreakToComponentsNode.shader @@ -0,0 +1,73 @@ +Shader "Hidden/BreakToComponentsNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tex2D( _A, i.uv ).x; + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tex2D( _A, i.uv ).y; + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tex2D( _A, i.uv ).z; + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tex2D( _A, i.uv ).w; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BreakToComponentsNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BreakToComponentsNode.shader.meta new file mode 100644 index 0000000..05a2374 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_BreakToComponentsNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5f58f74a202ba804daddec838b75207d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CeilOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CeilOpNode.shader new file mode 100644 index 0000000..7065d1e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CeilOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/CeilOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return ceil(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CeilOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CeilOpNode.shader.meta new file mode 100644 index 0000000..e278da2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CeilOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ce0588227a766a245a85291977c1f222 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClampOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClampOpNode.shader new file mode 100644 index 0000000..df9318e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClampOpNode.shader @@ -0,0 +1,33 @@ +Shader "Hidden/ClampOpNode" +{ + Properties + { + _A ("_Value", 2D) = "white" {} + _B ("_Min", 2D) = "white" {} + _C ("_Max", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag(v2f_img i) : SV_Target + { + float4 value = tex2D( _A, i.uv ); + float4 min = tex2D( _B, i.uv ); + float4 max = tex2D( _C, i.uv ); + + return clamp(value, min, max); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClampOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClampOpNode.shader.meta new file mode 100644 index 0000000..aedd754 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClampOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ab6163c4b10bfc84da8e3c486520490a +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Clip.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Clip.shader new file mode 100644 index 0000000..47bd6e0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Clip.shader @@ -0,0 +1,35 @@ +Shader "Hidden/Clip" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_C", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + float4 c = tex2D( _C, i.uv ); + + clip(b - c); + + return a; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Clip.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Clip.shader.meta new file mode 100644 index 0000000..637c32a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Clip.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1fca7774f364aee4d8c64e8634ef4be4 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClipPlanes.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClipPlanes.shader new file mode 100644 index 0000000..59f5543 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClipPlanes.shader @@ -0,0 +1,25 @@ +Shader "Hidden/ClipPlanes" +{ + Properties + { + _PlaneId ("_PlaneId", Int) = 0 + } + + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + int _PlaneId; + float4 frag( v2f_img i ) : SV_Target + { + return unity_CameraWorldClipPlanes[_PlaneId]; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClipPlanes.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClipPlanes.shader.meta new file mode 100644 index 0000000..7de7975 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ClipPlanes.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6afe5a4ad7bbd0e4ab352c758f543a09 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorNode.shader new file mode 100644 index 0000000..4663c49 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorNode.shader @@ -0,0 +1,24 @@ +Shader "Hidden/ColorNode" +{ + Properties { + _InputColor ("_InputColor", Color) = (0,0,0,0) + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 _InputColor; + + float4 frag( v2f_img i ) : SV_Target + { + return _InputColor; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorNode.shader.meta new file mode 100644 index 0000000..27cfeaf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6cf365ccc7ae776488ae8960d6d134c3 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorSpaceDouble.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorSpaceDouble.shader new file mode 100644 index 0000000..c27833a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorSpaceDouble.shader @@ -0,0 +1,19 @@ +Shader "Hidden/ColorSpaceDouble" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + return unity_ColorSpaceDouble; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorSpaceDouble.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorSpaceDouble.shader.meta new file mode 100644 index 0000000..66ba194 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ColorSpaceDouble.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ac680a8772bb97c46851a7f075fd04e3 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Compare.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Compare.shader new file mode 100644 index 0000000..7a3009b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Compare.shader @@ -0,0 +1,48 @@ +Shader "Hidden/TFHCCompareEqual" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_True", 2D) = "white" {} + _D ( "_False", 2D ) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + int _Operator; + + float4 frag(v2f_img i) : SV_Target + { + float A = tex2D( _A, i.uv ).x; + float B = tex2D( _B, i.uv ).x; + float4 True = tex2D( _C, i.uv ); + float4 False = tex2D ( _D, i.uv ); + + if( _Operator == 0 ) + return ( ( A == B ) ? True : False ); + else if( _Operator == 1 ) + return ( ( A != B ) ? True : False ); + else if( _Operator == 2 ) + return ( ( A > B ) ? True : False ); + else if( _Operator == 3 ) + return ( ( A >= B ) ? True : False ); + else if( _Operator == 4 ) + return ( ( A < B ) ? True : False ); + else + return ( ( A <= B ) ? True : False ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Compare.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Compare.shader.meta new file mode 100644 index 0000000..9e2ee0e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Compare.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 381937898f0c15747af1da09a751890c +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComponentMaskNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComponentMaskNode.shader new file mode 100644 index 0000000..b607639 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComponentMaskNode.shader @@ -0,0 +1,62 @@ +Shader "Hidden/ComponentMaskNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + float _Singular; + float4 _Order; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 r = 0; + if(_Singular == 0) + r = a.x; + else if(_Singular == 1) + r = a.y; + else if(_Singular == 2) + r = a.z; + else if(_Singular == 3) + r = a.w; + + if ( _Order.x == 0 ) + r.x = a.x; + else if(_Order.y == 0) + r.x = a.y; + else if(_Order.z == 0) + r.x = a.z; + else if(_Order.w == 0) + r.x = a.w; + + if(_Order.y == 1) + r.y = a.y; + else if(_Order.z == 1) + r.y = a.z; + else if(_Order.w == 1) + r.y = a.w; + + if(_Order.z == 2) + r.z = a.z; + else if(_Order.w == 2) + r.z = a.w; + + if(_Order.w == 3) + r.w = a.w; + + return r; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComponentMaskNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComponentMaskNode.shader.meta new file mode 100644 index 0000000..a019f58 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComponentMaskNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b78e2b295c265cd439c80d218fb3e88e +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComputeScreenPos.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComputeScreenPos.shader new file mode 100644 index 0000000..175ae3b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComputeScreenPos.shader @@ -0,0 +1,47 @@ +Shader "Hidden/ComputeScreenPos" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 screenPos = ComputeScreenPos(a); + return screenPos; + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag (v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + float4 screenPos = ComputeScreenPos(a); + screenPos = screenPos / screenPos.w; + screenPos.z = (UNITY_NEAR_CLIP_VALUE >= 0) ? screenPos.z : screenPos.z* 0.5 + 0.5; + return screenPos; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComputeScreenPos.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComputeScreenPos.shader.meta new file mode 100644 index 0000000..983e7e4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ComputeScreenPos.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 97bd4895d847d764eb21d2bf7aa13671 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ConditionalIfNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ConditionalIfNode.shader new file mode 100644 index 0000000..1121f0d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ConditionalIfNode.shader @@ -0,0 +1,47 @@ +Shader "Hidden/Preview_ConditionalIfNode" +{ + Properties + { + _A ( "_A", 2D) = "white" {} + _B ( "_B", 2D ) = "white" {} + _C ( "_AGreaterThanB", 2D ) = "white" {} + _D ( "_AEqualToB", 2D ) = "white" {} + _E ( "_ALessThanB", 2D ) = "white" {} + } + + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + uniform sampler2D _A; + uniform sampler2D _B; + uniform sampler2D _C; + uniform sampler2D _D; + uniform sampler2D _E; + + float4 frag ( v2f_img i ) : SV_Target + { + float aVal = tex2D ( _A, i.uv ).r; + float bVal = tex2D ( _B, i.uv ).r; + float4 aGreaterbVal = tex2D ( _C, i.uv ); + float4 aEqualbVal = tex2D ( _D, i.uv ); + float4 aLessbVal = tex2D ( _E, i.uv ); + + if ( aVal > bVal ) + return aGreaterbVal; + + if ( aVal == bVal ) + return aEqualbVal; + + return aLessbVal; + + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ConditionalIfNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ConditionalIfNode.shader.meta new file mode 100644 index 0000000..2a79ade --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ConditionalIfNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f6fb4d46bddf29e45a8a3ddfed75d0c0 +timeCreated: 1515424552 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosOpNode.shader new file mode 100644 index 0000000..7db0240 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/CosOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return cos(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosOpNode.shader.meta new file mode 100644 index 0000000..85cde2f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3dde9e80389196f459eb94137268de4a +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosTime.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosTime.shader new file mode 100644 index 0000000..8e591b6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosTime.shader @@ -0,0 +1,25 @@ +Shader "Hidden/CosTime" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float _EditorTime; + + float4 frag( v2f_img i ) : SV_Target + { + float4 t = _EditorTime; + t.x = _EditorTime / 8; + t.y = _EditorTime / 4; + t.z = _EditorTime / 2; + return cos(t); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosTime.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosTime.shader.meta new file mode 100644 index 0000000..4a17551 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CosTime.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3093999b42c3c0940a71799511d7781c +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CoshOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CoshOpNode.shader new file mode 100644 index 0000000..8bdcf40 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CoshOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/CoshOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return cosh(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CoshOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CoshOpNode.shader.meta new file mode 100644 index 0000000..cb2b2fe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CoshOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 154a4c85fe88657489a54a02416402c0 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CrossProductOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CrossProductOpNode.shader new file mode 100644 index 0000000..6b50b14 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CrossProductOpNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/CrossProductOpNode" +{ + Properties + { + _A ("_Lhs", 2D) = "white" {} + _B ("_Rhs", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return float4(cross(a.rgb, b.rgb),0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CrossProductOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CrossProductOpNode.shader.meta new file mode 100644 index 0000000..8a06c64 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_CrossProductOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 65a9be5cc7037654db8e148d669f03ee +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdxOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdxOpNode.shader new file mode 100644 index 0000000..d6fd37b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdxOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/DdxOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return ddx(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdxOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdxOpNode.shader.meta new file mode 100644 index 0000000..80e1431 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdxOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b54ea73d5568b3540977557813eb9c3c +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdyOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdyOpNode.shader new file mode 100644 index 0000000..cfffd11 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdyOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/DdyOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return ddy(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdyOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdyOpNode.shader.meta new file mode 100644 index 0000000..ec2c4ef --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DdyOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 197dcc7f05339da47b6b0e681c475c5e +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeDepthNormalNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeDepthNormalNode.shader new file mode 100644 index 0000000..41ee539 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeDepthNormalNode.shader @@ -0,0 +1,30 @@ +Shader "Hidden/DecodeDepthNormalNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float depthValue = 0; + float3 normalValue = 0; + DecodeDepthNormal( a , depthValue, normalValue ); + return float4( depthValue,normalValue ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeDepthNormalNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeDepthNormalNode.shader.meta new file mode 100644 index 0000000..6f6d8ac --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeDepthNormalNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: dbf37c4d3ce0f0b41822584d6c9ba203 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGBAHlpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGBAHlpNode.shader new file mode 100644 index 0000000..e749466 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGBAHlpNode.shader @@ -0,0 +1,27 @@ +Shader "Hidden/DecodeFloatRGBAHlpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + return DecodeFloatRGBA( a ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGBAHlpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGBAHlpNode.shader.meta new file mode 100644 index 0000000..a1237f6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGBAHlpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f71b31b15ff3f2042bafbed40acd29f4 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGHlpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGHlpNode.shader new file mode 100644 index 0000000..e60788c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGHlpNode.shader @@ -0,0 +1,27 @@ +Shader "Hidden/DecodeFloatRGHlpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + + float4 frag( v2f_img i ) : SV_Target + { + float2 a = tex2D( _A, i.uv ).rg; + return DecodeFloatRG( a ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGHlpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGHlpNode.shader.meta new file mode 100644 index 0000000..c6e62f2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeFloatRGHlpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1fb3121b1c8febb4dbcc2a507a2df2db +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeLightmapHlpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeLightmapHlpNode.shader new file mode 100644 index 0000000..b0629e6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeLightmapHlpNode.shader @@ -0,0 +1,26 @@ +Shader "Hidden/DecodeLighmapHlpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + return float4(DecodeLightmap ( a ),0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeLightmapHlpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeLightmapHlpNode.shader.meta new file mode 100644 index 0000000..e0806a2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeLightmapHlpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c2d3bee1aee183343b31b9208cb402e9 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeViewNormalStereoHlpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeViewNormalStereoHlpNode.shader new file mode 100644 index 0000000..cf7c62f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeViewNormalStereoHlpNode.shader @@ -0,0 +1,27 @@ +Shader "Hidden/DecodeViewNormalStereoHlpNode" +{ + Properties + { + _A ( "_A", 2D ) = "white" {} + } + + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag ( v2f_img i ) : SV_Target + { + float4 a = tex2D ( _A, i.uv ); + return float4( DecodeViewNormalStereo ( a ),0 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeViewNormalStereoHlpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeViewNormalStereoHlpNode.shader.meta new file mode 100644 index 0000000..409d139 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DecodeViewNormalStereoHlpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e996db1cc4510c84185cb9f933f916bb +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DegreesOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DegreesOpNode.shader new file mode 100644 index 0000000..9e91f8c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DegreesOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/DegreesOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return degrees(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DegreesOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DegreesOpNode.shader.meta new file mode 100644 index 0000000..67fd1f3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DegreesOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2a8eebb5566830c4a9d7c4b9021bb743 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DeltaTime.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DeltaTime.shader new file mode 100644 index 0000000..092d1f9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DeltaTime.shader @@ -0,0 +1,26 @@ +Shader "Hidden/DeltaTime" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float _EditorDeltaTime; + + float4 frag( v2f_img i ) : SV_Target + { + float4 t = _EditorDeltaTime; + t.y = 1 / _EditorDeltaTime; + t.z = _EditorDeltaTime; + t.w = 1 / _EditorDeltaTime; + return cos(t); + } + ENDCG + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DeltaTime.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DeltaTime.shader.meta new file mode 100644 index 0000000..c39cf8d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DeltaTime.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 9d69a693042c443498f96d6da60535eb +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DesaturateNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DesaturateNode.shader new file mode 100644 index 0000000..1bc967f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DesaturateNode.shader @@ -0,0 +1,34 @@ +Shader "Hidden/DesaturateNode" +{ + Properties + { + _A ( "_RBG", 2D ) = "white" {} + _B ( "_Fraction", 2D ) = "white" {} + } + + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + uniform sampler2D _A; + uniform sampler2D _B; + + float4 frag ( v2f_img i ) : SV_Target + { + float3 rgb = tex2D ( _A, i.uv ).rgb; + float fraction = tex2D ( _B, i.uv ).r; + + float dotResult = dot ( rgb, float3( 0.299, 0.587, 0.114 ) ); + float3 finalColor = lerp ( rgb, dotResult.xxx, fraction ); + + return float4( finalColor, 1 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DesaturateNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DesaturateNode.shader.meta new file mode 100644 index 0000000..97fe8c0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DesaturateNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: faabe9efdf44b9648a523f1742abdfd3 +timeCreated: 1515421907 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DiffuseAndSpecularFromMetallic.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DiffuseAndSpecularFromMetallic.shader new file mode 100644 index 0000000..9d2f407 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DiffuseAndSpecularFromMetallic.shader @@ -0,0 +1,32 @@ +Shader "Hidden/DiffuseAndSpecularFromMetallicNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #include "UnityStandardUtils.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag( v2f_img i ) : SV_Target + { + float4 albedo = tex2D( _A, i.uv ); + float metallic = tex2D( _A, i.uv ).r; + float3 specColor = 0; + float oneMinusReflectivity; + float3 albedoFinal = DiffuseAndSpecularFromMetallic(albedo,metallic,specColor,oneMinusReflectivity); + return float4( albedoFinal , 1 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DiffuseAndSpecularFromMetallic.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DiffuseAndSpecularFromMetallic.shader.meta new file mode 100644 index 0000000..46286ed --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DiffuseAndSpecularFromMetallic.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c7c4485750948a045b5dab0985896e17 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DistanceOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DistanceOpNode.shader new file mode 100644 index 0000000..0ba2dfd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DistanceOpNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/DistanceOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return distance( a, b ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DistanceOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DistanceOpNode.shader.meta new file mode 100644 index 0000000..6ca677b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DistanceOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3be9a95031c0cb740ae982e465dfc242 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DotProductOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DotProductOpNode.shader new file mode 100644 index 0000000..a467eed --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DotProductOpNode.shader @@ -0,0 +1,27 @@ +Shader "Hidden/DotProductOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag(v2f_img i) : SV_Target + { + return dot(tex2D(_A, i.uv).rgb, tex2D(_B, i.uv).rgb); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DotProductOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DotProductOpNode.shader.meta new file mode 100644 index 0000000..d506912 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DotProductOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 85f11fd5cb9bb954c8615a45c57a3784 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DynamicAppendNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DynamicAppendNode.shader new file mode 100644 index 0000000..d7e7b16 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DynamicAppendNode.shader @@ -0,0 +1,135 @@ +Shader "Hidden/DynamicAppendNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_C", 2D) = "white" {} + _D ("_D", 2D) = "white" {} + _Mask("_Mask", Vector) = (0,0,0,0) + } + SubShader + { + CGINCLUDE + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + + float4 _Mask; + ENDCG + + Pass //0 + { + Name "1111" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + float4 b = tex2D(_B, i.uv); + float4 c = tex2D(_C, i.uv); + float4 d = tex2D(_D, i.uv); + return float4(a.x,b.x,c.x,d.x)*_Mask; + } + ENDCG + } + + Pass //1 + { + Name "1120" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + float4 b = tex2D(_B, i.uv); + float4 c = tex2D(_C, i.uv); + + return float4(a.x,b.x,c.xy)*_Mask; + } + ENDCG + } + + Pass //2 + { + Name "1201" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + float4 b = tex2D(_B, i.uv); + float4 d = tex2D(_D, i.uv); + return float4(a.x,b.xy,d.x)*_Mask; + } + ENDCG + } + + Pass //3 + { + Name "1300" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + float4 b = tex2D(_B, i.uv); + return float4(a.x,b.xyz)*_Mask; + } + ENDCG + } + + Pass //4 + { + Name "2011" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + float4 c = tex2D(_C, i.uv); + float4 d = tex2D(_D, i.uv); + return float4(a.xy,c.x,d.x)*_Mask; + } + ENDCG + } + + Pass //5 + { + Name "2020" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + float4 c = tex2D(_C, i.uv); + return float4(a.xy,c.xy)*_Mask; + } + ENDCG + } + + Pass //6 + { + Name "3001" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + float4 d = tex2D(_D, i.uv); + return float4(a.xyz,d.x)*_Mask; + } + ENDCG + } + + Pass //7 + { + Name "4000" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return a*_Mask; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DynamicAppendNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DynamicAppendNode.shader.meta new file mode 100644 index 0000000..ebe42e4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_DynamicAppendNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: bfcd2919fe75bbf428fbbe583f463a9e +timeCreated: 1510580676 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGBAHlpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGBAHlpNode.shader new file mode 100644 index 0000000..80e3070 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGBAHlpNode.shader @@ -0,0 +1,27 @@ +Shader "Hidden/EncodeFloatRGBAHlpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + + float4 frag( v2f_img i ) : SV_Target + { + float a = tex2D( _A, i.uv ).r; + return EncodeFloatRGBA( a ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGBAHlpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGBAHlpNode.shader.meta new file mode 100644 index 0000000..416d650 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGBAHlpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c21569bf5b9371b4ca13c0c00abd5562 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGHlpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGHlpNode.shader new file mode 100644 index 0000000..f3b8ff1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGHlpNode.shader @@ -0,0 +1,27 @@ +Shader "Hidden/EncodeFloatRGNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + + float4 frag( v2f_img i ) : SV_Target + { + float a = tex2D( _A, i.uv ).r; + return float4( EncodeFloatRG( a ), 0,0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGHlpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGHlpNode.shader.meta new file mode 100644 index 0000000..8b064eb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeFloatRGHlpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a44b520baa5c39e41bc69a22ea46f24d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeViewNormalStereoHlpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeViewNormalStereoHlpNode.shader new file mode 100644 index 0000000..d23d09f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeViewNormalStereoHlpNode.shader @@ -0,0 +1,27 @@ +Shader "Hidden/EncodeViewNormalStereoHlpNode" +{ + Properties + { + _A ( "_A", 2D ) = "white" {} + } + + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag ( v2f_img i ) : SV_Target + { + float3 a = tex2D ( _A, i.uv ).rgb; + return float4( EncodeViewNormalStereo( a ),0,0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeViewNormalStereoHlpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeViewNormalStereoHlpNode.shader.meta new file mode 100644 index 0000000..1db2cbf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_EncodeViewNormalStereoHlpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3d0b3d482b7246c4cb60fa73e6ceac6c +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Exp2OpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Exp2OpNode.shader new file mode 100644 index 0000000..36ab711 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Exp2OpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/Exp2OpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return exp2(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Exp2OpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Exp2OpNode.shader.meta new file mode 100644 index 0000000..b5c6d56 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Exp2OpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ceb70ed5423a36647a504a41de7dbfe6 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ExpOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ExpOpNode.shader new file mode 100644 index 0000000..83afb73 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ExpOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/ExpOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return exp(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ExpOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ExpOpNode.shader.meta new file mode 100644 index 0000000..53b5e1e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ExpOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6416ff506137d97479a7ebde790b45e5 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FWidthOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FWidthOpNode.shader new file mode 100644 index 0000000..d711647 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FWidthOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/FWidthOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return fwidth(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FWidthOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FWidthOpNode.shader.meta new file mode 100644 index 0000000..c251ea4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FWidthOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 81ea481faaef9c8459a555479ba64df7 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FaceVariableNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FaceVariableNode.shader new file mode 100644 index 0000000..9cb4428 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FaceVariableNode.shader @@ -0,0 +1,19 @@ +Shader "Hidden/FaceVariableNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 frag( v2f_img i, half ase_vface : VFACE ) : SV_Target + { + return ase_vface; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FaceVariableNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FaceVariableNode.shader.meta new file mode 100644 index 0000000..9239bc9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FaceVariableNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4b0b5b9f16353b840a5f5ad2baab3c3c +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FloorOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FloorOpNode.shader new file mode 100644 index 0000000..ad11b59 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FloorOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/FloorOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return floor(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FloorOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FloorOpNode.shader.meta new file mode 100644 index 0000000..11687b4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FloorOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 46ae4a72a9a38de40a2d8f20cfccc67d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FmodOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FmodOpNode.shader new file mode 100644 index 0000000..2149b14 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FmodOpNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/FmodOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return fmod(a, b); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FmodOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FmodOpNode.shader.meta new file mode 100644 index 0000000..8bbfee6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FmodOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 65083930f9d7812479fd6ff203ad2992 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogAndAmbientColors.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogAndAmbientColors.shader new file mode 100644 index 0000000..b2b5b93 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogAndAmbientColors.shader @@ -0,0 +1,75 @@ +Shader "Hidden/FogAndAmbientColors" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + return UNITY_LIGHTMODEL_AMBIENT; + } + ENDCG + } + + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag (v2f_img i) : SV_Target + { + return unity_AmbientSky; + } + ENDCG + } + + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag (v2f_img i) : SV_Target + { + return unity_AmbientEquator; + } + ENDCG + } + + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag (v2f_img i) : SV_Target + { + return unity_AmbientGround; + } + ENDCG + } + + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag (v2f_img i) : SV_Target + { + return unity_FogColor; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogAndAmbientColors.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogAndAmbientColors.shader.meta new file mode 100644 index 0000000..40a27fe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogAndAmbientColors.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 937c7bde062f0f942b600d9950d2ebb2 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogParams.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogParams.shader new file mode 100644 index 0000000..c2914ce --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogParams.shader @@ -0,0 +1,19 @@ +Shader "Hidden/FogParams" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + return unity_FogParams; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogParams.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogParams.shader.meta new file mode 100644 index 0000000..bef9688 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FogParams.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 42abde3281b1848438c3b53443c91a1e +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FractNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FractNode.shader new file mode 100644 index 0000000..d85eaf6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FractNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/FractNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return frac(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FractNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FractNode.shader.meta new file mode 100644 index 0000000..4de2cee --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FractNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 53a335f8f18d4694b8d94e8aee21fdca +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FresnelNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FresnelNode.shader new file mode 100644 index 0000000..256a4d6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FresnelNode.shader @@ -0,0 +1,358 @@ +Shader "Hidden/FresnelNode" +{ + Properties + { + _A ("_Normal", 2D) = "white" {} + _B ("_Bias", 2D) = "white" {} + _C ("_Scale", 2D) = "white" {} + _D ("_Power", 2D) = "white" {} + _E ("_View", 2D) = "white" {} + } + SubShader + { + Pass //not connected world + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + //sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + int _FresnelType; + + float4 frag(v2f_img i) : SV_Target + { + float b = tex2D( _B, i.uv ).r; + float s = tex2D( _C, i.uv ).r; + float pw = tex2D( _D, i.uv ).r; + + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 worldNormal = normalize(float3(xy, z)); + float3 worldViewDir = normalize(float3(0,0,-5) - vertexPos); + + float fresnel = 0; + if(_FresnelType == 0) + fresnel = (b + s*pow(1 - dot( worldNormal, worldViewDir ) , pw)); + else if(_FresnelType == 1) + fresnel = (b + (1-b) * pow(1 - dot( worldNormal, worldViewDir ) , 5)); + else if(_FresnelType == 2) + { + float f0 = pow((1-s)/(1+s),2); + fresnel = (f0 + (1-f0) * pow(1 - dot( worldNormal, worldViewDir ) , 5)); + } + return fresnel; + } + ENDCG + } + + Pass //connected world + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + int _FresnelType; + + float4 frag(v2f_img i) : SV_Target + { + float b = tex2D( _B, i.uv ).r; + float s = tex2D( _C, i.uv ).r; + float pw = tex2D( _D, i.uv ).r; + + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 worldNormal = tex2D( _A, i.uv ); + float3 worldViewDir = normalize(float3(0,0,-5) - vertexPos); + + float fresnel = 0; + if(_FresnelType == 0) + fresnel = (b + s*pow(1 - dot( worldNormal, worldViewDir ) , pw)); + else if(_FresnelType == 1) + fresnel = (b + (1-b) * pow(1 - dot( worldNormal, worldViewDir ) , 5)); + else if(_FresnelType == 2) + { + float f0 = pow((1-s)/(1+s),2); + fresnel = (f0 + (1-f0) * pow(1 - dot( worldNormal, worldViewDir ) , 5)); + } + return fresnel; + } + ENDCG + } + + Pass //connected tangent + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + int _FresnelType; + + float4 frag(v2f_img i) : SV_Target + { + float b = tex2D( _B, i.uv ).r; + float s = tex2D( _C, i.uv ).r; + float pw = tex2D( _D, i.uv ).r; + + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 worldNormal = normalize(float3(xy, z)); + + float3 tangent = normalize(float3( -z, xy.y*0.01, xy.x )); + float3 worldPos = mul(unity_ObjectToWorld, float4(vertexPos,1)).xyz; + float3 worldTangent = UnityObjectToWorldDir(tangent); + float tangentSign = -1; + float3 worldBinormal = normalize( cross(worldNormal, worldTangent) * tangentSign); + float4 tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); + float4 tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); + float4 tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); + + float2 sphereUVs = i.uv; + + sphereUVs.x = (atan2(vertexPos.x, -vertexPos.z) / (UNITY_PI) + 0.5); + float3 tangentNormal = tex2D(_A, sphereUVs).xyz; + + worldNormal = fixed3( dot( tSpace0.xyz, tangentNormal ), dot( tSpace1.xyz, tangentNormal ), dot( tSpace2.xyz, tangentNormal ) ); + + float3 worldViewDir = normalize(float3(0,0,-5) - vertexPos); + + float fresnel = 0; + if(_FresnelType == 0) + fresnel = (b + s*pow(1 - dot( worldNormal, worldViewDir ) , pw)); + else if(_FresnelType == 1) + fresnel = (b + (1-b) * pow(1 - dot( worldNormal, worldViewDir ) , 5)); + else if(_FresnelType == 2) + { + float f0 = pow((1-s)/(1+s),2); + fresnel = (f0 + (1-f0) * pow(1 - dot( worldNormal, worldViewDir ) , 5)); + } + return fresnel; + } + ENDCG + } + + Pass //not connected half vector + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + //sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + int _FresnelType; + float4 _EditorWorldLightPos; + float4 frag(v2f_img i) : SV_Target + { + float b = tex2D( _B, i.uv ).r; + float s = tex2D( _C, i.uv ).r; + float pw = tex2D( _D, i.uv ).r; + + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-(dot(xy,xy))); + float3 vertexPos = normalize(float3(xy, z)); + float3 worldViewDir = normalize(float3(0,0,-5) - vertexPos); + float3 lightDir = normalize( _EditorWorldLightPos.xyz ); + float3 halfVector = normalize(worldViewDir+lightDir); + + float fresnel = 0; + if(_FresnelType == 0) + fresnel = (b + s*pow(1 - dot( halfVector, worldViewDir ) , pw)); + else if(_FresnelType == 1) + fresnel = (b + (1-b) * pow(1 - dot( halfVector, worldViewDir ) , 5)); + else if(_FresnelType == 2) + { + float f0 = pow((1-s)/(1+s),2); + fresnel = (f0 + (1-f0) * pow(1 - dot( halfVector, worldViewDir ) , 5)); + } + return fresnel; + } + ENDCG + } + + Pass //connected both + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + int _FresnelType; + + float4 frag(v2f_img i) : SV_Target + { + float b = tex2D( _B, i.uv ).r; + float s = tex2D( _C, i.uv ).r; + float pw = tex2D( _D, i.uv ).r; + + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 worldNormal = tex2D( _A, i.uv ); + float3 worldViewDir = tex2D( _E, i.uv );; + + float fresnel = 0; + if(_FresnelType == 0) + fresnel = (b + s*pow(1 - dot( worldNormal, worldViewDir ) , pw)); + else if(_FresnelType == 1) + fresnel = (b + (1-b) * pow(1 - dot( worldNormal, worldViewDir ) , 5)); + else if(_FresnelType == 2) + { + float f0 = pow((1-s)/(1+s),2); + fresnel = (f0 + (1-f0) * pow(1 - dot( worldNormal, worldViewDir ) , 5)); + } + return fresnel; + } + ENDCG + } + + Pass //not connected world and light + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + //sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + int _FresnelType; + float4 _EditorWorldLightPos; + + float4 frag(v2f_img i) : SV_Target + { + float b = tex2D( _B, i.uv ).r; + float s = tex2D( _C, i.uv ).r; + float pw = tex2D( _D, i.uv ).r; + + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-(dot(xy,xy))); + float3 vertexPos = normalize(float3(xy, z)); + float3 normal = normalize(vertexPos); + float3 worldNormal = UnityObjectToWorldNormal(normal); + float3 lightDir = normalize( _EditorWorldLightPos.xyz ); + + float fresnel = 0; + if(_FresnelType == 0) + fresnel = (b + s*pow(1 - dot( worldNormal, lightDir ) , pw)); + else if(_FresnelType == 1) + fresnel = (b + (1-b) * pow(1 - dot( worldNormal, lightDir ) , 5)); + else if(_FresnelType == 2) + { + float f0 = pow((1-s)/(1+s),2); + fresnel = (f0 + (1-f0) * pow(1 - dot( worldNormal, lightDir ) , 5)); + } + return fresnel; + } + ENDCG + } + + Pass //connected view + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + int _FresnelType; + + float4 frag(v2f_img i) : SV_Target + { + float b = tex2D( _B, i.uv ).r; + float s = tex2D( _C, i.uv ).r; + float pw = tex2D( _D, i.uv ).r; + + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 normal = normalize(vertexPos); + float3 worldNormal = UnityObjectToWorldNormal(normal); + float3 worldViewDir = tex2D( _E, i.uv ); + + float fresnel = 0; + if(_FresnelType == 0) + fresnel = (b + s*pow(1 - dot( worldNormal, worldViewDir ) , pw)); + else if(_FresnelType == 1) + fresnel = (b + (1-b) * pow(1 - dot( worldNormal, worldViewDir ) , 5)); + else if(_FresnelType == 2) + { + float f0 = pow((1-s)/(1+s),2); + fresnel = (f0 + (1-f0) * pow(1 - dot( worldNormal, worldViewDir ) , 5)); + } + return fresnel; + } + ENDCG + } + + Pass //not connected half vector with connected view + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + //sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + int _FresnelType; + float4 _EditorWorldLightPos; + float4 frag(v2f_img i) : SV_Target + { + float b = tex2D( _B, i.uv ).r; + float s = tex2D( _C, i.uv ).r; + float pw = tex2D( _D, i.uv ).r; + + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-(dot(xy,xy))); + float3 vertexPos = normalize(float3(xy, z)); + float3 worldViewDir = tex2D( _E, i.uv ); + float3 lightDir = normalize( _EditorWorldLightPos.xyz ); + float3 halfVector = normalize(worldViewDir+lightDir); + + float fresnel = 0; + if(_FresnelType == 0) + fresnel = (b + s*pow(1 - dot( halfVector, worldViewDir ) , pw)); + else if(_FresnelType == 1) + fresnel = (b + (1-b) * pow(1 - dot( halfVector, worldViewDir ) , 5)); + else if(_FresnelType == 2) + { + float f0 = pow((1-s)/(1+s),2); + fresnel = (f0 + (1-f0) * pow(1 - dot( halfVector, worldViewDir ) , 5)); + } + return fresnel; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FresnelNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FresnelNode.shader.meta new file mode 100644 index 0000000..c98c0fe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FresnelNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 240145eb70cf79f428015012559f4e7d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionInputNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionInputNode.shader new file mode 100644 index 0000000..898706a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionInputNode.shader @@ -0,0 +1,39 @@ +Shader "Hidden/FunctionInputNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + int _Type; + + float4 frag(v2f_img i) : SV_Target + { + if( _Type == 1 ) + { + return tex2D( _A, i.uv ).r; + } else if( _Type == 2 ) + { + return float4(tex2D( _A, i.uv ).rg,0,0); + } else if( _Type == 3 ) + { + return float4(tex2D( _A, i.uv ).rgb,0); + } + else + { + return tex2D( _A, i.uv ); + } + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionInputNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionInputNode.shader.meta new file mode 100644 index 0000000..e2cf164 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionInputNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 04bc8e7b317dccb4d8da601680dd8140 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionNode.shader new file mode 100644 index 0000000..e8b7c4a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/FunctionNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tex2D( _A, i.uv ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionNode.shader.meta new file mode 100644 index 0000000..7209bcd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: aca70c900c50c004e8ef0b47c4fac4d4 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionOutputNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionOutputNode.shader new file mode 100644 index 0000000..5fa7d2d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionOutputNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/FunctionOutputNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tex2D( _A, i.uv ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionOutputNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionOutputNode.shader.meta new file mode 100644 index 0000000..689efb6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_FunctionOutputNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e6d5f64114b18e24f99dc65290c0fe98 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GammaToLinearNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GammaToLinearNode.shader new file mode 100644 index 0000000..585f403 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GammaToLinearNode.shader @@ -0,0 +1,27 @@ +Shader "Hidden/GammaToLinearNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + float4 c = tex2D( _A, i.uv ); + c.rgb = GammaToLinearSpace( c.rgb ); + return c; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GammaToLinearNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GammaToLinearNode.shader.meta new file mode 100644 index 0000000..9ebe8de --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GammaToLinearNode.shader.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e82a888a6ebdb1443823aafceaa051b9 +timeCreated: 1489078120 +licenseType: Store +ShaderImporter: + defaultTextures: + - _MainTex: {instanceID: 0} + - _BackGround: {fileID: 2800000, guid: 750b1bd7ba8bd28489650de6d0a95cc5, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GetLocalVarNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GetLocalVarNode.shader new file mode 100644 index 0000000..f9398ac --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GetLocalVarNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/GetLocalVarNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tex2D( _A, i.uv ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GetLocalVarNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GetLocalVarNode.shader.meta new file mode 100644 index 0000000..513bcad --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GetLocalVarNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f21a6e44c7d7b8543afacd19751d24c6 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GradientSample.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GradientSample.shader new file mode 100644 index 0000000..28aebf5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GradientSample.shader @@ -0,0 +1,123 @@ +Shader "Hidden/GradientSample" +{ + Properties + { + _GTime( "_Time", 2D ) = "white" {} + _GType( "_GType", Int ) = 0 + _GColorNum( "_GColorNum", Int ) = 0 + _GAlphaNum( "_GAlphaNum", Int ) = 0 + _Col0( "_Col0", Vector ) = ( 0, 0, 0, 0 ) + _Col1( "_Col1", Vector ) = ( 0, 0, 0, 0 ) + _Col2( "_Col2", Vector ) = ( 0, 0, 0, 0 ) + _Col3( "_Col3", Vector ) = ( 0, 0, 0, 0 ) + _Col4( "_Col4", Vector ) = ( 0, 0, 0, 0 ) + _Col5( "_Col5", Vector ) = ( 0, 0, 0, 0 ) + _Col6( "_Col6", Vector ) = ( 0, 0, 0, 0 ) + _Col7( "_Col7", Vector ) = ( 0, 0, 0, 0 ) + _Alp0( "_Alp0", Vector ) = ( 0, 0, 0, 0 ) + _Alp1( "_Alp1", Vector ) = ( 0, 0, 0, 0 ) + _Alp2( "_Alp2", Vector ) = ( 0, 0, 0, 0 ) + _Alp3( "_Alp3", Vector ) = ( 0, 0, 0, 0 ) + _Alp4( "_Alp4", Vector ) = ( 0, 0, 0, 0 ) + _Alp5( "_Alp5", Vector ) = ( 0, 0, 0, 0 ) + _Alp6( "_Alp6", Vector ) = ( 0, 0, 0, 0 ) + _Alp7( "_Alp7", Vector ) = ( 0, 0, 0, 0 ) + } + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + sampler2D _GTime; + int _GType; + int _GColorNum; + int _GAlphaNum; + float4 _Col0; + float4 _Col1; + float4 _Col2; + float4 _Col3; + float4 _Col4; + float4 _Col5; + float4 _Col6; + float4 _Col7; + float4 _Alp0; + float4 _Alp1; + float4 _Alp2; + float4 _Alp3; + float4 _Alp4; + float4 _Alp5; + float4 _Alp6; + float4 _Alp7; + + struct Gradient + { + int type; + int colorsLength; + int alphasLength; + float4 colors[ 8 ]; + float2 alphas[ 8 ]; + }; + + Gradient NewGradient( int type, int colorsLength, int alphasLength, + float4 colors0, float4 colors1, float4 colors2, float4 colors3, float4 colors4, float4 colors5, float4 colors6, float4 colors7, + float2 alphas0, float2 alphas1, float2 alphas2, float2 alphas3, float2 alphas4, float2 alphas5, float2 alphas6, float2 alphas7 ) + { + Gradient g; + g.type = type; + g.colorsLength = colorsLength; + g.alphasLength = alphasLength; + g.colors[ 0 ] = colors0; + g.colors[ 1 ] = colors1; + g.colors[ 2 ] = colors2; + g.colors[ 3 ] = colors3; + g.colors[ 4 ] = colors4; + g.colors[ 5 ] = colors5; + g.colors[ 6 ] = colors6; + g.colors[ 7 ] = colors7; + g.alphas[ 0 ] = alphas0; + g.alphas[ 1 ] = alphas1; + g.alphas[ 2 ] = alphas2; + g.alphas[ 3 ] = alphas3; + g.alphas[ 4 ] = alphas4; + g.alphas[ 5 ] = alphas5; + g.alphas[ 6 ] = alphas6; + g.alphas[ 7 ] = alphas7; + return g; + } + + float4 SampleGradient( Gradient gradient, float time ) + { + float3 color = gradient.colors[ 0 ].rgb; + UNITY_UNROLL + for( int c = 1; c < 8; c++ ) + { + float colorPos = saturate( ( time - gradient.colors[ c - 1 ].w ) / ( gradient.colors[ c ].w - gradient.colors[ c - 1 ].w ) ) * step( c, (float)gradient.colorsLength - 1 ); + color = lerp( color, gradient.colors[ c ].rgb, lerp( colorPos, step( 0.01, colorPos ), gradient.type ) ); + } + #ifndef UNITY_COLORSPACE_GAMMA + color = GammaToLinearSpace( color ); + #endif + float alpha = gradient.alphas[ 0 ].x; + UNITY_UNROLL + for( int a = 1; a < 8; a++ ) + { + float alphaPos = saturate( ( time - gradient.alphas[ a - 1 ].y ) / ( gradient.alphas[ a ].y - gradient.alphas[ a - 1 ].y ) ) * step( a, (float)gradient.alphasLength - 1 ); + alpha = lerp( alpha, gradient.alphas[ a ].x, lerp( alphaPos, step( 0.01, alphaPos ), gradient.type ) ); + } + return float4( color, alpha ); + } + + float4 frag( v2f_img i ) : SV_Target + { + Gradient gradient = NewGradient( _GType, _GColorNum, _GAlphaNum, _Col0, _Col1, _Col2, _Col3, _Col4, _Col5, _Col6, _Col7, _Alp0.xy, _Alp1.xy, _Alp2.xy, _Alp3.xy, _Alp4.xy, _Alp5.xy, _Alp6.xy, _Alp7.xy ); + float time = tex2D( _GTime, i.uv ).r; + return SampleGradient( gradient, time ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GradientSample.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GradientSample.shader.meta new file mode 100644 index 0000000..5082a60 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GradientSample.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8a09124cd6e4aa54a996e7487ec16b90 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GrayscaleNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GrayscaleNode.shader new file mode 100644 index 0000000..2f60460 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GrayscaleNode.shader @@ -0,0 +1,62 @@ +Shader "Hidden/GrayscaleNode" +{ + Properties + { + _A ("_RGB", 2D) = "white" {} + } + SubShader + { + Pass //Luminance + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + float lum = Luminance( tex2D( _A, i.uv ) ); + return float4( lum.xxx, 1); + } + ENDCG + } + + Pass //Natural Classic + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag ( v2f_img i ) : SV_Target + { + float lum = dot ( tex2D ( _A, i.uv ), float3( 0.299,0.587,0.114 ) ); + return float4( lum.xxx, 1 ); + } + ENDCG + } + + Pass //Old School + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag ( v2f_img i ) : SV_Target + { + float3 rgbValue = tex2D ( _A, i.uv ).rgb; + float lum = ( rgbValue.r + rgbValue.g + rgbValue.b ) / 3; + return float4( lum.xxx, 1 ); + } + ENDCG + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GrayscaleNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GrayscaleNode.shader.meta new file mode 100644 index 0000000..329b709 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_GrayscaleNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 56781cd022be9124597f0f396a46a35f +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HSVToRGBNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HSVToRGBNode.shader new file mode 100644 index 0000000..3bb972a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HSVToRGBNode.shader @@ -0,0 +1,41 @@ +Shader "Hidden/HSVToRGBNode" +{ + Properties + { + _A ( "_Hue", 2D ) = "white" {} + _B ( "_Saturation", 2D ) = "white" {} + _C ( "_Value", 2D ) = "white" {} + } + + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + uniform sampler2D _A; + uniform sampler2D _B; + uniform sampler2D _C; + + float3 HSVToRGB( float3 c ) + { + float4 K = float4( 1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0 ); + float3 p = abs( frac( c.xxx + K.xyz ) * 6.0 - K.www ); + return c.z * lerp( K.xxx, saturate( p - K.xxx ), c.y ); + } + + float4 frag ( v2f_img i ) : SV_Target + { + float h = tex2D ( _A, i.uv ).r; + float s = tex2D ( _B, i.uv ).r; + float v = tex2D ( _C, i.uv ).r; + + return float4( HSVToRGB(float3(h,s,v)), 1 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HSVToRGBNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HSVToRGBNode.shader.meta new file mode 100644 index 0000000..952938e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HSVToRGBNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: fab445eb945d63047822a7a6b81b959d +timeCreated: 1515421907 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HeightMapTextureBlend.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HeightMapTextureBlend.shader new file mode 100644 index 0000000..f15f92e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HeightMapTextureBlend.shader @@ -0,0 +1,33 @@ +Shader "Hidden/HeightMapTextureBlend" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_C", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag( v2f_img i ) : SV_Target + { + float heightmap = tex2D( _A, i.uv ).x; + float splatMask = tex2D( _B, i.uv ).x; + float blendStrength = tex2D( _C, i.uv ).x; + float result = saturate( pow((( heightmap*splatMask ) * 4 ) + ( splatMask * 2 ), blendStrength )); + return float4( result.x , 0, 0, 1 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HeightMapTextureBlend.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HeightMapTextureBlend.shader.meta new file mode 100644 index 0000000..35ffff5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_HeightMapTextureBlend.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b2ac23d6d5dcb334982b6f31c2e7a734 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectDiffuseLight.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectDiffuseLight.shader new file mode 100644 index 0000000..6569557 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectDiffuseLight.shader @@ -0,0 +1,106 @@ +Shader "Hidden/IndirectDiffuseLight" +{ + Properties + { + _Intensity ("Intensity", Float) = 1 + } + + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + + float _Intensity; + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 worldNormal = normalize(float3(xy, z)); + float3 vertexPos = float3(xy, z); + float3 worldPos = mul(unity_ObjectToWorld, float4(vertexPos,1)).xyz; + float4 back = lerp(float4(0.4117,0.3843,0.3647,1),float4(0.4117,0.5059,0.6470,1),worldPos.y * 0.5 + 0.5); + return float4(GammaToLinearSpace(back.rgb * _Intensity),1); + } + ENDCG + } + + Pass // connected tangent + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + + float _Intensity; + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 normal = normalize(vertexPos); + float3 worldNormal = UnityObjectToWorldNormal(normal); + + float3 tangent = normalize(float3( -z, xy.y*0.01, xy.x )); + float3 worldPos = mul(unity_ObjectToWorld, float4(vertexPos,1)).xyz; + float3 worldTangent = UnityObjectToWorldDir(tangent); + float tangentSign = -1; + float3 worldBinormal = normalize( cross(worldNormal, worldTangent) * tangentSign); + float4 tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); + float4 tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); + float4 tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); + + float2 sphereUVs = i.uv; + + sphereUVs.x = (atan2(vertexPos.x, -vertexPos.z) / (UNITY_PI) + 0.5); + // Needs further checking + //float3 tangentNormal = tex2Dlod(_A, float4(sphereUVs,0,0)).xyz; + float3 tangentNormal = tex2D(_A, sphereUVs).xyz; + + worldNormal = fixed3( dot( tSpace0.xyz, tangentNormal ), dot( tSpace1.xyz, tangentNormal ), dot( tSpace2.xyz, tangentNormal ) ); + + float4 back = lerp(float4(0.4117,0.3843,0.3647,1),float4(0.4117,0.5059,0.6470,1),worldNormal.y * 0.5 + 0.5); + + return float4(GammaToLinearSpace(back.rgb * _Intensity),1); + } + ENDCG + } + + Pass // connected world + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + + float _Intensity; + sampler2D _A; + + float4 frag( v2f_img i ) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt( 1 - saturate( dot( xy,xy ) ) ); + float3 vertexPos = float3( xy, z ); + float3 normal = normalize( vertexPos ); + float3 worldNormal = tex2D( _A, i.uv ); + + float4 back = lerp( float4( 0.4117,0.3843,0.3647,1 ),float4( 0.4117,0.5059,0.6470,1 ),worldNormal.y * 0.5 + 0.5 ); + + return float4( GammaToLinearSpace( back.rgb * _Intensity ),1 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectDiffuseLight.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectDiffuseLight.shader.meta new file mode 100644 index 0000000..59f7461 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectDiffuseLight.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b45d57fa606c1ea438fe9a2c08426bc7 +timeCreated: 1512043114 +licenseType: Store +ShaderImporter: + defaultTextures: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectSpecularLight.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectSpecularLight.shader new file mode 100644 index 0000000..6c48d9e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectSpecularLight.shader @@ -0,0 +1,128 @@ +Shader "Hidden/IndirectSpecularLight" +{ + Properties + { + _Skybox("_Skybox", CUBE) = "white" {} + _A ("Normal", 2D) = "white" {} + _B ("Smoothness", 2D) = "white" {} + _C ("Occlusion", 2D) = "white" {} + } + + SubShader + { + Pass // not connected + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + + uniform samplerCUBE _Skybox; + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 worldNormal = normalize(float3(xy, z)); + float3 vertexPos = float3(xy, z); + float3 worldViewDir = normalize(float3(0,0,-5) - vertexPos); + + float3 worldRefl = -worldViewDir; + worldRefl = normalize(reflect( worldRefl, worldNormal )); + + float3 sky = texCUBElod( _Skybox, float4(worldRefl, (1-saturate(tex2D(_B,i.uv).r)) * 6) ).rgb; + + return float4(sky * tex2D(_C,i.uv).r, 1); + } + ENDCG + } + + Pass // connected tangent + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + + uniform samplerCUBE _Skybox; + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 normal = normalize(vertexPos); + float3 worldNormal = UnityObjectToWorldNormal(normal); + + float3 tangent = normalize(float3( -z, xy.y*0.01, xy.x )); + float3 worldPos = mul(unity_ObjectToWorld, float4(vertexPos,1)).xyz; + float3 worldViewDir = normalize(float3(0,0,-5) - vertexPos); + + float3 worldTangent = UnityObjectToWorldDir(tangent); + float tangentSign = -1; + float3 worldBinormal = normalize( cross(worldNormal, worldTangent) * tangentSign); + float4 tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); + float4 tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); + float4 tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); + + float3 worldRefl = -worldViewDir; + + float2 sphereUVs = i.uv; + sphereUVs.x = atan2(vertexPos.x, -vertexPos.z) / (UNITY_PI) + 0.5; + + // Needs further checking + //float3 tangentNormal = tex2Dlod(_A, float4(sphereUVs,0,0)).xyz; + float3 tangentNormal = tex2D(_A, sphereUVs).xyz; + + worldRefl = reflect( worldRefl, half3( dot( tSpace0.xyz, tangentNormal ), dot( tSpace1.xyz, tangentNormal ), dot( tSpace2.xyz, tangentNormal ) ) ); + + float3 sky = texCUBElod( _Skybox, float4(worldRefl, (1-saturate(tex2D(_B,i.uv).r)) * 6) ).rgb; + + return float4(sky * tex2D(_C,i.uv).r, 1); + } + ENDCG + } + + Pass // connected world + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + + uniform samplerCUBE _Skybox; + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 normal = normalize(vertexPos); + float3 worldNormal = tex2D( _A, i.uv ); + float3 worldViewDir = normalize(float3(0,0,-5) - vertexPos); + + float3 worldRefl = reflect( -worldViewDir, worldNormal ); + + float3 sky = texCUBElod( _Skybox, float4(worldRefl, (1-saturate(tex2D(_B,i.uv).r)) * 6) ).rgb; + + return float4(sky * tex2D(_C,i.uv).r, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectSpecularLight.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectSpecularLight.shader.meta new file mode 100644 index 0000000..44a99df --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IndirectSpecularLight.shader.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: d6e441d0a8608954c97fa347d3735e92 +timeCreated: 1512052132 +licenseType: Store +ShaderImporter: + defaultTextures: + - _Skybox: {fileID: 8900000, guid: ef7513b54a0670140b9b967af7620563, type: 3} + - _A: {instanceID: 0} + - _B: {instanceID: 0} + - _C: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_InstanceIDNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_InstanceIDNode.shader new file mode 100644 index 0000000..828da9f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_InstanceIDNode.shader @@ -0,0 +1,24 @@ +Shader "Hidden/InstanceIDNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag (v2f_img i) : SV_Target + { + uint currInstanceId = 0; + #ifdef UNITY_INSTANCING_ENABLED + currInstanceId = unity_InstanceID; + #endif + + return currInstanceId; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_InstanceIDNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_InstanceIDNode.shader.meta new file mode 100644 index 0000000..acd68c4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_InstanceIDNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 03febce56a8cf354b90e7d5180c1dbd7 +timeCreated: 1542641929 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IntNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IntNode.shader new file mode 100644 index 0000000..5e1b367 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IntNode.shader @@ -0,0 +1,24 @@ +Shader "Hidden/IntNode" +{ + Properties { + _InputInt ("_InputInt", Int) = 0 + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + int _InputInt; + + float4 frag( v2f_img i ) : SV_Target + { + return _InputInt; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IntNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IntNode.shader.meta new file mode 100644 index 0000000..6854db4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_IntNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0f64d695b6ffacc469f2dd31432a232a +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LODFadeNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LODFadeNode.shader new file mode 100644 index 0000000..b855246 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LODFadeNode.shader @@ -0,0 +1,19 @@ +Shader "Hidden/LODFadeNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + return unity_LODFade; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LODFadeNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LODFadeNode.shader.meta new file mode 100644 index 0000000..9fee1f6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LODFadeNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: fcd4d93f57ffc51458d4ade10df2fdb4 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LayeredBlendNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LayeredBlendNode.shader new file mode 100644 index 0000000..bf562c3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LayeredBlendNode.shader @@ -0,0 +1,90 @@ +Shader "Hidden/LayeredBlendNode" +{ + Properties + { + _A ( "_Weights", 2D) = "white" {} + _B ( "_LayerBase", 2D) = "white" {} + _C ( "_Layer1", 2D) = "white" {} + _D ( "_Layer2", 2D ) = "white" {} + _E ( "_Layer3", 2D ) = "white" {} + _F ( "_Layer4", 2D ) = "white" {} + } + SubShader + { + + CGINCLUDE + + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + sampler2D _A; + sampler2D _B; + sampler2D _C; + + ENDCG + + Pass + { + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 Weights = tex2D( _A, i.uv ); + float4 LayerBase = tex2D( _B, i.uv ); + float4 Layer1 = tex2D( _C, i.uv ); + return lerp ( LayerBase, Layer1, Weights.x ); + } + ENDCG + } + + Pass + { + CGPROGRAM + sampler2D _D; + float4 frag ( v2f_img i ) : SV_Target + { + float4 Weights = tex2D ( _A, i.uv ); + float4 LayerBase = tex2D ( _B, i.uv ); + float4 Layer1 = tex2D ( _C, i.uv ); + float4 Layer2 = tex2D ( _D, i.uv ); + return lerp ( lerp ( LayerBase, Layer1, Weights.x ), Layer2, Weights.y ); + } + ENDCG + } + + Pass + { + CGPROGRAM + sampler2D _D; + sampler2D _E; + float4 frag ( v2f_img i ) : SV_Target + { + float4 Weights = tex2D ( _A, i.uv ); + float4 LayerBase = tex2D ( _B, i.uv ); + float4 Layer1 = tex2D ( _C, i.uv ); + float4 Layer2 = tex2D ( _D, i.uv ); + float4 Layer3 = tex2D ( _E, i.uv ); + return lerp ( lerp ( lerp ( LayerBase, Layer1, Weights.x ), Layer2, Weights.y ), Layer3, Weights.z ); + } + ENDCG + } + + Pass + { + CGPROGRAM + sampler2D _D; + sampler2D _E; + sampler2D _F; + float4 frag ( v2f_img i ) : SV_Target + { + float4 Weights = tex2D ( _A, i.uv ); + float4 LayerBase = tex2D ( _B, i.uv ); + float4 Layer1 = tex2D ( _C, i.uv ); + float4 Layer2 = tex2D ( _D, i.uv ); + float4 Layer3 = tex2D ( _E, i.uv ); + float4 Layer4 = tex2D ( _F, i.uv ); + return lerp ( lerp ( lerp ( lerp ( LayerBase, Layer1, Weights.x ), Layer2, Weights.y ), Layer3, Weights.z ), Layer4, Weights.w ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LayeredBlendNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LayeredBlendNode.shader.meta new file mode 100644 index 0000000..81f601e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LayeredBlendNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 48faca2f6506fc44c97adb1e2b79c37d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LengthOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LengthOpNode.shader new file mode 100644 index 0000000..213607d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LengthOpNode.shader @@ -0,0 +1,73 @@ +Shader "Hidden/LengthOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag (v2f_img i) : SV_Target + { + return length( tex2D (_A, i.uv).x ); + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag (v2f_img i) : SV_Target + { + return length( tex2D(_A, i.uv).xy ); + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag (v2f_img i) : SV_Target + { + return length( tex2D(_A, i.uv).xyz ); + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag (v2f_img i) : SV_Target + { + return length( tex2D(_A, i.uv)); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LengthOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LengthOpNode.shader.meta new file mode 100644 index 0000000..641415a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LengthOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1c1f6d6512b758942a8b9dd1bea12f34 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LerpOp.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LerpOp.shader new file mode 100644 index 0000000..3b95b83 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LerpOp.shader @@ -0,0 +1,32 @@ +Shader "Hidden/LerpOp" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_Alpha", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + float4 alpha = tex2D( _C, i.uv ); + return lerp(a,b,alpha); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LerpOp.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LerpOp.shader.meta new file mode 100644 index 0000000..07b4fbc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LerpOp.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 34d9c4cdcf1fadb49af2de3f90bbc57d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightAttenuation.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightAttenuation.shader new file mode 100644 index 0000000..a3fc384 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightAttenuation.shader @@ -0,0 +1,26 @@ +Shader "Hidden/LightAttenuation" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + #include "Lighting.cginc" + + float4 _EditorWorldLightPos; + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 worldNormal = normalize(float3(xy, z)); + float3 lightDir = normalize( _EditorWorldLightPos.xyz ); + return saturate(dot(worldNormal ,lightDir) * 10 + 0.1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightAttenuation.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightAttenuation.shader.meta new file mode 100644 index 0000000..7f133af --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightAttenuation.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4b12227498a5c8d46b6c44ea018e5b56 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightColorNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightColorNode.shader new file mode 100644 index 0000000..ad3d5eb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightColorNode.shader @@ -0,0 +1,56 @@ +Shader "Hidden/LightColorNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + #include "Lighting.cginc" + + float4 _EditorLightColor; + + float4 frag(v2f_img i) : SV_Target + { + return _EditorLightColor; + } + ENDCG + } + + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + #include "Lighting.cginc" + + float4 _EditorLightColor; + + float4 frag(v2f_img i) : SV_Target + { + return float4(_EditorLightColor.rgb, 0); + } + ENDCG + } + + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + #include "Lighting.cginc" + + float4 _EditorLightColor; + + float4 frag(v2f_img i) : SV_Target + { + return _EditorLightColor.a; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightColorNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightColorNode.shader.meta new file mode 100644 index 0000000..fcd8689 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LightColorNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 43f5d3c033eb5044e9aeb40241358349 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearDepthNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearDepthNode.shader new file mode 100644 index 0000000..0bcf779 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearDepthNode.shader @@ -0,0 +1,43 @@ +Shader "Hidden/LinearDepthNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + float depthValue = tex2D( _A, i.uv ).r; + return LinearEyeDepth( depthValue ); + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + float depthValue = tex2D( _A, i.uv ).r; + return Linear01Depth( depthValue ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearDepthNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearDepthNode.shader.meta new file mode 100644 index 0000000..754a2f4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearDepthNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2b0785cc8b854974ab4e45419072705a +timeCreated: 1546440865 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearToGammaNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearToGammaNode.shader new file mode 100644 index 0000000..b246880 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearToGammaNode.shader @@ -0,0 +1,27 @@ +Shader "Hidden/LinearToGammaNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + float4 c = tex2D( _A, i.uv ); + c.rgb = LinearToGammaSpace( c.rgb ); + return c; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearToGammaNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearToGammaNode.shader.meta new file mode 100644 index 0000000..2c413a8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LinearToGammaNode.shader.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9027c408b928c5c4d8b450712049d541 +timeCreated: 1489078120 +licenseType: Store +ShaderImporter: + defaultTextures: + - _MainTex: {instanceID: 0} + - _BackGround: {fileID: 2800000, guid: 750b1bd7ba8bd28489650de6d0a95cc5, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log10OpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log10OpNode.shader new file mode 100644 index 0000000..6259c6c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log10OpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/Log10OpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return log10(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log10OpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log10OpNode.shader.meta new file mode 100644 index 0000000..981dbc5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log10OpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 9e7cfa357dd261f499d0ba8637ff2614 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log2OpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log2OpNode.shader new file mode 100644 index 0000000..44dabdb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log2OpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/Log2OpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return log2(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log2OpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log2OpNode.shader.meta new file mode 100644 index 0000000..a8a3888 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Log2OpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5975a154432d4c64cacd78d015ed08ba +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LogOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LogOpNode.shader new file mode 100644 index 0000000..b95abb0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LogOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/LogOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return log(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LogOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LogOpNode.shader.meta new file mode 100644 index 0000000..317db1f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LogOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a3293e0a73834b24682775f5d8ee1e7c +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LuminanceNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LuminanceNode.shader new file mode 100644 index 0000000..a56bbe3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LuminanceNode.shader @@ -0,0 +1,26 @@ +Shader "Hidden/LuminanceNode" +{ + Properties + { + _A ("_RGB", 2D) = "white" {} + } + SubShader + { + Pass //Luminance + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + float lum = Luminance( tex2D( _A, i.uv ) ); + return float4( lum.xxx, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LuminanceNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LuminanceNode.shader.meta new file mode 100644 index 0000000..a303971 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_LuminanceNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 81e1d8ffeec8a4b4cabb1094bc981048 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NegateNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NegateNode.shader new file mode 100644 index 0000000..9d94ffb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NegateNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/NegateNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return -(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NegateNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NegateNode.shader.meta new file mode 100644 index 0000000..8cff94e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NegateNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b035bc40da1ac7c4eafad4116382ec79 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NodeMasking.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NodeMasking.shader new file mode 100644 index 0000000..b129ccc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NodeMasking.shader @@ -0,0 +1,55 @@ +Shader "Hidden/NodeMasking" +{ + Properties { + _Ports ("_Ports", Vector) = (0,0,0,0) + _MainTex("_MainTex", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _MainTex; + float4 _Ports; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _MainTex, i.uv ); + return a * _Ports; + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _MaskTex; + float _Port; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _MaskTex, i.uv ); + float4 c = 0; + if ( _Port == 1 ) + c = a.x; + else if ( _Port == 2 ) + c = a.y; + else if ( _Port == 3 ) + c = a.z; + else if ( _Port == 4 ) + c = a.w; + + return c; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NodeMasking.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NodeMasking.shader.meta new file mode 100644 index 0000000..4a020c3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NodeMasking.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 9c34f18ebe2be3e48b201b748c73dec0 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NoiseGeneratorNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NoiseGeneratorNode.shader new file mode 100644 index 0000000..a8b9286 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NoiseGeneratorNode.shader @@ -0,0 +1,267 @@ +Shader "Hidden/NoiseGeneratorNode" +{ + Properties + { + _A ("_RGB", 2D) = "white" {} + _B ("_RGB", 2D) = "white" {} + _To01Range ("_To01Range", Float) = 0 + } + + SubShader + { + CGINCLUDE + sampler2D _A; + sampler2D _B; + float _To01Range; + ENDCG + + Pass //Simplex2D + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + + float3 mod2D289 ( float3 x ) { return x - floor ( x * ( 1.0 / 289.0 ) ) * 289.0; } + float2 mod2D289 ( float2 x ) { return x - floor ( x * ( 1.0 / 289.0 ) ) * 289.0; } + float3 permute ( float3 x ) { return mod2D289 ( ( ( x * 34.0 ) + 1.0 ) * x ); } + + float snoise ( float2 v ) + { + const float4 C = float4( 0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439 ); + float2 i = floor ( v + dot ( v, C.yy ) ); + float2 x0 = v - i + dot ( i, C.xx ); + float2 i1; + i1 = ( x0.x > x0.y ) ? float2( 1.0, 0.0 ) : float2( 0.0, 1.0 ); + float4 x12 = x0.xyxy + C.xxzz; + x12.xy -= i1; + i = mod2D289 ( i ); + float3 p = permute ( permute ( i.y + float3( 0.0, i1.y, 1.0 ) ) + i.x + float3( 0.0, i1.x, 1.0 ) ); + float3 m = max ( 0.5 - float3( dot ( x0, x0 ), dot ( x12.xy, x12.xy ), dot ( x12.zw, x12.zw ) ), 0.0 ); + m = m * m; + m = m * m; + float3 x = 2.0 * frac ( p * C.www ) - 1.0; + float3 h = abs ( x ) - 0.5; + float3 ox = floor ( x + 0.5 ); + float3 a0 = x - ox; + m *= 1.79284291400159 - 0.85373472095314 * ( a0 * a0 + h * h ); + float3 g; + g.x = a0.x * x0.x + h.x * x0.y; + g.yz = a0.yz * x12.xz + h.yz * x12.yw; + return 130.0 * dot ( m, g ); + } + float4 frag(v2f_img i) : SV_Target + { + float2 size = tex2D( _A, i.uv ).rg; + float scale = tex2D (_B, i.uv).r; + float noiseVal = snoise ( size * scale ); + noiseVal = (_To01Range > 0) ? noiseVal * 0.5 + 0.5 : noiseVal; + return float4( noiseVal.xxx, 1); + } + ENDCG + } + + Pass //Simplex3D + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float3 mod3D289 ( float3 x ) { return x - floor ( x / 289.0 ) * 289.0; } + + float4 mod3D289 ( float4 x ) { return x - floor ( x / 289.0 ) * 289.0; } + + float4 permute ( float4 x ) { return mod3D289 ( ( x * 34.0 + 1.0 ) * x ); } + + float4 taylorInvSqrt ( float4 r ) { return 1.79284291400159 - r * 0.85373472095314; } + + float snoise ( float3 v ) + { + const float2 C = float2( 1.0 / 6.0, 1.0 / 3.0 ); + float3 i = floor ( v + dot ( v, C.yyy ) ); + float3 x0 = v - i + dot ( i, C.xxx ); + float3 g = step ( x0.yzx, x0.xyz ); + float3 l = 1.0 - g; + float3 i1 = min ( g.xyz, l.zxy ); + float3 i2 = max ( g.xyz, l.zxy ); + float3 x1 = x0 - i1 + C.xxx; + float3 x2 = x0 - i2 + C.yyy; + float3 x3 = x0 - 0.5; + i = mod3D289 ( i ); + float4 p = permute ( permute ( permute ( i.z + float4( 0.0, i1.z, i2.z, 1.0 ) ) + i.y + float4( 0.0, i1.y, i2.y, 1.0 ) ) + i.x + float4( 0.0, i1.x, i2.x, 1.0 ) ); + float4 j = p - 49.0 * floor ( p / 49.0 ); // mod(p,7*7) + float4 x_ = floor ( j / 7.0 ); + float4 y_ = floor ( j - 7.0 * x_ ); // mod(j,N) + float4 x = ( x_ * 2.0 + 0.5 ) / 7.0 - 1.0; + float4 y = ( y_ * 2.0 + 0.5 ) / 7.0 - 1.0; + float4 h = 1.0 - abs ( x ) - abs ( y ); + float4 b0 = float4( x.xy, y.xy ); + float4 b1 = float4( x.zw, y.zw ); + float4 s0 = floor ( b0 ) * 2.0 + 1.0; + float4 s1 = floor ( b1 ) * 2.0 + 1.0; + float4 sh = -step ( h, 0.0 ); + float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy; + float4 a1 = b1.xzyw + s1.xzyw * sh.zzww; + float3 g0 = float3( a0.xy, h.x ); + float3 g1 = float3( a0.zw, h.y ); + float3 g2 = float3( a1.xy, h.z ); + float3 g3 = float3( a1.zw, h.w ); + float4 norm = taylorInvSqrt ( float4( dot ( g0, g0 ), dot ( g1, g1 ), dot ( g2, g2 ), dot ( g3, g3 ) ) ); + g0 *= norm.x; + g1 *= norm.y; + g2 *= norm.z; + g3 *= norm.w; + float4 m = max ( 0.6 - float4( dot ( x0, x0 ), dot ( x1, x1 ), dot ( x2, x2 ), dot ( x3, x3 ) ), 0.0 ); + m = m* m; + m = m* m; + float4 px = float4( dot ( x0, g0 ), dot ( x1, g1 ), dot ( x2, g2 ), dot ( x3, g3 ) ); + return 42.0 * dot ( m, px ); + } + + float4 frag ( v2f_img i ) : SV_Target + { + float3 size = tex2D ( _A, i.uv ).rgb; + float scale = tex2D (_B, i.uv).r; + float noiseVal = snoise ( size * scale ); + noiseVal = (_To01Range > 0) ? noiseVal * 0.5 + 0.5 : noiseVal; + return float4( noiseVal.xxx, 1 ); + } + ENDCG + } + + Pass // Gradient - Shader Toy + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + //https://www.shadertoy.com/view/XdXGW8 + float2 GradientNoiseDir (float2 x) + { + const float2 k = float2(0.3183099, 0.3678794); + x = x * k + k.yx; + return -1.0 + 2.0 * frac (16.0 * k * frac (x.x * x.y * (x.x + x.y))); + } + + float GradientNoise (float2 UV, float Scale) + { + float2 p = UV * Scale; + float2 i = floor (p); + float2 f = frac (p); + float2 u = f * f * (3.0 - 2.0 * f); + return lerp (lerp (dot (GradientNoiseDir (i + float2(0.0, 0.0)), f - float2(0.0, 0.0)), + dot (GradientNoiseDir (i + float2(1.0, 0.0)), f - float2(1.0, 0.0)), u.x), + lerp (dot (GradientNoiseDir (i + float2(0.0, 1.0)), f - float2(0.0, 1.0)), + dot (GradientNoiseDir (i + float2(1.0, 1.0)), f - float2(1.0, 1.0)), u.x), u.y); + } + + float4 frag (v2f_img i) : SV_Target + { + float3 size = tex2D (_A, i.uv).rgb; + float scale = tex2D (_B, i.uv).r; + float noiseVal = GradientNoise (size , scale); + noiseVal = (_To01Range > 0) ? noiseVal * 0.5 + 0.5 : noiseVal; + return float4(noiseVal.xxx, 1); + } + ENDCG + } + + Pass // Gradient - Unity + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float2 UnityGradientNoiseDir (float2 p) + { + p = fmod (p , 289); + float x = fmod ((34 * p.x + 1) * p.x , 289) + p.y; + x = fmod ((34 * x + 1) * x , 289); + x = frac (x / 41) * 2 - 1; + return normalize (float2(x - floor (x + 0.5), abs (x) - 0.5)); + } + + float UnityGradientNoise (float2 UV, float Scale) + { + float2 p = UV * Scale; + float2 ip = floor (p); + float2 fp = frac (p); + float d00 = dot (UnityGradientNoiseDir (ip), fp); + float d01 = dot (UnityGradientNoiseDir (ip + float2(0, 1)), fp - float2(0, 1)); + float d10 = dot (UnityGradientNoiseDir (ip + float2(1, 0)), fp - float2(1, 0)); + float d11 = dot (UnityGradientNoiseDir (ip + float2(1, 1)), fp - float2(1, 1)); + fp = fp * fp * fp * (fp * (fp * 6 - 15) + 10); + return lerp (lerp (d00, d01, fp.y), lerp (d10, d11, fp.y), fp.x) + 0.5; + } + + float4 frag (v2f_img i) : SV_Target + { + float3 size = tex2D (_A, i.uv).rgb; + float scale = tex2D (_B, i.uv).r; + float noiseVal = UnityGradientNoise(size , scale); + noiseVal = (_To01Range > 0) ? noiseVal * 0.5 + 0.5 : noiseVal; + return float4(noiseVal.xxx, 1); + } + ENDCG + } + + Pass // Simple + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + inline float noise_randomValue (float2 uv) { return frac(sin(dot(uv, float2(12.9898, 78.233)))*43758.5453); } + inline float noise_interpolate (float a, float b, float t) { return (1.0-t)*a + (t*b); } + inline float valueNoise (float2 uv) + { + float2 i = floor(uv); + float2 f = frac( uv ); + f = f* f * (3.0 - 2.0 * f); + uv = abs( frac(uv) - 0.5); + float2 c0 = i + float2( 0.0, 0.0 ); + float2 c1 = i + float2( 1.0, 0.0 ); + float2 c2 = i + float2( 0.0, 1.0 ); + float2 c3 = i + float2( 1.0, 1.0 ); + float r0 = noise_randomValue( c0 ); + float r1 = noise_randomValue( c1 ); + float r2 = noise_randomValue( c2 ); + float r3 = noise_randomValue( c3 ); + float bottomOfGrid = noise_interpolate( r0, r1, f.x ); + float topOfGrid = noise_interpolate( r2, r3, f.x ); + float t = noise_interpolate( bottomOfGrid, topOfGrid, f.y ); + return t; + } + + float SimpleNoise(float2 UV) + { + float t = 0.0; + float freq = pow( 2.0, float( 0 ) ); + float amp = pow( 0.5, float( 3 - 0 ) ); + t += valueNoise( UV/freq )*amp; + freq = pow(2.0, float(1)); + amp = pow(0.5, float(3-1)); + t += valueNoise( UV/freq )*amp; + freq = pow(2.0, float(2)); + amp = pow(0.5, float(3-2)); + t += valueNoise( UV/freq )*amp; + return t; + } + + float4 frag (v2f_img i) : SV_Target + { + float3 size = tex2D (_A, i.uv).rgb; + float scale = tex2D (_B, i.uv).r; + float noiseVal = SimpleNoise(size * scale); + noiseVal = (_To01Range == 0) ? noiseVal * 2 - 1 : noiseVal; + return float4(noiseVal.xxx, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NoiseGeneratorNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NoiseGeneratorNode.shader.meta new file mode 100644 index 0000000..d92bbfc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NoiseGeneratorNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: cd2d37ef5da190b42a91a5a690ba2a7d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalVertexDataNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalVertexDataNode.shader new file mode 100644 index 0000000..8fce5f6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalVertexDataNode.shader @@ -0,0 +1,22 @@ +Shader "Hidden/NormalVertexDataNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 normal = normalize(float3(xy, z)); + return float4(normal, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalVertexDataNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalVertexDataNode.shader.meta new file mode 100644 index 0000000..9ec1526 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalVertexDataNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6b24b06c33f9fe84c8a2393f13ab5406 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalizeNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalizeNode.shader new file mode 100644 index 0000000..fdcc64f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalizeNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/NormalizeNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return normalize(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalizeNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalizeNode.shader.meta new file mode 100644 index 0000000..98ea8d3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_NormalizeNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a51b11dfb6b32884e930595e5f9defa8 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceLightDirHlpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceLightDirHlpNode.shader new file mode 100644 index 0000000..4aa3e88 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceLightDirHlpNode.shader @@ -0,0 +1,22 @@ +Shader "Hidden/ObjSpaceLightDirHlpNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 _EditorWorldLightPos; + + float4 frag( v2f_img i ) : SV_Target + { + float3 lightDir = mul(unity_WorldToObject, normalize( _EditorWorldLightPos.xyz ) ); + return float4 ( lightDir, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceLightDirHlpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceLightDirHlpNode.shader.meta new file mode 100644 index 0000000..a1d64ec --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceLightDirHlpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c7852de24cec4a744b5358921e23feee +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceViewDirHlpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceViewDirHlpNode.shader new file mode 100644 index 0000000..3535052 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceViewDirHlpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/ObjSpaceViewDirHlpNode" +{ +Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + sampler2D _A; + + float4 frag( v2f_img i ) : SV_Target + { + return float4(ObjSpaceViewDir(tex2D( _A, i.uv )),0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceViewDirHlpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceViewDirHlpNode.shader.meta new file mode 100644 index 0000000..4c8fc97 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjSpaceViewDirHlpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b6b985e165d0dd44c96a05b46e267e64 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectScaleNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectScaleNode.shader new file mode 100644 index 0000000..445c627 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectScaleNode.shader @@ -0,0 +1,36 @@ +Shader "Hidden/ObjectScaleNode" +{ + SubShader + { + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 frag(v2f_img i) : SV_Target + { + float3 objectScale = float3( length( unity_ObjectToWorld[ 0 ].xyz ), length( unity_ObjectToWorld[ 1 ].xyz ), length( unity_ObjectToWorld[ 2 ].xyz ) ); + return float4(objectScale, 1); + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 frag (v2f_img i) : SV_Target + { + float3 objectScale = 1.0 / float3(length (unity_WorldToObject[0].xyz), length (unity_WorldToObject[1].xyz), length (unity_WorldToObject[2].xyz)); + return float4(objectScale, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectScaleNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectScaleNode.shader.meta new file mode 100644 index 0000000..3c410d6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectScaleNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5540033c6c52f51468938c1a42bd2730 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToClipPos.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToClipPos.shader new file mode 100644 index 0000000..b85a410 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToClipPos.shader @@ -0,0 +1,28 @@ +Shader "Hidden/ObjectToClipPos" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag( v2f_img i ) : SV_Target + { + float3 pos = tex2D( _A, i.uv ).xyz; + return UnityObjectToClipPos(pos); + } + ENDCG + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToClipPos.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToClipPos.shader.meta new file mode 100644 index 0000000..929708b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToClipPos.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 14ec765a147a53340877b489e73f1c9f +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToViewPos.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToViewPos.shader new file mode 100644 index 0000000..6acf81a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToViewPos.shader @@ -0,0 +1,29 @@ +Shader "Hidden/ObjectToViewPos" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag( v2f_img i ) : SV_Target + { + float3 pos = tex2D( _A, i.uv ).xyz; + float3 result = UnityObjectToViewPos(pos); + return float4(result, 1.0); + } + ENDCG + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToViewPos.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToViewPos.shader.meta new file mode 100644 index 0000000..9453774 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToViewPos.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b790bc1d468a51840a9facef372b4729 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToWorldTransfNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToWorldTransfNode.shader new file mode 100644 index 0000000..57050b8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToWorldTransfNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/ObjectToWorldTransfNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return mul(unity_ObjectToWorld, tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToWorldTransfNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToWorldTransfNode.shader.meta new file mode 100644 index 0000000..9aa0dd9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ObjectToWorldTransfNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a4044ee165813654486d0cecd0de478c +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OneMinusNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OneMinusNode.shader new file mode 100644 index 0000000..6c290ee --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OneMinusNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/OneMinusNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return 1-tex2D(_A, i.uv); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OneMinusNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OneMinusNode.shader.meta new file mode 100644 index 0000000..84d6766 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OneMinusNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: bed5300b92e7bb0419d0f4accb853312 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OrthoParams.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OrthoParams.shader new file mode 100644 index 0000000..119867b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OrthoParams.shader @@ -0,0 +1,19 @@ +Shader "Hidden/OrthoParams" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + return unity_OrthoParams; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OrthoParams.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OrthoParams.shader.meta new file mode 100644 index 0000000..b619a3a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_OrthoParams.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 88a910ece3dce224793e669bb1bc158d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PannerNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PannerNode.shader new file mode 100644 index 0000000..be63723 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PannerNode.shader @@ -0,0 +1,40 @@ +Shader "Hidden/PannerNode" +{ + Properties + { + _A ("_UVs", 2D) = "white" {} + _B ("_PanTime", 2D) = "white" {} + _C ("_PanSpeed", 2D ) = "white" {} + } + SubShader + { + Pass + { + Name "Panner" // 14 - UV panner node + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float _UsingEditor; + float _EditorTime; + + float4 frag(v2f_img i) : SV_Target + { + float multiplier = tex2D ( _B, i.uv ).r; + float time = _EditorTime*multiplier; + if ( _UsingEditor == 0 ) + { + time = multiplier; + } + float2 speed = tex2D ( _C, i.uv ).rg; + return tex2D( _A, i.uv) + time * float4( speed, 0, 0 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PannerNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PannerNode.shader.meta new file mode 100644 index 0000000..d3b5057 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PannerNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6f89a5d96bdad114b9bbd0c236cac622 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxMappingNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxMappingNode.shader new file mode 100644 index 0000000..5ea1a1b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxMappingNode.shader @@ -0,0 +1,44 @@ +Shader "Hidden/ParallaxMappingNode" +{ + Properties + { + _A ("_UV", 2D) = "white" {} + _B ("_Height", 2D) = "white" {} + _C ("_Scale", 2D) = "white" {} + _D ("_ViewDirTan", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + float _ParallaxType; + + float4 frag(v2f_img i) : SV_Target + { + float2 uv = tex2D( _A, i.uv ).rg; + float h = tex2D( _B, i.uv ).r; + float s = tex2D( _C, i.uv ).r; + float3 vt = tex2D( _D, i.uv ).xyz; + float2 parallaxed = uv; + if ( _ParallaxType == 1 ) { + parallaxed = ( ( h - 1 )*( vt.xy / vt.z ) * s ) + uv; + } + else { + parallaxed = ( ( h - 1 )*( vt.xy ) * s ) + uv; + } + + return float4(parallaxed, 0 , 0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxMappingNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxMappingNode.shader.meta new file mode 100644 index 0000000..35dfe96 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxMappingNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 589f12f68e00ac74286815aa56053fcc +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxOffset.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxOffset.shader new file mode 100644 index 0000000..0db961a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxOffset.shader @@ -0,0 +1,35 @@ +Shader "Hidden/ParallaxOffset" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_C", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag( v2f_img i ) : SV_Target + { + float h = tex2D( _A, i.uv ).x; + float height = tex2D( _B, i.uv ).x; + float3 viewDir = tex2D( _C, i.uv ).xyz; + float2 result = ParallaxOffset (h, height, viewDir); + return float4(result, 0, 1); + + } + ENDCG + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxOffset.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxOffset.shader.meta new file mode 100644 index 0000000..5c74486 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ParallaxOffset.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6085f804c6fbf354eac039c11feaa7cc +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PiNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PiNode.shader new file mode 100644 index 0000000..000e8c0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PiNode.shader @@ -0,0 +1,21 @@ +Shader "Hidden/PiNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tex2D( _A, i.uv ).r * UNITY_PI; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PiNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PiNode.shader.meta new file mode 100644 index 0000000..a3cac8c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PiNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: bf4a65726dab3d445a69fb1d0945c33e +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosVertexDataNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosVertexDataNode.shader new file mode 100644 index 0000000..15f3ad9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosVertexDataNode.shader @@ -0,0 +1,22 @@ +Shader "Hidden/PosVertexDataNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + return float4(vertexPos, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosVertexDataNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosVertexDataNode.shader.meta new file mode 100644 index 0000000..b86aa1a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosVertexDataNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a5c14f759dd021b4b8d4b6eeb85ac227 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosterizeNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosterizeNode.shader new file mode 100644 index 0000000..099d105 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosterizeNode.shader @@ -0,0 +1,35 @@ +Shader "Hidden/PosterizeNode" +{ + Properties + { + _A ( "_RGBA", 2D ) = "white" {} + _B ( "_Power", 2D ) = "white" {} + } + + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + uniform sampler2D _A; + uniform sampler2D _B; + + float4 frag ( v2f_img i ) : SV_Target + { + float4 rgba = tex2D ( _B, i.uv ); + float power = tex2D ( _A, i.uv ).r; + if ( power < 1 ) + return float4(0,0,0,0); + float divideOp = 256.0 / float ( (int)power ); + float4 finalColor = ( floor ( rgba * divideOp ) / divideOp ); + + return finalColor; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosterizeNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosterizeNode.shader.meta new file mode 100644 index 0000000..e652f83 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PosterizeNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ecb3048ef0eec1645bad1d72a98d8279 +timeCreated: 1515421907 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PowerNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PowerNode.shader new file mode 100644 index 0000000..721fe1d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PowerNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/PowerNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return pow(a, b); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PowerNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PowerNode.shader.meta new file mode 100644 index 0000000..205e037 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PowerNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 758cc2f8b537b4e4b93d9833075d138c +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PrimitiveIDVariableNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PrimitiveIDVariableNode.shader new file mode 100644 index 0000000..30dc0ca --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PrimitiveIDVariableNode.shader @@ -0,0 +1,19 @@ +Shader "Hidden/PrimitiveIDVariableNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 frag( v2f_img i, uint ase_primitiveId : SV_PrimitiveID ) : SV_Target + { + return ase_primitiveId; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PrimitiveIDVariableNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PrimitiveIDVariableNode.shader.meta new file mode 100644 index 0000000..f2438c3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_PrimitiveIDVariableNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 92c1b588d7658594cb219696f593f64b +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ProjectionParams.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ProjectionParams.shader new file mode 100644 index 0000000..835f886 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ProjectionParams.shader @@ -0,0 +1,19 @@ +Shader "Hidden/ProjectionParams" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + return _ProjectionParams; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ProjectionParams.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ProjectionParams.shader.meta new file mode 100644 index 0000000..acd5433 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ProjectionParams.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 97ae846cb0a6b044388fad3bc03bb4c2 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RGBToHSVNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RGBToHSVNode.shader new file mode 100644 index 0000000..510fb75 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RGBToHSVNode.shader @@ -0,0 +1,37 @@ +Shader "Hidden/RGBToHSVNode" +{ + Properties + { + _A ( "_RGB", 2D ) = "white" {} + } + + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + uniform sampler2D _A; + + float3 RGBToHSV(float3 c) + { + float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + float4 p = lerp( float4( c.bg, K.wz ), float4( c.gb, K.xy ), step( c.b, c.g ) ); + float4 q = lerp( float4( p.xyw, c.r ), float4( c.r, p.yzx ), step( p.x, c.r ) ); + float d = q.x - min( q.w, q.y ); + float e = 1.0e-10; + return float3( abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); + } + + float4 frag ( v2f_img i ) : SV_Target + { + float3 rgb = tex2D ( _A, i.uv ).rgb; + return float4( RGBToHSV(rgb), 1 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RGBToHSVNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RGBToHSVNode.shader.meta new file mode 100644 index 0000000..87cdb89 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RGBToHSVNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0f2f09b49bf4954428aafa2dfe1a9a09 +timeCreated: 1515423140 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RadiansOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RadiansOpNode.shader new file mode 100644 index 0000000..48c8343 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RadiansOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/RadiansOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return radians(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RadiansOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RadiansOpNode.shader.meta new file mode 100644 index 0000000..aa74094 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RadiansOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: d27d189eaf6eeb04fae9913d9617ece5 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RangedFloatNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RangedFloatNode.shader new file mode 100644 index 0000000..62a378e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RangedFloatNode.shader @@ -0,0 +1,24 @@ +Shader "Hidden/RangedFloatNode" +{ + Properties { + _InputFloat ("_InputFloat", Float) = 0 + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float _InputFloat; + + float4 frag( v2f_img i ) : SV_Target + { + return _InputFloat; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RangedFloatNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RangedFloatNode.shader.meta new file mode 100644 index 0000000..35db24d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RangedFloatNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: d9ca47581ac157145bff6f72ac5dd73e +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ReflectOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ReflectOpNode.shader new file mode 100644 index 0000000..c9f2a55 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ReflectOpNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/ReflectOpNode" +{ + Properties + { + _A ("_Incident", 2D) = "white" {} + _B ("_Normal", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return reflect(a, b); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ReflectOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ReflectOpNode.shader.meta new file mode 100644 index 0000000..48ebfd4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ReflectOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: fb520f2145c0fa0409320a9e6d720758 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RefractOpVec.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RefractOpVec.shader new file mode 100644 index 0000000..0aee3cf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RefractOpVec.shader @@ -0,0 +1,32 @@ +Shader "Hidden/RefractOpVec" +{ + Properties + { + _A ("_Incident", 2D) = "white" {} + _B ("_Normal", 2D) = "white" {} + _C ("_Eta", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag(v2f_img i) : SV_Target + { + float4 inc = tex2D( _A, i.uv ); + float4 nor = tex2D( _B, i.uv ); + float4 eta = tex2D( _C, i.uv ); + return refract( inc, nor, eta ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RefractOpVec.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RefractOpVec.shader.meta new file mode 100644 index 0000000..47b5f3d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RefractOpVec.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5ab44ca484bed8b4884b03b1c00fdc3d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RegisterLocalVarNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RegisterLocalVarNode.shader new file mode 100644 index 0000000..8538155 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RegisterLocalVarNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/RegisterLocalVarNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tex2D( _A, i.uv ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RegisterLocalVarNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RegisterLocalVarNode.shader.meta new file mode 100644 index 0000000..af9e1be --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RegisterLocalVarNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5aaa1d3ea9e1fa64781647e035a82334 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RelayNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RelayNode.shader new file mode 100644 index 0000000..598f22b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RelayNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/RelayNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tex2D( _A, i.uv ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RelayNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RelayNode.shader.meta new file mode 100644 index 0000000..29421ef --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RelayNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 74e4d859fbdb2c0468de3612145f4929 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RotatorNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RotatorNode.shader new file mode 100644 index 0000000..59c2d43 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RotatorNode.shader @@ -0,0 +1,43 @@ +Shader "Hidden/RotatorNode" +{ + Properties + { + _A ("_UVs", 2D) = "white" {} + _B ("_Anchor", 2D) = "white" {} + _C ("_RotTimeTex", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + sampler2D _A; + sampler2D _B; + sampler2D _C; + float _UsingEditor; + float _EditorTime; + + float4 frag(v2f_img i) : SV_Target + { + float multiplier = tex2D ( _C, i.uv ).r; + float time = _EditorTime*multiplier; + + if ( _UsingEditor == 0 ) + { + time = multiplier; + } + + float cosT = cos( time ); + float sinT = sin( time ); + + float2 a = tex2D( _B, i.uv ).rg; + return float4( mul( tex2D( _A, i.uv ).xy - a, float2x2( cosT, -sinT, sinT, cosT ) ) + a, 0, 1 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RotatorNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RotatorNode.shader.meta new file mode 100644 index 0000000..c9a283e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RotatorNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e21408a1c7f12f14bbc2652f69bce1fc +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RoundOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RoundOpNode.shader new file mode 100644 index 0000000..85226ad --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RoundOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/RoundOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return round(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RoundOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RoundOpNode.shader.meta new file mode 100644 index 0000000..21a0a03 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RoundOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 554d561417b207c4bb3cd4a0c86b6907 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RsqrtOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RsqrtOpNode.shader new file mode 100644 index 0000000..b15f1eb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RsqrtOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/RSqrtOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return rsqrt(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RsqrtOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RsqrtOpNode.shader.meta new file mode 100644 index 0000000..077ff4f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_RsqrtOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c58c17cb1f7f6e6429a2c7a6cdaef87d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SamplerNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SamplerNode.shader new file mode 100644 index 0000000..95cda8f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SamplerNode.shader @@ -0,0 +1,143 @@ +Shader "Hidden/SamplerNode" +{ + Properties + { + _B ("_UVs", 2D) = "white" {} + _C ("_Level", 2D) = "white" {} + _F ("_NormalScale", 2D) = "white" {} + _G ("Index", 2D) = "white" {} + _CustomUVs ("_CustomUVs", Int) = 0 + _Unpack ("_Unpack", Int) = 0 + _LodType ("_LodType", Int) = 0 + + _Sampler ("_Sampler", 2D) = "white" {} + _Sampler3D ("_Sampler3D", 3D) = "white" {} + _Array ("_Array", 2DArray) = "white" {} + _Cube( "_Cube", CUBE) = "white" {} + _Default ("_Default", Int) = 0 + _Type ("_Type", Int) = 0 + } + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #pragma exclude_renderers d3d9 + #pragma target 3.5 + #include "UnityCG.cginc" + #include "UnityStandardUtils.cginc" + + sampler2D _F; + int _CustomUVs; + int _Unpack; + int _Default; + + float4 frag( v2f_img i ) : SV_Target + { + if( _Default == 1 ) + { + return 1; + } + else if( _Default == 2 ) + { + return 0; + } + else if( _Default == 3 ) + { + return 0.5f; + } + else if( _Default == 4 ) + { + float4 h = float4(0.5,0.5,1,1); + if ( _Unpack == 1 ) + { + h.rgb = UnpackScaleNormal( h.xxyy, tex2D( _F, i.uv ).r ); + } + return h; + } + return 1; + } + ENDCG + } + + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #pragma exclude_renderers d3d9 + #pragma target 3.5 + #include "UnityCG.cginc" + #include "UnityStandardUtils.cginc" + + sampler2D _B; + sampler2D _C; + sampler2D _F; + sampler2D _G; + int _CustomUVs; + int _Unpack; + int _LodType; + + UNITY_DECLARE_TEX2DARRAY (_Array); + samplerCUBE _Cube; + sampler2D _Sampler; + sampler3D _Sampler3D; + int _Type; + + float4 frag (v2f_img i) : SV_Target + { + if (_Type == 4) + { + return UNITY_SAMPLE_TEX2DARRAY ( _Array, float3(i.uv, tex2D( _G, i.uv ).r ) ); + } + else if (_Type == 3) + { + float3 uvs = float3(i.uv,0); + + if (_CustomUVs == 1) + uvs = tex2D (_B, i.uv).xyz; + + return texCUBE (_Cube, uvs); + } + else if (_Type == 2) + { + return tex3D (_Sampler3D, float3(i.uv,0)); + } + else + { + float2 uvs = i.uv; + float4 c = 0; + + if (_CustomUVs == 1) + uvs = tex2D (_B, i.uv).xy; + + if (_LodType == 1) + { + float lod = tex2D (_C, i.uv).r; + c = tex2Dlod (_Sampler, float4(uvs,0,lod)); + } + else if (_LodType == 2) + { + float bias = tex2D (_C, i.uv).r; + c = tex2Dbias (_Sampler, float4(uvs,0,bias)); + } + else + { + c = tex2D (_Sampler, uvs); + } + + if (_Unpack == 1) + { + float nscale = tex2D (_F, i.uv).r; + c.rgb = UnpackScaleNormal (c, nscale); + } + + return c; + } + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SamplerNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SamplerNode.shader.meta new file mode 100644 index 0000000..c212b3b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SamplerNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7b4e86a89b70ae64993bf422eb406422 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SaturateNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SaturateNode.shader new file mode 100644 index 0000000..53af8e0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SaturateNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/SaturateNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return saturate(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SaturateNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SaturateNode.shader.meta new file mode 100644 index 0000000..9dc04ea --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SaturateNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: d9e53418dc8b9d34fb395e3ea3c75985 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleAndOffsetNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleAndOffsetNode.shader new file mode 100644 index 0000000..fadf991 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleAndOffsetNode.shader @@ -0,0 +1,33 @@ +Shader "Hidden/ScaleAndOffsetNode" +{ + Properties + { + _A ("_Value", 2D) = "white" {} + _B ("_Scale", 2D) = "white" {} + _C ("_Offset", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag(v2f_img i) : SV_Target + { + float4 v = tex2D( _A, i.uv ); + float4 s = tex2D( _B, i.uv ); + float4 o = tex2D( _C, i.uv ); + + return v * s + o; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleAndOffsetNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleAndOffsetNode.shader.meta new file mode 100644 index 0000000..6bb6382 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleAndOffsetNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a1f1053d4d9c3be439e0382038b74771 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleNode.shader new file mode 100644 index 0000000..4a8f15c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleNode.shader @@ -0,0 +1,27 @@ +Shader "Hidden/ScaleNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + float _ScaleFloat; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + return a * _ScaleFloat; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleNode.shader.meta new file mode 100644 index 0000000..1f8ba8e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScaleNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6d8ec9d9dab62c44aa2dcc0e3987760d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenParams.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenParams.shader new file mode 100644 index 0000000..65e42ba --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenParams.shader @@ -0,0 +1,19 @@ +Shader "Hidden/ScreenParams" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + return _ScreenParams; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenParams.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenParams.shader.meta new file mode 100644 index 0000000..697cc33 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenParams.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 78173633b803de4419206191fed3d61e +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenPosInputsNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenPosInputsNode.shader new file mode 100644 index 0000000..4c0338c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenPosInputsNode.shader @@ -0,0 +1,62 @@ +Shader "Hidden/ScreenPosInputsNode" +{ + SubShader + { + CGINCLUDE + #include "UnityCG.cginc" + inline float4 PrevComputeNonStereoScreenPos (float4 pos) { + float4 o = pos * 0.5f; + o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w; + o.zw = pos.zw; + return o; + } + + inline float4 CalculateScreenPos (float2 uv) + { + float2 xy = 2 * uv - 1; + float z = -sqrt (1 - saturate (dot (xy,xy))); + float3 vertexPos = float3(xy, z); + float4x4 P = float4x4(1,0,0,0,0,-1,0,0,0,0,1,0,0,0,0,1); //UNITY_MATRIX_P + float4x4 V = UNITY_MATRIX_V;//float4x4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1); //UNITY_MATRIX_V + float4x4 M = unity_ObjectToWorld;//float4x4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1); //unity_ObjectToWorld + float4x4 VPmatrix = mul (P, V); + float4 clipPos = mul (VPmatrix, mul (M, float4(vertexPos, 1.0))); //same as object to clip pos + float4 screenPos = ComputeScreenPos (clipPos); + return screenPos; + } + ENDCG + + //Normalized + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + + + float4 frag( v2f_img i ) : SV_Target + { + return CalculateScreenPos(i.uv); + } + ENDCG + } + + //Screen + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + + uniform float4 _ASEPreviewSize; + + float4 frag (v2f_img i) : SV_Target + { + float4 screenPos = CalculateScreenPos (i.uv); + screenPos.xy *= _ASEPreviewSize.xy; + return screenPos; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenPosInputsNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenPosInputsNode.shader.meta new file mode 100644 index 0000000..f6c791d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ScreenPosInputsNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a5e7295278a404175b732f1516fb68a6 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ShadeVertexLights.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ShadeVertexLights.shader new file mode 100644 index 0000000..23dc3b3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ShadeVertexLights.shader @@ -0,0 +1,34 @@ +Shader "Hidden/ShadeVertexLights" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _LightCount( "_LightCount", Int ) = 4 + _IsSpotlight ("_IsSpotlight", Int) = 0 + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + int _LightCount; + int _IsSpotlight; + + float4 frag( v2f_img i ) : SV_Target + { + float4 vertexPosition = tex2D( _A, i.uv ); + float3 vertexNormal = tex2D( _B, i.uv ).xyz; + float3 result = ShadeVertexLightsFull (vertexPosition, vertexNormal, _LightCount, (_IsSpotlight > 0)); + return float4(result, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ShadeVertexLights.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ShadeVertexLights.shader.meta new file mode 100644 index 0000000..73b03f3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ShadeVertexLights.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3b6075034a85ad047be2d31dd213fb4f +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SignOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SignOpNode.shader new file mode 100644 index 0000000..45da74a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SignOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/SignOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return sign(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SignOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SignOpNode.shader.meta new file mode 100644 index 0000000..6a6b6fd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SignOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3aca80b49aadf5046b7133730818e18f +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleAddOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleAddOpNode.shader new file mode 100644 index 0000000..e8965d9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleAddOpNode.shader @@ -0,0 +1,66 @@ +Shader "Hidden/SimpleAddOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_C", 2D) = "white" {} + _D ("_D", 2D) = "white" {} + _E ("_E", 2D) = "white" {} + _F ("_F", 2D) = "white" {} + _G ("_G", 2D) = "white" {} + _H ("_H", 2D) = "white" {} + _I ("_I", 2D) = "white" {} + _J ("_J", 2D) = "white" {} + _Count ("_Count", Int) = 0 + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + sampler2D _F; + sampler2D _G; + sampler2D _H; + sampler2D _I; + sampler2D _J; + int _Count; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + float4 final = a + b; + + if( _Count > 2 ) + final += tex2D( _C, i.uv ); + if( _Count > 3 ) + final += tex2D( _D, i.uv ); + if( _Count > 4 ) + final += tex2D( _E, i.uv ); + if( _Count > 5 ) + final += tex2D( _F, i.uv ); + if( _Count > 6 ) + final += tex2D( _G, i.uv ); + if( _Count > 7 ) + final += tex2D( _H, i.uv ); + if( _Count > 8 ) + final += tex2D( _I, i.uv ); + if( _Count > 9 ) + final += tex2D( _J, i.uv ); + + return final; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleAddOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleAddOpNode.shader.meta new file mode 100644 index 0000000..acd038b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleAddOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 9eb150cbc752cbc458a0a37984b9934a +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleContrastNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleContrastNode.shader new file mode 100644 index 0000000..96fa3b1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleContrastNode.shader @@ -0,0 +1,39 @@ +Shader "Hidden/SimpleContrastNode" +{ + Properties + { + _A ( "_RBG", 2D ) = "white" {} + _B ( "_Fraction", 2D ) = "white" {} + } + + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + uniform sampler2D _A; + uniform sampler2D _B; + + float4 CalculateContrast ( float contrastValue, float4 colorTarget ) + { + float t = 0.5 * ( 1.0 - contrastValue ); + return mul ( float4x4( contrastValue, 0, 0, t, 0, contrastValue, 0, t, 0, 0, contrastValue, t, 0, 0, 0, 1 ), colorTarget ); + } + + float4 frag ( v2f_img i ) : SV_Target + { + float4 rgba = tex2D ( _B, i.uv ); + float value = tex2D ( _A, i.uv ).r; + + float4 finalColor = CalculateContrast( value , rgba ); + + return finalColor; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleContrastNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleContrastNode.shader.meta new file mode 100644 index 0000000..5c780fe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleContrastNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8d76799413f9f0547ac9b1de7ba798f1 +timeCreated: 1515421907 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleDivideOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleDivideOpNode.shader new file mode 100644 index 0000000..5f414cd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleDivideOpNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/SimpleDivideOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return a / b; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleDivideOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleDivideOpNode.shader.meta new file mode 100644 index 0000000..582a69b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleDivideOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 409f06d00d1094849b0834c52791fa72 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMaxOp.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMaxOp.shader new file mode 100644 index 0000000..f973907 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMaxOp.shader @@ -0,0 +1,29 @@ +Shader "Hidden/SimpleMaxOp" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return max( a, b ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMaxOp.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMaxOp.shader.meta new file mode 100644 index 0000000..9575af5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMaxOp.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 79d7f2a11092ac84a95ef6823b34adf2 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMinNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMinNode.shader new file mode 100644 index 0000000..183d0dd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMinNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/SimpleMinNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return min( a, b ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMinNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMinNode.shader.meta new file mode 100644 index 0000000..0f2a266 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMinNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: d6033298044f0f14aa9932ca46e58ce6 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMultiplyOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMultiplyOpNode.shader new file mode 100644 index 0000000..5bd25e3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMultiplyOpNode.shader @@ -0,0 +1,272 @@ +Shader "Hidden/SimpleMultiplyOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_C", 2D) = "white" {} + _D ("_D", 2D) = "white" {} + _E ("_E", 2D) = "white" {} + _F ("_F", 2D) = "white" {} + _G ("_G", 2D) = "white" {} + _H ("_H", 2D) = "white" {} + _I ("_I", 2D) = "white" {} + _J ("_J", 2D) = "white" {} + _Count ("_Count", Int) = 0 + } + + SubShader + { + Pass //2 + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + + return a * b; + } + ENDCG + } + + Pass //3 + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + float4 c = tex2D( _C, i.uv ); + + return a * b * c; + } + ENDCG + } + + Pass //4 + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + float4 c = tex2D( _C, i.uv ); + float4 d = tex2D( _D, i.uv ); + + return a * b * c * d; + } + ENDCG + } + + Pass //5 + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + float4 c = tex2D( _C, i.uv ); + float4 d = tex2D( _D, i.uv ); + float4 e = tex2D( _E, i.uv ); + + return a * b * c * d * e; + } + ENDCG + } + + Pass //6 + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + sampler2D _F; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + float4 c = tex2D( _C, i.uv ); + float4 d = tex2D( _D, i.uv ); + float4 e = tex2D( _E, i.uv ); + float4 f = tex2D( _F, i.uv ); + + return a * b * c * d * e * f; + } + ENDCG + } + + Pass //7 + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + sampler2D _F; + sampler2D _G; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + float4 c = tex2D( _C, i.uv ); + float4 d = tex2D( _D, i.uv ); + float4 e = tex2D( _E, i.uv ); + float4 f = tex2D( _F, i.uv ); + float4 g = tex2D( _G, i.uv ); + + return a * b * c * d * e * f * g; + } + ENDCG + } + + Pass //8 + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + sampler2D _F; + sampler2D _G; + sampler2D _H; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + float4 c = tex2D( _C, i.uv ); + float4 d = tex2D( _D, i.uv ); + float4 e = tex2D( _E, i.uv ); + float4 f = tex2D( _F, i.uv ); + float4 g = tex2D( _G, i.uv ); + float4 h = tex2D( _H, i.uv ); + + return a * b * c * d * e * f * g * h; + } + ENDCG + } + + Pass //9 + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + sampler2D _F; + sampler2D _G; + sampler2D _H; + sampler2D _I; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + float4 c = tex2D( _C, i.uv ); + float4 d = tex2D( _D, i.uv ); + float4 e = tex2D( _E, i.uv ); + float4 f = tex2D( _F, i.uv ); + float4 g = tex2D( _G, i.uv ); + float4 h = tex2D( _H, i.uv ); + float4 is = tex2D( _I, i.uv ); + + return a * b * c * d * e * f * g * h * is; + } + ENDCG + } + + Pass //10 + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + sampler2D _F; + sampler2D _G; + sampler2D _H; + sampler2D _I; + sampler2D _J; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + float4 c = tex2D( _C, i.uv ); + float4 d = tex2D( _D, i.uv ); + float4 e = tex2D( _E, i.uv ); + float4 f = tex2D( _F, i.uv ); + float4 g = tex2D( _G, i.uv ); + float4 h = tex2D( _H, i.uv ); + float4 is = tex2D( _I, i.uv ); + float4 j = tex2D( _J, i.uv ); + + return a * b * c * d * e * f * g * h * is * j; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMultiplyOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMultiplyOpNode.shader.meta new file mode 100644 index 0000000..721b5df --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleMultiplyOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1ba1e43e86415ff4bbdf4d81dfcf035b +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleRemainderNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleRemainderNode.shader new file mode 100644 index 0000000..b62c655 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleRemainderNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/SimpleRemainderNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return a % b; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleRemainderNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleRemainderNode.shader.meta new file mode 100644 index 0000000..1cf624d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleRemainderNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8fdfc429d6b191c4985c9531364c1a95 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleSubtractOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleSubtractOpNode.shader new file mode 100644 index 0000000..7282f97 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleSubtractOpNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/SimpleSubtractOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return a - b; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleSubtractOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleSubtractOpNode.shader.meta new file mode 100644 index 0000000..8956501 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleSubtractOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5725e8300be208449973f771ab6682f2 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleTimeNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleTimeNode.shader new file mode 100644 index 0000000..428eea6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleTimeNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/SimpleTimeNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _Count ("_Count", Int) = 0 + } + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + sampler2D _A; + float _EditorTime; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 t = _EditorTime; + return t * a.x; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleTimeNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleTimeNode.shader.meta new file mode 100644 index 0000000..2fa5654 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimpleTimeNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 45b7107d5d11f124fad92bcb1fa53661 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimplifiedFModOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimplifiedFModOpNode.shader new file mode 100644 index 0000000..8cc3d4a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimplifiedFModOpNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/SimplifiedFModOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return frac( a / b ) * b; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimplifiedFModOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimplifiedFModOpNode.shader.meta new file mode 100644 index 0000000..29f7167 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SimplifiedFModOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2688236fb4f37ce47b81cc818c53321d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinOpNode.shader new file mode 100644 index 0000000..0645bf4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/SinOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return sin(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinOpNode.shader.meta new file mode 100644 index 0000000..bf7ab48 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: bcd9f8749ddd3ac4f94f4c2071c1d0d4 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinTimeNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinTimeNode.shader new file mode 100644 index 0000000..443f807 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinTimeNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/SinTimeNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float _EditorTime; + + float4 frag( v2f_img i ) : SV_Target + { + float4 t = _EditorTime; + t.x = _EditorTime / 8; + t.y = _EditorTime / 4; + t.z = _EditorTime / 2; + return sin(t); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinTimeNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinTimeNode.shader.meta new file mode 100644 index 0000000..2cbb3c1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinTimeNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e4ba809e0badeb94994170b2cbbbba10 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinhOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinhOpNode.shader new file mode 100644 index 0000000..b1c0984 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinhOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/SinhOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return sinh(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinhOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinhOpNode.shader.meta new file mode 100644 index 0000000..e989054 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SinhOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4e9c00e6dceb4024f80d4e3d7786abad +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SmoothstepOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SmoothstepOpNode.shader new file mode 100644 index 0000000..bcfb876 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SmoothstepOpNode.shader @@ -0,0 +1,32 @@ +Shader "Hidden/SmoothstepOpNode" +{ + Properties + { + _A ("_Alpha", 2D) = "white" {} + _B ("_Min", 2D) = "white" {} + _C ("_Max", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag(v2f_img i) : SV_Target + { + float4 alpha = tex2D( _A, i.uv ); + float4 min = tex2D( _B, i.uv ); + float4 max = tex2D( _C, i.uv ); + return smoothstep(min, max, alpha); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SmoothstepOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SmoothstepOpNode.shader.meta new file mode 100644 index 0000000..817fd47 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SmoothstepOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 954cdd40a7a528344a0a4d3ff1db5176 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SqrtOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SqrtOpNode.shader new file mode 100644 index 0000000..b45f325 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SqrtOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/SqrtOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return sqrt(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SqrtOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SqrtOpNode.shader.meta new file mode 100644 index 0000000..a5ab372 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SqrtOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1791e2fbf36af084da7ecfc289e89b6e +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StaticSwitchNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StaticSwitchNode.shader new file mode 100644 index 0000000..4931a07 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StaticSwitchNode.shader @@ -0,0 +1,59 @@ +Shader "Hidden/StaticSwitchNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_C", 2D) = "white" {} + _D ("_D", 2D) = "white" {} + _E ("_E", 2D) = "white" {} + _F ("_F", 2D) = "white" {} + _G ("_G", 2D) = "white" {} + _H ("_H", 2D) = "white" {} + _I ("_I", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + sampler2D _F; + sampler2D _G; + sampler2D _H; + sampler2D _I; + int _Condition; + + float4 frag( v2f_img i ) : SV_Target + { + if( _Condition == 0) + return tex2D( _B, i.uv ); // A nd B are switched + else if( _Condition == 1 ) + return tex2D( _A, i.uv ); + else if( _Condition == 2 ) + return tex2D( _C, i.uv ); + else if( _Condition == 3 ) + return tex2D( _D, i.uv ); + else if( _Condition == 4 ) + return tex2D( _E, i.uv ); + else if( _Condition == 5 ) + return tex2D( _F, i.uv ); + else if( _Condition == 6 ) + return tex2D( _G, i.uv ); + else if( _Condition == 7 ) + return tex2D( _H, i.uv ); + else + return tex2D( _I, i.uv ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StaticSwitchNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StaticSwitchNode.shader.meta new file mode 100644 index 0000000..306b981 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StaticSwitchNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0b708c11c68e6a9478ac97fe3643eab1 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StepOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StepOpNode.shader new file mode 100644 index 0000000..86fdf06 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StepOpNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/StepOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return step(a, b); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StepOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StepOpNode.shader.meta new file mode 100644 index 0000000..a23d36d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_StepOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2c757add7f97ecd4abd9ce6ec4659697 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SubstanceSamplerNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SubstanceSamplerNode.shader new file mode 100644 index 0000000..86a2adc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SubstanceSamplerNode.shader @@ -0,0 +1,53 @@ +Shader "Hidden/SubstanceSamplerNode" +{ + Properties + { + _A ("_UV", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _GenTex; + int _CustomUVs; + + float4 frag( v2f_img i ) : SV_Target + { + float2 uvs = i.uv; + if( _CustomUVs == 1 ) + uvs = tex2D( _A, i.uv ).xy; + float4 genTex = tex2D( _GenTex, uvs); + return genTex; + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _GenTex; + int _CustomUVs; + + float4 frag( v2f_img i ) : SV_Target + { + float2 uvs = i.uv; + if( _CustomUVs == 1 ) + uvs = tex2D( _A, i.uv ).xy; + float3 genTex = UnpackNormal( tex2D( _GenTex, uvs ) ); + return float4( genTex, 0 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SubstanceSamplerNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SubstanceSamplerNode.shader.meta new file mode 100644 index 0000000..322d784 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SubstanceSamplerNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6f322c1da33f1e744941aafcb0ad1a2d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SummedBlendNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SummedBlendNode.shader new file mode 100644 index 0000000..4f3b670 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SummedBlendNode.shader @@ -0,0 +1,85 @@ +Shader "Hidden/SummedBlendNode" +{ + Properties + { + _A ( "_Weights", 2D) = "white" {} + _B ( "_Layer1", 2D) = "white" {} + _C ( "_Layer2", 2D ) = "white" {} + _D ( "_Layer3", 2D ) = "white" {} + _E ( "_Layer4", 2D ) = "white" {} + } + + SubShader + { + + CGINCLUDE + + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + sampler2D _A; + sampler2D _B; + + ENDCG + + Pass + { + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 Weights = tex2D ( _A, i.uv ); + float4 Layer1 = tex2D( _B, i.uv ); + return Weights*Layer1; + } + ENDCG + } + + Pass + { + CGPROGRAM + sampler2D _C; + float4 frag ( v2f_img i ) : SV_Target + { + float4 Weights = tex2D ( _A, i.uv ); + float4 Layer1 = tex2D ( _B, i.uv ); + float4 Layer2 = tex2D ( _C, i.uv ); + return ( Weights.x*Layer1 + Weights.y*Layer2 ); + } + ENDCG + } + + Pass + { + CGPROGRAM + sampler2D _C; + sampler2D _D; + float4 frag ( v2f_img i ) : SV_Target + { + float4 Weights = tex2D( _A, i.uv ); + float4 Layer1 = tex2D( _B, i.uv ); + float4 Layer2 = tex2D( _C, i.uv ); + float4 Layer3 = tex2D( _D, i.uv ); + return ( Weights.x*Layer1 + Weights.y*Layer2 + Weights.z*Layer3 ); + } + ENDCG + } + + Pass + { + CGPROGRAM + sampler2D _C; + sampler2D _D; + sampler2D _E; + float4 frag ( v2f_img i ) : SV_Target + { + float4 Weights = tex2D ( _A, i.uv ); + float4 Layer1 = tex2D ( _B, i.uv ); + float4 Layer2 = tex2D ( _C, i.uv ); + float4 Layer3 = tex2D ( _D, i.uv ); + float4 Layer4 = tex2D ( _E, i.uv ); + return ( Weights.x*Layer1 + Weights.y*Layer2 + Weights.z*Layer3 + Weights.w*Layer4 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SummedBlendNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SummedBlendNode.shader.meta new file mode 100644 index 0000000..700d2e6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SummedBlendNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: eda18b96e13f78b49bbdaa4da3fead19 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchByFaceNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchByFaceNode.shader new file mode 100644 index 0000000..0f8176c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchByFaceNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/SwitchByFaceNode" +{ + Properties + { + _A ("_Front", 2D) = "white" {} + _B ("_Back", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag( v2f_img i, half ase_vface : VFACE ) : SV_Target + { + float4 front = tex2D( _A, i.uv ); + float4 back = tex2D( _B, i.uv ); + return ( ( ase_vface > 0 ) ? ( front ) : ( back ) ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchByFaceNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchByFaceNode.shader.meta new file mode 100644 index 0000000..1dbf813 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchByFaceNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f4edf6febb54dc743b25bd5b56facea8 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchNode.shader new file mode 100644 index 0000000..d797872 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchNode.shader @@ -0,0 +1,59 @@ +Shader "Hidden/SwitchNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_C", 2D) = "white" {} + _D ("_D", 2D) = "white" {} + _E ("_E", 2D) = "white" {} + _F ("_F", 2D) = "white" {} + _G ("_G", 2D) = "white" {} + _H ("_H", 2D) = "white" {} + _I ("_I", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + sampler2D _F; + sampler2D _G; + sampler2D _H; + sampler2D _I; + float _Current; + + float4 frag( v2f_img i ) : SV_Target + { + if( _Current == 0 ) + return tex2D( _A, i.uv ); + else if( _Current == 1 ) + return tex2D( _B, i.uv ); + else if( _Current == 2 ) + return tex2D( _C, i.uv ); + else if( _Current == 3 ) + return tex2D( _D, i.uv ); + else if( _Current == 4 ) + return tex2D( _E, i.uv ); + else if( _Current == 5 ) + return tex2D( _F, i.uv ); + else if( _Current == 6 ) + return tex2D( _G, i.uv ); + else if( _Current == 7 ) + return tex2D( _H, i.uv ); + else + return tex2D( _I, i.uv ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchNode.shader.meta new file mode 100644 index 0000000..8319d2a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwitchNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a58e46feaa5e3d14383bfeac24d008bc +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwizzleNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwizzleNode.shader new file mode 100644 index 0000000..9433c79 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwizzleNode.shader @@ -0,0 +1,3103 @@ +Shader "Hidden/SwizzleNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _Mask("_Mask", Vector) = (0,0,0,0) + } + SubShader + { + CGINCLUDE + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + + float4 _Mask; + ENDCG + /////////////////////////////////////////////////////////////////////////////// + Pass + { + Name "xxxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.y,a.x)*_Mask; + } + ENDCG + } + + + Pass + { + Name "xxyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxwx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxwy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxwz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xxww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.x,a.w,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.y,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xywx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xywy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xywz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xyww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.y,a.w,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.y,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzwx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzwy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzwz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xzww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.z,a.w,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.y,a.x)*_Mask; + } + ENDCG + } + + + Pass + { + Name "xwyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwwx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwwy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwwz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "xwww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.x,a.w,a.w,a.w)*_Mask; + } + ENDCG + } + /////////////////////////////////////////////////////////////////////////////// + Pass + { + Name "yxxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.y,a.x)*_Mask; + } + ENDCG + } + + + Pass + { + Name "yxyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxwx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxwy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxwz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "yxww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.x,a.w,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.y,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "yywx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "yywy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "yywz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "yyww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.y,a.w,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.y,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzwx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzwy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzwz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "yzww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.z,a.w,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.y,a.x)*_Mask; + } + ENDCG + } + + + Pass + { + Name "ywyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywwx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywwy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywwz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "ywww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.y,a.w,a.w,a.w)*_Mask; + } + ENDCG + } + /////////////////////////////////////////////////////////////////////////////// + Pass + { + Name "zxxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.y,a.x)*_Mask; + } + ENDCG + } + + + Pass + { + Name "zxyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxwx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxwy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxwz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zxww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.x,a.w,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.y,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zywx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zywy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zywz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zyww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.y,a.w,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.y,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzwx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzwy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzwz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zzww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.z,a.w,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.y,a.x)*_Mask; + } + ENDCG + } + + + Pass + { + Name "zwyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwwx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwwy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwwz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "zwww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.z,a.w,a.w,a.w)*_Mask; + } + ENDCG + } + /////////////////////////////////////////////////////////////////////////////// + Pass + { + Name "wxxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.y,a.x)*_Mask; + } + ENDCG + } + + + Pass + { + Name "wxyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxwx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxwy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxwz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wxww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.x,a.w,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.y,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wywx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wywy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wywz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wyww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.y,a.w,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.y,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzwx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzwy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzwz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wzww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.z,a.w,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwxx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.x,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwxy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.x,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwxz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.x,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwxw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.x,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwyx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.y,a.x)*_Mask; + } + ENDCG + } + + + Pass + { + Name "wwyy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.y,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwyz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.y,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwyw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.y,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwzx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.z,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwzy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.z,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwzz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.z,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwzw" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.z,a.w)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwwx" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.w,a.x)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwwy" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.w,a.y)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwwz" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.w,a.z)*_Mask; + } + ENDCG + } + + Pass + { + Name "wwww" + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 a = tex2D(_A, i.uv); + return float4(a.w,a.w,a.w,a.w)*_Mask; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwizzleNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwizzleNode.shader.meta new file mode 100644 index 0000000..0fdc111 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_SwizzleNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: d20531704ce28b14bafb296f291f6608 +timeCreated: 1510580676 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareEqual.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareEqual.shader new file mode 100644 index 0000000..83bf4a8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareEqual.shader @@ -0,0 +1,35 @@ +Shader "Hidden/TFHCCompareEqual" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_True", 2D) = "white" {} + _D ( "_False", 2D ) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + + float4 frag(v2f_img i) : SV_Target + { + float A = tex2D( _A, i.uv ).x; + float B = tex2D( _B, i.uv ).x; + float4 True = tex2D( _C, i.uv ); + float4 False = tex2D ( _D, i.uv ); + return ( ( A == B ) ? True : False ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareEqual.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareEqual.shader.meta new file mode 100644 index 0000000..730c9a8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareEqual.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6904de6cf8c08e7439672390b425ab50 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreater.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreater.shader new file mode 100644 index 0000000..3c5d934 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreater.shader @@ -0,0 +1,35 @@ +Shader "Hidden/TFHCCompareGreater" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_True", 2D) = "white" {} + _D ( "_False", 2D ) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + + float4 frag(v2f_img i) : SV_Target + { + float A = tex2D( _A, i.uv ).x; + float B = tex2D( _B, i.uv ).x; + float4 True = tex2D( _C, i.uv ); + float4 False = tex2D ( _D, i.uv ); + return ( ( A > B ) ? True : False ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreater.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreater.shader.meta new file mode 100644 index 0000000..bd60bd3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreater.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 363192dbd019ad2478f2fe6c277b7e48 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreaterEqual.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreaterEqual.shader new file mode 100644 index 0000000..9da87b1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreaterEqual.shader @@ -0,0 +1,35 @@ +Shader "Hidden/TFHCCompareGreaterEqual" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_True", 2D) = "white" {} + _D ( "_False", 2D ) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + + float4 frag(v2f_img i) : SV_Target + { + float A = tex2D( _A, i.uv ).x; + float B = tex2D( _B, i.uv ).x; + float4 True = tex2D( _C, i.uv ); + float4 False = tex2D ( _D, i.uv ); + return ( ( A >= B ) ? True : False ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreaterEqual.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreaterEqual.shader.meta new file mode 100644 index 0000000..0b28956 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareGreaterEqual.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f4ff76282a117c2429a1bcd8ba3a9112 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLessNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLessNode.shader new file mode 100644 index 0000000..e5eb198 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLessNode.shader @@ -0,0 +1,35 @@ +Shader "Hidden/TFHCCompareLess" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_True", 2D) = "white" {} + _D ( "_False", 2D ) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + + float4 frag(v2f_img i) : SV_Target + { + float A = tex2D( _A, i.uv ).x; + float B = tex2D( _B, i.uv ).x; + float4 True = tex2D( _C, i.uv ); + float4 False = tex2D ( _D, i.uv ); + return ( ( A < B ) ? True : False ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLessNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLessNode.shader.meta new file mode 100644 index 0000000..6cca110 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLessNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8024509244392ed44b37c28473e66a8a +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLowerEqual.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLowerEqual.shader new file mode 100644 index 0000000..be9b7f0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLowerEqual.shader @@ -0,0 +1,35 @@ +Shader "Hidden/TFHCCompareLessEqual" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_True", 2D) = "white" {} + _D ( "_False", 2D ) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + + float4 frag(v2f_img i) : SV_Target + { + float A = tex2D( _A, i.uv ).x; + float B = tex2D( _B, i.uv ).x; + float4 True = tex2D( _C, i.uv ); + float4 False = tex2D ( _D, i.uv ); + return ( ( A <= B ) ? True : False ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLowerEqual.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLowerEqual.shader.meta new file mode 100644 index 0000000..471968d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareLowerEqual.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 9a3e17508793b9d42b1efaaf5bcd2554 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareNotEqual.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareNotEqual.shader new file mode 100644 index 0000000..b40f85e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareNotEqual.shader @@ -0,0 +1,35 @@ +Shader "Hidden/TFHCCompareNotEqual" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_True", 2D) = "white" {} + _D ( "_False", 2D ) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + + float4 frag(v2f_img i) : SV_Target + { + float A = tex2D( _A, i.uv ).x; + float B = tex2D( _B, i.uv ).x; + float4 True = tex2D( _C, i.uv ); + float4 False = tex2D ( _D, i.uv ); + return ( ( A != B ) ? True : False ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareNotEqual.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareNotEqual.shader.meta new file mode 100644 index 0000000..44e64f9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareNotEqual.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 75f433376eef1ad4a881d99124e08008 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareWithRange.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareWithRange.shader new file mode 100644 index 0000000..516727f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareWithRange.shader @@ -0,0 +1,38 @@ +Shader "Hidden/TFHCCompareWithRange" +{ + Properties + { + _A ("_Value", 2D) = "white" {} + _B ("_RangeMin", 2D) = "white" {} + _C ("_RangeMax", 2D) = "white" {} + _D ( "_True", 2D ) = "white" {} + _E ( "_False", 2D ) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + + float4 frag(v2f_img i) : SV_Target + { + float4 Value = tex2D( _A, i.uv ).x; + float4 RangeMin = tex2D( _B, i.uv ).x; + float4 RangeMax = tex2D( _C, i.uv ); + float4 True = tex2D ( _D, i.uv ); + float4 False = tex2D ( _E, i.uv ); + return ( ( Value >= RangeMin && Value <= RangeMax ) ? True : False ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareWithRange.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareWithRange.shader.meta new file mode 100644 index 0000000..65b4bf6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCCompareWithRange.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 127d114eed178d7409f900134a6c00d1 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCFlipBookUVAnimation.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCFlipBookUVAnimation.shader new file mode 100644 index 0000000..a377898 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCFlipBookUVAnimation.shader @@ -0,0 +1,89 @@ +Shader "Hidden/TFHCFlipBookUVAnimation" +{ + Properties + { + _A ("_UV", 2D) = "white" {} + _B ("_Columns", 2D) = "white" {} + _C ("_Rows", 2D) = "white" {} + _D ("_Speed", 2D) = "white" {} + _E ("_StartFrame", 2D) = "white" {} + _F ("_Speed", 2D) = "white" {} + } + SubShader + { + CGINCLUDE + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + sampler2D _F; + float _EditorTime; + ENDCG + + //Time port disconnected + Pass + { + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float2 uv = tex2D( _A, i.uv ).rg; + float col = tex2D( _B, i.uv ).r; + float row = tex2D( _C, i.uv ).r; + float spd = tex2D( _D, i.uv ).r; + float str = tex2D( _E, i.uv ).r; + + float fbtotaltiles = col * row; + float fbcolsoffset = 1.0f / col; + float fbrowsoffset = 1.0f / row; + float fbspeed = _EditorTime * spd; + float2 fbtiling = float2(fbcolsoffset, fbrowsoffset); + float fbcurrenttileindex = round( fmod( fbspeed + str, fbtotaltiles) ); + fbcurrenttileindex += ( fbcurrenttileindex < 0) ? fbtotaltiles : 0; + float fblinearindextox = round ( fmod ( fbcurrenttileindex, col ) ); + float fboffsetx = fblinearindextox * fbcolsoffset; + float fblinearindextoy = round( fmod( ( fbcurrenttileindex - fblinearindextox ) / col, row ) ); + fblinearindextoy = (int)(row-1) - fblinearindextoy; + float fboffsety = fblinearindextoy * fbrowsoffset; + float2 fboffset = float2(fboffsetx, fboffsety); + float2 fbuv = float4( uv, 0.0 , 0.0 ) * fbtiling + fboffset; + return float4(fbuv, 0 , 0); + } + ENDCG + } + + //Time port connected + Pass + { + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float2 uv = tex2D( _A, i.uv ).rg; + float col = tex2D( _B, i.uv ).r; + float row = tex2D( _C, i.uv ).r; + float spd = tex2D( _D, i.uv ).r; + float str = tex2D( _E, i.uv ).r; + float time = tex2D( _F, i.uv ).r; + float fbtotaltiles = col * row; + float fbcolsoffset = 1.0f / col; + float fbrowsoffset = 1.0f / row; + float fbspeed = time * spd; + float2 fbtiling = float2(fbcolsoffset, fbrowsoffset); + float fbcurrenttileindex = round( fmod( fbspeed + str, fbtotaltiles) ); + fbcurrenttileindex += ( fbcurrenttileindex < 0) ? fbtotaltiles : 0; + float fblinearindextox = round ( fmod ( fbcurrenttileindex, col ) ); + float fboffsetx = fblinearindextox * fbcolsoffset; + float fblinearindextoy = round( fmod( ( fbcurrenttileindex - fblinearindextox ) / col, row ) ); + fblinearindextoy = (int)(row-1) - fblinearindextoy; + float fboffsety = fblinearindextoy * fbrowsoffset; + float2 fboffset = float2(fboffsetx, fboffsety); + float2 fbuv = float4( uv, 0.0 , 0.0 ) * fbtiling + fboffset; + return float4(fbuv, 0 , 0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCFlipBookUVAnimation.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCFlipBookUVAnimation.shader.meta new file mode 100644 index 0000000..9f79680 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCFlipBookUVAnimation.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 04fe24be792bfd5428b92132d7cf0f7d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCIf.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCIf.shader new file mode 100644 index 0000000..fb605cb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCIf.shader @@ -0,0 +1,41 @@ +Shader "Hidden/TFHCIf" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + _C ("_AGreaterB", 2D) = "white" {} + _D ( "_AEqualsB", 2D ) = "white" {} + _E ( "_ALessB", 2D ) = "white" {} + _F ( "_EqualThreshold", 2D ) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + sampler2D _F; + + float4 frag(v2f_img i) : SV_Target + { + float4 A = tex2D( _A, i.uv ).x; + float4 B = tex2D( _B, i.uv ).x; + float4 AGreaterB = tex2D( _C, i.uv ); + float4 AEqualsB = tex2D ( _D, i.uv ); + float4 ALessB = tex2D ( _E, i.uv ); + float4 EqualThreshold = tex2D ( _F, i.uv ); + return ( A - EqualThreshold > B ? AGreaterB : A - EqualThreshold <= B && A + EqualThreshold >= B ? AEqualsB : ALessB ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCIf.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCIf.shader.meta new file mode 100644 index 0000000..5d18716 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCIf.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5c7bc7e3cab81da499e4864ace0d86c5 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCPixelateUV.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCPixelateUV.shader new file mode 100644 index 0000000..f9d3d8a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCPixelateUV.shader @@ -0,0 +1,35 @@ +Shader "Hidden/TFHCPixelateUV" +{ + Properties + { + _A ("_UV", 2D) = "white" {} + _B ("_PixelX", 2D) = "white" {} + _C ("_PixelY", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + + float4 frag(v2f_img i) : SV_Target + { + float2 uv = tex2D( _A, i.uv ).rg; + float pix = tex2D( _B, i.uv ).r; + float piy = tex2D( _C, i.uv ).r; + + float2 steppedPixel = float2( pix, piy ); + float2 pixelatedUV = floor( uv * steppedPixel ) / steppedPixel; + return float4(pixelatedUV, 0 , 0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCPixelateUV.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCPixelateUV.shader.meta new file mode 100644 index 0000000..bfaaa63 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCPixelateUV.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e2f7e3c513ed18340868b8cbd0d85cfb +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCRemap.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCRemap.shader new file mode 100644 index 0000000..bf10c8a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCRemap.shader @@ -0,0 +1,49 @@ +Shader "Hidden/TFHCRemap" +{ + Properties + { + _A ("_Value", 2D) = "white" {} + _B ("_MinOld", 2D) = "white" {} + _C ("_MaxOld", 2D) = "white" {} + _D ("_MinNew", 2D) = "white" {} + _E ("_MaxNew", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + + float4 frag(v2f_img i) : SV_Target + { + float4 value = tex2D( _A, i.uv ); + float4 minold = tex2D( _B, i.uv ); + float4 maxold = tex2D( _C, i.uv ); + float4 minnew = tex2D( _D, i.uv ); + float4 maxnew = tex2D( _E, i.uv ); + + float4 denom = maxold - minold; + if(denom.x == 0) + denom.x = 0.000001; + if(denom.y == 0) + denom.y = 0.000001; + if(denom.z == 0) + denom.z = 0.000001; + if(denom.w == 0) + denom.w = 0.000001; + + return (minnew + (value - minold) * (maxnew - minnew) / denom); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCRemap.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCRemap.shader.meta new file mode 100644 index 0000000..8ebceb4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TFHCRemap.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 72dd1cbea889fa047b929d5191e360c0 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanOpNode.shader new file mode 100644 index 0000000..475be37 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/TanOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tan(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanOpNode.shader.meta new file mode 100644 index 0000000..f7a22d2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 312e291832cac5749a3626547dfc8607 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentSignVertexDataNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentSignVertexDataNode.shader new file mode 100644 index 0000000..c84d7f2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentSignVertexDataNode.shader @@ -0,0 +1,31 @@ +Shader "Hidden/TangentVertexDataNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + //float2 tp = 2 * i.uv - 1; + //float tr = sqrt( dot(tp,tp) ); + //tr = saturate( tr ); + + //float2 tuvs; + //float f = ( 1 - sqrt( 1 - tr ) ) / tr; + + //float3 tangent = normalize(float3( (1-f)*2, tp.y*0.01, tp.x )); + + //float4((tangent), 1); + + //TODO: needs revision at some point + return -1; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentSignVertexDataNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentSignVertexDataNode.shader.meta new file mode 100644 index 0000000..15b2740 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentSignVertexDataNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f5466d126f4bb1f49917eac88b1cb6af +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentVertexDataNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentVertexDataNode.shader new file mode 100644 index 0000000..e465eaf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentVertexDataNode.shader @@ -0,0 +1,22 @@ +Shader "Hidden/TangentVertexDataNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 tangent = normalize(float3( -z, xy.y*0.01, xy.x )); + return float4((tangent), 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentVertexDataNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentVertexDataNode.shader.meta new file mode 100644 index 0000000..f3c7c38 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TangentVertexDataNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0a44bb521d06d6143a4acbc3602037f8 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanhOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanhOpNode.shader new file mode 100644 index 0000000..f4c54f8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanhOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/TanhOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tanh(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanhOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanhOpNode.shader.meta new file mode 100644 index 0000000..b3565b6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TanhOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 52f78d3a1c66d1c489cd63b0a9300b38 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TauNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TauNode.shader new file mode 100644 index 0000000..4bd66c5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TauNode.shader @@ -0,0 +1,19 @@ +Shader "Hidden/TauNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 frag(v2f_img i) : SV_Target + { + return UNITY_PI * 2; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TauNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TauNode.shader.meta new file mode 100644 index 0000000..e46f21a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TauNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 701bc295c0d75d8429eabcf45e8e008d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TemplateShaderProperty.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TemplateShaderProperty.shader new file mode 100644 index 0000000..9285b9b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TemplateShaderProperty.shader @@ -0,0 +1,47 @@ +Shader "Hidden/TemplateShaderProperty" +{ + Properties + { + [HideFromInspector]_IntData ( "_IntData", Int ) = 0 + [HideFromInspector]_FloatData ( "_FloatData", Float ) = 0 + [HideFromInspector]_VectorData ( "_VectorData", Vector ) = ( 0,0,0,0 ) + [HideFromInspector]_Sampler2DData ( "_Sampler2DData", 2D ) = "white" {} + [HideFromInspector]_Sampler3DData ( "_Sampler3DData", 3D ) = "white" {} + [HideFromInspector]_SamplerCubeData ( "_SamplerCubeData", Cube ) = "white" {} + } + + CGINCLUDE + #include "UnityCG.cginc" + uniform int _IntData; + uniform float _FloatData; + uniform float4 _VectorData; + uniform sampler2D _Sampler2DData; + uniform sampler3D _Sampler3DData; + uniform samplerCUBE _SamplerCubeData; + + #pragma vertex vert_img + #pragma fragment frag + + float4 CalculatePreviewColor ( v2f_img i, const int dataType ) + { + /*Int*/ if ( dataType == 0 ) return float4( _IntData.xxx,1); + /*Float*/ if ( dataType == 1 ) return float4( _FloatData.xxx, 1 ); + /*Vector4/Color*/ if ( dataType == 2 ) return _VectorData; + /*Sampler 2D*/ if ( dataType == 3 ) return tex2D ( _Sampler2DData, i.uv ); + /*Sampler 3D*/ if ( dataType == 4 ) return tex3D ( _Sampler3DData, float3( i.uv, 0.0 ) ); + /*Sampler Cube*/ if ( dataType == 5 ) return texCUBE ( _SamplerCubeData, float3( i.uv, 0.0 ) ); + return (0).xxxx; + } + + ENDCG + + SubShader + { + Pass{ CGPROGRAM float4 frag ( v2f_img i ) : SV_Target { return CalculatePreviewColor(i,0); } ENDCG } + Pass{ CGPROGRAM float4 frag ( v2f_img i ) : SV_Target { return CalculatePreviewColor(i,1); } ENDCG } + Pass{ CGPROGRAM float4 frag ( v2f_img i ) : SV_Target { return CalculatePreviewColor(i,2); } ENDCG } + Pass{ CGPROGRAM float4 frag ( v2f_img i ) : SV_Target { return CalculatePreviewColor(i,3); } ENDCG } + Pass{ CGPROGRAM float4 frag ( v2f_img i ) : SV_Target { return CalculatePreviewColor(i,4); } ENDCG } + Pass{ CGPROGRAM float4 frag ( v2f_img i ) : SV_Target { return CalculatePreviewColor(i,5); } ENDCG } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TemplateShaderProperty.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TemplateShaderProperty.shader.meta new file mode 100644 index 0000000..4a4090d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TemplateShaderProperty.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4feb2016be0ece148b8bf234508f6aa4 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexCoordVertexDataNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexCoordVertexDataNode.shader new file mode 100644 index 0000000..e03aca7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexCoordVertexDataNode.shader @@ -0,0 +1,19 @@ +Shader "Hidden/TexCoordVertexDataNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 frag( v2f_img i ) : SV_Target + { + return float4( i.uv, 0, 0 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexCoordVertexDataNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexCoordVertexDataNode.shader.meta new file mode 100644 index 0000000..01ddea9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexCoordVertexDataNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6c1bee77276896041bbb73b1b9e7f8ac +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexelSize.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexelSize.shader new file mode 100644 index 0000000..b3e43ff --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexelSize.shader @@ -0,0 +1,80 @@ +Shader "Hidden/TexelSize" +{ + Properties + { + _Sampler ("_Sampler", 2D) = "white" {} + _Sampler3D ("_Sampler3D", 3D) = "white" {} + _Array ("_Array", 2DArray) = "white" {} + _Cube ("_Cube", CUBE) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _Sampler; + float4 _Sampler_TexelSize; + + float4 frag( v2f_img i ) : SV_Target + { + return _Sampler_TexelSize; + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler3D _Sampler3D; + float4 _Sampler3D_TexelSize; + + float4 frag (v2f_img i) : SV_Target + { + return _Sampler3D_TexelSize; + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + UNITY_DECLARE_TEX2DARRAY (_Array); + float4 _Array_TexelSize; + + float4 frag (v2f_img i) : SV_Target + { + return _Array_TexelSize; + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + samplerCUBE _Cube; + float4 _Cube_TexelSize; + + float4 frag (v2f_img i) : SV_Target + { + return _Cube_TexelSize; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexelSize.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexelSize.shader.meta new file mode 100644 index 0000000..b4773e8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexelSize.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6b20226576a059443b58aa2d0b942276 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Texture2D.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Texture2D.shader new file mode 100644 index 0000000..b1f48be --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Texture2D.shader @@ -0,0 +1,19 @@ +Shader "Hidden/Texture2D" +{ + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 frag( v2f_img i ) : SV_Target + { + return 0; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Texture2D.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Texture2D.shader.meta new file mode 100644 index 0000000..9297922 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Texture2D.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 13bd295c44d04e1419f20f792d331e33 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureArrayNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureArrayNode.shader new file mode 100644 index 0000000..9b9c8be --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureArrayNode.shader @@ -0,0 +1,63 @@ +Shader "Hidden/TextureArrayNode" +{ + Properties + { + _A ("_UVs", 2D) = "white" {} + _B ("_Index", 2D) = "white" {} + _C ("_Lod", 2D) = "white" {} + _D ("_NormalScale", 2D) = "white" {} + _G ("_Tex", 2D) = "white" {} + _TexConnected ("_TexConnected", Int) = 0 + } + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #pragma target 3.5 + #include "UnityCG.cginc" + #include "UnityStandardUtils.cginc" + + uniform UNITY_DECLARE_TEX2DARRAY( _Sampler ); + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _G; + float _CustomUVs; + float _LodType; + float _Unpack; + int _TexConnected; + + float4 frag( v2f_img i ) : SV_Target + { + float2 uvs = i.uv; + if ( _CustomUVs == 1 ) + uvs = tex2D( _A, i.uv ).xy; + + float n = tex2D( _D, i.uv ).r; + float4 c = 0; + if ( _LodType == 1 ) { + float lod = tex2D( _C, i.uv ).r; + c = UNITY_SAMPLE_TEX2DARRAY_LOD( _Sampler, float3( uvs, tex2D( _B, i.uv ).r ), lod ); + } + else if( _TexConnected == 0) { + c = UNITY_SAMPLE_TEX2DARRAY( _Sampler, float3( uvs, tex2D( _B, i.uv ).r ) ); + } + else { + c = tex2D( _G, uvs ); + } + + if ( _Unpack == 1 ) + { + c.rgb = UnpackScaleNormal(c, n); + } + + return c; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureArrayNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureArrayNode.shader.meta new file mode 100644 index 0000000..936540b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureArrayNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2e6d093df2d289f47b827b36efb31a81 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureCoordinatesNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureCoordinatesNode.shader new file mode 100644 index 0000000..aaa78e0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureCoordinatesNode.shader @@ -0,0 +1,29 @@ +Shader "Hidden/TextureCoordinatesNode" +{ + Properties + { + _A ("_Tilling", 2D) = "white" {} + _B ("_Offset", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + + float4 frag( v2f_img i ) : SV_Target + { + float4 t = tex2D( _A, i.uv ); + float4 o = tex2D( _B, i.uv ); + return float4( i.uv * t.xy + o.xy, 0, 0 ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureCoordinatesNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureCoordinatesNode.shader.meta new file mode 100644 index 0000000..656fedd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureCoordinatesNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 085e462b2de441a42949be0e666cf5d2 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexturePropertyNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexturePropertyNode.shader new file mode 100644 index 0000000..28079d6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexturePropertyNode.shader @@ -0,0 +1,84 @@ +Shader "Hidden/TexturePropertyNode" +{ + Properties + { + _Sampler ("_Sampler", 2D) = "white" {} + _Sampler3D ("_Sampler3D", 3D) = "white" {} + _Array ("_Array", 2DArray) = "white" {} + _Cube( "_Cube", CUBE) = "white" {} + _Default ("_Default", Int) = 0 + _Type ("_Type", Int) = 0 + } + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #pragma exclude_renderers d3d9 + #pragma target 3.5 + #include "UnityCG.cginc" + int _Default; + float4 frag( v2f_img i ) : SV_Target + { + if(_Default == 1) + { + return 1; + } + else if(_Default == 2) + { + return 0; + } + else if(_Default == 3) + { + return 0.5f; + } + else if(_Default == 4) + { + return float4(0.5,0.5,1,1); + } + + return 1; + } + ENDCG + } + + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #pragma exclude_renderers d3d9 + #pragma target 3.5 + #include "UnityCG.cginc" + + UNITY_DECLARE_TEX2DARRAY (_Array); + samplerCUBE _Cube; + sampler2D _Sampler; + sampler3D _Sampler3D; + int _Type; + + float4 frag (v2f_img i) : SV_Target + { + if (_Type == 4) + { + return UNITY_SAMPLE_TEX2DARRAY (_Array, float3(i.uv, 0)); + } + else if (_Type == 3) + { + return texCUBE (_Cube, float3(i.uv,0)); + } + else if (_Type == 2) + { + return tex3D (_Sampler3D, float3(i.uv,0)); + } + else + { + return tex2D (_Sampler, i.uv); + } + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexturePropertyNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexturePropertyNode.shader.meta new file mode 100644 index 0000000..c2ac2c0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TexturePropertyNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e53988745ec6e034694ee2640cd3d372 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureTransform.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureTransform.shader new file mode 100644 index 0000000..55adec1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureTransform.shader @@ -0,0 +1,87 @@ +Shader "Hidden/TextureTransform" +{ + Properties + { + _Sampler ("_Sampler", 2D) = "white" {} + _Sampler3D ("_Sampler3D", 3D) = "white" {} + _Array ("_Array", 2DArray) = "white" {} + _Cube ("_Cube", CUBE) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + int _PreviewID = 0; + sampler2D _Sampler; + float4 _Sampler_ST; + + float4 frag( v2f_img i ) : SV_Target + { + return _PreviewID == 0?float4(_Sampler_ST.xy,0,0): float4(_Sampler_ST.zw,0,0); + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + int _PreviewID = 0; + sampler3D _Sampler3D; + float4 _Sampler3D_ST; + + float4 frag (v2f_img i) : SV_Target + { + return _Sampler3D_ST; + return _PreviewID == 0 ? float4(_Sampler3D_ST.xy, 0, 0) : float4(_Sampler3D_ST.zw, 0, 0); + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + int _PreviewID = 0; + UNITY_DECLARE_TEX2DARRAY (_Array); + float4 _Array_ST; + + float4 frag (v2f_img i) : SV_Target + { + return _Array_ST; + return _PreviewID == 0 ? float4(_Array_ST.xy, 0, 0) : float4(_Array_ST.zw, 0, 0); + } + ENDCG + } + + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + int _PreviewID = 0; + samplerCUBE _Cube; + float4 _Cube_ST; + + float4 frag (v2f_img i) : SV_Target + { + return _Cube_ST; + return _PreviewID == 0 ? float4(_Cube_ST.xy, 0, 0) : float4(_Cube_ST.zw, 0, 0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureTransform.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureTransform.shader.meta new file mode 100644 index 0000000..6d5bc4e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TextureTransform.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 25ba2903568b00343ae06788994cab54 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TimeNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TimeNode.shader new file mode 100644 index 0000000..7a5fc9e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TimeNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/TimeNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float _EditorTime; + + float4 frag( v2f_img i ) : SV_Target + { + float4 t = _EditorTime; + t.x = _EditorTime / 20; + t.z = _EditorTime * 2; + t.w = _EditorTime * 3; + return t; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TimeNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TimeNode.shader.meta new file mode 100644 index 0000000..43a3698 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TimeNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 73abc10c8d1399444827a7eeb9c24c2a +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ToggleSwitchNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ToggleSwitchNode.shader new file mode 100644 index 0000000..e9d0eec --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ToggleSwitchNode.shader @@ -0,0 +1,30 @@ +Shader "Hidden/ToggleSwitchNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + _B ("_B", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + sampler2D _B; + float _Current; + + float4 frag( v2f_img i ) : SV_Target + { + float4 a = tex2D( _A, i.uv ); + float4 b = tex2D( _B, i.uv ); + return lerp(a,b,_Current); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ToggleSwitchNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ToggleSwitchNode.shader.meta new file mode 100644 index 0000000..a6c388c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ToggleSwitchNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: beeb138daeb592a4887454f81dba2b3f +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TriplanarNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TriplanarNode.shader new file mode 100644 index 0000000..1b7843c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TriplanarNode.shader @@ -0,0 +1,105 @@ +Shader "Hidden/TriplanarNode" +{ + Properties + { + _A ("_TopTex", 2D) = "white" {} + _B ("_MidTex", 2D) = "white" {} + _C ("_BotTex", 2D) = "white" {} + _D ("_Tilling", 2D) = "white" {} + _E ("_Falloff", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #pragma target 3.0 + #include "UnityCG.cginc" + #include "UnityStandardUtils.cginc" + + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + sampler2D _E; + float _IsNormal; + float _IsTangent; + float _IsSpherical; + + inline float3 TriplanarSamplingCNF( sampler2D topTexMap, sampler2D midTexMap, sampler2D botTexMap, float3 worldPos, float3 worldNormal, float falloff, float tilling ) + { + float3 projNormal = ( pow( abs( worldNormal ), falloff ) ); + projNormal /= projNormal.x + projNormal.y + projNormal.z; + float3 nsign = sign( worldNormal ); + float negProjNormalY = max( 0, projNormal.y * -nsign.y ); + projNormal.y = max( 0, projNormal.y * nsign.y ); + half4 xNorm; half4 yNorm; half4 yNormN; half4 zNorm; + xNorm = ( tex2D( midTexMap, tilling * worldPos.zy * float2( nsign.x, 1.0 ) ) ); + yNorm = ( tex2D( topTexMap, tilling * worldPos.xz * float2( nsign.y, 1.0 ) ) ); + yNormN = ( tex2D( botTexMap, tilling * worldPos.xz * float2( nsign.y, 1.0 ) ) ); + zNorm = ( tex2D( midTexMap, tilling * worldPos.xy * float2( -nsign.z, 1.0 ) ) ); + xNorm.xyz = half3( UnpackNormal( xNorm ).xy * float2( nsign.x, 1.0 ) + worldNormal.zy, worldNormal.x ).zyx; + yNorm.xyz = half3( UnpackNormal( yNorm ).xy * float2( nsign.y, 1.0 ) + worldNormal.xz, worldNormal.y ).xzy; + zNorm.xyz = half3( UnpackNormal( zNorm ).xy * float2( -nsign.z, 1.0 ) + worldNormal.xy, worldNormal.z ).xyz; + yNormN.xyz = half3( UnpackNormal( yNormN ).xy * float2( nsign.y, 1.0 ) + worldNormal.xz, worldNormal.y ).xzy; + return normalize( xNorm.xyz * projNormal.x + yNorm.xyz * projNormal.y + yNormN.xyz * negProjNormalY + zNorm.xyz * projNormal.z ); + } + + inline float4 TriplanarSamplingCF( sampler2D topTexMap, sampler2D midTexMap, sampler2D botTexMap, float3 worldPos, float3 worldNormal, float falloff, float tilling ) + { + float3 projNormal = ( pow( abs( worldNormal ), falloff ) ); + projNormal /= projNormal.x + projNormal.y + projNormal.z; + float3 nsign = sign( worldNormal ); + float negProjNormalY = max( 0, projNormal.y * -nsign.y ); + projNormal.y = max( 0, projNormal.y * nsign.y ); + half4 xNorm; half4 yNorm; half4 yNormN; half4 zNorm; + xNorm = ( tex2D( midTexMap, tilling * worldPos.zy * float2( nsign.x, 1.0 ) ) ); + yNorm = ( tex2D( topTexMap, tilling * worldPos.xz * float2( nsign.y, 1.0 ) ) ); + yNormN = ( tex2D( botTexMap, tilling * worldPos.xz * float2( nsign.y, 1.0 ) ) ); + zNorm = ( tex2D( midTexMap, tilling * worldPos.xy * float2( -nsign.z, 1.0 ) ) ); + return xNorm * projNormal.x + yNorm * projNormal.y + yNormN * negProjNormalY + zNorm * projNormal.z; + } + + float4 frag( v2f_img i ) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 normal = normalize(vertexPos); + float3 worldNormal = UnityObjectToWorldNormal(normal); + float3 worldPos = mul(unity_ObjectToWorld, vertexPos).xyz; + + float falloff = tex2D( _E, xy ).r; + float tilling = tex2D( _D, xy ).r * 0.625; + float4 triplanar = 1; + + if ( _IsNormal == 1 ) { + float3 tangent = normalize(float3( -z, xy.y*0.01, xy.x )); + float3 worldTangent = UnityObjectToWorldDir(tangent); + float tangentSign = -1; + float3 worldBinormal = normalize( cross(worldNormal, worldTangent) * tangentSign); + float3x3 worldToTangent = float3x3( worldTangent, worldBinormal, worldNormal ); + if ( _IsSpherical == 1 ) + triplanar.xyz = TriplanarSamplingCNF( _A, _A, _A, worldPos, worldNormal, falloff, tilling ); + else + triplanar.xyz = TriplanarSamplingCNF( _A, _B, _C, worldPos, worldNormal, falloff, tilling ); + + if( _IsTangent == 1 ) + triplanar.xyz = mul( worldToTangent, triplanar.xyz ); + } + else + { + if ( _IsSpherical == 1 ) + triplanar = TriplanarSamplingCF( _A, _A, _A, worldPos, worldNormal, falloff, tilling ); + else + triplanar = TriplanarSamplingCF( _A, _B, _C, worldPos, worldNormal, falloff, tilling ); + } + + return triplanar; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TriplanarNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TriplanarNode.shader.meta new file mode 100644 index 0000000..d990502 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TriplanarNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8723015ec59743143aadfbe480e34391 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TruncOpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TruncOpNode.shader new file mode 100644 index 0000000..31b23c1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TruncOpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/TruncOpNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return trunc(tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TruncOpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TruncOpNode.shader.meta new file mode 100644 index 0000000..40189d2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_TruncOpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c717aaa68f4ac9e469b15763e82933e1 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_UnpackScaleNormalNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_UnpackScaleNormalNode.shader new file mode 100644 index 0000000..72e2fcf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_UnpackScaleNormalNode.shader @@ -0,0 +1,33 @@ +Shader "Hidden/UnpackScaleNormalNode" +{ + Properties + { + _A ("_Value", 2D) = "white" {} + _B ("_NormalScale", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #pragma target 3.0 + #include "UnityCG.cginc" + #include "UnityStandardUtils.cginc" + + sampler2D _A; + sampler2D _B; + + float4 frag( v2f_img i ) : SV_Target + { + float4 c = tex2D( _A, i.uv ); + float n = tex2D( _B, i.uv ).r; + c.rgb = UnpackScaleNormal( c, n ); + + return float4(c.rgb, 0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_UnpackScaleNormalNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_UnpackScaleNormalNode.shader.meta new file mode 100644 index 0000000..7cf87f1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_UnpackScaleNormalNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8b0ae05e25d280c45af81ded56f8012e +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector2Node.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector2Node.shader new file mode 100644 index 0000000..4edf77f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector2Node.shader @@ -0,0 +1,24 @@ +Shader "Hidden/Vector2Node" +{ + Properties { + _InputVector ("_InputVector", Vector) = (0,0,0,0) + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 _InputVector; + + float4 frag( v2f_img i ) : SV_Target + { + return float4(_InputVector.x,_InputVector.y,0,0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector2Node.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector2Node.shader.meta new file mode 100644 index 0000000..b9e7d39 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector2Node.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 88b4191eb06084d4da85d1dd2f984085 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector3Node.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector3Node.shader new file mode 100644 index 0000000..299f3ad --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector3Node.shader @@ -0,0 +1,24 @@ +Shader "Hidden/Vector3Node" +{ + Properties { + _InputVector ("_InputVector", Vector) = (0,0,0,0) + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 _InputVector; + + float4 frag( v2f_img i ) : SV_Target + { + return float4(_InputVector.x,_InputVector.y,_InputVector.z,0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector3Node.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector3Node.shader.meta new file mode 100644 index 0000000..677eadc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector3Node.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8a44d38f06246bf48944b3f314bc7920 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector4Node.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector4Node.shader new file mode 100644 index 0000000..044be7a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector4Node.shader @@ -0,0 +1,24 @@ +Shader "Hidden/Vector4Node" +{ + Properties { + _InputVector ("_InputVector", Vector) = (0,0,0,0) + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 _InputVector; + + float4 frag( v2f_img i ) : SV_Target + { + return _InputVector; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector4Node.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector4Node.shader.meta new file mode 100644 index 0000000..e90efaf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_Vector4Node.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: aac241d0e47a5a84fbd2edcd640788dc +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexBinormalNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexBinormalNode.shader new file mode 100644 index 0000000..f54cf44 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexBinormalNode.shader @@ -0,0 +1,31 @@ +Shader "Hidden/VertexBinormalNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 normal = normalize(vertexPos); + float3 worldNormal = UnityObjectToWorldNormal(normal); + + float3 tangent = normalize(float3( -z, xy.y*0.01, xy.x )); + float3 worldPos = mul(unity_ObjectToWorld, vertexPos).xyz; + float3 worldTangent = UnityObjectToWorldDir(tangent); + float tangentSign = -1; + float3 worldBinormal = normalize( cross(worldNormal, worldTangent) * tangentSign); + + return float4(worldBinormal, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexBinormalNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexBinormalNode.shader.meta new file mode 100644 index 0000000..ec27e26 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexBinormalNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 76873532ab67d2947beaf07151383cbe +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexColorNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexColorNode.shader new file mode 100644 index 0000000..99b62ca --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexColorNode.shader @@ -0,0 +1,19 @@ +Shader "Hidden/VertexColorNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + return 1; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexColorNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexColorNode.shader.meta new file mode 100644 index 0000000..0ac109c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexColorNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ca1d22db6470c5f4d9f93a9873b4f5bc +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexIdVariableNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexIdVariableNode.shader new file mode 100644 index 0000000..a3ef76f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexIdVariableNode.shader @@ -0,0 +1,39 @@ +Shader "Hidden/VertexIdVariableNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert + #pragma fragment frag + + struct appdata_custom + { + float4 vertex : POSITION; + uint vertexId : SV_VertexID; + }; + + struct v2f_custom + { + float4 pos : SV_POSITION; + half vertexId : TEXCOORD0; + }; + + v2f_custom vert( appdata_custom v ) + { + v2f_custom o; + o.pos = UnityObjectToClipPos (v.vertex); + o.vertexId = v.vertexId; + return o; + } + + float4 frag( v2f_custom i ) : SV_Target + { + return i.vertexId; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexIdVariableNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexIdVariableNode.shader.meta new file mode 100644 index 0000000..e7ac67a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexIdVariableNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5934bf2c10b127a459177a3b622cea65 +timeCreated: 1542641929 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexTangentNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexTangentNode.shader new file mode 100644 index 0000000..3769192 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexTangentNode.shader @@ -0,0 +1,31 @@ +Shader "Hidden/VertexTangentNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + float2 tp = 2 * i.uv - 1; + float tr = sqrt( dot(tp,tp) ); + tr = saturate( tr ); + //if ( tr < 1 ) { + float2 tuvs; + float f = ( 1 - sqrt( 1 - tr ) ) / tr; + + float3 tangent = normalize(float3( (1-f)*2, tp.y*0.01, tp.x )); + return float4((tangent), 1); + //} + //else { + // return 0; + //} + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexTangentNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexTangentNode.shader.meta new file mode 100644 index 0000000..93c49b1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VertexTangentNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 61f0b80493c9b404d8c7bf56d59c3f81 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ViewDirInputsCoordNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ViewDirInputsCoordNode.shader new file mode 100644 index 0000000..7bf6d61 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ViewDirInputsCoordNode.shader @@ -0,0 +1,57 @@ +Shader "Hidden/WorldPosInputsNode" +{ + SubShader + { + Pass //world space + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 worldViewDir = normalize(float3(0,0,-5) - vertexPos); + + return float4(worldViewDir, 1); + } + ENDCG + } + + Pass //tangent space + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 worldViewDir = normalize(float3(0,0,-5) - vertexPos); + + float3 normal = normalize(vertexPos); + float3 worldNormal = UnityObjectToWorldNormal(normal); + + float3 tangent = normalize(float3( -z, xy.y*0.01, xy.x )); + float3 worldPos = mul(unity_ObjectToWorld, float4(vertexPos,1)).xyz; + float3 worldTangent = UnityObjectToWorldDir(tangent); + float tangentSign = -1; + float3 worldBinormal = normalize( cross(worldNormal, worldTangent) * tangentSign); + float4 tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); + float4 tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); + float4 tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); + + fixed3 viewDirTan = tSpace0.xyz * worldViewDir.x + tSpace1.xyz * worldViewDir.y + tSpace2.xyz * worldViewDir.z; + + return float4(viewDirTan, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ViewDirInputsCoordNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ViewDirInputsCoordNode.shader.meta new file mode 100644 index 0000000..6fdc1d1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ViewDirInputsCoordNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 07b57d9823df4bd4d8fe6dcb29fca36a +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VoronoiNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VoronoiNode.shader new file mode 100644 index 0000000..f2c5beb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VoronoiNode.shader @@ -0,0 +1,263 @@ +Shader "Hidden/VoronoiNode" +{ + Properties + { + _A("_RGB", 2D) = "white" {} + _B("_RGB", 2D) = "white" {} + _C("_RGB", 2D) = "white" {} + _D ("_RGB", 2D) = "white" {} + _UseTileScale("_UseTileScale", Float) = 0 + _TileScale ("_TileScale", Int) = 1 + _MinkowskiPower("_MinkowskiPower", Float) = 0 + _DistFunc("_DistFunc", Int) = 0 + _MethodType("_MethodType", Int) = 0 + _SearchQuality("_SearchQuality", Int) = 1 + _Octaves("_Octaves", Int) = 1 + _UseSmoothness("_UseSmoothness", Int ) = 0 + } + SubShader + { + Tags { "RenderType"="Opaque" } + CGINCLUDE + sampler2D _A; + sampler2D _B; + sampler2D _C; + sampler2D _D; + float _UseTileScale = 0; + int _TileScale = 1; + float _MinkowskiPower = 1; + int _DistFunc = 0; + int _MethodType = 0; + int _SearchQuality = 0; + int _Octaves = 1; + int _PreviewID = 0; + int _UseSmoothness = 0; + int _CustomUVs; + + float2 VoronoiHash( float2 p ) + { + p = lerp( p, p - _TileScale * floor (p / _TileScale), _UseTileScale ); + p = float2(dot (p, float2(127.1, 311.7)), dot (p, float2(269.5, 183.3))); + return frac (sin (p) *43758.5453); + } + + float Voronoi( float2 v, float time, inout float2 id, inout float2 mr, float smoothness ) + { + float2 n = floor(v); + float2 f = frac(v); + float F1 = 8.0; + float F2 = 8.0; + float2 mg = 0; + for (int j = -_SearchQuality; j <= _SearchQuality; j++) + { + for (int i = -_SearchQuality; i <= _SearchQuality; i++) + { + float2 g = float2(i, j); + float2 o = VoronoiHash (n + g); + o = (sin (time + o * 6.2831) * 0.5 + 0.5); float2 r = f - g - o; + float d = 0; + //Euclidean^2 + if (_DistFunc == 0) + { + d = 0.5 * dot (r, r); + } + //Euclidean + else if (_DistFunc == 1) + { + d = 0.707 * sqrt (dot (r, r)); + } + //Manhattan + else if (_DistFunc == 2) + { + d = 0.5 * (abs (r.x) + abs (r.y)); + } + //Chebyshev + else if (_DistFunc == 3) + { + d = max (abs (r.x), abs (r.y)); + } + //Minkowski + else if (_DistFunc == 4) + { + d = (1 / pow(2, 1 / _MinkowskiPower)) * pow( ( pow( abs( r.x ), _MinkowskiPower) + pow( abs( r.y ), _MinkowskiPower) ), (1 / _MinkowskiPower)); + } + + if (_MethodType == 0 && _UseSmoothness == 1) + { + float h = smoothstep (0.0, 1.0, 0.5 + 0.5 * (F1 - d) / smoothness); + F1 = lerp (F1, d, h) - smoothness * h * (1.0 - h); + mg = g; mr = r; id = o; + } + else + { + if (d < F1) + { + F2 = F1; + F1 = d; mg = g; mr = r; id = o; + } + else if (d < F2) + { + F2 = d; + } + + } + + } + } + + //Cells + if(_MethodType == 0) + { + return F1; + } + //Crystal + else if (_MethodType == 1) + { + return F2; + } + //Glass + else if (_MethodType == 2) + { + return F2 - F1; + } + //Caustic + else if (_MethodType == 3) + { + return (F2 + F1) * 0.5; + } + //Distance + else if (_MethodType == 4) + { + F1 = 8.0; + for (int j = -2; j <= 2; j++) + { + for (int i = -2; i <= 2; i++) + { + float2 g = mg + float2(i, j); + float2 o = VoronoiHash (n + g); + o = ( sin (time + o * 6.2831) * 0.5 + 0.5); + float2 r = f - g - o; + float d = dot (0.5 * (mr + r), normalize (r - mr)); + F1 = min (F1, d); + } + } + return F1; + } + else + return F1; + } + + + ENDCG + + Pass // Voronoi - Unity + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + inline float2 UnityVoronoiRandomVector (float2 UV, float offset) + { + float2x2 m = float2x2(15.27, 47.63, 99.41, 89.98); + UV = frac (sin (mul (UV, m)) * 46839.32); + return float2(sin (UV.y* +offset) * 0.5 + 0.5, cos (UV.x* offset) * 0.5 + 0.5); + } + + //x - Out y - Cells + float3 UnityVoronoi (float2 UV, float AngleOffset, float CellDensity, inout float2 mr) + { + float2 g = floor (UV * CellDensity); + float2 f = frac (UV * CellDensity); + float t = 8.0; + float3 res = float3(8.0, 0.0, 0.0); + + for (int y = -1; y <= 1; y++) + { + for (int x = -1; x <= 1; x++) + { + float2 lattice = float2(x, y); + float2 offset = UnityVoronoiRandomVector (lattice + g, AngleOffset); + float d = distance (lattice + offset, f); + if (d < res.x) + { + mr = f - lattice - offset; + res = float3(d, offset.x, offset.y); + } + } + } + return res; + } + + float4 frag (v2f_img i) : SV_Target + { + float2 uvValue = i.uv; + if (_CustomUVs == 1) + uvValue = tex2D(_A, i.uv).rg; + float angleOffset = tex2D(_B, i.uv).r; + float cellDensity = tex2D(_C, i.uv).r; + float2 uv = 0; + float3 voronoiVal = UnityVoronoi( uvValue, angleOffset , cellDensity, uv ); + if( _PreviewID == 2) + return float4( uv, 0, 1 ); + else if( _PreviewID == 1) + return float4( voronoiVal.yz, 0, 1 ); + else + return float4( voronoiVal.xxx, 1); + } + ENDCG + } + + Pass // Voronoi - ASE + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 frag (v2f_img i) : SV_Target + { + float2 uvValue = i.uv; + if (_CustomUVs == 1) + uvValue = tex2D(_A, i.uv).rg; + float time = tex2D (_B, i.uv).r; + float scale = tex2D (_C, i.uv).r; + float smoothness = tex2D (_D, i.uv).r; + + float2 id = 0; + float2 uv = 0; + float voronoiVal = Voronoi( uvValue*scale,time, id, uv, smoothness ); + if (_Octaves == 1) + { + if( _PreviewID == 2) + return float4( uv, 0, 1 ); + else if( _PreviewID == 1) + return float4( id, 0, 1 ); + else + return float4(voronoiVal.xxx, 1); + } + else + { + float fade = 0.5; + float voroi = 0; + float rest = 0; + for (int it = 0; it < _Octaves; it++) + { + voroi += fade * Voronoi( uvValue*scale, time, id, uv, smoothness); + rest += fade; + uvValue *= 2; + fade *= 0.5; + } + voroi /= rest; + if( _PreviewID == 2) + return float4( uv, 0, 1 ); + else if( _PreviewID == 1) + return float4( id, 0, 1 ); + else + return float4(voroi.xxx, 1); + } + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VoronoiNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VoronoiNode.shader.meta new file mode 100644 index 0000000..420e71c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_VoronoiNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: bc1498ccdade442479038b24982fc946 +timeCreated: 1566905239 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WeightedBlendNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WeightedBlendNode.shader new file mode 100644 index 0000000..e0a46b5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WeightedBlendNode.shader @@ -0,0 +1,84 @@ +Shader "Hidden/WeightedBlendNode" +{ + Properties + { + _A ( "_Weights", 2D) = "white" {} + _B ( "_Layer1", 2D) = "white" {} + _C ( "_Layer2", 2D ) = "white" {} + _D ( "_Layer3", 2D ) = "white" {} + _E ( "_Layer4", 2D ) = "white" {} + } + + SubShader + { + + CGINCLUDE + + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + sampler2D _A; + sampler2D _B; + + ENDCG + + Pass + { + CGPROGRAM + float4 frag(v2f_img i) : SV_Target + { + float4 Layer1 = tex2D( _B, i.uv ); + return Layer1; + } + ENDCG + } + + Pass + { + CGPROGRAM + sampler2D _C; + float4 frag ( v2f_img i ) : SV_Target + { + float4 Weights = tex2D ( _A, i.uv ); + float4 Layer1 = tex2D ( _B, i.uv ); + float4 Layer2 = tex2D ( _C, i.uv ); + return ( Weights.x*Layer1 + Weights.y*Layer2 ) / ( Weights.x + Weights.y ); + } + ENDCG + } + + Pass + { + CGPROGRAM + sampler2D _C; + sampler2D _D; + float4 frag ( v2f_img i ) : SV_Target + { + float4 Weights = tex2D( _A, i.uv ); + float4 Layer1 = tex2D( _B, i.uv ); + float4 Layer2 = tex2D( _C, i.uv ); + float4 Layer3 = tex2D( _D, i.uv ); + return ( Weights.x*Layer1 + Weights.y*Layer2 + Weights.z*Layer3 ) / ( Weights.x + Weights.y + Weights.z ); + } + ENDCG + } + + Pass + { + CGPROGRAM + sampler2D _C; + sampler2D _D; + sampler2D _E; + float4 frag ( v2f_img i ) : SV_Target + { + float4 Weights = tex2D ( _A, i.uv ); + float4 Layer1 = tex2D ( _B, i.uv ); + float4 Layer2 = tex2D ( _C, i.uv ); + float4 Layer3 = tex2D ( _D, i.uv ); + float4 Layer4 = tex2D ( _E, i.uv ); + return ( Weights.x*Layer1 + Weights.y*Layer2 + Weights.z*Layer3 + Weights.w*Layer4 ) / ( Weights.x + Weights.y + Weights.z + Weights.w ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WeightedBlendNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WeightedBlendNode.shader.meta new file mode 100644 index 0000000..9738a46 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WeightedBlendNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6076cbeaa41ebb14c85ff81b58df7d88 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WireNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WireNode.shader new file mode 100644 index 0000000..7d04059 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WireNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/WireNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return tex2D( _A, i.uv ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WireNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WireNode.shader.meta new file mode 100644 index 0000000..255c336 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WireNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: fa1e3e404e6b3c243b5527b82739d682 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldNormalVector.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldNormalVector.shader new file mode 100644 index 0000000..7a6983b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldNormalVector.shader @@ -0,0 +1,66 @@ +Shader "Hidden/WorldNormalVector" +{ + Properties + { + _A ("_WorldNormal", 2D) = "white" {} + } + SubShader + { + Pass //not connected + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 worldNormal = normalize(float3(xy, z)); + return float4(worldNormal, 1); + } + ENDCG + } + + Pass //connected + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 normal = normalize(vertexPos); + float3 worldNormal = UnityObjectToWorldNormal(normal); + + float3 tangent = normalize(float3( -z, xy.y*0.01, xy.x )); + float3 worldPos = mul(unity_ObjectToWorld, float4(vertexPos,1)).xyz; + float3 worldTangent = UnityObjectToWorldDir(tangent); + float tangentSign = -1; + float3 worldBinormal = normalize( cross(worldNormal, worldTangent) * tangentSign); + float4 tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); + float4 tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); + float4 tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); + + float2 sphereUVs = i.uv; + + sphereUVs.x = (atan2(vertexPos.x, -vertexPos.z) / (UNITY_PI) + 0.5); + // Needs further checking + //float3 tangentNormal = tex2Dlod(_A, float4(sphereUVs,0,0)).xyz; + float3 tangentNormal = tex2D(_A, sphereUVs).xyz; + + worldNormal = fixed3( dot( tSpace0.xyz, tangentNormal ), dot( tSpace1.xyz, tangentNormal ), dot( tSpace2.xyz, tangentNormal ) ); + + return float4(worldNormal, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldNormalVector.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldNormalVector.shader.meta new file mode 100644 index 0000000..dfc9ffa --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldNormalVector.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5f55f4841abb61e45967957788593a9d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldPosInputsNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldPosInputsNode.shader new file mode 100644 index 0000000..c36df0f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldPosInputsNode.shader @@ -0,0 +1,23 @@ +Shader "Hidden/WorldPosInputsNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float4 vertexPos = float4(xy, z,1); + float4 worldPos = mul(unity_ObjectToWorld, vertexPos); + return float4 (worldPos.xyz, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldPosInputsNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldPosInputsNode.shader.meta new file mode 100644 index 0000000..713d2ac --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldPosInputsNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 70d5405009b31a349a4d8285f30cf5d9 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldReflectionVector.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldReflectionVector.shader new file mode 100644 index 0000000..e3cfb4e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldReflectionVector.shader @@ -0,0 +1,77 @@ +Shader "Hidden/WorldReflectionVector" +{ + Properties + { + _A ("_TangentNormal", 2D) = "white" {} + } + SubShader + { + Pass //not connected + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 normal = normalize(vertexPos); + float3 worldNormal = UnityObjectToWorldNormal(normal); + + float3 worldViewDir = normalize(float3(0,0,-5) - vertexPos); + float3 worldRefl = -worldViewDir; + worldRefl = reflect( worldRefl, worldNormal ); + + return float4((worldRefl), 1); + } + ENDCG + } + + Pass //connected + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + float2 xy = 2 * i.uv - 1; + float z = -sqrt(1-saturate(dot(xy,xy))); + float3 vertexPos = float3(xy, z); + float3 normal = normalize(vertexPos); + float3 worldNormal = UnityObjectToWorldNormal(normal); + + float3 tangent = normalize(float3( -z, xy.y*0.01, xy.x )); + float3 worldPos = mul(unity_ObjectToWorld, float4(vertexPos,1)).xyz; + float3 worldViewDir = normalize(float3(0,0,-5) - vertexPos); + + float3 worldTangent = UnityObjectToWorldDir(tangent); + float tangentSign = -1; + float3 worldBinormal = normalize( cross(worldNormal, worldTangent) * tangentSign); + float4 tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); + float4 tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); + float4 tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); + + float3 worldRefl = -worldViewDir; + + float2 sphereUVs = i.uv; + sphereUVs.x = atan2(vertexPos.x, -vertexPos.z) / (UNITY_PI) + 0.5; + + // Needs further checking + //float3 tangentNormal = tex2Dlod(_A, float4(sphereUVs,0,0)).xyz; + float3 tangentNormal = tex2D(_A, sphereUVs).xyz; + + worldRefl = reflect( worldRefl, half3( dot( tSpace0.xyz, tangentNormal ), dot( tSpace1.xyz, tangentNormal ), dot( tSpace2.xyz, tangentNormal ) ) ); + + return float4((worldRefl), 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldReflectionVector.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldReflectionVector.shader.meta new file mode 100644 index 0000000..44034b5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldReflectionVector.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8e267e9aa545eeb418585a730f50273e +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceCameraPos.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceCameraPos.shader new file mode 100644 index 0000000..9f04ac1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceCameraPos.shader @@ -0,0 +1,20 @@ +Shader "Hidden/WorldSpaceCameraPos" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + //_WorldSpaceCameraPos + return float4(float3(0,0,-5),0); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceCameraPos.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceCameraPos.shader.meta new file mode 100644 index 0000000..78177ce --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceCameraPos.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6b0c78411043dd24dac1152c84bb63ba +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightDirHlpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightDirHlpNode.shader new file mode 100644 index 0000000..742e492 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightDirHlpNode.shader @@ -0,0 +1,22 @@ +Shader "Hidden/WorldSpaceLightDirHlpNode" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 _EditorWorldLightPos; + + float4 frag( v2f_img i ) : SV_Target + { + float3 lightDir = normalize( _EditorWorldLightPos.xyz ); + return float4 ( lightDir, 1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightDirHlpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightDirHlpNode.shader.meta new file mode 100644 index 0000000..10ed275 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightDirHlpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2e8dc46eb6fb2124d9f0007caf9567e3 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightPosNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightPosNode.shader new file mode 100644 index 0000000..3bb5ef1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightPosNode.shader @@ -0,0 +1,33 @@ +Shader "Hidden/WorldSpaceLightPosNode" +{ + SubShader + { + CGINCLUDE + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + ENDCG + + Pass + { + CGPROGRAM + float4 _EditorWorldLightPos; + float4 frag( v2f_img i ) : SV_Target + { + float3 lightDir = normalize( _EditorWorldLightPos.xyz ); + return float4 ( lightDir, 0); + } + ENDCG + } + + Pass + { + CGPROGRAM + float4 frag( v2f_img i ) : SV_Target + { + return (0).xxxx; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightPosNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightPosNode.shader.meta new file mode 100644 index 0000000..f9fa58c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceLightPosNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2292a614672283c41a367b22cdde4620 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceViewDirHlpNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceViewDirHlpNode.shader new file mode 100644 index 0000000..e90bacb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceViewDirHlpNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/WorldSpaceViewDirHlpNode" +{ +Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + sampler2D _A; + + float4 frag( v2f_img i ) : SV_Target + { + return float4( float3( 0,0,-5 ) - tex2D( _A, i.uv ).rgb,1); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceViewDirHlpNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceViewDirHlpNode.shader.meta new file mode 100644 index 0000000..edeada6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldSpaceViewDirHlpNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: fe0e09756a8a0ba408015b43e66cb8a6 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldToObjectTransfNode.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldToObjectTransfNode.shader new file mode 100644 index 0000000..d3ff2a7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldToObjectTransfNode.shader @@ -0,0 +1,25 @@ +Shader "Hidden/WorldToObjectTransfNode" +{ + Properties + { + _A ("_A", 2D) = "white" {} + } + SubShader + { + Pass + { + CGPROGRAM + #include "UnityCG.cginc" + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _A; + + float4 frag(v2f_img i) : SV_Target + { + return mul(unity_WorldToObject, tex2D( _A, i.uv )); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldToObjectTransfNode.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldToObjectTransfNode.shader.meta new file mode 100644 index 0000000..069ac0b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldToObjectTransfNode.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 79a5efd1e3309f54d8ba3e7fdf5e459b +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldTransformParams.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldTransformParams.shader new file mode 100644 index 0000000..9272676 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldTransformParams.shader @@ -0,0 +1,20 @@ +Shader "Hidden/WorldTransformParams" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + return unity_WorldTransformParams; + } + ENDCG + } + + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldTransformParams.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldTransformParams.shader.meta new file mode 100644 index 0000000..b6b2479 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_WorldTransformParams.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5a2642605f085da458d6e03ade47b87a +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ZBufferParams.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ZBufferParams.shader new file mode 100644 index 0000000..9f817b1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ZBufferParams.shader @@ -0,0 +1,19 @@ +Shader "Hidden/ZBufferParams" +{ + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #include "UnityCG.cginc" + + float4 frag( v2f_img i ) : SV_Target + { + return _ZBufferParams; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ZBufferParams.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ZBufferParams.shader.meta new file mode 100644 index 0000000..c7caf5e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/Preview_ZBufferParams.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 56c42c106bcb497439187f5bb6b6f94d +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/TextureArrayInspector.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/TextureArrayInspector.shader new file mode 100644 index 0000000..408050d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/TextureArrayInspector.shader @@ -0,0 +1,30 @@ +Shader "Hidden/TextureArrayEditor" +{ + Properties + { + _MainTex ("_MainTex", 2DArray) = "white" {} + _Index ("_Index", Int) = 0 + } + SubShader + { + Pass + { + CGPROGRAM + #pragma vertex vert_img + #pragma fragment frag + #pragma target 3.5 + #include "UnityCG.cginc" + #include "UnityStandardUtils.cginc" + + uniform UNITY_DECLARE_TEX2DARRAY( _MainTex ); + int _Index; + + float4 frag( v2f_img i ) : SV_Target + { + //return UNITY_SAMPLE_TEX2DARRAY_LOD( _MainTex, float3( i.uv, _Index), 0 ); + return UNITY_SAMPLE_TEX2DARRAY( _MainTex, float3( i.uv, _Index) ); + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/TextureArrayInspector.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/TextureArrayInspector.shader.meta new file mode 100644 index 0000000..8f6ce0a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Previews/TextureArrayInspector.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 610c24aad350fba4583068c6c22fa428 +timeCreated: 1488289785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions.meta new file mode 100644 index 0000000..96c839a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e21dd05d276e6c8438cc722d4559a0c3 +folderAsset: yes +timeCreated: 1507301549 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/And.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/And.asset new file mode 100644 index 0000000..8cba006 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/And.asset @@ -0,0 +1,39 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: And + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18101\n468;180;1104;762;810;372;1;True;False\nNode;AmplifyShaderEditor.FunctionInput;2;-320,0;Inherit;False;A;1;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;-320,80;Inherit;False;B;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CustomExpressionNode;1;-160,0;Inherit;False;float + result = A && B@$return result@;1;False;2;True;A;FLOAT;0;In;;Inherit;False;True;B;FLOAT;0;In;;Inherit;False;ASEAnd;False;False;0;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;1;0;2;0\nWireConnection;1;1;3;0\nWireConnection;0;0;1;0\nASEEND*/\n//CHKSM=194105DDA916A991C9946AB2786628346B491717" + m_functionName: + m_description: Returns 1 if both the inputs A and B are 1 + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 6 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/And.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/And.asset.meta new file mode 100644 index 0000000..cea5c99 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/And.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 50f923f3b90822e47953386ea346e02f +timeCreated: 1589816062 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bacteria.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bacteria.asset new file mode 100644 index 0000000..56013f7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bacteria.asset @@ -0,0 +1,38 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Bacteria + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1440;-254;1004;726;5555.52;2071.572;5.733906;True;False\nNode;AmplifyShaderEditor.SimpleAddOpNode;40;-512,-224;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;42;-912,0;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0.6;False;2;FLOAT;0.55;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;55;-512,320;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;41;-912,-128;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0.7;False;2;FLOAT;0.65;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;44;-256,0;Inherit;True;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;45;-912,144;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0.2;False;2;FLOAT;0.15;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;33;-704,-320;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-3872,160;Inherit;False;Tiling;2;0;False;1;0;FLOAT2;5,5;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;32;-912,-384;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0.45;False;2;FLOAT;0.4;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;46;-912,272;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0.1;False;2;FLOAT;0.05;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;43;-704,-80;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;34;-912,-256;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0.35;False;2;FLOAT;0.3;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;49;-912,400;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0.2;False;2;FLOAT;0.15;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;50;-912,528;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0.1;False;2;FLOAT;0.05;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;47;-704,208;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;48;-704,464;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LengthOpNode;53;-1120,464;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LengthOpNode;51;-1120,224;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;52;-1280,224;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0.5,1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;54;-1280,464;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;1,0.5;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.LengthOpNode;37;-1152,-176;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;31;-1616,0;Inherit;True;3;3;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;4;-3920,0;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;3;-3680,64;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FloorOpNode;6;-3520,-128;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;5;-3504,-48;Inherit;False;Seed;1;1;False;1;0;FLOAT;560;False;1;FLOAT;0\nNode;AmplifyShaderEditor.NoiseGeneratorNode;7;-3344,-112;Inherit;False;Simple;False;False;2;0;FLOAT2;0,0;False;1;FLOAT;560;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FractNode;12;-3088,-112;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FractNode;13;-3072,64;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.StepOpNode;14;-2848,-192;Inherit;False;2;0;FLOAT;0.75;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.OneMinusNode;17;-2848,-80;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.StepOpNode;16;-2800,304;Inherit;False;2;0;FLOAT;0.25;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;1;-2816,176;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.OneMinusNode;19;-2528,160;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;20;-2352,176;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.StepOpNode;15;-2832,32;Inherit;False;2;0;FLOAT;0.5;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.OneMinusNode;23;-2208,96;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;22;-2208,-16;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;24;-2032,16;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;21;-2160,-176;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;25;-1840,-112;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;26;-1904,176;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;27;-2144,256;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.OneMinusNode;28;-2112,352;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;29;-1888,384;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;30;-2832,432;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;40;0;33;0\nWireConnection;40;1;43;0\nWireConnection;42;0;37;0\nWireConnection;55;0;47;0\nWireConnection;55;1;48;0\nWireConnection;41;0;37;0\nWireConnection;44;0;40;0\nWireConnection;44;1;55;0\nWireConnection;45;0;51;0\nWireConnection;33;0;32;0\nWireConnection;33;1;34;0\nWireConnection;32;0;37;0\nWireConnection;46;0;51;0\nWireConnection;43;0;41;0\nWireConnection;43;1;42;0\nWireConnection;34;0;37;0\nWireConnection;49;0;53;0\nWireConnection;50;0;53;0\nWireConnection;47;0;45;0\nWireConnection;47;1;46;0\nWireConnection;48;0;49;0\nWireConnection;48;1;50;0\nWireConnection;53;0;54;0\nWireConnection;51;0;52;0\nWireConnection;52;0;31;0\nWireConnection;54;0;31;0\nWireConnection;37;0;31;0\nWireConnection;31;0;25;0\nWireConnection;31;1;26;0\nWireConnection;31;2;29;0\nWireConnection;3;0;4;0\nWireConnection;3;1;2;0\nWireConnection;6;0;3;0\nWireConnection;7;0;6;0\nWireConnection;7;1;5;0\nWireConnection;12;0;7;0\nWireConnection;13;0;3;0\nWireConnection;14;1;12;0\nWireConnection;17;0;13;0\nWireConnection;16;1;12;0\nWireConnection;1;0;13;0\nWireConnection;19;0;1;0\nWireConnection;20;0;19;0\nWireConnection;20;1;1;1\nWireConnection;15;1;12;0\nWireConnection;23;0;20;0\nWireConnection;22;0;15;0\nWireConnection;22;1;14;0\nWireConnection;24;0;22;0\nWireConnection;24;1;23;0\nWireConnection;21;0;14;0\nWireConnection;21;1;17;0\nWireConnection;25;0;21;0\nWireConnection;25;1;24;0\nWireConnection;26;0;20;0\nWireConnection;26;1;27;0\nWireConnection;27;0;16;0\nWireConnection;27;1;15;0\nWireConnection;28;0;16;0\nWireConnection;29;0;28;0\nWireConnection;29;1;30;0\nWireConnection;30;0;13;0\nWireConnection;0;0;44;0\nASEEND*/\n//CHKSM=A7931AF4EE98C9341AB309047876D23C8E9396B7" + m_functionName: + m_description: + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bacteria.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bacteria.asset.meta new file mode 100644 index 0000000..3cd0009 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bacteria.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c4b8e21d0aca1b04d843e80ebaf2ba67 +timeCreated: 1586867844 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Precompute.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Precompute.asset new file mode 100644 index 0000000..c07e0c1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Precompute.asset @@ -0,0 +1,57 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Bicubic Precompute + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18600\n0;537;1729;822;2496.342;532.7923;2.001278;True;False\nNode;AmplifyShaderEditor.FunctionInput;5;-931.3976,161.7528;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;55;-937.6257,292.313;Inherit;False;Texel + Size;4;1;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.CustomExpressionNode;2;-712.9393,184.7253;Inherit;False;UV + = UV * TexelSize.zw - 0.5@$float2 f = frac( UV )@$UV -= f@$$float4 xn = float4( + 1.0, 2.0, 3.0, 4.0 ) - f.xxxx@$float4 yn = float4( 1.0, 2.0, 3.0, 4.0 ) - f.yyyy@$$float4 + xs = xn * xn * xn@$float4 ys = yn * yn * yn@$$float3 xv = float3( xs.x, xs.y - + 4.0 * xs.x, xs.z - 4.0 * xs.y + 6.0 * xs.x )@$float3 yv = float3( ys.x, ys.y - + 4.0 * ys.x, ys.z - 4.0 * ys.y + 6.0 * ys.x )@$float4 xc = float4( xv.xyz, 6.0 + - xv.x - xv.y - xv.z )@$float4 yc = float4( yv.xyz, 6.0 - yv.x - yv.y - yv.z )@$$float4 + c = float4( UV.x - 0.5, UV.x + 1.5, UV.y - 0.5, UV.y + 1.5 )@$float4 s = float4( + xc.x + xc.y, xc.z + xc.w, yc.x + yc.y, yc.z + yc.w )@$$float w0 = s.x / ( s.x + + s.y )@$float w1 = s.z / ( s.z + s.w )@$$Offsets = ( c + float4( xc.y, xc.w, + yc.y, yc.w ) / s ) * TexelSize.xyxy@$Weights = float2( w0, w1 )@$;7;False;4;True;UV;FLOAT2;0,0;In;;Float;False;True;TexelSize;FLOAT4;0,0,0,0;In;;Inherit;False;True;Offsets;FLOAT4;0,0,0,0;Out;;Float;False;True;Weights;FLOAT2;0,0;Out;;Float;False;Stochastic + Tiling;False;False;0;5;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT4;0,0,0,0;False;3;FLOAT4;0,0,0,0;False;4;FLOAT2;0,0;False;3;FLOAT;0;FLOAT4;4;FLOAT2;5\nNode;AmplifyShaderEditor.FunctionOutput;34;-379.6704,177.7769;Inherit;False;True;-1;Offsets;0;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionOutput;54;-378.9186,285.9598;Inherit;False;False;-1;Weights;1;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nWireConnection;2;1;5;0\nWireConnection;2;2;55;0\nWireConnection;34;0;2;4\nWireConnection;54;0;2;5\nASEEND*/\n//CHKSM=83289324BA5D4E43B3BB2E090095EB3689FE9CE1" + m_functionName: + m_description: 'Precomputation step (1 of 2) for bicubic sampling. + + + IMPORTANT + + This node only precomputes data that is fed into the "Bicubic Sample" nodes using + Fetch sampling mode. All textures sharing the same precomputation step must also + share the same size and UV coordinates. ' + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 1 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 12 + m_customNodeCategory: Rust + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Precompute.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Precompute.asset.meta new file mode 100644 index 0000000..1ce087c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Precompute.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 818835145cc522e4da1f9915d8b8a984 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Sample.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Sample.asset new file mode 100644 index 0000000..8b46b58 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Sample.asset @@ -0,0 +1,97 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Bicubic Sample + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18600\n0;537;1729;822;-467.7644;465.2727;1.320468;True;False\nNode;AmplifyShaderEditor.CommentaryNode;201;-1043.748,1734.264;Inherit;False;2226.074;1089.492;;25;205;187;192;188;204;203;202;176;196;195;194;193;191;190;189;186;185;184;183;182;181;180;179;178;177;Fetch + 2D;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;130;-1074.157,-571.3032;Inherit;False;2248.869;991.9108;;28;126;131;40;4;44;45;120;124;122;121;119;118;2;123;125;127;66;128;43;6;7;46;68;67;129;167;168;169;2D;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;71;1388.118,-555.2822;Inherit;False;1546.347;970.757;;15;84;82;85;83;86;72;80;76;74;88;81;79;73;87;78;Outputs;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;89;-2721.481,-555.8615;Inherit;False;1378.169;964.4158;;17;197;199;94;97;198;105;96;200;99;102;98;92;91;93;101;103;100;Inputs;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;132;-1059.981,593.8146;Inherit;False;2248.869;991.9108;;33;157;156;155;154;153;152;151;150;149;148;147;146;145;144;142;141;140;139;138;137;136;135;134;133;158;159;160;161;162;163;164;165;166;2D + Array;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;206;-1034.245,2999.804;Inherit;False;2216.924;1095.592;;32;231;230;229;228;227;226;225;224;223;222;221;220;219;218;217;216;215;214;213;212;211;210;209;208;207;232;233;234;235;236;237;238;Fetch + 2D Array;1,1,1,1;0;0\nNode;AmplifyShaderEditor.WireNode;218;-269.7177,3218.184;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;217;-272.4329,3188.314;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;191;-311.0844,1978.569;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SwizzleNode;214;-540.3856,3483.624;Inherit;False;FLOAT2;1;2;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SwizzleNode;213;-540.3856,3663.624;Inherit;False;FLOAT2;1;3;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;219;-287.368,3242.624;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.GetLocalVarNode;227;-924.5254,3528.712;Inherit;False;197;Input_FetchOffsets;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.WireNode;189;-296.1492,1924.26;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;233;-190.7924,3352.336;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;127;-95.72092,292.4236;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;226;517.788,3744.942;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;234;-201.4768,3473.426;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;180;-110.8541,2465.857;Inherit;True;Property;_TextureSample11;Texture + Sample 11;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.LerpOp;181;318.6297,2397.643;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.LerpOp;224;728.2203,3446.359;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.LerpOp;176;704.5042,2182.305;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SamplerNode;207;-90.20921,3317.818;Inherit;True;Property;_TextureSample2;Texture + Sample 2;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;177;-113.9256,2053.764;Inherit;True;Property;_TextureSample8;Texture + Sample 8;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;158;-740.9282,796.8607;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.SwizzleNode;216;-542.3856,3574.624;Inherit;False;FLOAT2;0;3;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.CustomExpressionNode;145;-657.9156,1104.576;Inherit;False;{$ + UV = UV * TexelSize.zw - 0.5@$ float2 f = frac( UV )@$ UV -= f@$$ float4 + xn = float4( 1.0, 2.0, 3.0, 4.0 ) - f.xxxx@$ float4 yn = float4( 1.0, 2.0, + 3.0, 4.0 ) - f.yyyy@$$ float4 xs = xn * xn * xn@$ float4 ys = yn * yn * + yn@$$ float3 xv = float3( xs.x, xs.y - 4.0 * xs.x, xs.z - 4.0 * xs.y + 6.0 + * xs.x )@$ float3 yv = float3( ys.x, ys.y - 4.0 * ys.x, ys.z - 4.0 * ys.y + + 6.0 * ys.x )@$ float4 xc = float4( xv.xyz, 6.0 - xv.x - xv.y - xv.z )@$ float4 + yc = float4( yv.xyz, 6.0 - yv.x - yv.y - yv.z )@$$ float4 c = float4( UV.x + - 0.5, UV.x + 1.5, UV.y - 0.5, UV.y + 1.5 )@$ float4 s = float4( xc.x + xc.y, + xc.z + xc.w, yc.x + yc.y, yc.z + yc.w )@$$ float4 off = ( c + float4( xc.y, + xc.w, yc.y, yc.w ) / s ) * TexelSize.xyxy@$$ UV0 = off.xz@$ UV1 = off.yz@$ + \ UV2 = off.xw@$ UV3 = off.yw@$ W0 = s.x / ( s.x + s.y )@$ W1 = s.z / + ( s.z + s.w )@$};7;False;8;True;UV;FLOAT2;0,0;In;;Float;False;True;TexelSize;FLOAT4;0,0,0,0;In;;Inherit;False;True;UV0;FLOAT2;0,0;Out;;Float;False;True;UV1;FLOAT2;0,0;Out;;Float;False;True;UV2;FLOAT2;0,0;Out;;Float;False;True;UV3;FLOAT2;0,0;Out;;Inherit;False;True;W0;FLOAT;0;Out;;Inherit;False;True;W1;FLOAT;0;Out;;Inherit;False;Bicubic + Prepare;False;False;0;9;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT4;0,0,0,0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT2;0,0;False;6;FLOAT2;0,0;False;7;FLOAT;0;False;8;FLOAT;0;False;7;FLOAT;0;FLOAT2;4;FLOAT2;5;FLOAT2;6;FLOAT2;7;FLOAT;8;FLOAT;9\nNode;AmplifyShaderEditor.WireNode;190;-293.4339,1954.13;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SamplerNode;179;-113.5429,2257.507;Inherit;True;Property;_TextureSample10;Texture + Sample 10;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.RegisterLocalVarNode;105;-1643.842,35.19871;Inherit;False;Input_SS;-1;True;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.LerpOp;45;351.319,-373.6947;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;203;494.0718,2480.887;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;220;-370.9889,3317.928;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.LerpOp;211;342.3458,3661.698;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SamplerNode;209;-89.82652,3521.562;Inherit;True;Property;_TextureSample16;Texture + Sample 16;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;193;-415.6305,2008.959;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;159;-334.8512,736.2561;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.SamplerNode;208;-85.47648,3112.596;Inherit;True;Property;_TextureSample0;Texture + Sample 0;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.BreakToComponentsNode;230;-19.01893,3942.506;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.LerpOp;182;314.7018,1978.976;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SwizzleNode;185;-570.4064,2125.433;Inherit;False;FLOAT2;0;2;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;161;-309.4034,811.0089;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.SwizzleNode;186;-566.1018,2310.57;Inherit;False;FLOAT2;0;3;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;202;878.0947,2176.097;Inherit;False;Output_Fetch2D;-1;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionInput;198;-2580.608,143.3581;Inherit;False;Offsets;4;4;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;187;-42.73524,2678.451;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FunctionInput;199;-2581.965,245.189;Inherit;False;Weights;2;5;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSubtitle;88;1783.674,101.3291;Inherit;False;Fetch + 2D Array (2/2);1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionSubtitle;76;1794.327,-169.9491;Inherit;False;2D + Array;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;74;2490.12,0.7858257;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FunctionSubtitle;80;1803.251,-313.9693;Inherit;False;2D;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;87;1442.031,99.73958;Inherit;False;225;Output_Fetch2DArray;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;78;1496.474,-317.2461;Inherit;False;131;Output_2D;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;225;901.8109,3440.151;Inherit;False;Output_Fetch2DArray;-1;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;160;-326.8987,769.6562;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.GetLocalVarNode;231;-377.444,3934.225;Inherit;False;200;Input_FetchWeights;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;235;-357.6844,3222.431;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSubtitle;81;1787.2,-40.47982;Inherit;False;Fetch + 2D (2/2);1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.CustomExpressionNode;2;-672.0914,-60.54211;Inherit;False;{$ + UV = UV * TexelSize.zw - 0.5@$ float2 f = frac( UV )@$ UV -= f@$$ float4 + xn = float4( 1.0, 2.0, 3.0, 4.0 ) - f.xxxx@$ float4 yn = float4( 1.0, 2.0, + 3.0, 4.0 ) - f.yyyy@$$ float4 xs = xn * xn * xn@$ float4 ys = yn * yn * + yn@$$ float3 xv = float3( xs.x, xs.y - 4.0 * xs.x, xs.z - 4.0 * xs.y + 6.0 + * xs.x )@$ float3 yv = float3( ys.x, ys.y - 4.0 * ys.x, ys.z - 4.0 * ys.y + + 6.0 * ys.x )@$ float4 xc = float4( xv.xyz, 6.0 - xv.x - xv.y - xv.z )@$ float4 + yc = float4( yv.xyz, 6.0 - yv.x - yv.y - yv.z )@$$ float4 c = float4( UV.x + - 0.5, UV.x + 1.5, UV.y - 0.5, UV.y + 1.5 )@$ float4 s = float4( xc.x + xc.y, + xc.z + xc.w, yc.x + yc.y, yc.z + yc.w )@$$ float4 off = ( c + float4( xc.y, + xc.w, yc.y, yc.w ) / s ) * TexelSize.xyxy@$$ UV0 = off.xz@$ UV1 = off.yz@$ + \ UV2 = off.xw@$ UV3 = off.yw@$ W0 = s.x / ( s.x + s.y )@$ W1 = s.z / + ( s.z + s.w )@$};7;False;8;True;UV;FLOAT2;0,0;In;;Float;False;True;TexelSize;FLOAT4;0,0,0,0;In;;Inherit;False;True;UV0;FLOAT2;0,0;Out;;Float;False;True;UV1;FLOAT2;0,0;Out;;Float;False;True;UV2;FLOAT2;0,0;Out;;Float;False;True;UV3;FLOAT2;0,0;Out;;Inherit;False;True;W0;FLOAT;0;Out;;Inherit;False;True;W1;FLOAT;0;Out;;Inherit;False;Bicubic + Prepare;False;False;0;9;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT4;0,0,0,0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT2;0,0;False;6;FLOAT2;0,0;False;7;FLOAT;0;False;8;FLOAT;0;False;7;FLOAT;0;FLOAT2;4;FLOAT2;5;FLOAT2;6;FLOAT2;7;FLOAT;8;FLOAT;9\nNode;AmplifyShaderEditor.SwizzleNode;183;-564.1018,2399.57;Inherit;False;FLOAT2;1;3;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;118;-955.8895,-151.2794;Inherit;False;100;Input_UV;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SwizzleNode;215;-546.6902,3389.487;Inherit;False;FLOAT2;0;2;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;196;-399.3375,2086.351;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;195;-396.6223,2064.626;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;238;-353.1872,3276.79;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;204;-948.2417,2264.657;Inherit;False;197;Input_FetchOffsets;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.WireNode;194;-402.0527,2038.829;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SwizzleNode;184;-564.1018,2219.57;Inherit;False;FLOAT2;1;2;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.LerpOp;212;338.418,3243.03;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;197;-1637.331,141.5877;Inherit;False;Input_FetchOffsets;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.WireNode;128;248.1051,292.4236;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;192;-647.9,1997.286;Inherit;False;105;Input_SS;1;0;OBJECT;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.GetLocalVarNode;188;-663.9133,1852.121;Inherit;False;101;Input_Texture;1;0;OBJECT;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SamplerNode;6;-77.30836,-298.9066;Inherit;True;Property;_TextureSample1;Texture + Sample 1;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;94;-2587.118,36.96911;Inherit;False;SS;13;6;False;1;0;SAMPLERSTATE;0;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;156;956.144,991.3506;Inherit;False;Output_2DArray;-1;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SamplerNode;178;-109.1929,1848.542;Inherit;True;Property;_TextureSample9;Texture + Sample 9;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;97;-1783.926,-341.5729;Inherit;False;UV;2;3;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;139;-60.06113,1278.305;Inherit;True;Property;_TextureSample6;Texture + Sample 6;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.LerpOp;152;365.4948,791.4232;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.TexelSizeNode;155;-968.2141,1150.107;Inherit;False;-1;1;0;SAMPLER2DARRAY;;False;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;91;-2601.69,-153.4011;Inherit;False;Texture + Array;12;1;False;1;0;SAMPLER2DARRAY;0;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;68;-88.63429,348.3121;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;92;-2128.13,-340.859;Inherit;False;Option;False;0;4;-1;2D;2D + Array;Triplanar;Triplanar Array;Instance;72;9;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;FLOAT2;0,0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;157;-993.7668,956.1034;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;142;-81.54513,1457.542;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;162;-670.3486,817.4661;Inherit;False;98;Input_Index;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;151;-406.4995,963.3865;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;163;-384.1563,834.8665;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;79;1470.797,-174.3436;Inherit;False;156;Output_2DArray;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.LerpOp;44;750.9617,-170.366;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;119;-652.9467,-253.246;Inherit;False;105;Input_SS;1;0;OBJECT;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;134;-77.88247,1485.869;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;210;-87.13773,3729.912;Inherit;True;Property;_TextureSample1;Texture + Sample 1;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.GetLocalVarNode;124;-967.2612,-508.0312;Inherit;False;101;Input_Texture;1;0;OBJECT;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;148;-406.0995,985.9865;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;140;262.2807,1457.542;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;167;-339.9795,-424.4737;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.FunctionInput;93;-2533.613,-48.14872;Inherit;False;Index;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;138;-63.13266,866.2112;Inherit;True;Property;_TextureSample5;Texture + Sample 5;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.TextureCoordinatesNode;103;-2395.848,-231.0578;Inherit;False;0;-1;2;3;2;SAMPLER2DARRAY;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.RegisterLocalVarNode;101;-1648.95,-438.0066;Inherit;False;Input_Texture;-1;True;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.GetLocalVarNode;146;-941.7139,1013.838;Inherit;False;100;Input_UV;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.LerpOp;136;369.4226,1210.091;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;100;-1640.919,-341.9367;Inherit;False;Input_UV;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.LerpOp;46;355.2469,44.97323;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;144;-404.5566,1029.196;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SamplerNode;154;-58.39999,660.9893;Inherit;True;Property;_TextureSample7;Texture + Sample 7;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;43;-74.23686,113.1873;Inherit;True;Property;_TextureSample4;Texture + Sample 4;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.TexelSizeNode;40;-982.3898,-15.01096;Inherit;False;-1;1;0;SAMPLER2D;;False;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;137;-62.74997,1069.955;Inherit;True;Property;_TextureSample3;Texture + Sample 3;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;166;-387.3372,888.9426;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;149;-403.2565,1011.686;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;237;-354.9358,3257.045;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;141;239.3885,1414.408;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;66;225.2129,249.2902;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;99;-2573.558,-440.557;Inherit;False;Texture;9;0;False;1;0;SAMPLER2D;0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;169;-326.6317,-354.7689;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;126;-1003.882,-231.9052;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;131;941.968,-173.7672;Inherit;False;Output_2D;-1;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;96;-1649.888,-153.7866;Inherit;False;Input_TextureArray;-1;True;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;164;-379.3847,853.952;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;229;-572.9658,3296.807;Inherit;False;105;Input_SS;1;0;OBJECT;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SamplerNode;7;-76.92567,-95.16291;Inherit;True;Property;_TextureSample2;Texture + Sample 2;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.GetLocalVarNode;232;-581.6864,3211.935;Inherit;False;98;Input_Index;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;129;299.7782,302.3605;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;133;313.9539,1467.479;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;4;-72.57567,-504.1286;Inherit;True;Property;_TextureSample0;Texture + Sample 0;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;123;-399.6465,-182.0461;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;165;-384.1563,873.0378;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;120;-392.0465,-249.4461;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.LerpOp;153;765.1377,994.7519;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;150;-921.8599,664.8158;Inherit;False;96;Input_TextureArray;1;0;OBJECT;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;125;-792.2485,-371.2797;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;121;-391.6465,-226.8461;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;102;-2396.089,-365.7368;Inherit;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;223;-372.0595,3381.453;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;236;-352.8128,3242.612;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;221;-370.7801,3337.677;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.GetLocalVarNode;228;-617.197,3114.176;Inherit;False;96;Input_TextureArray;1;0;OBJECT;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;168;-329.5981,-387.3966;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;67;-92.05823,320.7514;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;200;-1638.688,242.1192;Inherit;False;Input_FetchWeights;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitch;72;2095.89,-139.1704;Inherit;False;Sample + Mode;False;0;4;-1;2D;2D Array;Fetch 2D;Fetch 2D Array;Object;-1;9;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;3;COLOR;0,0,0,0;False;4;COLOR;0,0,0,0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;222;-367.2213,3359.789;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.GetLocalVarNode;205;-401.1604,2671.893;Inherit;False;200;Input_FetchWeights;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;147;-661.0379,957.996;Inherit;False;105;Input_SS;1;0;OBJECT;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;98;-1643.479,-47.99601;Inherit;False;Input_Index;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;73;1469.538,-43.06931;Inherit;False;202;Output_Fetch2D;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;122;-398.3464,-201.1461;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;135;-74.45852,1513.43;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;85;2768.492,1.857527;Inherit;False;False;-1;G;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;82;2771.692,77.05763;Inherit;False;True;-1;B;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;83;2773.292,155.4575;Inherit;False;False;-1;A;4;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;84;2768.492,-68.54239;Inherit;False;False;-1;R;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;86;2768.33,-138.4119;Inherit;False;False;-1;RGBA;0;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nWireConnection;218;0;228;0\nWireConnection;217;0;228;0\nWireConnection;191;0;188;0\nWireConnection;214;0;227;0\nWireConnection;213;0;227;0\nWireConnection;219;0;228;0\nWireConnection;189;0;188;0\nWireConnection;233;0;215;0\nWireConnection;127;0;2;8\nWireConnection;226;0;230;1\nWireConnection;234;0;214;0\nWireConnection;180;0;191;0\nWireConnection;180;1;183;0\nWireConnection;180;7;196;0\nWireConnection;181;0;180;0\nWireConnection;181;1;179;0\nWireConnection;181;2;187;0\nWireConnection;224;0;211;0\nWireConnection;224;1;212;0\nWireConnection;224;2;226;0\nWireConnection;176;0;181;0\nWireConnection;176;1;182;0\nWireConnection;176;2;203;0\nWireConnection;207;0;217;0\nWireConnection;207;1;234;0\nWireConnection;207;6;236;0\nWireConnection;207;7;221;0\nWireConnection;177;0;189;0\nWireConnection;177;1;184;0\nWireConnection;177;7;194;0\nWireConnection;158;0;150;0\nWireConnection;216;0;227;0\nWireConnection;145;1;146;0\nWireConnection;145;2;155;0\nWireConnection;190;0;188;0\nWireConnection;179;0;190;0\nWireConnection;179;1;186;0\nWireConnection;179;7;195;0\nWireConnection;105;0;94;0\nWireConnection;45;0;6;0\nWireConnection;45;1;4;0\nWireConnection;45;2;66;0\nWireConnection;203;0;187;1\nWireConnection;220;0;229;0\nWireConnection;211;0;210;0\nWireConnection;211;1;209;0\nWireConnection;211;2;230;0\nWireConnection;209;0;218;0\nWireConnection;209;1;216;0\nWireConnection;209;6;237;0\nWireConnection;209;7;222;0\nWireConnection;193;0;192;0\nWireConnection;159;0;150;0\nWireConnection;208;0;228;0\nWireConnection;208;1;233;0\nWireConnection;208;6;235;0\nWireConnection;208;7;220;0\nWireConnection;230;0;231;0\nWireConnection;182;0;177;0\nWireConnection;182;1;178;0\nWireConnection;182;2;187;0\nWireConnection;185;0;204;0\nWireConnection;161;0;150;0\nWireConnection;186;0;204;0\nWireConnection;202;0;176;0\nWireConnection;187;0;205;0\nWireConnection;88;0;87;0\nWireConnection;76;0;79;0\nWireConnection;74;0;72;0\nWireConnection;80;0;78;0\nWireConnection;225;0;224;0\nWireConnection;160;0;150;0\nWireConnection;235;0;232;0\nWireConnection;81;0;73;0\nWireConnection;2;1;118;0\nWireConnection;2;2;40;0\nWireConnection;183;0;204;0\nWireConnection;215;0;227;0\nWireConnection;196;0;192;0\nWireConnection;195;0;192;0\nWireConnection;238;0;232;0\nWireConnection;194;0;192;0\nWireConnection;184;0;204;0\nWireConnection;212;0;207;0\nWireConnection;212;1;208;0\nWireConnection;212;2;230;0\nWireConnection;197;0;198;0\nWireConnection;128;0;67;0\nWireConnection;6;0;167;0\nWireConnection;6;1;2;5\nWireConnection;6;7;121;0\nWireConnection;156;0;153;0\nWireConnection;178;0;188;0\nWireConnection;178;1;185;0\nWireConnection;178;7;193;0\nWireConnection;97;0;92;0\nWireConnection;139;0;161;0\nWireConnection;139;1;145;7\nWireConnection;139;6;166;0\nWireConnection;139;7;144;0\nWireConnection;152;0;138;0\nWireConnection;152;1;154;0\nWireConnection;152;2;141;0\nWireConnection;155;0;157;0\nWireConnection;68;0;2;9\nWireConnection;92;0;102;0\nWireConnection;92;1;103;0\nWireConnection;92;2;102;0\nWireConnection;92;3;103;0\nWireConnection;157;0;158;0\nWireConnection;142;0;145;8\nWireConnection;151;0;147;0\nWireConnection;163;0;162;0\nWireConnection;44;0;46;0\nWireConnection;44;1;45;0\nWireConnection;44;2;129;0\nWireConnection;134;0;145;8\nWireConnection;210;0;219;0\nWireConnection;210;1;213;0\nWireConnection;210;6;238;0\nWireConnection;210;7;223;0\nWireConnection;148;0;147;0\nWireConnection;140;0;134;0\nWireConnection;167;0;124;0\nWireConnection;138;0;159;0\nWireConnection;138;1;145;5\nWireConnection;138;6;164;0\nWireConnection;138;7;148;0\nWireConnection;103;2;91;0\nWireConnection;101;0;99;0\nWireConnection;136;0;139;0\nWireConnection;136;1;137;0\nWireConnection;136;2;140;0\nWireConnection;100;0;97;0\nWireConnection;46;0;43;0\nWireConnection;46;1;7;0\nWireConnection;46;2;128;0\nWireConnection;144;0;147;0\nWireConnection;154;0;150;0\nWireConnection;154;1;145;4\nWireConnection;154;6;163;0\nWireConnection;154;7;151;0\nWireConnection;43;0;169;0\nWireConnection;43;1;2;7\nWireConnection;43;7;123;0\nWireConnection;40;0;126;0\nWireConnection;137;0;160;0\nWireConnection;137;1;145;6\nWireConnection;137;6;165;0\nWireConnection;137;7;149;0\nWireConnection;166;0;162;0\nWireConnection;149;0;147;0\nWireConnection;237;0;232;0\nWireConnection;141;0;142;0\nWireConnection;66;0;127;0\nWireConnection;169;0;124;0\nWireConnection;126;0;125;0\nWireConnection;131;0;44;0\nWireConnection;96;0;91;0\nWireConnection;164;0;162;0\nWireConnection;7;0;168;0\nWireConnection;7;1;2;6\nWireConnection;7;7;122;0\nWireConnection;129;0;68;0\nWireConnection;133;0;135;0\nWireConnection;4;0;124;0\nWireConnection;4;1;2;4\nWireConnection;4;7;120;0\nWireConnection;123;0;119;0\nWireConnection;165;0;162;0\nWireConnection;120;0;119;0\nWireConnection;153;0;136;0\nWireConnection;153;1;152;0\nWireConnection;153;2;133;0\nWireConnection;125;0;124;0\nWireConnection;121;0;119;0\nWireConnection;102;2;99;0\nWireConnection;223;0;229;0\nWireConnection;236;0;232;0\nWireConnection;221;0;229;0\nWireConnection;168;0;124;0\nWireConnection;67;0;2;8\nWireConnection;200;0;199;0\nWireConnection;72;0;80;0\nWireConnection;72;1;76;0\nWireConnection;72;2;81;0\nWireConnection;72;3;88;0\nWireConnection;222;0;229;0\nWireConnection;98;0;93;0\nWireConnection;122;0;119;0\nWireConnection;135;0;145;9\nWireConnection;85;0;74;1\nWireConnection;82;0;74;2\nWireConnection;83;0;74;3\nWireConnection;84;0;74;0\nWireConnection;86;0;72;0\nASEEND*/\n//CHKSM=92DC859C84122553D9A506AB24FD12161823607A" + m_functionName: + m_description: 'Fast 4-Tap bicubic texture sampling. Smoother than regular texture + sampling at a slightly higher performance cost. + + + IMPORTANT + + Fetch modes are faster sampling paths for multiple textures that share the same + size and UVs. For these modes, the "Bicubic Precompute" node must be used to feed + the necessary data.' + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 1 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 12 + m_customNodeCategory: Rust + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Sample.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Sample.asset.meta new file mode 100644 index 0000000..eaf0052 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bicubic Sample.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ce0e14d5ad5eac645b2e5892ab3506ff +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bidirectional Parallax Mapping.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bidirectional Parallax Mapping.asset new file mode 100644 index 0000000..0c655e0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bidirectional Parallax Mapping.asset @@ -0,0 +1,49 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Bidirectional Parallax Mapping + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18811\n-2078;98;1539;885;2195.799;594.0439;1.72294;False;False\nNode;AmplifyShaderEditor.FunctionInput;32;-1173.847,777.5085;Inherit;False;SS;13;1;False;1;0;SAMPLERSTATE;0;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.FunctionInput;11;-1895.168,-38.58259;Inherit;False;Heightmap + Tex;9;0;False;1;0;SAMPLER2D;0.0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SamplerStateNode;33;-1646.789,729.798;Inherit;False;0;0;0;1;-1;1;0;SAMPLER2D;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.CustomExpressionNode;35;-693.9971,-314.8272;Float;False;UVs + += plane * scale * refp * ite@$for(int i = 0@ i < ite@ i++)${$\tUVs += (tex2D(tex, + UVs).g - 1) * plane * scale@$}$return UVs@;2;False;6;True;tex;SAMPLER2D;0.0;In;;Float;False;True;UVs;FLOAT2;0,0;In;;Float;False;True;plane;FLOAT2;0,0;In;;Float;False;True;ite;INT;0;In;;Float;False;True;refp;FLOAT;0;In;;Float;False;True;scale;FLOAT;0;In;;Float;False;IterativeParallaxLegacy;True;False;0;6;0;SAMPLER2D;0.0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;INT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.CustomExpressionNode;27;-727.9086,-54.66006;Float;False;UVs + += plane * scale * refp * ite@$for(int i = 0@ i < ite@ i++)${$#if ASE_USING_SAMPLING_MACROS$\tUVs + += (SAMPLE_TEXTURE2D( tex, customSS, UVs ).g - 1) * plane * scale@$#else$\tUVs + += (tex2D(tex, UVs).g - 1) * plane * scale@$#endif$}$return UVs@;2;False;7;True;tex;SAMPLER2D;0.0;In;;Float;False;True;UVs;FLOAT2;0,0;In;;Float;False;True;plane;FLOAT2;0,0;In;;Float;False;True;ite;INT;0;In;;Float;False;True;refp;FLOAT;0;In;;Float;False;True;scale;FLOAT;0;In;;Float;False;True;customSS;SAMPLERSTATE;;In;;Inherit;False;IterativeParallax;True;False;0;7;0;SAMPLER2D;0.0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;INT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;SAMPLERSTATE;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitch;34;-372.7607,78.24609;Inherit;False;Unity + 2018 or Higher;True;1;2;-1;In 0;In 1;Object;-1;9;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;9;-1181.702,667.7348;Inherit;False;Parallax + Scale;1;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;22;-1295.124,60.47374;Inherit;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.DynamicAppendNode;2;-1371.897,195.5105;Inherit;False;FLOAT2;4;0;FLOAT2;0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;4;-1166.738,231.9931;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;25;-1196.823,405.4736;Inherit;False;Iterations;0;4;False;1;0;INT;1;False;1;INT;0\nNode;AmplifyShaderEditor.FunctionInput;10;-1187.709,555.5891;Inherit;False;Reference + Plane;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ViewDirInputsCoordNode;1;-1618.191,180.3121;Float;False;Tangent;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionOutput;0;0.5848999,-19.6864;Inherit;False;True;-1;Out;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nWireConnection;32;0;33;0\nWireConnection;33;0;11;0\nWireConnection;35;0;11;0\nWireConnection;35;1;22;0\nWireConnection;35;2;4;0\nWireConnection;35;3;25;0\nWireConnection;35;4;10;0\nWireConnection;35;5;9;0\nWireConnection;27;0;11;0\nWireConnection;27;1;22;0\nWireConnection;27;2;4;0\nWireConnection;27;3;25;0\nWireConnection;27;4;10;0\nWireConnection;27;5;9;0\nWireConnection;27;6;32;0\nWireConnection;34;0;35;0\nWireConnection;34;1;27;0\nWireConnection;22;2;11;0\nWireConnection;2;0;1;0\nWireConnection;4;0;2;0\nWireConnection;4;1;1;3\nWireConnection;0;0;34;0\nASEEND*/\n//CHKSM=6EE46B6FFD57D58A4296B6A03938C323EF31A8F5" + m_functionName: + m_description: Creates a parallax mapping effect with user defined iterations and + reference plane. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_customEdited: 0 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 15 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bidirectional Parallax Mapping.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bidirectional Parallax Mapping.asset.meta new file mode 100644 index 0000000..bfca124 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bidirectional Parallax Mapping.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ab457a4ccb6d8f745b63ef50e1417242 +timeCreated: 1507301651 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Half Vector.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Half Vector.asset new file mode 100644 index 0000000..567173c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Half Vector.asset @@ -0,0 +1,23 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Blinn-Phong Half Vector + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=13705\n487;506;979;512;774.2847;195.955;1;False;False\nNode;AmplifyShaderEditor.WorldSpaceLightDirHlpNode;2;-640,96;Float;False;1;0;FLOAT;0.0;False;4;FLOAT3;FLOAT;FLOAT;FLOAT\nNode;AmplifyShaderEditor.ViewDirInputsCoordNode;1;-592,-64;Float;False;World;0;4;FLOAT3;FLOAT;FLOAT;FLOAT\nNode;AmplifyShaderEditor.SimpleAddOpNode;3;-336,0;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0.0,0,0;False;1;FLOAT3\nNode;AmplifyShaderEditor.NormalizeNode;4;-176,0;Float;False;1;0;FLOAT3;0,0,0,0;False;1;FLOAT3\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Float;False;True;XYZ;0;1;0;FLOAT3;0,0,0;False;0\nWireConnection;3;0;1;0\nWireConnection;3;1;2;0\nWireConnection;4;0;3;0\nWireConnection;0;0;4;0\nASEEND*/\n//CHKSM=CDF922191A60D2395104E4F539CAFDF78289C070" + m_functionName: + m_description: Calculates the halfway vector between view direction and light direction + in world space. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_nodeCategory: 11 + m_customNodeCategory: Custom Lighting diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Half Vector.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Half Vector.asset.meta new file mode 100644 index 0000000..ddcbca9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Half Vector.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 91a149ac9d615be429126c95e20753ce +timeCreated: 1509361778 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Light.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Light.asset new file mode 100644 index 0000000..d5779fb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Light.asset @@ -0,0 +1,41 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Blinn-Phong Light + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=16306\n716;346;1066;687;501.1261;294.544;1;False;False\nNode;AmplifyShaderEditor.ComponentMaskNode;29;48,-496;Float;False;True;True;True;False;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RangedFloatNode;22;-352,-224;Float;False;Property;_Shininess;Shininess;2;0;Create;True;0;0;False;0;0.1;0;0.01;1;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;37;609.1547,-34.90417;Float;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT3;0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;59;-336,-320;Float;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionNode;51;-832,-288;Float;False;Blinn-Phong + Half Vector;-1;;2;91a149ac9d615be429126c95e20753ce;0;0;1;FLOAT3;0\nNode;AmplifyShaderEditor.ComponentMaskNode;44;48,-416;Float;False;False;False;False;True;1;0;COLOR;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ColorNode;24;-368,-496;Float;False;Property;_SpecularColor;Specular + Color;1;0;Create;True;0;0;False;0;0.3921569,0.3921569,0.3921569,1;0,0,0,0;False;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.PowerNode;21;112,-320;Float;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.IndirectDiffuseLighting;34;337.1547,77.09583;Float;False;World;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;36;417.1547,-34.90417;Float;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.LightColorNode;17;14.82559,-84.1315;Float;False;0;3;COLOR;0;FLOAT3;1;FLOAT;2\nNode;AmplifyShaderEditor.LightAttenuation;10;-27.48053,45.50479;Float;False;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;38;1009.155,-34.90417;Float;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT3;0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.ComponentMaskNode;47;769.1547,93.09583;Float;False;True;True;True;False;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.ComponentMaskNode;50;769.1547,189.0958;Float;False;False;False;False;True;1;0;COLOR;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;25;801.1547,-274.9042;Float;False;4;4;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.DotProductOpNode;19;-512,-240;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WorldNormalVector;12;-937.117,-98.03006;Float;False;False;1;0;FLOAT3;0,0,0;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.WireNode;67;395.671,-128.7589;Float;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;55;-518.842,331.2534;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.NormalizeNode;64;-729.1198,-98.03006;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.ColorNode;26;353.1547,189.0958;Float;False;Property;_MainColor;Main + Color;0;0;Create;True;0;0;False;0;0.3921569,0.3921569,0.3921569,1;0,0,0,0;False;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMaxOpNode;15;-65.18457,141.2409;Float;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;40;232.9505,-46.9381;Float;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;39;1185.155,-162.9042;Float;False;2;2;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionInput;42;625.1547,189.0958;Float;False;Diffuse;5;0;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionInput;52;-1065.115,-98.03006;Float;False;Normal;3;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;43;-128,-496;Float;False;Specular;5;2;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;60;-48,-256;Float;False;2;2;0;FLOAT;0;False;1;FLOAT;128;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;56;165.1989,329.8424;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WorldSpaceLightDirHlpNode;13;-487.8197,165.9312;Float;False;False;1;0;FLOAT;0;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.Vector3Node;53;-1273.115,-98.03006;Float;False;Constant;_DefaultNormal;DefaultNormal;3;0;Create;True;0;0;False;0;0,0,1;0,0,0;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.DotProductOpNode;14;-210.7447,112.9567;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;1329.155,-162.9042;Float;False;True;RGB;0;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionOutput;57;1329.155,-82.90417;Float;False;True;Alpha;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;29;0;43;0\nWireConnection;37;0;36;0\nWireConnection;37;1;34;0\nWireConnection;59;0;19;0\nWireConnection;44;0;43;0\nWireConnection;21;0;59;0\nWireConnection;21;1;60;0\nWireConnection;34;0;56;0\nWireConnection;36;0;40;0\nWireConnection;36;1;15;0\nWireConnection;38;0;37;0\nWireConnection;38;1;47;0\nWireConnection;47;0;42;0\nWireConnection;50;0;42;0\nWireConnection;25;0;29;0\nWireConnection;25;1;44;0\nWireConnection;25;2;21;0\nWireConnection;25;3;67;0\nWireConnection;19;0;51;0\nWireConnection;19;1;64;0\nWireConnection;12;0;52;0\nWireConnection;67;0;40;0\nWireConnection;55;0;64;0\nWireConnection;64;0;12;0\nWireConnection;15;0;14;0\nWireConnection;40;0;17;0\nWireConnection;40;1;10;0\nWireConnection;39;0;25;0\nWireConnection;39;1;38;0\nWireConnection;42;0;26;0\nWireConnection;52;0;53;0\nWireConnection;43;0;24;0\nWireConnection;60;0;22;0\nWireConnection;56;0;55;0\nWireConnection;14;0;64;0\nWireConnection;14;1;13;0\nWireConnection;0;0;39;0\nWireConnection;57;0;50;0\nASEEND*/\n//CHKSM=57C0C1F3D628A2FE0988ED3E128E1C80E9BEE859" + m_functionName: + m_description: Generates a lighting model using Blinn-Phong reflectance model and + closely resembles Unity legacy shaders. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 5 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Light.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Light.asset.meta new file mode 100644 index 0000000..af90b62 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Blinn-Phong Light.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cf814dba44d007a4e958d2ddd5813da6 +timeCreated: 1510331168 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BlinnPhongLightWrap.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BlinnPhongLightWrap.asset new file mode 100644 index 0000000..5ae1746 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BlinnPhongLightWrap.asset @@ -0,0 +1,48 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: BlinnPhongLightWrap + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=16205\n234;92;1063;705;1563.922;447.6829;2.241337;True;False\nNode;AmplifyShaderEditor.CommentaryNode;82;-868.7166,1513.25;Float;False;615.7619;256.2104;;4;0;73;72;71;Diffuse + + Specular;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;62;-874.5117,944.6415;Float;False;2334.29;521.7126;Comment;20;60;1;69;66;68;67;61;56;55;47;50;53;51;52;49;48;45;46;44;70;Diffuse + Color;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;43;-873.949,406.1891;Float;False;1347.446;439.3573;;11;41;40;42;2;33;34;36;37;39;38;32;Specular + Color;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;31;-871.1387,-356.8812;Float;False;1192.721;289.2242;;7;21;20;18;23;19;4;17;NDotL;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;30;-875.0961,-9.355102;Float;False;977.2441;332.3028;;6;26;29;28;27;77;76;Half + Dir;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;15;-856.0029,-727.2549;Float;False;924;294;;7;3;10;12;13;11;9;14;Gloss;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;16;-866.0001,-1064.568;Float;False;748.5;272;;4;8;7;5;6;Light + Attenuation;1,1,1,1;0;0\nNode;AmplifyShaderEditor.Exp2OpNode;9;-310.0023,-612.2548;Float;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LightColorNode;6;-768.0001,-1014.568;Float;False;0;3;COLOR;0;FLOAT3;1;FLOAT;2\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;61;351.8147,1114.297;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;40;22.70839,527.0504;Float;False;3;3;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;36;-412.9491,536.5466;Float;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;55;193.8148,1072.297;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RangedFloatNode;46;-819.0866,1078.04;Float;False;Constant;_Float3;Float + 3;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;34;-823.949,563.5466;Float;False;23;CurrentNormal;1;0;OBJECT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SwizzleNode;48;-461.0868,1017.04;Float;False;FLOAT3;0;0;0;0;1;0;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;45;-614.0866,1015.04;Float;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;33;-809.7029,474.5466;Float;False;29;HalfDirection;1;0;OBJECT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;44;-824.5117,994.6415;Float;False;Light + Wrapping;1;4;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;41;-314.718,456.1892;Float;False;8;AttenuationColor;1;0;OBJECT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DotProductOpNode;32;-562.3635,499.8815;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;51;-189.0866,1179.04;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;47;-292.0868,1021.04;Float;False;LightWrapVector;-1;True;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;50;-605.0866,1170.04;Float;False;47;LightWrapVector;1;0;OBJECT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.OneMinusNode;49;-358.0868,1176.04;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FogAndAmbientColorsNode;67;339.0064,1220.623;Float;False;UNITY_LIGHTMODEL_AMBIENT;0;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;73;-560,1600;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;72;-832,1664;Float;False;42;specularFinalColor;1;0;OBJECT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;71;-832,1568;Float;False;70;DiffuseColor;1;0;OBJECT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RangedFloatNode;37;-566.9489,632.5466;Float;False;Constant;_Float2;Float + 2;0;0;Create;True;0;0;False;0;0;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;66;790.0066,1122.623;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.Vector3Node;56;-16.18523,1193.297;Float;False;Constant;_Vector1;Vector + 1;0;0;Create;True;0;0;False;0;0,0,0;0,0,0;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.GetLocalVarNode;60;9.172014,1340.574;Float;False;8;AttenuationColor;1;0;OBJECT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;10;-614.0029,-660.2548;Float;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;12;-806.0029,-564.2547;Float;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;10;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;53;-20.54932,1092.818;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;70;1146.801,1151.155;Float;False;DiffuseColor;-1;True;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;42;200.4974,524.5294;Float;False;specularFinalColor;-1;True;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RangedFloatNode;13;-630.0029,-548.2548;Float;False;Constant;_Float1;Float + 1;0;0;Create;True;0;0;False;0;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;14;-182.0024,-628.2548;Float;False;SpecularPower;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SwizzleNode;68;609.0066,1209.623;Float;False;FLOAT3;0;1;2;3;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;7;-576.0001,-950.5679;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;1;736.0968,1302.828;Float;False;Diffuse;3;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;52;-398.0868,1262.04;Float;False;21;NDotL;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;69;976.0066,1143.623;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;11;-454.0023,-612.2548;Float;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.PowerNode;38;-239.3654,550.192;Float;False;2;0;FLOAT;0;False;1;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-234.7179,664.1893;Float;False;Specular;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;39;-516.949,730.5465;Float;False;14;SpecularPower;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WorldSpaceLightPos;76;-854.467,61.70709;Float;False;0;3;FLOAT4;0;FLOAT3;1;FLOAT;2\nNode;AmplifyShaderEditor.NormalizeNode;77;-598.467,61.70709;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WorldNormalVector;19;-521.2433,-309.2914;Float;False;True;1;0;FLOAT3;0,0,1;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.RegisterLocalVarNode;23;-329.2433,-309.2914;Float;False;CurrentNormal;-1;True;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.Vector3Node;17;-857.2433,-309.2914;Float;False;Constant;_Vector0;Vector + 0;0;0;Create;True;0;0;False;0;0,0,1;0,0,0;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionInput;4;-681.2433,-309.2914;Float;False;Normal;3;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;3;-785.0029,-677.2548;Float;False;Gloss;1;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LightAttenuation;5;-816.0001,-886.5679;Float;False;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;8;-400,-966.5679;Float;False;AttenuationColor;-1;True;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WorldSpaceLightDirHlpNode;18;-329.2433,-213.2914;Float;False;False;1;0;FLOAT;0;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.DotProductOpNode;20;-57.24332,-277.2914;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;21;86.75671,-261.2914;Float;False;NDotL;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ViewDirInputsCoordNode;26;-800,160;Float;False;World;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.SimpleAddOpNode;27;-422.467,77.70709;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.NormalizeNode;28;-294.467,77.70709;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;29;-134.467,77.70709;Float;False;HalfDirection;-1;True;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;-416,1616;Float;False;True;Output;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;9;0;11;0\nWireConnection;61;0;55;0\nWireConnection;61;1;60;0\nWireConnection;40;0;41;0\nWireConnection;40;1;38;0\nWireConnection;40;2;2;0\nWireConnection;36;0;32;0\nWireConnection;36;1;37;0\nWireConnection;55;0;53;0\nWireConnection;55;1;56;0\nWireConnection;48;0;45;0\nWireConnection;45;0;44;0\nWireConnection;45;1;46;0\nWireConnection;32;0;33;0\nWireConnection;32;1;34;0\nWireConnection;51;0;49;0\nWireConnection;51;1;52;0\nWireConnection;47;0;48;0\nWireConnection;49;0;50;0\nWireConnection;73;0;71;0\nWireConnection;73;1;72;0\nWireConnection;66;0;61;0\nWireConnection;66;1;68;0\nWireConnection;10;0;3;0\nWireConnection;10;1;12;0\nWireConnection;53;0;47;0\nWireConnection;53;1;51;0\nWireConnection;70;0;69;0\nWireConnection;42;0;40;0\nWireConnection;14;0;9;0\nWireConnection;68;0;67;0\nWireConnection;7;0;6;1\nWireConnection;7;1;5;0\nWireConnection;69;0;66;0\nWireConnection;69;1;1;0\nWireConnection;11;0;10;0\nWireConnection;11;1;13;0\nWireConnection;38;0;36;0\nWireConnection;38;1;39;0\nWireConnection;77;0;76;1\nWireConnection;19;0;4;0\nWireConnection;23;0;19;0\nWireConnection;4;0;17;0\nWireConnection;8;0;7;0\nWireConnection;20;0;23;0\nWireConnection;20;1;18;0\nWireConnection;21;0;20;0\nWireConnection;27;0;77;0\nWireConnection;27;1;26;0\nWireConnection;28;0;27;0\nWireConnection;29;0;28;0\nWireConnection;0;0;73;0\nASEEND*/\n//CHKSM=2875532B381E030A9F10046AE6BB0271C00931BB" + m_functionName: + m_description: + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BlinnPhongLightWrap.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BlinnPhongLightWrap.asset.meta new file mode 100644 index 0000000..ec6b34e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BlinnPhongLightWrap.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 139fed909c1bc1a42a96c42d8cf09006 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BoxMask.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BoxMask.asset new file mode 100644 index 0000000..2de5098 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BoxMask.asset @@ -0,0 +1,27 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: BoxMask + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=14205\n585;92;1335;966;841.4062;390.9513;1;True;False\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;3;-770.7323,-83.37894;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0.0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;7;-359.1361,-15.58681;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.AbsOpNode;6;-536.6868,-59.16749;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;15;268.7505,-15.58675;Float;False;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;12;-99.26636,-15.5865;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;1;-1107.93,-142.7251;Float;False;World + Position;3;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;10;-880.4891,142.5947;Float;False;Size;3;2;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;4;-1091.939,-4.288156;Float;False;Center;3;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;17;37.9352,82.87358;Float;False;Falloff;1;3;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DistanceOpNode;13;36.31915,-15.58687;Float;False;2;0;FLOAT3;0,0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;8;-599.6362,161.9639;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0.5,0.5,0.5;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;461.6318,-16.14097;Float;False;True;Output;0;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nWireConnection;3;0;1;0\nWireConnection;3;1;4;0\nWireConnection;7;0;6;0\nWireConnection;7;1;8;0\nWireConnection;6;0;3;0\nWireConnection;15;0;13;0\nWireConnection;15;1;17;0\nWireConnection;12;0;7;0\nWireConnection;13;0;12;0\nWireConnection;8;0;10;0\nWireConnection;0;0;15;0\nASEEND*/\n//CHKSM=B3B832D729B3AA37648FFC3D368D473533835BDC" + m_functionName: + m_description: Box Mask + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BoxMask.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BoxMask.asset.meta new file mode 100644 index 0000000..ab3c8b1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/BoxMask.asset.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 9dce4093ad5a42b4aa255f0153c4f209 +timeCreated: 1516621733 +licenseType: Store +NativeFormatImporter: + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bricks Pattern.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bricks Pattern.asset new file mode 100644 index 0000000..123cc59 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bricks Pattern.asset @@ -0,0 +1,41 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Bricks Pattern + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1462;-370;1004;726;3880.583;1484.979;4.133047;True;False\nNode;AmplifyShaderEditor.FractNode;23;-1104,-16;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DynamicAppendNode;27;-1296,-80;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;30;-1472,-192;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FloorOpNode;32;-928,-256;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;12;-1760,192;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.BreakToComponentsNode;31;-736,-176;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FunctionInput;17;-960,-160;Inherit;False;Luminance + Range;2;3;False;1;0;FLOAT2;0,1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;29;-1648,-192;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;19;-2464,48;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;15;-2640,176;Inherit;False;Tiling;2;0;False;1;0;FLOAT2;2,4;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;18;-2704,48;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.StepOpNode;28;-1808,-192;Inherit;False;2;0;FLOAT;1;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;26;-2272,-80;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.SimpleRemainderNode;25;-2000,-160;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;16;-1808,-272;Inherit;False;Offset;1;2;False;1;0;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;22;-1504,368;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;14;-832,192;Inherit;False;Size;1;1;False;1;0;FLOAT;0.65;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;4;-672,80;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;6;-928,80;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionNode;2;-448,0;Inherit;False;Rectangle;-1;;1;6b23e0c975270fb4084c354b2c83366a;0;3;1;FLOAT2;0,0;False;2;FLOAT;0.5;False;3;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionNode;24;-448,-256;Inherit;False;Random + Range;-1;;2;7b754edb8aebbfb4a9ace907af661cfc;0;3;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;1;-160,-256;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;5;-672,256;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;9;-1104,288;Inherit;False;2;0;FLOAT;-1;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMinOpNode;20;-1104,384;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SignOpNode;21;-1360,368;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;8;-1104,80;Inherit;False;2;0;FLOAT;1;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;7;-928,288;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;11;-1104,192;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;True;True;-1;Bricks;0;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;3;0,-256;Inherit;True;False;-1;Luminance;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;23;0;27;0\nWireConnection;27;0;30;0\nWireConnection;27;1;26;1\nWireConnection;30;0;29;0\nWireConnection;30;1;26;0\nWireConnection;32;0;27;0\nWireConnection;12;0;15;0\nWireConnection;31;0;17;0\nWireConnection;29;0;16;0\nWireConnection;29;1;28;0\nWireConnection;19;0;18;0\nWireConnection;19;1;15;0\nWireConnection;28;1;25;0\nWireConnection;26;0;19;0\nWireConnection;25;0;26;1\nWireConnection;22;0;12;1\nWireConnection;22;1;12;0\nWireConnection;4;0;6;0\nWireConnection;4;1;14;0\nWireConnection;6;0;8;0\nWireConnection;6;1;11;0\nWireConnection;2;1;23;0\nWireConnection;2;2;4;0\nWireConnection;2;3;5;0\nWireConnection;24;1;32;0\nWireConnection;24;2;31;0\nWireConnection;24;3;31;1\nWireConnection;1;0;24;0\nWireConnection;1;1;2;0\nWireConnection;5;0;14;0\nWireConnection;5;1;7;0\nWireConnection;9;1;12;0\nWireConnection;20;0;21;0\nWireConnection;21;0;22;0\nWireConnection;8;1;12;1\nWireConnection;7;0;9;0\nWireConnection;7;1;20;0\nWireConnection;11;0;21;0\nWireConnection;0;0;2;0\nWireConnection;3;0;1;0\nASEEND*/\n//CHKSM=27789CFA7C579B24211E55A89520C287602B2C4E" + m_functionName: + m_description: Creates a repeated bricks pattern with alternating offsetted lines + of bricks. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bricks Pattern.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bricks Pattern.asset.meta new file mode 100644 index 0000000..a382913 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Bricks Pattern.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7d219d3a79fd53a48987a86fa91d6bac +timeCreated: 1586861586 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Checkerboard.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Checkerboard.asset new file mode 100644 index 0000000..c3a6f65 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Checkerboard.asset @@ -0,0 +1,56 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Checkerboard + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17500\n2092;369;1066;673;519.6959;768.1077;1.3;True;False\nNode;AmplifyShaderEditor.CommentaryNode;18;-1101.678,-1164.645;Inherit;False;1511.133;506.8259;;12;6;1;10;11;12;4;9;13;14;15;16;17;UV + and Derivatives;1,1,1,1;0;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;39;-1068.804,243.1458;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RangedFloatNode;40;-1228.804,307.1458;Inherit;False;Constant;_Float4;Float + 4;0;0;Create;True;0;0;False;0;4;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;32;-1208.804,195.1458;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RangedFloatNode;42;-1068.804,355.1458;Inherit;False;Constant;_Float5;Float + 5;0;0;Create;True;0;0;False;0;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;95.94269,118.7242;Inherit;False;Color + B;5;2;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;37;-1340.804,195.1458;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RangedFloatNode;38;-1532.805,275.1458;Inherit;False;Constant;_Float3;Float + 3;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;66;-60.19727,349.9423;Inherit;False;Constant;_Float9;Float + 9;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.ColorNode;8;-112.0574,118.7242;Inherit;False;Constant;_Color1;Color + 1;0;0;Create;True;0;0;False;0;0.6980392,0.6980392,0.6980392,0;0,0,0,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.RangedFloatNode;50;-829.9077,762.2733;Inherit;False;Constant;_Float6;Float + 6;0;0;Create;True;0;0;False;0;1.1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;68;-56.59735,495.6422;Inherit;False;4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;67;95.94269,422.7241;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ColorNode;7;-112.0574,-73.27585;Inherit;False;Constant;_Color0;Color + 0;0;0;Create;True;0;0;False;0;0.2,0.2,0.2,0;0,0,0,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.BreakToComponentsNode;71;-302.0974,513.8422;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FractNode;33;-1484.805,163.1458;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SqrtOpNode;48;-366.826,795.2014;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;49;-517.6261,801.4014;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;53;-1232.34,860.269;Inherit;False;29;derivativesLength;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;55;-1036.94,854.6689;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.RangedFloatNode;58;-637.4819,548.7932;Inherit;False;Constant;_Float7;Float + 7;0;0;Create;True;0;0;False;0;-1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;35;-1596.804,163.1458;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;51;-662.9076,794.273;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ClampOpNode;57;-477.4815,516.7932;Inherit;False;3;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT2;1,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;63;-637.4819,452.7921;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;41;-924.8043,291.1458;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;45;-987.7781,549.8922;Inherit;False;29;derivativesLength;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RangedFloatNode;59;-637.4819,628.7933;Inherit;False;Constant;_Float8;Float + 8;0;0;Create;True;0;0;False;0;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;43;-956.7781,452.0911;Inherit;False;Constant;_Float1;Float + 1;0;0;Create;True;0;0;False;0;0.35;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;44;-774.1779,498.6923;Inherit;False;2;0;FLOAT;0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.LerpOp;73;383.9426,22.72415;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SqrtOpNode;26;-160,-448;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DynamicAppendNode;19;-593.6686,-565.8171;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DynamicAppendNode;21;-592,-368;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DynamicAppendNode;25;-288,-448;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;28;-966.1454,-418.2566;Inherit;False;FLOAT4;1;0;FLOAT4;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.DotProductOpNode;23;-448,-336;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;95.94269,-73.27585;Inherit;False;Color + A;5;1;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;10;-678.6784,-881.8192;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DynamicAppendNode;22;-592,-272;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DynamicAppendNode;20;-592,-464;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;12;-549.6785,-980.8192;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;6;-1051.678,-816.8192;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.DdyOpNode;15;-140.6784,-877.8192;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;27;-1139.145,-405.2566;Inherit;False;17;UVDerivatives;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RangedFloatNode;11;-833.6784,-945.8192;Inherit;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;69;-223.9972,434.8422;Inherit;False;Constant;_Float10;Float + 10;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;36;-1740.804,211.1458;Inherit;False;Constant;_Float2;Float + 2;0;0;Create;True;0;0;False;0;0.25;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;34;-1755.153,114.0224;Inherit;False;13;FinalUV;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SaturateNode;65;253.0029,341.8422;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;52;-810.9399,854.6689;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;29;-48,-448;Inherit;False;derivativesLength;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DotProductOpNode;24;-448,-544;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.Vector2Node;9;-994.1925,-1114.645;Inherit;False;Constant;_Vector0;Vector + 0;0;0;Create;True;0;0;False;0;1,1;0,0;0;3;FLOAT2;0;FLOAT;1;FLOAT;2\nNode;AmplifyShaderEditor.FunctionInput;1;-855.6784,-822.8192;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;4;-828.1924,-1094.645;Inherit;False;Frequency;2;3;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;13;-395.1576,-957.8666;Inherit;False;FinalUV;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DynamicAppendNode;16;17.45426,-967.288;Inherit;False;FLOAT4;4;0;FLOAT2;0,0;False;1;FLOAT;0;False;2;FLOAT2;0,0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;17;185.4542,-971.288;Inherit;False;UVDerivatives;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.DdxOpNode;14;-140.6784,-1005.819;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;0;612.215,21.62323;Inherit;False;True;-1;Out;0;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nWireConnection;39;0;32;0\nWireConnection;39;1;40;0\nWireConnection;32;0;37;0\nWireConnection;3;0;8;0\nWireConnection;37;0;33;0\nWireConnection;37;1;38;0\nWireConnection;68;0;69;0\nWireConnection;68;1;71;0\nWireConnection;68;2;71;1\nWireConnection;68;3;48;0\nWireConnection;67;0;66;0\nWireConnection;67;1;68;0\nWireConnection;71;0;57;0\nWireConnection;33;0;35;0\nWireConnection;48;0;49;0\nWireConnection;49;0;51;0\nWireConnection;55;0;53;0\nWireConnection;35;0;34;0\nWireConnection;35;1;36;0\nWireConnection;51;0;50;0\nWireConnection;51;1;52;0\nWireConnection;57;0;63;0\nWireConnection;57;1;58;0\nWireConnection;57;2;59;0\nWireConnection;63;0;41;0\nWireConnection;63;1;44;0\nWireConnection;41;0;39;0\nWireConnection;41;1;42;0\nWireConnection;44;0;43;0\nWireConnection;44;1;45;0\nWireConnection;73;0;2;0\nWireConnection;73;1;3;0\nWireConnection;73;2;65;0\nWireConnection;26;0;25;0\nWireConnection;19;0;28;0\nWireConnection;19;1;28;2\nWireConnection;21;0;28;1\nWireConnection;21;1;28;3\nWireConnection;25;0;24;0\nWireConnection;25;1;23;0\nWireConnection;28;0;27;0\nWireConnection;23;0;21;0\nWireConnection;23;1;22;0\nWireConnection;2;0;7;0\nWireConnection;10;0;11;0\nWireConnection;10;1;1;0\nWireConnection;22;0;28;1\nWireConnection;22;1;28;3\nWireConnection;20;0;28;0\nWireConnection;20;1;28;2\nWireConnection;12;0;4;0\nWireConnection;12;1;10;0\nWireConnection;15;0;13;0\nWireConnection;65;0;67;0\nWireConnection;52;0;55;0\nWireConnection;52;1;55;1\nWireConnection;29;0;26;0\nWireConnection;24;0;19;0\nWireConnection;24;1;20;0\nWireConnection;1;0;6;0\nWireConnection;4;0;9;0\nWireConnection;13;0;12;0\nWireConnection;16;0;14;0\nWireConnection;16;2;15;0\nWireConnection;17;0;16;0\nWireConnection;14;0;13;0\nWireConnection;0;0;73;0\nASEEND*/\n//CHKSM=2A92AA4C137FA7B827E342AC45B5BF06C4CEEF0A" + m_functionName: + m_description: Created a checkerboard pattern with given colors where Frequency + controls its tiling + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Checkerboard.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Checkerboard.asset.meta new file mode 100644 index 0000000..bc0c991 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Checkerboard.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 43dad715d66e03a4c8ad5f9564018081 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Color Mask.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Color Mask.asset new file mode 100644 index 0000000..c230320 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Color Mask.asset @@ -0,0 +1,37 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Color Mask + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=15401\n346;92;1025;714;609.2212;273.3323;1.054284;True;False\nNode;AmplifyShaderEditor.FunctionInput;1;-653.5797,-106.7027;Float;False;In;3;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DistanceOpNode;6;-448.5804,-174.703;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;14;608.4777,116.7526;Float;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;-640.5798,-192.703;Float;False;Mask + Color;3;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;4;-658.4253,3.963058;Float;False;Range;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;11;90.87174,229.5228;Float;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;5;-114.1282,184.5228;Float;False;Fuzziness;1;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;12;-74.12819,316.5228;Float;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;1E-05;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;8;-172.7711,-116.3855;Float;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;10;224.5456,-26.87407;Float;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.OneMinusNode;7;382.857,35.49149;Float;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;773.5771,78.81425;Float;False;True;Output;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;6;0;3;0\nWireConnection;6;1;1;0\nWireConnection;14;0;7;0\nWireConnection;11;0;5;0\nWireConnection;11;1;12;0\nWireConnection;8;0;6;0\nWireConnection;8;1;4;0\nWireConnection;10;0;8;0\nWireConnection;10;1;11;0\nWireConnection;7;0;10;0\nWireConnection;0;0;14;0\nASEEND*/\n//CHKSM=17BE7B1AD5B755695D444DE4E62340591EEA3488" + m_functionName: + m_description: + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesFoldout: 0 + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Color Mask.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Color Mask.asset.meta new file mode 100644 index 0000000..363f104 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Color Mask.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eec747d987850564c95bde0e5a6d1867 +timeCreated: 1529242750 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ComputeFilterWidth.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ComputeFilterWidth.asset new file mode 100644 index 0000000..286a8b8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ComputeFilterWidth.asset @@ -0,0 +1,22 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: ComputeFilterWidth + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=14001\n389;92;1064;673;507.116;202.918;1;True;False\nNode;AmplifyShaderEditor.DotProductOpNode;4;-216,-85;Float;False;2;0;FLOAT3;0,0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SqrtOpNode;7;263,-7;Float;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ConditionalIfNode;6;38,-37;Float;False;False;5;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DotProductOpNode;5;-185,84;Float;False;2;0;FLOAT3;0,0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DdxOpNode;2;-398,-75;Float;False;1;0;FLOAT3;0.0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;1;-610,-13;Float;False;In;3;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DdyOpNode;3;-372,94;Float;False;1;0;FLOAT3;0.0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;411,14;Float;False;True;Result;0;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nWireConnection;4;0;2;0\nWireConnection;4;1;2;0\nWireConnection;7;0;6;0\nWireConnection;6;0;4;0\nWireConnection;6;1;5;0\nWireConnection;6;2;4;0\nWireConnection;6;3;5;0\nWireConnection;6;4;5;0\nWireConnection;5;0;3;0\nWireConnection;5;1;3;0\nWireConnection;2;0;1;0\nWireConnection;3;0;1;0\nWireConnection;0;0;7;0\nASEEND*/\n//CHKSM=492807FC2E3C8BD5838861DEE6C6EDB10A2FF2D2" + m_functionName: + m_description: + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_nodeCategory: 7 + m_customNodeCategory: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ComputeFilterWidth.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ComputeFilterWidth.asset.meta new file mode 100644 index 0000000..799467f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ComputeFilterWidth.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 326bea850683cca44ae7af083d880d70 +timeCreated: 1512498793 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ConstantBiasScale.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ConstantBiasScale.asset new file mode 100644 index 0000000..a7250c5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ConstantBiasScale.asset @@ -0,0 +1,26 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: ConstantBiasScale + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=14407\n389;92;1064;673;789;458;1;True;False\nNode;AmplifyShaderEditor.SimpleAddOpNode;6;-227,-128;Float;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;-392,-184;Float;False;Input;1;0;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;1;-391,-91;Float;False;Bias;1;1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;7;-102,-19;Float;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-392,16;Float;False;Scale;1;2;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;78,-35;Float;False;True;Output;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;6;0;3;0\nWireConnection;6;1;1;0\nWireConnection;7;0;6;0\nWireConnection;7;1;2;0\nWireConnection;0;0;7;0\nASEEND*/\n//CHKSM=917F8D80859772EF16ACCF69C2333B732B3FBEF4" + m_functionName: + m_description: Simple Bias and Scale operation. Output = (Input + Bias) * Scale + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ConstantBiasScale.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ConstantBiasScale.asset.meta new file mode 100644 index 0000000..c1fa681 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/ConstantBiasScale.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 63208df05c83e8e49a48ffbdce2e43a0 +timeCreated: 1519302963 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/CotangentFrame.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/CotangentFrame.asset new file mode 100644 index 0000000..ab1673a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/CotangentFrame.asset @@ -0,0 +1,37 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: CotangentFrame + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=15103\n344;92;1056;673;1041.108;554.3792;1;True;False\nNode;AmplifyShaderEditor.FunctionInput;2;-613.4943,-271.5543;Float;False;View + Dir;3;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;1;-608.4943,-157.5543;Float;False;UV;2;2;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;4;-592.4943,-397.5543;Float;False;World + Normal;3;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.CustomExpressionNode;3;-421.4942,-290.5543;Float;False;float3 + dp1 = ddx ( position )@$float3 dp2 = ddy ( position )@$float2 duv1 = ddx ( uv + )@$float2 duv2 = ddy ( uv )@$float3 dp2perp = cross ( dp2, normal )@$float3 dp1perp + = cross ( normal, dp1 )@$float3 tangent = dp2perp * duv1.x + dp1perp * duv2.x@$float3 + bitangent = dp2perp * duv1.y + dp1perp * duv2.y@$float invmax = rsqrt ( max ( + dot ( tangent, tangent ), dot ( bitangent, bitangent ) ) )@$tangent *= invmax@$bitangent + *= invmax@$return float3x3 (\ttangent.x, bitangent.x, normal.x,$\t\t\t\t\ttangent.y, + bitangent.y, normal.y,$\t\t\t\t\ttangent.z, bitangent.z, normal.z )@;5;False;3;True;normal;FLOAT3;0,0,0;In;True;position;FLOAT3;0,0,0;In;True;uv;FLOAT2;0,0;In;CotangentFrame;False;False;3;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT2;0,0;False;1;FLOAT3x3;0\nNode;AmplifyShaderEditor.FunctionOutput;5;-204.4942,-327.5543;Float;False;True;TBN;0;False;1;0;FLOAT3x3;0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1;False;1;FLOAT3x3;0\nWireConnection;3;0;4;0\nWireConnection;3;1;2;0\nWireConnection;3;2;1;0\nWireConnection;5;0;3;0\nASEEND*/\n//CHKSM=D848432022B91999196CE4B6F7A8557013863A11" + m_functionName: + m_description: 'Calculating Cotangent frame without precomputed data + + http://www.thetenthplanet.de/archives/1180' + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/CotangentFrame.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/CotangentFrame.asset.meta new file mode 100644 index 0000000..d33591f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/CotangentFrame.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 62ce0f00f1417804bb4f2b38501ba0d0 +timeCreated: 1522316215 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Create Orthogonal Vector.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Create Orthogonal Vector.asset new file mode 100644 index 0000000..ad111c8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Create Orthogonal Vector.asset @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Create Orthogonal Vector + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=15104\n465;615;1039;403;1446.756;132.3935;1.734783;True;False\nNode;AmplifyShaderEditor.CrossProductOpNode;28;-512,192;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;26;-896,208;Float;False;Vector + 2;3;1;False;1;0;FLOAT3;0,1,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.CrossProductOpNode;30;-96,128;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.NormalizeNode;29;-336,192;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.NormalizeNode;27;-720,0;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;25;-896,0;Float;False;Vector + 1;3;0;False;1;0;FLOAT3;1,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.NormalizeNode;31;-720,208;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;128,0;Float;False;True;Vector + 1;0;True;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;2;128,256;Float;False;False;Vector + 3;2;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;1;128,128;Float;False;False;Vector + 2;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;28;0;27;0\nWireConnection;28;1;31;0\nWireConnection;30;0;29;0\nWireConnection;30;1;27;0\nWireConnection;29;0;28;0\nWireConnection;27;0;25;0\nWireConnection;31;0;26;0\nWireConnection;0;0;27;0\nWireConnection;2;0;29;0\nWireConnection;1;0;30;0\nASEEND*/\n//CHKSM=18CFF9C2BBF194BC2C63D4F07354C52613D46DD0" + m_functionName: + m_description: Providing two vectors creates a third one which is orthogonal to + the first two. It uses the first vector as the main guiding vector changing the + second accordingly. All results are normalized. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_nodeCategory: 16 + m_customNodeCategory: + m_previewPosition: 1 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Create Orthogonal Vector.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Create Orthogonal Vector.asset.meta new file mode 100644 index 0000000..7cd3334 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Create Orthogonal Vector.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 83358ef05db30f04ba825a1be5f469d8 +timeCreated: 1518189974 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Decode Directional Lighmap.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Decode Directional Lighmap.asset new file mode 100644 index 0000000..54f3072 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Decode Directional Lighmap.asset @@ -0,0 +1,45 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Decode Directional Lighmap + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17701\n412;73;1609;802;1389.521;361.4048;1;True;False\nNode;AmplifyShaderEditor.CustomExpressionNode;1;-135.5,-181;Float;False;return + DecodeDirectionalLightmap( Color,DirTex,NormalWorld)@;3;False;3;True;Color;FLOAT3;0,0,0;In;;Float;False;True;DirTex;FLOAT4;0,0,0,0;In;;Float;False;True;NormalWorld;FLOAT3;0,0,0;In;;Float;False;ASEDecodeDirectionalLightmap;False;False;0;3;0;FLOAT3;0,0,0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;23;-622.1301,-200.5;Inherit;False;inputColor;-1;True;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;4;-466.5,-12;Inherit;False;NormalWorld;3;2;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RangedFloatNode;9;-480,240;Inherit;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;13;293.7467,121.8659;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;16;356.1465,405.266;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;17;190.3352,367.6559;Inherit;False;Constant;_Float2;Float + 2;0;0;Create;True;0;0;False;0;0.0001;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SwizzleNode;18;176.3352,467.6559;Inherit;False;FLOAT;3;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;20;-527.6785,372.98;Inherit;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;15;502.8605,106.8558;Inherit;False;2;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;5;682.8613,-173.207;Inherit;False;4;0;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SwizzleNode;6;-480,160;Inherit;False;FLOAT3;0;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DotProductOpNode;7;-144,64;Inherit;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;8;-320,176;Inherit;False;2;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RangedFloatNode;12;-140.6092,173.8985;Inherit;False;Constant;_Float1;Float + 1;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;11;48,96;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-857.1957,-104.1015;Inherit;False;DirTex;4;1;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionInput;3;-852.2914,-189.0047;Inherit;False;Color;3;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;24;40.90209,216.6535;Inherit;False;23;inputColor;1;0;OBJECT;;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;916.3615,-183.7863;Inherit;False;True;-1;Output;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;1;0;23;0\nWireConnection;1;1;2;0\nWireConnection;1;2;4;0\nWireConnection;23;0;3;0\nWireConnection;13;0;11;0\nWireConnection;13;1;24;0\nWireConnection;16;0;17;0\nWireConnection;16;1;18;0\nWireConnection;18;0;20;0\nWireConnection;20;0;2;0\nWireConnection;15;0;13;0\nWireConnection;15;1;16;0\nWireConnection;5;0;1;0\nWireConnection;5;3;1;0\nWireConnection;5;1;15;0\nWireConnection;5;2;15;0\nWireConnection;6;0;2;0\nWireConnection;7;0;4;0\nWireConnection;7;1;8;0\nWireConnection;8;0;6;0\nWireConnection;8;1;9;0\nWireConnection;11;0;7;0\nWireConnection;11;1;12;0\nWireConnection;0;0;5;0\nASEEND*/\n//CHKSM=887A7A2BA5CFB5CBB9854D026B260CA7971382E5" + m_functionName: + m_description: 'Calls Unity internal DecodeDirectionalLightmap function. + + Uses custom graph on all other pipelines' + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Decode Directional Lighmap.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Decode Directional Lighmap.asset.meta new file mode 100644 index 0000000..b33de37 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Decode Directional Lighmap.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8132441d5c7c63f479ea1c42855420a8 +timeCreated: 1550589461 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/DepthMaskedRefraction.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/DepthMaskedRefraction.asset new file mode 100644 index 0000000..5667239 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/DepthMaskedRefraction.asset @@ -0,0 +1,52 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: DepthMaskedRefraction + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18501\n352;92;1481;859;5529.478;1867.746;3.751044;True;False\nNode;AmplifyShaderEditor.CommentaryNode;42;-1534.82,-801.194;Inherit;False;1532.902;402.5788;;8;9;11;15;14;16;17;13;1;Artifact + Correction;1,1,1,1;0;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;10;-1793.859,-388.0908;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT;1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;4;-2173.438,17.72729;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;40;-3154.926,-42.33801;Inherit;False;Boundaries;False;0;2;-1;Continous;Discontinous;Object;-1;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;41;-3398.61,-20.0625;Inherit;False;Constant;_Float1;Float + 1;0;0;Create;True;0;0;False;0;False;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;29;-3573.743,-87.7131;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ScreenDepthNode;28;-3823.751,-92.9282;Inherit;False;0;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;21;-3400.329,-87.85226;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;5;-1980.353,17.46826;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;1;-241.299,-550.8569;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;13;-818.5988,-648.5499;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;89;54.23302,-226.3335;Inherit;False;4;0;FLOAT2;0,0;False;3;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;17;-426.9748,-742.0114;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SwizzleNode;16;-1056.131,-538.2838;Inherit;False;FLOAT2;0;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SwizzleNode;32;-1232.117,-189.1583;Inherit;False;FLOAT2;0;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RangedFloatNode;104;-3565.097,-516.2079;Inherit;False;Constant;_Float2;Float + 2;0;0;Create;True;0;0;False;0;False;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.ScreenPosInputsNode;19;-2842.449,-169.8328;Float;False;0;False;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;35;-3255.611,-273.0523;Inherit;False;Normals;3;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.NormalVertexDataNode;97;-3494.124,-268.1942;Inherit;False;0;5;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SwizzleNode;26;-2978.274,-271.8887;Inherit;False;FLOAT2;0;1;2;3;1;0;FLOAT3;0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;20;-2766.966,-392.6118;Inherit;False;3;3;0;FLOAT2;1,1;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;7;-2569.792,-276.0808;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.Vector4Node;9;-1446.455,-736.3716;Inherit;False;Global;_CameraDepthTexture_TexelSize;_CameraDepthTexture_TexelSize;21;0;Fetch;True;0;0;True;0;False;0,0,0,0;0.001383126,0.001470588,723,680;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleAddOpNode;18;-1576.075,-184.5327;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SwizzleNode;11;-1053.65,-736.3645;Inherit;False;FLOAT2;2;3;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FloorOpNode;14;-667.9666,-648.5499;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.ScreenDepthNode;2;-2384.089,-51.48779;Inherit;False;0;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;103;-3375.097,-436.2079;Inherit;False;Strength + Scaling;False;0;2;-1;Scale with distance;Constant;Object;-1;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;105;-2972.097,-452.2079;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;37;-3265.538,-527.2198;Inherit;False;Refraction + Strength;1;1;False;1;0;FLOAT;0.02;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;101;-3546.097,-431.2079;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0.1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;15;-712.0767,-726.3988;Inherit;False;Constant;_Float0;Float + 0;1;0;Create;True;0;0;False;0;False;0.5;0.5;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SurfaceDepthNode;27;-3936.345,30.59574;Inherit;False;0;1;0;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;38;357.6264,-224.0661;Inherit;False;True;-1;Refracted + UV;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nWireConnection;10;0;20;0\nWireConnection;10;1;5;0\nWireConnection;4;0;2;0\nWireConnection;4;1;27;0\nWireConnection;40;0;21;0\nWireConnection;40;1;41;0\nWireConnection;29;0;28;0\nWireConnection;29;1;27;0\nWireConnection;21;0;29;0\nWireConnection;5;0;4;0\nWireConnection;1;0;17;0\nWireConnection;1;1;16;0\nWireConnection;13;0;32;0\nWireConnection;13;1;11;0\nWireConnection;89;0;1;0\nWireConnection;89;3;1;0\nWireConnection;89;1;32;0\nWireConnection;89;2;32;0\nWireConnection;17;0;14;0\nWireConnection;17;1;15;0\nWireConnection;16;0;9;0\nWireConnection;32;0;18;0\nWireConnection;35;0;97;0\nWireConnection;26;0;35;0\nWireConnection;20;0;26;0\nWireConnection;20;1;105;0\nWireConnection;20;2;40;0\nWireConnection;7;0;20;0\nWireConnection;7;1;19;0\nWireConnection;18;0;10;0\nWireConnection;18;1;19;0\nWireConnection;11;0;9;0\nWireConnection;14;0;13;0\nWireConnection;2;0;7;0\nWireConnection;103;0;101;0\nWireConnection;103;1;104;0\nWireConnection;105;0;37;0\nWireConnection;105;1;103;0\nWireConnection;101;0;27;0\nWireConnection;38;0;89;0\nASEEND*/\n//CHKSM=E126823090EC4C04CD6801119B18A02F540BA131" + m_functionName: + m_description: 'Outputs normal-warped UVs for use in a Screen Color node to simulate + refraction. Depth Textures have to be enabled. In URP, ''Depth Texture'' and ''Opaque + Texture'' have to be enabled and ''Opaque Downsampling'' set to ''None'' to obtain + no artifacts. + + Created by community member Sai + + https://twitter.com/saismirk' + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/DepthMaskedRefraction.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/DepthMaskedRefraction.asset.meta new file mode 100644 index 0000000..ae88d29 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/DepthMaskedRefraction.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c805f061214177c42bca056464193f81 +timeCreated: 1600098425 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Derive Tangent Basis.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Derive Tangent Basis.asset new file mode 100644 index 0000000..3a73911 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Derive Tangent Basis.asset @@ -0,0 +1,64 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Derive Tangent Basis + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17102\n0;731;1536;630;1714.5;318.7658;1;True;False\nNode;AmplifyShaderEditor.WorldNormalVector;10;-821.4876,20.21545;Inherit;False;False;1;0;FLOAT3;0,0,1;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionInput;5;-784.8259,164.9036;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WorldPosInputsNode;13;-823.4999,-127.2658;Inherit;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.CustomExpressionNode;1;-529.4937,-4.008303;Inherit;False;#if + (SHADER_TARGET >= 45)$float3 dPdx = ddx_fine( WorldPosition )@$float3 dPdy = ddy_fine( + WorldPosition )@$#else$float3 dPdx = ddx( WorldPosition )@$float3 dPdy = ddy( + WorldPosition )@$#endif$$float3 sigmaX = dPdx - dot( dPdx, WorldNormal ) * WorldNormal@$float3 + sigmaY = dPdy - dot( dPdy, WorldNormal ) * WorldNormal@$$float flip_sign = dot( + dPdy, cross( WorldNormal, dPdx ) ) < 0 ? -1 : 1@$$#if (SHADER_TARGET >= 45)$float2 + dSTdx = ddx_fine( UV )@$float2 dSTdy = ddy_fine( UV )@$#else$float2 dSTdx = ddx( + UV )@$float2 dSTdy = ddy( UV )@$#endif$$float det = dot( dSTdx, float2( dSTdy.y, + -dSTdy.x ) )@$float sign_det = ( det < 0 ) ? -1 : 1@$$float2 invC0 = sign_det + * float2( dSTdy.y, -dSTdx.y )@$$float3 T = sigmaX * invC0.x + sigmaY * invC0.y@$if + ( abs( det ) > 0 ) T = normalize( T )@$$float3 B = ( sign_det * flip_sign ) * + cross( WorldNormal, T )@$$WorldToTangent = float3x3( T, B, WorldNormal )@$TangentToWorld + = transpose( WorldToTangent )@$return@;7;False;5;True;WorldPosition;FLOAT3;0,0,0;In;;Float;False;True;WorldNormal;FLOAT3;0,0,0;In;;Float;False;True;UV;FLOAT2;0,0;In;;Float;False;True;TangentToWorld;FLOAT3x3;1,0,0,1,1,1,1,0,1;Out;;Float;False;True;WorldToTangent;FLOAT3x3;1,0,0,1,1,1,1,0,1;Out;;Float;False;Derive + Tangent Basis;False;False;0;6;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT2;0,0;False;4;FLOAT3x3;1,0,0,1,1,1,1,0,1;False;5;FLOAT3x3;1,0,0,1,1,1,1,0,1;False;3;FLOAT3;0;FLOAT3x3;5;FLOAT3x3;6\nNode;AmplifyShaderEditor.FunctionOutput;0;-147.9617,-6.546963;Inherit;False;True;Tangent + To World;0;False;1;0;FLOAT3x3;0,0,0,1,1,1,1,0,1;False;1;FLOAT3x3;0\nNode;AmplifyShaderEditor.FunctionOutput;6;-143.2227,68.66327;Inherit;False;False;World + To Tangent;1;False;1;0;FLOAT3x3;0,0,0,1,1,1,1,0,1;False;1;FLOAT3x3;0\nWireConnection;1;1;13;0\nWireConnection;1;2;10;0\nWireConnection;1;3;5;0\nWireConnection;0;0;1;5\nWireConnection;6;0;1;6\nASEEND*/\n//CHKSM=AEDC509876FA685886EABAB4978B0630E667D50E" + m_functionName: + m_description: 'This function derives a per-pixel tangent basis for a specific set + of UV coordinates. The built-in tangent basis is based on UV0. This function allows + normal mapping for UV1 or any other UV set, including runtime generated. + + + Typical usage case: + + Blending additional normal mapped layers that require non-UV0 coordinates. + + + Based on "Surface Gradient Based Bump Mapping Framework" by Morten S. Mikkelsen' + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Derive Tangent Basis.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Derive Tangent Basis.asset.meta new file mode 100644 index 0000000..89b545c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Derive Tangent Basis.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fee816718ad753c4f9b25822c0d67438 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Detail Albedo.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Detail Albedo.asset new file mode 100644 index 0000000..785378c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Detail Albedo.asset @@ -0,0 +1,30 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Detail Albedo + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=15308\n234;92;1334;669;1058.943;684.4172;1.391955;True;False\nNode;AmplifyShaderEditor.FunctionInput;11;-791.7281,-222.1082;Float;False;Detail + Albedo;3;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.ComponentMaskNode;10;-1044.388,-263.2733;Float;False;True;True;True;False;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SamplerNode;2;-1374.942,-264.6411;Float;True;Property;_DetailAlbedo;Detail + Albedo;1;0;Create;True;0;0;False;0;None;bdbe94d7623ec3940947b62544306f1c;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;7;-917.0518,-585.9581;Float;True;Property;_Albedo;Albedo;0;0;Create;True;0;0;False;0;None;37e6f91f3efb0954cbdce254638862ea;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.ComponentMaskNode;5;-897.4531,2.035467;Float;False;True;True;True;False;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.ComponentMaskNode;13;-545.7818,-575.8773;Float;False;True;True;True;False;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;3;-621.8271,-138.6786;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.ColorSpaceDouble;1;-1143.392,22.29117;Float;False;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;9;-388.3632,289.7231;Float;False;Detail + Mask;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;4;-724.7507,221.7417;Float;True;Property;_DetailMask;Detail + Mask;2;0;Create;True;0;0;False;0;None;37e6f91f3efb0954cbdce254638862ea;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;12;-215.2053,-435.8505;Float;False;Albedo;3;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DynamicAppendNode;16;116.0423,225.5565;Float;False;FLOAT3;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;17;-72.95755,102.5566;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.OneMinusNode;18;-88.95757,230.5565;Float;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;15;311.0422,102.5566;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;8;487.2353,-311.0565;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;677.5877,-317.7978;Float;False;True;Output;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;11;0;10;0\nWireConnection;10;0;2;0\nWireConnection;5;0;1;0\nWireConnection;13;0;7;0\nWireConnection;3;0;11;0\nWireConnection;3;1;5;0\nWireConnection;9;0;4;4\nWireConnection;12;0;13;0\nWireConnection;16;0;18;0\nWireConnection;16;1;18;0\nWireConnection;16;2;18;0\nWireConnection;17;0;3;0\nWireConnection;17;1;9;0\nWireConnection;18;0;9;0\nWireConnection;15;0;17;0\nWireConnection;15;1;16;0\nWireConnection;8;0;12;0\nWireConnection;8;1;15;0\nWireConnection;0;0;8;0\nASEEND*/\n//CHKSM=98DA4DD57D5904F6ADF4806CACEF92157BC023C5" + m_functionName: + m_description: Adds Detail Abledo X2 map, similar to Standard Material + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Detail Albedo.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Detail Albedo.asset.meta new file mode 100644 index 0000000..4f4f8d9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Detail Albedo.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 29e5a290b15a7884983e27c8f1afaa8c +timeCreated: 1527501568 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Dots Pattern.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Dots Pattern.asset new file mode 100644 index 0000000..aee150d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Dots Pattern.asset @@ -0,0 +1,42 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Dots Pattern + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1462;-370;1004;726;3436.004;1250.192;3.58226;True;False\nNode;AmplifyShaderEditor.FunctionInput;4;-1216,-64;Inherit;False;Offset + X;1;3;False;1;0;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;16;-1712,-128;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FractNode;6;-400,0;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;2;-400,96;Inherit;False;Size;1;2;False;1;0;FLOAT;0.9;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionNode;1;-256,0;Inherit;True;Ellipse;-1;;1;3ba94b7b3cfd5f447befde8107c04d52;0;3;2;FLOAT2;0,0;False;7;FLOAT;0.5;False;9;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;22;-1953.205,-105.9789;Inherit;False;Custom + UVs;True;0;2;0;In 0;In 1;Object;-1;9;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;21;-2144,-16;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;13;-2416,-128;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;3;-2368,0;Inherit;False;Tiling;2;1;False;1;0;FLOAT2;8,8;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;15;-2144,-128;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;17;-896,128;Inherit;True;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleRemainderNode;11;-1408,32;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.StepOpNode;10;-1216,16;Inherit;False;2;0;FLOAT;1;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;8;-896,-128;Inherit;True;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;9;-1056,-32;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;18;-1056,208;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;7;-560,0;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;5;-1216,176;Inherit;False;Offset + Y;1;4;False;1;0;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleRemainderNode;20;-1408,288;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.StepOpNode;19;-1216,272;Inherit;False;2;0;FLOAT;1;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;16;0;22;0\nWireConnection;6;0;7;0\nWireConnection;1;2;6;0\nWireConnection;1;7;2;0\nWireConnection;1;9;2;0\nWireConnection;22;0;15;0\nWireConnection;22;1;21;0\nWireConnection;21;0;13;0\nWireConnection;15;0;13;0\nWireConnection;15;1;3;0\nWireConnection;17;0;16;1\nWireConnection;17;1;18;0\nWireConnection;11;0;16;1\nWireConnection;10;1;11;0\nWireConnection;8;0;16;0\nWireConnection;8;1;9;0\nWireConnection;9;0;4;0\nWireConnection;9;1;10;0\nWireConnection;18;0;5;0\nWireConnection;18;1;19;0\nWireConnection;7;0;8;0\nWireConnection;7;1;17;0\nWireConnection;20;0;16;0\nWireConnection;19;1;20;0\nWireConnection;0;0;1;0\nASEEND*/\n//CHKSM=26E6410FBC1EBC56E76C21CF54FC55DEAFFEA95F" + m_functionName: + m_description: Creates a repeated dots pattern with alternating offsetted lines + or columns of dots. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Dots Pattern.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Dots Pattern.asset.meta new file mode 100644 index 0000000..dad7905 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Dots Pattern.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7d8d5e315fd9002418fb41741d3a59cb +timeCreated: 1586787388 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Ellipse.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Ellipse.asset new file mode 100644 index 0000000..4891837 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Ellipse.asset @@ -0,0 +1,40 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Ellipse + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1410;-481;1109;726;1067.283;573.8351;2;True;False\nNode;AmplifyShaderEditor.SimpleDivideOpNode;15;736,128;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.OneMinusNode;13;560,128;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;11;64,304;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SaturateNode;16;880,128;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FWidthOpNode;14;560,208;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LengthOpNode;17;384,128;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;12;240,128;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;9;-112,384;Inherit;False;Height;1;2;False;1;0;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;7;-112,304;Inherit;False;Width;1;1;False;1;0;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ScaleAndOffsetNode;3;-48,32;Inherit;True;3;0;FLOAT2;0,0;False;1;FLOAT;2;False;2;FLOAT;-1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RangedFloatNode;5;-272,128;Inherit;False;Constant;_Float1;Float + 1;0;0;Create;True;0;0;False;0;-1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;4;-272,32;Inherit;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;2;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-272,-64;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;1;-496,-64;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionOutput;0;1024,128;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;15;0;13;0\nWireConnection;15;1;14;0\nWireConnection;13;0;17;0\nWireConnection;11;0;7;0\nWireConnection;11;1;9;0\nWireConnection;16;0;15;0\nWireConnection;14;0;17;0\nWireConnection;17;0;12;0\nWireConnection;12;0;3;0\nWireConnection;12;1;11;0\nWireConnection;3;0;2;0\nWireConnection;3;1;4;0\nWireConnection;3;2;5;0\nWireConnection;2;0;1;0\nWireConnection;0;0;16;0\nASEEND*/\n//CHKSM=00B1FD172E8372FBCF36CB9A133FB643740A4B46" + m_functionName: + m_description: Creates an ellipse based on given uv and dimensions + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Ellipse.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Ellipse.asset.meta new file mode 100644 index 0000000..4899a58 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Ellipse.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3ba94b7b3cfd5f447befde8107c04d52 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchHDColorPyramid.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchHDColorPyramid.asset new file mode 100644 index 0000000..58671c7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchHDColorPyramid.asset @@ -0,0 +1,40 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: FetchHDColorPyramid + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=15502\n460;92;961;705;422.5;427.5;1;True;False\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;4;192.5,-174.5;Float;False;3;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.Vector4Node;5;-38.5,-232.5;Float;False;Constant;_Vector0;Vector + 0;0;0;Create;True;0;0;False;0;0,0,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.CustomExpressionNode;1;-33.5,-23.5;Float;False;LOAD_TEXTURE2D_LOD(\r + \ _ColorPyramidTexture,UV,LOD);4;False;2;True;UV;FLOAT2;0,0;In;;True;LOD;FLOAT;0;In;;FetchColorPyramid;True;False;0;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionInput;2;-195.5,35.5;Float;False;LOD;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;-227.5,-119.5;Float;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;0;432,-54;Float;False;True;Output;0;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nWireConnection;4;0;5;0\nWireConnection;4;1;5;0\nWireConnection;4;2;1;0\nWireConnection;1;0;3;0\nWireConnection;1;1;2;0\nWireConnection;0;0;4;0\nASEEND*/\n//CHKSM=FCEB018C27BAF233C7FC33A2B4BB473BEB28E231" + m_functionName: + m_description: 'Fetches the _ColorPyramidTexture texture of the HDRP pipeline. + + Using this over LW or default pipelines will result in incorrect behaviors.' + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchHDColorPyramid.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchHDColorPyramid.asset.meta new file mode 100644 index 0000000..29497be --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchHDColorPyramid.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e17d5b1cd6898394dbe1f30e05022025 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchLightmapValue.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchLightmapValue.asset new file mode 100644 index 0000000..48ad2d2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchLightmapValue.asset @@ -0,0 +1,48 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: FetchLightmapValue + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18905\n529;92;1273;1015;362.0724;565.6241;1.3;True;False\nNode;AmplifyShaderEditor.Vector4Node;8;-500.423,19.56814;Float;False;Global;unity_LightmapST;unity_LightmapST;2;0;Fetch;True;0;0;0;False;0;False;0,0,0,0;1,1,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.VertexToFragmentNode;10;368,-112;Inherit;False;False;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SwizzleNode;4;-188.546,21.5814;Inherit;False;FLOAT2;0;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;5;-28.547,-122.4186;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;2;-528,-128;Inherit;False;1;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.CustomExpressionNode;19;1108.877,25.22512;Inherit;False;return + float4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0, 0)@;4;Create;0;URPDecodeInstruction;True;False;0;;False;0;1;FLOAT4;0\nNode;AmplifyShaderEditor.TexturePropertyNode;1;314.5027,-433.4464;Float;True;Global;unity_Lightmap;unity_Lightmap;0;0;Fetch;True;0;0;0;False;0;False;None;None;False;white;Auto;Texture2D;-1;0;2;SAMPLER2D;0;SAMPLERSTATE;1\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;20;1405.278,220.2255;Inherit;False;4;0;FLOAT4;0,0,0,0;False;3;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.DecodeLightmapHlpNode;6;1661.949,-191.024;Inherit;False;2;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.StaticSwitch;13;981.1006,204.6251;Float;False;Property;_Keyword0;Keyword + 0;1;0;Create;True;0;0;0;False;0;False;0;0;0;False;UNITY_LIGHTMAP_FULL_HDR;Toggle;2;Key0;Key1;Fetch;True;True;9;1;FLOAT4;0,0,0,0;False;0;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;3;FLOAT4;0,0,0,0;False;4;FLOAT4;0,0,0,0;False;5;FLOAT4;0,0,0,0;False;6;FLOAT4;0,0,0,0;False;7;FLOAT4;0,0,0,0;False;8;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.CustomExpressionNode;11;735.7104,-21.51056;Float;False;return + SAMPLE_TEXTURE2D( unity_Lightmap, samplerunity_Lightmap, UV )@;4;Create;1;True;UV;FLOAT2;0,0;In;;Float;False;SampleLightmapHD;True;False;0;;False;1;0;FLOAT2;0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.Vector4Node;16;754.9202,321.7659;Float;False;Constant;_Vector1;Vector + 1;3;0;Create;True;0;0;0;False;0;False;0,0,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SwizzleNode;9;-188.546,133.5814;Inherit;False;FLOAT2;2;3;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;12;1027.71,-224.5106;Inherit;False;4;0;COLOR;0,0,0,0;False;3;COLOR;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.Vector4Node;18;322.9202,307.7659;Float;False;Constant;_Vector3;Vector + 3;3;0;Create;True;0;0;0;False;0;False;34.49324,2.2,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;7;654.0723,-337.4277;Inherit;True;Property;_TextureSample0;Texture + Sample 0;0;0;Create;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleAddOpNode;3;224,-32;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.Vector4Node;17;329.9202,94.76587;Float;False;Constant;_Vector2;Vector + 2;3;0;Create;True;0;0;0;False;0;False;2,2.2,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.StaticSwitch;15;602.9202,151.7659;Float;False;Property;_Keyword2;Keyword + 2;2;0;Create;True;0;0;0;False;0;False;0;0;0;False;UNITY_LIGHTMAP_RGBM_ENCODING;Toggle;2;Key0;Key1;Fetch;True;True;9;1;FLOAT4;0,0,0,0;False;0;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;3;FLOAT4;0,0,0,0;False;4;FLOAT4;0,0,0,0;False;5;FLOAT4;0,0,0,0;False;6;FLOAT4;0,0,0,0;False;7;FLOAT4;0,0,0,0;False;8;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionOutput;0;1894.252,-186.4676;Inherit;False;True;-1;Output;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;10;0;3;0\nWireConnection;4;0;8;0\nWireConnection;5;0;2;0\nWireConnection;5;1;4;0\nWireConnection;20;0;13;0\nWireConnection;20;3;13;0\nWireConnection;20;1;19;0\nWireConnection;20;2;13;0\nWireConnection;6;0;12;0\nWireConnection;6;1;20;0\nWireConnection;13;1;15;0\nWireConnection;13;0;16;0\nWireConnection;11;0;10;0\nWireConnection;9;0;8;0\nWireConnection;12;0;7;0\nWireConnection;12;3;7;0\nWireConnection;12;1;11;0\nWireConnection;12;2;11;0\nWireConnection;7;0;1;0\nWireConnection;7;1;10;0\nWireConnection;3;0;5;0\nWireConnection;3;1;9;0\nWireConnection;15;1;17;0\nWireConnection;15;0;18;0\nWireConnection;0;0;6;0\nASEEND*/\n//CHKSM=FCE0FF5C172DFAFF1D74B3B4A7C51BADF1025740" + m_functionName: + m_description: 'Fetches the value from the lightmap. Multiply the fetched value + by the final fragment color. ' + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_customEdited: 0 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchLightmapValue.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchLightmapValue.asset.meta new file mode 100644 index 0000000..af3eb8d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/FetchLightmapValue.asset.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 43de3d4ae59f645418fdd020d1b8e78e +timeCreated: 1528994083 +licenseType: Store +NativeFormatImporter: + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flipbook.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flipbook.asset new file mode 100644 index 0000000..7c8153f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flipbook.asset @@ -0,0 +1,36 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Flipbook + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=14204\n487;595;979;423;2696.247;1459.301;4.894685;True;False\nNode;AmplifyShaderEditor.GetLocalVarNode;50;-816,96;Float;False;39;0;1;FLOAT;0\nNode;AmplifyShaderEditor.ClampOpNode;42;-992,80;Float;False;3;0;FLOAT;0.0;False;1;FLOAT;0.0001;False;2;FLOAT;8.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;8;-128,-128;Float;False;FLOAT2;4;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;49;640,-112;Float;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.SimpleDivideOpNode;27;-608,0;Float;False;2;0;FLOAT;0.0;False;1;FLOAT;9.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FractNode;35;-464,0;Float;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;44;-1168,160;Float;False;2;0;FLOAT;0.0;False;1;FLOAT;1.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-992,0;Float;False;Time;1;5;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FloorOpNode;10;160,-64;Float;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;24;-1200,80;Float;False;Start + Frame;1;4;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;39;-464,-176;Float;False;totalFrames;-1;True;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;68;1408,-720;Float;False;Mip + Mode;False;0;3;1;Auto;Bias;Level;8;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;COLOR;0\nNode;AmplifyShaderEditor.OneMinusNode;38;-304,64;Float;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;40;-1376,160;Float;False;39;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleTimeNode;3;-1200,0;Float;False;1;0;FLOAT;1.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;9;16,-64;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0.0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;15;480,-224;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0.0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DynamicAppendNode;7;-128,-256;Float;False;FLOAT2;4;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;14;-128,-384;Float;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;67;-304,160;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;5;-768,-96;Float;False;Rows;1;3;False;1;0;FLOAT;3.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;6;-624,-176;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;4;-768,-256;Float;False;Colums;1;2;False;1;0;FLOAT;3.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;29;-128,0;Float;False;FLOAT2;4;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;13;128,-384;Float;False;UV;2;1;False;1;0;FLOAT2;1,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;69;896,-512;Float;True;Property;_SamplerLevel;Sampler + Level;0;0;Create;True;None;None;True;0;False;white;Auto;False;Object;-1;MipLevel;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleDivideOpNode;12;320,-288;Float;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;51;512,-896;Float;False;Tex;9;0;False;1;0;SAMPLER2D;0.0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;11;320,-160;Float;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;22;-768,0;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;70;512,-512;Float;False;Mip + Level;1;7;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;52;896,-896;Float;True;Property;_SamplerAuto;Sampler + Auto;0;0;Create;True;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;57;896,-704;Float;True;Property;_SamplerBias;Sampler + Bias;0;0;Create;True;None;None;True;0;False;white;Auto;False;Object;-1;MipBias;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;55;512,-704;Float;False;Mip + Bias;1;6;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;71;1654.729,-742.7292;Float;False;Use + Texture;True;0;2;0;False;True;8;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionOutput;0;896,-224;Float;False;True;UV;1;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;53;1882.438,-748.9789;Float;False;False;RGBA;0;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionOutput;47;896,-128;Float;False;False;U;2;False;1;0;FLOAT;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;62;-112,160;Float;False;False;Cur + Frame;4;False;1;0;FLOAT;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;48;896,-64;Float;False;False;V;3;False;1;0;FLOAT;0,0;False;1;FLOAT;0\nWireConnection;42;0;24;0\nWireConnection;42;2;44;0\nWireConnection;8;0;39;0\nWireConnection;8;1;5;0\nWireConnection;49;0;15;0\nWireConnection;27;0;22;0\nWireConnection;27;1;50;0\nWireConnection;35;0;27;0\nWireConnection;44;0;40;0\nWireConnection;2;0;3;0\nWireConnection;10;0;9;0\nWireConnection;39;0;6;0\nWireConnection;68;0;52;0\nWireConnection;68;1;57;0\nWireConnection;68;2;69;0\nWireConnection;38;0;35;0\nWireConnection;9;0;8;0\nWireConnection;9;1;29;0\nWireConnection;15;0;12;0\nWireConnection;15;1;11;0\nWireConnection;7;0;4;0\nWireConnection;7;1;5;0\nWireConnection;67;0;35;0\nWireConnection;67;1;50;0\nWireConnection;6;0;4;0\nWireConnection;6;1;5;0\nWireConnection;29;0;35;0\nWireConnection;29;1;38;0\nWireConnection;13;0;14;0\nWireConnection;69;0;51;0\nWireConnection;69;1;15;0\nWireConnection;69;2;70;0\nWireConnection;12;0;13;0\nWireConnection;12;1;7;0\nWireConnection;11;0;10;0\nWireConnection;11;1;7;0\nWireConnection;22;0;2;0\nWireConnection;22;1;42;0\nWireConnection;52;0;51;0\nWireConnection;52;1;15;0\nWireConnection;57;0;51;0\nWireConnection;57;1;15;0\nWireConnection;57;2;55;0\nWireConnection;71;1;68;0\nWireConnection;0;0;15;0\nWireConnection;53;0;71;0\nWireConnection;47;0;49;0\nWireConnection;62;0;67;0\nWireConnection;48;0;49;1\nASEEND*/\n//CHKSM=312D1CE7E23C444F9583CB6B462131FEE8B66987" + m_functionName: + m_description: This node generates either UVs or a final color which scroll through + a texture sheet. Make sure your texture wrap mode is set to repeat. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_nodeCategory: 0 + m_customNodeCategory: + m_previewPosition: 1 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flipbook.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flipbook.asset.meta new file mode 100644 index 0000000..c24f34a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flipbook.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 53c2488c220f6564ca6c90721ee16673 +timeCreated: 1515152873 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flow.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flow.asset new file mode 100644 index 0000000..1e3c708 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flow.asset @@ -0,0 +1,50 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Flow + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17500\n368;498;1477;895;2968.752;895.1555;2.383106;True;False\nNode;AmplifyShaderEditor.CommentaryNode;47;-1168,448;Inherit;False;527;247;Linear + Blend;3;32;30;31;;1,1,1,1;0;0\nNode;AmplifyShaderEditor.FunctionInput;18;-1712,80;Inherit;False;Flow + Direction;2;2;False;1;0;FLOAT2;0,1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;41;-1472,80;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.NegateNode;46;-1872,80;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RangedFloatNode;42;-1728,176;Float;False;Constant;_Rescalevectors;Rescale + vectors;3;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleTimeNode;22;-1792,416;Inherit;False;1;0;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FractNode;27;-1440,416;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;28;-1584,528;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;24;-1984,416;Inherit;False;Flow + Speed;1;4;False;1;0;FLOAT;0.2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;26;-1776,624;Float;False;Constant;_Float0;Float + 0;1;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;17;-1488,272;Inherit;False;Flow + Strength;2;3;False;1;0;FLOAT2;1,1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;12;-896,224;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;14;-1184,256;Inherit;False;3;3;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;2;-1696,-160;Inherit;False;UVs;2;1;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.VertexColorNode;45;-2288,80;Inherit;False;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.ComponentMaskNode;44;-2096,80;Inherit;False;True;True;False;False;1;0;COLOR;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;43;-1920,-160;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleDivideOpNode;37;-1472,-48;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;49;-544,384;Inherit;True;Property;_TextureSample3;Texture + Sample 3;3;0;Create;True;0;0;False;0;-1;None;None;True;0;False;bump;Auto;True;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;8;-544,192;Inherit;True;Property;_TextureSample1;Texture + Sample 1;1;0;Create;True;0;0;False;0;-1;e28dc97a9541e3642a48c0e3886688c5;e28dc97a9541e3642a48c0e3886688c5;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.LerpOp;9;144,112;Inherit;False;3;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SamplerNode;48;-544,-64;Inherit;True;Property;_TextureSample2;Texture + Sample 2;2;0;Create;True;0;0;False;0;-1;None;None;True;0;False;bump;Auto;True;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;30;-1120,496;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;32;-800,560;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;7;-544,-256;Inherit;True;Property;_TextureSample0;Texture + Sample 0;1;0;Create;True;0;0;False;0;-1;e28dc97a9541e3642a48c0e3886688c5;e28dc97a9541e3642a48c0e3886688c5;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.AbsOpNode;31;-944,496;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ComponentMaskNode;4;-1200,-16;Inherit;False;True;True;True;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;13;-1184,80;Inherit;False;3;3;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RangedFloatNode;38;-1808,-16;Float;False;Property;_Size;Size;1;0;Create;True;0;0;False;0;1;0;0;10;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FractNode;29;-1440,528;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;11;-896,-16;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;52;0,528;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;5;-1008,-256;Inherit;False;Tex;9;0;False;1;0;SAMPLER2D;0,0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.TexturePropertyNode;6;-1248,-256;Float;True;Property;_Tex;Tex;0;0;Create;True;0;0;False;0;e28dc97a9541e3642a48c0e3886688c5;e28dc97a9541e3642a48c0e3886688c5;False;white;Auto;Texture2D;-1;0;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.FunctionSwitch;50;-160,16;Inherit;False;Is + Normal;True;1;2;-1;In 0;In 1;Object;-1;9;0;COLOR;0,0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionSwitch;51;-160,192;Inherit;False;Is + Normal;True;1;2;-1;In 0;In 1;Instance;50;9;0;COLOR;0,0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;320,112;Inherit;True;True;-1;Output;0;True;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;18;0;46;0\nWireConnection;41;0;18;0\nWireConnection;41;1;42;0\nWireConnection;46;0;44;0\nWireConnection;22;0;24;0\nWireConnection;27;0;22;0\nWireConnection;28;0;22;0\nWireConnection;28;1;26;0\nWireConnection;12;0;4;0\nWireConnection;12;1;14;0\nWireConnection;14;0;41;0\nWireConnection;14;1;17;0\nWireConnection;14;2;29;0\nWireConnection;2;0;43;0\nWireConnection;44;0;45;0\nWireConnection;37;0;2;0\nWireConnection;37;1;38;0\nWireConnection;49;0;5;0\nWireConnection;49;1;12;0\nWireConnection;8;0;5;0\nWireConnection;8;1;12;0\nWireConnection;9;0;50;0\nWireConnection;9;1;51;0\nWireConnection;9;2;52;0\nWireConnection;48;0;5;0\nWireConnection;48;1;11;0\nWireConnection;30;0;27;0\nWireConnection;30;1;26;0\nWireConnection;32;0;31;0\nWireConnection;32;1;26;0\nWireConnection;7;0;5;0\nWireConnection;7;1;11;0\nWireConnection;31;0;30;0\nWireConnection;4;0;37;0\nWireConnection;13;0;41;0\nWireConnection;13;1;17;0\nWireConnection;13;2;27;0\nWireConnection;29;0;28;0\nWireConnection;11;0;4;0\nWireConnection;11;1;13;0\nWireConnection;52;0;32;0\nWireConnection;5;0;6;0\nWireConnection;50;0;7;0\nWireConnection;50;1;48;0\nWireConnection;51;0;8;0\nWireConnection;51;1;49;0\nWireConnection;0;0;9;0\nASEEND*/\n//CHKSM=E084CD7EC3DACA44AFB695EB557ABBE5C34C5A63" + m_functionName: + m_description: Creates a flow effect which can be given from a flow map. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: My noise category + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flow.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flow.asset.meta new file mode 100644 index 0000000..1bf2997 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Flow.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: acad10cc8145e1f4eb8042bebe2d9a42 +timeCreated: 1575558674 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Four Splats First Pass Terrain.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Four Splats First Pass Terrain.asset new file mode 100644 index 0000000..18cbf7b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Four Splats First Pass Terrain.asset @@ -0,0 +1,101 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Four Splats First Pass Terrain + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18903\n-2137;98;1030;1062;3248.526;5496.417;3.217857;True;False\nNode;AmplifyShaderEditor.CommentaryNode;252;-1586,-4578.742;Inherit;False;2177.426;1916.196;;41;270;224;238;239;264;227;265;223;250;249;248;246;247;245;251;236;237;242;234;228;241;240;243;226;229;235;233;232;253;244;259;222;221;256;263;262;255;261;260;254;258;Layer + Tint;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;159;252.6284,2169.96;Inherit;False;917.8029;677.2048;;10;140;139;138;130;113;112;114;137;111;141;Compute + Masks;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;69;97.99105,251.4516;Inherit;False;1299.523;553.9363;;9;217;220;212;213;216;45;58;215;214;Smoothness;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;209;-339.216,268.535;Inherit;False;408.144;170.0303;;2;46;47;Old + Smoothness;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;66;-75.88382,1489.471;Inherit;False;1596.247;581.4266;;13;54;56;57;48;49;50;203;53;219;202;55;204;51;Metallic;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;64;-1838.406,612.7104;Inherit;False;1582.024;883.2601;;14;11;73;71;72;10;1;70;14;12;8;2;61;84;85;Normal;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;67;-23.4915,-70.91965;Inherit;False;686.1986;184.0211;;3;27;19;62;Alpha;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;170;296.9723,2913.144;Inherit;False;827.0509;423.9417;;10;149;158;157;156;155;151;153;152;150;154;Mask + Smoothness;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;95;-70.55766,-610.683;Inherit;False;758.3281;346.0931;;3;99;100;98;Holes;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;68;-84.15448,1030.644;Inherit;False;1134.33;398.6418;Comment;8;17;77;80;75;78;16;76;81;Tangents;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;171;303.88,3430.155;Inherit;False;807.0508;423.9419;;10;165;164;169;168;163;162;161;160;166;167;Mask + Metallic;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;182;303.4217,3942.71;Inherit;False;812.6509;423.9421;;10;177;176;181;180;175;174;173;172;179;178;Mask + Occlusion;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;199;416.7253,4483.475;Inherit;False;1281.122;462.335;;9;201;198;197;218;200;192;195;196;193;Occlusion;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;129;-954.9393,2741.565;Inherit;False;1210.908;2784.683;;21;124;123;122;128;127;125;126;132;133;134;135;131;136;121;103;104;105;106;188;189;191;Mask + Variables;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;63;-2707.89,-60.62326;Inherit;False;1931.073;500.6417;Comment;10;24;20;5;74;22;59;23;26;25;21;Control;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;65;-1745.172,-2649.6;Inherit;False;1607.268;2363.729;;31;269;7;44;42;43;32;267;31;41;40;6;39;266;38;36;30;37;3;210;205;206;28;60;9;33;34;257;35;4;29;207;Albedo;1,1,1,1;0;0\nNode;AmplifyShaderEditor.GetLocalVarNode;174;357.6143,4251.252;Inherit;False;141;mask3;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;169;886.1307,3557.652;Inherit;False;maskMetallic;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.DynamicAppendNode;55;297.546,1713.904;Inherit;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionInput;58;931.6936,507.8923;Inherit;False;Custom + Smoothness;1;4;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;71;-1808,880;Inherit;False;0;3;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.RangedFloatNode;134;-859.5417,5329.349;Inherit;False;Global;_LayerHasMask3;_LayerHasMask3;23;0;Create;True;0;0;0;False;0;False;0;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;201;1243.743,4725.404;Inherit;False;Custom + Occlusion;1;5;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;180;731.0833,4065.856;Inherit;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.Vector4Node;127;-912,4304;Inherit;False;Global;_MaskMapRemapScale2;_MaskMapRemapScale2;23;0;Create;True;0;0;0;True;0;False;0,0,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleAddOpNode;190;-287.0641,3742.854;Inherit;False;2;2;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;73;-1808,1312;Inherit;False;0;7;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SwizzleNode;167;529.8993,3726.496;Inherit;False;FLOAT;0;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;85;-614.1091,1096.369;Inherit;False;Draw + SRP Per Pixel Normals;True;0;2;-1;In 0;In 1;Object;-1;9;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RangedFloatNode;133;-846.5417,5243.348;Inherit;False;Global;_LayerHasMask2;_LayerHasMask2;23;0;Create;True;0;0;0;False;0;False;0;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;195;441.4373,4605.778;Inherit;False;191;defaultOcclusion;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SamplerNode;1;-1568,864;Inherit;True;Property;_Normal1;Normal1;7;1;[HideInInspector];Create;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;61;-637.6442,821.6487;Inherit;False;Custom + Normal;3;2;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.Vector4Node;122;-930.8565,3265.366;Inherit;False;Global;_MaskMapRemapOffset1;_MaskMapRemapOffset1;23;0;Create;True;0;0;0;True;0;False;0,0,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.DotProductOpNode;53;1011.853,1573.078;Inherit;False;2;0;COLOR;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SwizzleNode;178;529.441,4159.051;Inherit;False;FLOAT;1;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;4;-1604.067,-2423.468;Inherit;True;Property;_Splat0;Splat0;5;1;[HideInInspector];Create;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.GetLocalVarNode;150;353.9599,2963.144;Inherit;False;138;mask0;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.Vector4Node;123;-935.1711,3467.736;Inherit;False;Global;_MaskMapRemapOffset2;_MaskMapRemapOffset2;23;0;Create;True;0;0;0;True;0;False;0,0,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.RangedFloatNode;48;-25.88388,1619.345;Float;False;Property;_Metallic0;Metallic0;14;2;[HideInInspector];[Gamma];Create;True;0;0;0;False;0;False;0;0;0;1;0;1;FLOAT;0\nNode;AmplifyShaderEditor.CustomExpressionNode;130;625.6312,2412.965;Inherit;False;masks0 + = 0.5h@$masks1 = 0.5h@$masks2 = 0.5h@$masks3 = 0.5h@$#ifdef _MASKMAP$masks0 = + lerp(masks0, SAMPLE_TEXTURE2D(_Mask0, sampler_Mask0, uvMask0), hasMask.x)@$masks1 + = lerp(masks1, SAMPLE_TEXTURE2D(_Mask1, sampler_Mask0, uvMask1), hasMask.y)@$masks2 + = lerp(masks2, SAMPLE_TEXTURE2D(_Mask2, sampler_Mask0, uvMask2), hasMask.z)@$masks3 + = lerp(masks3, SAMPLE_TEXTURE2D(_Mask3, sampler_Mask0, uvMask3), hasMask.w)@$#endif$masks0 + *= _MaskMapRemapScale0.rgba@$masks0 += _MaskMapRemapOffset0.rgba@$masks1 *= _MaskMapRemapScale1.rgba@$masks1 + += _MaskMapRemapOffset1.rgba@$masks2 *= _MaskMapRemapScale2.rgba@$masks2 += _MaskMapRemapOffset2.rgba@$masks3 + *= _MaskMapRemapScale3.rgba@$masks3 += _MaskMapRemapOffset3.rgba@;7;Create;9;True;masks0;FLOAT4;0,0,0,0;Out;;Inherit;False;True;masks1;FLOAT4;0,0,0,0;Out;;Inherit;False;True;masks2;FLOAT4;0,0,0,0;Out;;Inherit;False;True;masks3;FLOAT4;0,0,0,0;Out;;Inherit;False;False;hasMask;FLOAT4;0,0,0,0;In;;Inherit;False;False;uvMask0;FLOAT2;0,0;In;;Inherit;False;False;uvMask1;FLOAT2;0,0;In;;Inherit;False;False;uvMask2;FLOAT2;0,0;In;;Inherit;False;True;uvMask3;FLOAT2;0,0;In;;Inherit;False;ComputeMasks;True;False;0;;False;10;0;FLOAT;0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;3;FLOAT4;0,0,0,0;False;4;FLOAT4;0,0,0,0;False;5;FLOAT4;0,0,0,0;False;6;FLOAT2;0,0;False;7;FLOAT2;0,0;False;8;FLOAT2;0,0;False;9;FLOAT2;0,0;False;5;FLOAT;0;FLOAT4;2;FLOAT4;3;FLOAT4;4;FLOAT4;5\nNode;AmplifyShaderEditor.DynamicAppendNode;188;-485.4102,3647.58;Inherit;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SamplerNode;98;-48.01836,-552.3624;Inherit;True;Property;_TerrainHolesTexture;_TerrainHolesTexture;0;1;[HideInInspector];Create;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.RangedFloatNode;132;-848.5417,5153.348;Inherit;False;Global;_LayerHasMask1;_LayerHasMask1;23;0;Create;True;0;0;0;False;0;False;0;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;22;-2261.105,164.0728;Float;False;SplatWeight;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;189;-460.6728,3882.633;Inherit;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;26;-1568,16;Float;False;SplatControl;-1;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SwizzleNode;177;529.441,4079.052;Inherit;False;FLOAT;1;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;203;411.0664,1824.774;Inherit;False;169;maskMetallic;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;23;-1712,16;Inherit;False;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;181;885.6727,4070.208;Inherit;False;maskOcclusion;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.UnpackScaleNormalNode;12;-898.4255,806.7103;Inherit;False;2;0;FLOAT4;0,0,0,0;False;1;FLOAT;1;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.Vector4Node;125;-912,3904;Inherit;False;Global;_MaskMapRemapScale0;_MaskMapRemapScale0;23;0;Create;True;0;0;0;True;0;False;0,0,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.RegisterLocalVarNode;136;-415.5418,5176.348;Inherit;False;layerHasMask;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;198;884.6371,4816.325;Inherit;False;26;SplatControl;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.RangedFloatNode;51;-8.215824,1904.193;Float;False;Property;_Metallic3;Metallic3;16;2;[HideInInspector];[Gamma];Create;True;0;0;0;False;0;False;0;0;0;1;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SummedBlendNode;8;-1106.425,902.7103;Inherit;False;5;0;FLOAT4;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;3;COLOR;0,0,0,0;False;4;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.Vector4Node;21;-2689.97,184.6759;Float;False;Constant;_Vector0;Vector + 0;9;0;Create;True;0;0;0;False;0;False;1,1,1,1;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.DynamicAppendNode;168;731.5413,3553.301;Inherit;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.CustomExpressionNode;100;514.496,-539.1801;Inherit;False;#ifdef + _ALPHATEST_ON$\tclip(Hole == 0.0f ? -1 : 1)@$#endif;1;Call;1;True;Hole;FLOAT;0;In;;Inherit;False;ClipHoles;False;False;0;;False;2;0;FLOAT4;0,0,0,0;False;1;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RangedFloatNode;25;-2144,256;Float;False;Constant;_Float0;Float + 0;9;0;Create;True;0;0;0;False;0;False;0.001;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;29;-1695.172,-2521.711;Float;False;Property;_Smoothness0;Smoothness0;12;1;[HideInInspector];Create;True;0;0;0;False;0;False;1;0;0;1;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;207;-561.7282,-2497.895;Inherit;False;2;2;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.Vector4Node;126;-912,4112;Inherit;False;Global;_MaskMapRemapScale1;_MaskMapRemapScale1;23;0;Create;True;0;0;0;True;0;False;0,0,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.GetLocalVarNode;162;358.0726,3738.697;Inherit;False;141;mask3;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.DotProductOpNode;20;-2392.622,167.361;Inherit;False;2;0;COLOR;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;258;-685.2346,-4478.496;Inherit;False;FLOAT4;4;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;254;-437,-4042;Inherit;False;tintLayer1;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RangedFloatNode;260;-724.2346,-3862.496;Inherit;False;Constant;_Float7;Float + 6;27;0;Create;True;0;0;0;False;0;False;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;261;-594.2346,-4040.496;Inherit;False;FLOAT4;4;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;255;-375,-3645;Inherit;False;tintLayer2;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RangedFloatNode;262;-707.2346,-3425.496;Inherit;False;Constant;_Float8;Float + 6;27;0;Create;True;0;0;0;False;0;False;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;263;-577.2346,-3603.496;Inherit;False;FLOAT4;4;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;256;-424,-3165;Inherit;False;tintLayer3;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SamplerNode;5;-2698.008,-13.10038;Inherit;True;Property;_Control;Control;1;1;[HideInInspector];Create;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;101;112.4228,-666.2932;Inherit;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;175;356.217,4076.562;Inherit;False;139;mask1;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RangedFloatNode;131;-861.5417,5073.348;Inherit;False;Global;_LayerHasMask0;_LayerHasMask0;23;0;Create;True;0;0;0;False;0;False;0;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;24;-1836.506,177.3755;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;153;351.1649,3221.686;Inherit;False;141;mask3;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;114;305.6313,2684.965;Inherit;False;0;7;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.StaticSwitch;84;-1024.719,1119.15;Inherit;False;Property;_EnablePerpixelNormals;Enable + Per-pixel Normals;18;0;Create;True;0;0;0;False;0;False;0;0;0;True;_TERRAIN_INSTANCED_PERPIXEL_NORMAL;Toggle;2;Key0;Key1;Create;True;False;9;1;FLOAT3;0,0,0;False;0;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;4;FLOAT3;0,0,0;False;5;FLOAT3;0,0,0;False;6;FLOAT3;0,0,0;False;7;FLOAT3;0,0,0;False;8;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;149;879.2237,3040.641;Inherit;False;maskSmoothness;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.Vector4Node;121;-941.6769,3065.909;Inherit;False;Global;_MaskMapRemapOffset0;_MaskMapRemapOffset0;23;0;Create;True;0;0;0;True;0;False;0,0,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.GetLocalVarNode;269;-1436.563,-486.7653;Inherit;False;256;tintLayer3;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RangedFloatNode;259;-815.2346,-4300.496;Inherit;False;Constant;_Float6;Float + 6;27;0;Create;True;0;0;0;False;0;False;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;244;-944,-4496;Inherit;False;4;0;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;70;-1808,688;Inherit;False;0;4;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;2;-1570.425,662.7104;Inherit;True;Property;_Normal0;Normal0;6;1;[HideInInspector];Create;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.GetLocalVarNode;257;-1522.68,-2215.868;Inherit;False;253;tintLayer0;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;253;-459,-4502;Inherit;False;tintLayer0;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RangedFloatNode;34;-1551.94,-2599.6;Float;False;Constant;_Float1;Float + 1;13;0;Create;True;0;0;0;False;0;False;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;172;360.4093,3992.71;Inherit;False;138;mask0;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;72;-1808,1072;Inherit;False;0;6;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.GetLocalVarNode;204;418.8666,1933.974;Inherit;False;136;layerHasMask;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SwizzleNode;165;529.8993,3566.496;Inherit;False;FLOAT;0;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LerpOp;215;389.3123,504.1568;Inherit;False;3;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SwizzleNode;164;529.8993,3486.496;Inherit;False;FLOAT;0;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;152;346.9723,3130.847;Inherit;False;140;mask2;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;191;-119.3642,3742.854;Inherit;False;defaultOcclusion;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;78;152.2551,1153.509;Inherit;False;3;3;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SwizzleNode;166;529.8993,3646.496;Inherit;False;FLOAT;0;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;59;-1356.444,20.82132;Inherit;False;Custom + Control;4;0;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionInput;62;288.6909,-19.04097;Inherit;False;Custom + Alpha;1;6;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;7;-1574.537,-761.6443;Inherit;True;Property;_Splat3;Splat3;2;1;[HideInInspector];Create;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SwizzleNode;155;522.9917,3049.485;Inherit;False;FLOAT;3;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.Vector4Node;128;-912,4496;Inherit;False;Global;_MaskMapRemapScale3;_MaskMapRemapScale3;23;0;Create;True;0;0;0;True;0;False;0,0,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;219;829.7055,1679.817;Inherit;False;4;0;FLOAT4;0,0,0,0;False;3;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.NormalVertexDataNode;81;-66.2998,1212.924;Inherit;False;0;5;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.Vector4Node;124;-934.2458,3669.353;Inherit;False;Global;_MaskMapRemapOffset3;_MaskMapRemapOffset3;23;0;Create;True;0;0;0;True;0;False;0,0,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;35;-1212.452,-2477.088;Inherit;False;3;3;0;FLOAT4;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SwizzleNode;156;522.9917,3129.485;Inherit;False;FLOAT;3;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;137;327.5631,2219.96;Inherit;False;136;layerHasMask;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;99;252.4595,-530.1924;Inherit;False;holeClipValue;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LerpOp;202;657.944,1768.564;Inherit;False;3;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SwizzleNode;179;529.441,4239.051;Inherit;False;FLOAT;1;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SwizzleNode;232;-1280,-3872;Inherit;False;FLOAT3;0;1;2;3;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;151;349.7676,3046.995;Inherit;False;139;mask1;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;233;-1120,-3968;Inherit;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DynamicAppendNode;33;-1404.325,-2595.872;Inherit;False;FLOAT4;4;0;FLOAT;1;False;1;FLOAT;1;False;2;FLOAT;1;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.TangentVertexDataNode;77;-72.23888,1072.639;Inherit;False;0;0;5;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.GetLocalVarNode;193;440.4074,4760.303;Inherit;False;136;layerHasMask;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.DotProductOpNode;197;1089.656,4723.663;Inherit;False;2;0;FLOAT4;0,0,0,0;False;1;COLOR;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;214;154.0529,668.0095;Inherit;False;136;layerHasMask;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RangedFloatNode;80;-45.98957,1349.331;Float;False;Constant;_Float5;Float + 5;17;0;Create;True;0;0;0;False;0;False;0;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SummedBlendNode;9;-801.6271,-1321.763;Inherit;False;5;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;3;FLOAT4;0,0,0,0;False;4;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;196;440.4074,4680.303;Inherit;False;181;maskOcclusion;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;113;305.6313,2556.965;Inherit;False;0;6;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;75;647.9054,1106.737;Inherit;False;4;0;FLOAT;0;False;3;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;57;1177.389,1568.532;Inherit;False;Custom + Metallic;1;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;173;353.4217,4160.415;Inherit;False;140;mask2;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionInput;60;-335.3854,-1405.575;Inherit;False;Custom + Albedo;4;1;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.TexturePropertyNode;103;-867.7384,2839.526;Inherit;True;Property;_Mask0;_Mask0;20;1;[HideInInspector];Create;True;0;0;0;True;0;False;None;None;False;white;Auto;Texture2D;-1;0;2;SAMPLER2D;0;SAMPLERSTATE;1\nNode;AmplifyShaderEditor.DotProductOpNode;216;817.0565,513.2891;Inherit;False;2;0;FLOAT4;0,0,0,0;False;1;COLOR;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;141;940.2234,2675.739;Inherit;False;mask3;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionSwitch;102;791.2579,-704.1357;Inherit;False;Activate + Holes;True;1;2;-1;In 0;In 1;Object;-1;9;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;235;-1520,-4000;Inherit;False;26;SplatControl;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.DynamicAppendNode;205;-760.6844,-2561.812;Inherit;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;139;929.6311,2444.965;Inherit;False;mask1;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;111;302.6284,2306.024;Inherit;False;0;4;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;229;-1104,-4352;Inherit;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SwizzleNode;226;-1312,-4256;Inherit;False;FLOAT3;0;1;2;3;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;140;944.0311,2564.296;Inherit;False;mask2;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.LerpOp;192;664.4073,4664.303;Inherit;False;3;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RangedFloatNode;50;-19.21585,1806.193;Float;False;Property;_Metallic2;Metallic2;15;2;[HideInInspector];[Gamma];Create;True;0;0;0;False;0;False;0;0;0;1;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;28;-595.3801,-1327.405;Float;False;MixDiffuse;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;160;360.8676,3480.155;Inherit;False;138;mask0;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.DynamicAppendNode;158;724.6343,3036.289;Inherit;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.TexturePropertyNode;105;-434.9858,2836.898;Inherit;True;Property;_Mask2;_Mask2;19;1;[HideInInspector];Create;True;0;0;0;True;0;False;None;None;False;white;Auto;Texture2D;-1;0;2;SAMPLER2D;0;SAMPLERSTATE;1\nNode;AmplifyShaderEditor.GetLocalVarNode;163;356.6753,3564.007;Inherit;False;139;mask1;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;243;-1504,-3088;Inherit;False;26;SplatControl;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.SwizzleNode;240;-1264,-2944;Inherit;False;FLOAT3;0;1;2;3;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;241;-1104,-3088;Inherit;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SwizzleNode;228;-1328,-4384;Inherit;False;FLOAT3;0;0;0;3;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SwizzleNode;234;-1312,-3984;Inherit;False;FLOAT3;1;1;1;3;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SamplerNode;10;-1568,1072;Inherit;True;Property;_Normal2;Normal2;8;1;[HideInInspector];Create;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SwizzleNode;154;522.9917,2969.485;Inherit;False;FLOAT;3;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SwizzleNode;242;-1313,-3088;Inherit;False;FLOAT3;3;3;3;3;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RangedFloatNode;49;-24.21591,1708.193;Float;False;Property;_Metallic1;Metallic1;17;2;[HideInInspector];[Gamma];Create;True;0;0;0;False;0;False;0;0;0;1;0;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;213;128.0529,504.0095;Inherit;False;149;maskSmoothness;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;217;414.0565,655.2891;Inherit;False;26;SplatControl;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;220;570.5651,410.0537;Inherit;False;4;0;FLOAT4;0,0,0,0;False;3;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SwizzleNode;47;-82.6719,320.1653;Inherit;False;FLOAT;3;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CustomExpressionNode;74;-2041.122,125.4553;Float;False;#if + !defined(SHADER_API_MOBILE) && defined(TERRAIN_SPLAT_ADDPASS)$\tclip(SplatWeight + == 0.0f ? -1 : 1)@$#endif;1;Call;1;True;SplatWeight;FLOAT;0;In;;Float;False;SplatClip;False;False;0;;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;210;-394.5478,-2471.56;Inherit;False;defaultSmoothness;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.DynamicAppendNode;206;-766.3322,-2394.8;Inherit;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;46;-289.2161,318.535;Inherit;False;28;MixDiffuse;1;0;OBJECT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;54;680.1399,1554.148;Inherit;False;26;SplatControl;1;0;OBJECT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.DynamicAppendNode;135;-622.5417,5160.348;Inherit;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SamplerNode;11;-1568,1280;Inherit;True;Property;_Normal3;Normal3;9;1;[HideInInspector];Create;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;218;867.7135,4622.045;Inherit;False;4;0;FLOAT4;0,0,0,0;False;3;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;212;101.0529,324.0095;Inherit;False;210;defaultSmoothness;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.CustomExpressionNode;16;395.9061,1093.737;Float;False;v.tangent.xyz + = cross ( v.normal, float3( 0, 0, 1 ) )@$v.tangent.w = -1@;1;Call;0;CalculateTangentsStandard;True;False;0;;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.TexturePropertyNode;106;-219.8126,2839.176;Inherit;True;Property;_Mask3;_Mask3;22;1;[HideInInspector];Create;True;0;0;0;True;0;False;None;None;False;white;Auto;Texture2D;-1;0;2;SAMPLER2D;0;SAMPLERSTATE;1\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;237;-1073.023,-3535.196;Inherit;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SwizzleNode;236;-1249.023,-3423.196;Inherit;False;FLOAT3;0;1;2;3;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;251;-924.545,-3181.242;Inherit;False;4;0;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.Vector3Node;245;-1120,-4528;Inherit;False;Constant;_Vector1;Vector + 1;27;0;Create;True;0;0;0;False;0;False;1,1,1;0,0,0;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;247;-928,-4048;Inherit;False;4;0;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.Vector3Node;246;-1152,-4144;Inherit;False;Constant;_Vector2;Vector + 1;27;0;Create;True;0;0;0;False;0;False;1,1,1;0,0,0;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.Vector3Node;248;-1152,-3744;Inherit;False;Constant;_Vector3;Vector + 1;27;0;Create;True;0;0;0;False;0;False;1,1,1;0,0,0;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;249;-912,-3648;Inherit;False;4;0;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.Vector3Node;250;-1133.545,-3290.242;Inherit;False;Constant;_Vector4;Vector + 1;27;0;Create;True;0;0;0;False;0;False;1,1,1;0,0,0;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.TextureCoordinatesNode;112;305.6313,2427.848;Inherit;False;0;3;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.GetLocalVarNode;161;353.88,3647.859;Inherit;False;140;mask2;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;138;945.6311,2284.965;Inherit;False;mask0;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SwizzleNode;157;522.9917,3209.485;Inherit;False;FLOAT;3;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;265;-588.2346,-3138.496;Inherit;False;FLOAT4;4;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SwizzleNode;176;529.441,3999.052;Inherit;False;FLOAT;1;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CustomExpressionNode;76;346.3839,1191.393;Float;False;v.ase_tangent.xyz + = cross ( v.ase_normal, float3( 0, 0, 1 ) )@$v.ase_tangent.w = -1@;1;Call;0;CalculateTangentsSRP;True;False;0;;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;227;-1536,-4384;Inherit;False;26;SplatControl;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.RangedFloatNode;264;-762.2346,-2984.496;Inherit;False;Constant;_Float9;Float + 6;27;0;Create;True;0;0;0;False;0;False;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;3;-1593.087,-1888.93;Inherit;True;Property;_Splat1;Splat1;4;1;[HideInInspector];Create;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.RangedFloatNode;37;-1562.174,-2063.607;Float;False;Constant;_Float2;Float + 2;13;0;Create;True;0;0;0;False;0;False;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;30;-1686.317,-1982.215;Float;False;Property;_Smoothness1;Smoothness1;11;1;[HideInInspector];Create;True;0;0;0;False;0;False;1;0;0;1;0;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;36;-1408.004,-2079.365;Inherit;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;27;26.5085,-20.91957;Inherit;False;22;SplatWeight;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;266;-1461.644,-1691.477;Inherit;False;254;tintLayer1;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.DynamicAppendNode;39;-1425.281,-1522.915;Inherit;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SamplerNode;6;-1567.664,-1354.183;Inherit;True;Property;_Splat2;Splat2;3;1;[HideInInspector];Create;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;38;-1217.042,-1975.033;Inherit;False;3;3;0;FLOAT4;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;41;-1253.081,-1379.023;Inherit;False;3;3;0;FLOAT4;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;239;-1505.854,-3559.323;Inherit;False;26;SplatControl;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.SwizzleNode;238;-1297.023,-3567.196;Inherit;False;FLOAT3;2;2;2;3;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RangedFloatNode;40;-1587.667,-1526.298;Float;False;Constant;_Float3;Float + 3;13;0;Create;True;0;0;0;False;0;False;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.TexturePropertyNode;104;-649.9539,2840.603;Inherit;True;Property;_Mask1;_Mask1;21;1;[HideInInspector];Create;True;0;0;0;True;0;False;None;None;False;white;Auto;Texture2D;-1;0;2;SAMPLER2D;0;SAMPLERSTATE;1\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;44;-1217.623,-874.4141;Inherit;False;3;3;0;FLOAT4;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RangedFloatNode;43;-1556.608,-1008.322;Float;False;Constant;_Float4;Float + 4;13;0;Create;True;0;0;0;False;0;False;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;32;-1670.563,-880.3899;Float;False;Property;_Smoothness3;Smoothness3;10;1;[HideInInspector];Create;True;0;0;0;False;0;False;1;0;0;1;0;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;267;-1408.563,-1125.765;Inherit;False;255;tintLayer2;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.RangedFloatNode;31;-1696.902,-1434.615;Float;False;Property;_Smoothness2;Smoothness2;13;1;[HideInInspector];Create;True;0;0;0;False;0;False;1;0;0;1;0;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;42;-1379.608,-967.3223;Inherit;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.StickyNoteNode;270;-175.1112,-4469.897;Inherit;False;576;423;Usage + on URP;;0.7205882,0.2331315,0.2331315,1;For the user to be able to set tint color + over URP, the UnityEditor.Rendering.Universal.TerrainLitShaderGUI must be set + over the Custom Inspector. Unity must be reloaded for it to take effect over the + terrain custom inspector.;0;0\nNode;AmplifyShaderEditor.ColorNode;221;-1531.898,-4254.082;Inherit;False;Global;_DiffuseRemapScale0;_DiffuseRemapScale0;23;0;Create;True;0;0;0;False;0;False;1,1,1,1;0,0,0,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.ColorNode;222;-1520,-3872;Inherit;False;Global;_DiffuseRemapScale1;_DiffuseRemapScale1;23;0;Create;True;0;0;0;False;0;False;1,1,1,1;0,0,0,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.ColorNode;223;-1481.145,-3434.682;Inherit;False;Global;_DiffuseRemapScale2;_DiffuseRemapScale2;23;0;Create;True;0;0;0;False;0;False;1,1,1,1;0,0,0,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.ColorNode;224;-1488,-2944;Inherit;False;Global;_DiffuseRemapScale3;_DiffuseRemapScale3;23;0;Create;True;0;0;0;False;0;False;1,1,1,1;0,0,0,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionOutput;200;1474.611,4755.851;Inherit;False;False;-1;Occlusion;4;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;56;1366.832,1559.547;Inherit;False;False;-1;Metallic;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;14;-417.8965,823.1106;Inherit;False;False;-1;Normal;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;17;887.9049,1074.737;Inherit;False;False;-1;Tangents;6;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;45;1145.995,514.5017;Inherit;False;False;-1;Smoothness;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;19;493.604,-31.32466;Inherit;False;False;-1;Alpha;5;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;1098.414,-685.4164;Inherit;False;True;-1;Albedo;0;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nWireConnection;169;0;168;0\nWireConnection;55;0;48;0\nWireConnection;55;1;49;0\nWireConnection;55;2;50;0\nWireConnection;55;3;51;0\nWireConnection;58;0;216;0\nWireConnection;201;0;197;0\nWireConnection;180;0;176;0\nWireConnection;180;1;177;0\nWireConnection;180;2;178;0\nWireConnection;180;3;179;0\nWireConnection;190;0;188;0\nWireConnection;190;1;189;0\nWireConnection;167;0;162;0\nWireConnection;85;0;61;0\nWireConnection;85;1;84;0\nWireConnection;1;1;71;0\nWireConnection;61;0;12;0\nWireConnection;53;0;54;0\nWireConnection;53;1;219;0\nWireConnection;178;0;173;0\nWireConnection;130;5;137;0\nWireConnection;130;6;111;0\nWireConnection;130;7;112;0\nWireConnection;130;8;113;0\nWireConnection;130;9;114;0\nWireConnection;188;0;121;2\nWireConnection;188;1;122;2\nWireConnection;188;2;123;2\nWireConnection;188;3;124;2\nWireConnection;22;0;20;0\nWireConnection;189;0;125;2\nWireConnection;189;1;126;2\nWireConnection;189;2;127;2\nWireConnection;189;3;128;2\nWireConnection;26;0;23;0\nWireConnection;177;0;175;0\nWireConnection;23;0;5;0\nWireConnection;23;1;24;0\nWireConnection;181;0;180;0\nWireConnection;12;0;8;0\nWireConnection;136;0;135;0\nWireConnection;8;0;59;0\nWireConnection;8;1;2;0\nWireConnection;8;2;1;0\nWireConnection;8;3;10;0\nWireConnection;8;4;11;0\nWireConnection;168;0;164;0\nWireConnection;168;1;165;0\nWireConnection;168;2;166;0\nWireConnection;168;3;167;0\nWireConnection;100;0;101;0\nWireConnection;100;1;99;0\nWireConnection;207;0;205;0\nWireConnection;207;1;206;0\nWireConnection;20;0;5;0\nWireConnection;20;1;21;0\nWireConnection;258;0;244;0\nWireConnection;258;3;259;0\nWireConnection;254;0;261;0\nWireConnection;261;0;247;0\nWireConnection;261;3;260;0\nWireConnection;255;0;263;0\nWireConnection;263;0;249;0\nWireConnection;263;3;262;0\nWireConnection;256;0;265;0\nWireConnection;101;0;60;0\nWireConnection;24;0;74;0\nWireConnection;24;1;25;0\nWireConnection;84;1;61;0\nWireConnection;84;0;61;0\nWireConnection;149;0;158;0\nWireConnection;244;0;245;0\nWireConnection;244;3;245;0\nWireConnection;244;1;229;0\nWireConnection;244;2;245;0\nWireConnection;2;1;70;0\nWireConnection;253;0;258;0\nWireConnection;165;0;163;0\nWireConnection;215;0;212;0\nWireConnection;215;1;213;0\nWireConnection;215;2;214;0\nWireConnection;164;0;160;0\nWireConnection;191;0;190;0\nWireConnection;78;0;77;0\nWireConnection;78;1;81;0\nWireConnection;78;2;80;0\nWireConnection;166;0;161;0\nWireConnection;59;0;26;0\nWireConnection;62;0;27;0\nWireConnection;155;0;151;0\nWireConnection;219;0;55;0\nWireConnection;219;3;55;0\nWireConnection;219;1;202;0\nWireConnection;219;2;202;0\nWireConnection;35;0;33;0\nWireConnection;35;1;4;0\nWireConnection;35;2;257;0\nWireConnection;156;0;152;0\nWireConnection;99;0;98;1\nWireConnection;202;0;55;0\nWireConnection;202;1;203;0\nWireConnection;202;2;204;0\nWireConnection;179;0;174;0\nWireConnection;232;0;222;0\nWireConnection;233;0;234;0\nWireConnection;233;1;232;0\nWireConnection;33;0;34;0\nWireConnection;33;1;34;0\nWireConnection;33;2;34;0\nWireConnection;33;3;29;0\nWireConnection;197;0;218;0\nWireConnection;197;1;198;0\nWireConnection;9;0;59;0\nWireConnection;9;1;35;0\nWireConnection;9;2;38;0\nWireConnection;9;3;41;0\nWireConnection;9;4;44;0\nWireConnection;75;0;16;0\nWireConnection;75;3;76;0\nWireConnection;75;1;76;0\nWireConnection;75;2;76;0\nWireConnection;57;0;53;0\nWireConnection;60;0;28;0\nWireConnection;216;0;220;0\nWireConnection;216;1;217;0\nWireConnection;141;0;130;5\nWireConnection;102;0;60;0\nWireConnection;102;1;100;0\nWireConnection;205;0;29;0\nWireConnection;205;1;30;0\nWireConnection;205;2;31;0\nWireConnection;205;3;32;0\nWireConnection;139;0;130;3\nWireConnection;229;0;228;0\nWireConnection;229;1;226;0\nWireConnection;226;0;221;0\nWireConnection;140;0;130;4\nWireConnection;192;0;195;0\nWireConnection;192;1;196;0\nWireConnection;192;2;193;0\nWireConnection;28;0;9;0\nWireConnection;158;0;154;0\nWireConnection;158;1;155;0\nWireConnection;158;2;156;0\nWireConnection;158;3;157;0\nWireConnection;240;0;224;0\nWireConnection;241;0;242;0\nWireConnection;241;1;240;0\nWireConnection;228;0;227;0\nWireConnection;234;0;235;0\nWireConnection;10;1;72;0\nWireConnection;154;0;150;0\nWireConnection;242;0;243;0\nWireConnection;220;0;212;0\nWireConnection;220;3;212;0\nWireConnection;220;1;215;0\nWireConnection;220;2;215;0\nWireConnection;47;0;46;0\nWireConnection;74;0;22;0\nWireConnection;74;1;22;0\nWireConnection;210;0;207;0\nWireConnection;206;0;4;4\nWireConnection;206;1;3;4\nWireConnection;206;2;6;4\nWireConnection;206;3;7;4\nWireConnection;135;0;131;0\nWireConnection;135;1;132;0\nWireConnection;135;2;133;0\nWireConnection;135;3;134;0\nWireConnection;11;1;73;0\nWireConnection;218;0;195;0\nWireConnection;218;3;195;0\nWireConnection;218;1;192;0\nWireConnection;218;2;192;0\nWireConnection;237;0;238;0\nWireConnection;237;1;236;0\nWireConnection;236;0;223;0\nWireConnection;251;0;250;0\nWireConnection;251;3;250;0\nWireConnection;251;1;241;0\nWireConnection;251;2;250;0\nWireConnection;247;0;246;0\nWireConnection;247;3;246;0\nWireConnection;247;1;233;0\nWireConnection;247;2;246;0\nWireConnection;249;0;248;0\nWireConnection;249;3;248;0\nWireConnection;249;1;237;0\nWireConnection;249;2;248;0\nWireConnection;138;0;130;2\nWireConnection;157;0;153;0\nWireConnection;265;0;251;0\nWireConnection;265;3;264;0\nWireConnection;176;0;172;0\nWireConnection;76;0;78;0\nWireConnection;36;0;37;0\nWireConnection;36;1;37;0\nWireConnection;36;2;37;0\nWireConnection;36;3;30;0\nWireConnection;39;0;40;0\nWireConnection;39;1;40;0\nWireConnection;39;2;40;0\nWireConnection;39;3;31;0\nWireConnection;38;0;36;0\nWireConnection;38;1;3;0\nWireConnection;38;2;266;0\nWireConnection;41;0;39;0\nWireConnection;41;1;6;0\nWireConnection;41;2;267;0\nWireConnection;238;0;239;0\nWireConnection;44;0;42;0\nWireConnection;44;1;7;0\nWireConnection;44;2;269;0\nWireConnection;42;0;43;0\nWireConnection;42;1;43;0\nWireConnection;42;2;43;0\nWireConnection;42;3;32;0\nWireConnection;200;0;201;0\nWireConnection;56;0;57;0\nWireConnection;14;0;85;0\nWireConnection;17;0;75;0\nWireConnection;45;0;58;0\nWireConnection;19;0;62;0\nWireConnection;0;0;102;0\nASEEND*/\n//CHKSM=F04683E56427ADCFAB4D7B24E2D812548FF9154E" + m_functionName: + m_description: Creates a Standard Terrain shader. On main shader the tag SplatCount + must be created with a value of 4. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 1 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_customEdited: 0 + m_additionalDirectives: + - {fileID: 0} + - {fileID: 0} + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: + - LineType: 2 + LineValue: multi_compile_local __ _ALPHATEST_ON + GUIDToggle: 0 + GUIDValue: + Origin: 2 + - LineType: 2 + LineValue: shader_feature_local _MASKMAP + GUIDToggle: 0 + GUIDValue: + Origin: 2 + m_nodeCategory: 9 + m_customNodeCategory: Terrain + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Four Splats First Pass Terrain.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Four Splats First Pass Terrain.asset.meta new file mode 100644 index 0000000..e85e4e6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Four Splats First Pass Terrain.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 37452fdfb732e1443b7e39720d05b708 +timeCreated: 1513337564 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Grid.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Grid.asset new file mode 100644 index 0000000..6ed5ad4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Grid.asset @@ -0,0 +1,38 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Grid + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1462;-370;1004;726;1341.279;420.1091;1.453505;True;False\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;3;-928,0;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.ScaleAndOffsetNode;4;-656,0;Inherit;False;3;0;FLOAT2;0,0;False;1;FLOAT2;1,0;False;2;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;6;-848,208;Inherit;False;Offset;2;1;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;5;-864,128;Inherit;False;Tiling;2;0;False;1;0;FLOAT2;8,8;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionNode;1;-240,0;Inherit;True;Rectangle;-1;;1;6b23e0c975270fb4084c354b2c83366a;0;3;1;FLOAT2;0,0;False;2;FLOAT;0.5;False;3;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-415,77;Inherit;False;Size;1;2;False;1;0;FLOAT;0.9;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FractNode;7;-416,0;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;4;0;3;0\nWireConnection;4;1;5;0\nWireConnection;4;2;6;0\nWireConnection;1;1;7;0\nWireConnection;1;2;2;0\nWireConnection;1;3;2;0\nWireConnection;7;0;4;0\nWireConnection;0;0;1;0\nASEEND*/\n//CHKSM=8522C6065F43CA9B41D4DCA7DB4B032BEE05BFF8" + m_functionName: + m_description: Creates a rectangular shaped grid. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Grid.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Grid.asset.meta new file mode 100644 index 0000000..393f362 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Grid.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a9240ca2be7e49e4f9fa3de380c0dbe9 +timeCreated: 1586860862 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Half Lambert Term.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Half Lambert Term.asset new file mode 100644 index 0000000..f28ec2c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Half Lambert Term.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Half Lambert Term + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=13705\n487;595;979;423;884.665;200.5353;1.013844;True;False\nNode;AmplifyShaderEditor.FunctionInput;3;-640,-32;Float;False;World + Normal;3;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3\nNode;AmplifyShaderEditor.ScaleAndOffsetNode;6;-208,0;Float;False;3;0;FLOAT;0.0;False;1;FLOAT;1.0;False;2;FLOAT;0.0;False;1;FLOAT\nNode;AmplifyShaderEditor.WorldSpaceLightDirHlpNode;8;-672,64;Float;False;1;0;FLOAT;0.0;False;4;FLOAT3;FLOAT;FLOAT;FLOAT\nNode;AmplifyShaderEditor.RangedFloatNode;7;-416,96;Float;False;Constant;_RemapValue;Remap + Value;0;0;0.5;0;0;0;1;FLOAT\nNode;AmplifyShaderEditor.DotProductOpNode;5;-416,0;Float;False;2;0;FLOAT3;0,0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.WorldNormalVector;2;-864,-32;Float;False;1;0;FLOAT3;0,0,0;False;4;FLOAT3;FLOAT;FLOAT;FLOAT\nNode;AmplifyShaderEditor.FunctionOutput;0;16,0;Float;False;True;Out;0;1;0;FLOAT;0.0;False;0\nWireConnection;3;0;2;0\nWireConnection;6;0;5;0\nWireConnection;6;1;7;0\nWireConnection;6;2;7;0\nWireConnection;5;0;3;0\nWireConnection;5;1;8;0\nWireConnection;0;0;6;0\nASEEND*/\n//CHKSM=D225A64D2A31472128B6D003C45B4417097300C7" + m_functionName: + m_description: Generates a linear gradient from black to white that represents the + surface facing term to a light. Useful for cloth shading, skin or toon ramps. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_nodeCategory: 11 + m_customNodeCategory: Lighting Models diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Half Lambert Term.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Half Lambert Term.asset.meta new file mode 100644 index 0000000..568356e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Half Lambert Term.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 86299dc21373a954aa5772333626c9c1 +timeCreated: 1510234721 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Height-based Blending.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Height-based Blending.asset new file mode 100644 index 0000000..8158f31 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Height-based Blending.asset @@ -0,0 +1,44 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Height-based Blending + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17102\n1280.5;1;1278;1369;-764.8537;728.8295;1.036422;True;False\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;7;413,-443;Inherit;False;3;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;1;164.1368,-535.239;Inherit;False;Alpha;1;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;4;162.6766,-437.1684;Inherit;False;Height;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;5;236.3459,-320.3895;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;6;47.11577,-341;Float;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;22.54278,-256.0706;Inherit;False;Blend + Factor;1;4;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.PowerNode;8;886.6812,-337.8587;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;9;1092.221,-338.2482;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;10;663.4116,-374.5408;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;27.04797,-99.6286;Inherit;False;Blend + Falloff;1;5;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;11;422.4116,-240.5408;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LerpOp;14;1512.113,-459.3596;Inherit;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionInput;12;1247.828,-566.1115;Inherit;False;Bottom;5;1;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionInput;13;1246.79,-467.6507;Inherit;False;Top;5;0;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionOutput;15;1711.107,-460.3962;Inherit;False;False;Result;0;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionOutput;0;1519.228,-232.7731;Inherit;False;True;Alpha;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;7;0;1;0\nWireConnection;7;1;4;0\nWireConnection;7;2;5;0\nWireConnection;5;0;6;0\nWireConnection;5;1;2;0\nWireConnection;8;0;10;0\nWireConnection;8;1;11;0\nWireConnection;9;0;8;0\nWireConnection;10;0;7;0\nWireConnection;11;0;3;0\nWireConnection;14;0;12;0\nWireConnection;14;1;13;0\nWireConnection;14;2;9;0\nWireConnection;15;0;14;0\nWireConnection;0;0;9;0\nASEEND*/\n//CHKSM=EAEFB89C4A5CD1A06A1578CB7E39D908044F001C" + m_functionName: + m_description: Implements height-based blending to allow blending a bottom layer + to a top layer using a height map and a few control parameters, including alpha, + which can be from vertex color channel. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Height-based Blending.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Height-based Blending.asset.meta new file mode 100644 index 0000000..a7845b2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Height-based Blending.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 31c0084e26e17dc4c963d2f60261c022 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Herringbone.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Herringbone.asset new file mode 100644 index 0000000..1b94b60 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Herringbone.asset @@ -0,0 +1,38 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Herringbone + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1478;80;1004;726;3587.759;1370.986;3.835479;True;False\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;10;-1072,16;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;9;-1248,16;Inherit;False;Width;1;1;False;1;0;FLOAT;0.2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;3;-400,-176;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;4;-624,-304;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;35;-928,128;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RoundOpNode;36;-1104,128;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleRemainderNode;29;-1248,-128;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;1;-208,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;2;-416,192;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;5;-640,240;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;14;-880,240;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.StepOpNode;12;-640,368;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleRemainderNode;33;-880,400;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleRemainderNode;34;-880,-128;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleRemainderNode;31;-1264,400;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.StepOpNode;11;-624,-160;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;30;-1056,-128;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;32;-1056,400;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;6;-857.5597,0.1007617;Inherit;False;2;2;0;FLOAT;0.05;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;26;-880,-304;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;28;-1440,192;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RoundOpNode;18;-1760,-192;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;22;-1600,-304;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;27;-1408,-128;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;-1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;23;-1568,-128;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RoundOpNode;20;-1760,352;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;25;-1520,416;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;15;-2496,64;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;16;-2256,128;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;17;-2112,128;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.WireNode;38;-1810.665,-224.2363;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;24;-1520,304;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FloorOpNode;21;-1760,432;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FloorOpNode;19;-1760,-112;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;7;-2448,224;Inherit;False;Tiling;2;0;False;1;0;FLOAT2;6,6;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;8;-1600,128;Inherit;False;Cells;1;2;False;1;0;FLOAT;3;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;True;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;10;0;9;0\nWireConnection;3;0;4;0\nWireConnection;3;1;11;0\nWireConnection;4;0;26;0\nWireConnection;4;1;6;0\nWireConnection;4;2;10;0\nWireConnection;35;0;36;0\nWireConnection;36;0;8;0\nWireConnection;29;0;27;0\nWireConnection;29;1;28;0\nWireConnection;1;0;3;0\nWireConnection;1;1;2;0\nWireConnection;2;0;5;0\nWireConnection;2;1;12;0\nWireConnection;5;0;14;0\nWireConnection;5;1;6;0\nWireConnection;5;2;10;0\nWireConnection;14;0;24;0\nWireConnection;12;0;35;0\nWireConnection;12;1;33;0\nWireConnection;33;0;32;0\nWireConnection;33;1;28;0\nWireConnection;34;0;30;0\nWireConnection;34;1;28;0\nWireConnection;31;0;25;0\nWireConnection;31;1;28;0\nWireConnection;11;0;35;0\nWireConnection;11;1;34;0\nWireConnection;30;0;29;0\nWireConnection;30;1;28;0\nWireConnection;32;0;31;0\nWireConnection;32;1;28;0\nWireConnection;6;1;10;0\nWireConnection;26;0;22;0\nWireConnection;28;0;8;0\nWireConnection;18;0;17;0\nWireConnection;22;0;38;0\nWireConnection;22;1;18;0\nWireConnection;27;0;23;0\nWireConnection;23;0;18;0\nWireConnection;23;1;19;0\nWireConnection;20;0;17;1\nWireConnection;25;0;20;0\nWireConnection;25;1;21;0\nWireConnection;16;0;15;0\nWireConnection;16;1;7;0\nWireConnection;17;0;16;0\nWireConnection;38;0;17;0\nWireConnection;24;0;17;1\nWireConnection;24;1;20;0\nWireConnection;21;0;17;0\nWireConnection;19;0;17;1\nWireConnection;0;0;1;0\nASEEND*/\n//CHKSM=BCB7F728B16C2B7BFFF600A14B7FC9C20F79CED1" + m_functionName: + m_description: Creates a herringbone rectangular floor tile pattern. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Herringbone.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Herringbone.asset.meta new file mode 100644 index 0000000..112fc8d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Herringbone.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dbdb22f3b40ddf6459baf32842f7168a +timeCreated: 1586866005 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Hex Lattice.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Hex Lattice.asset new file mode 100644 index 0000000..9861493 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Hex Lattice.asset @@ -0,0 +1,40 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Hex Lattice + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1451;-120;1004;726;5300.028;1982.368;5.575107;True;False\nNode;AmplifyShaderEditor.SmoothstepOpNode;1;-192,0;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;6;-512,0;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;13;-1616,64;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;7;-688,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;8;-841,3;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;5;-352,0;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;-3664,256;Inherit;False;Tiling;2;0;False;1;0;FLOAT2;10,10;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;2;-864,112;Inherit;False;Hex + Scale;1;1;False;1;0;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;4;-368,96;Inherit;False;Edge + Width;1;2;False;1;0;FLOAT;0.2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;11;-1184,-16;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;1.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;9;-1008,-16;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;10;-1024,80;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;14;-2144,64;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleRemainderNode;15;-1968,64;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;1,1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;24;-2304,144;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;23;-2448,224;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleRemainderNode;22;-2656,224;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FloorOpNode;21;-2800,224;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;16;-1760,64;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0.5,0.5;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;19;-3312,128;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;18;-3472,128;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;17;-3712,128;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.BreakToComponentsNode;12;-1472,64;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;20;-3008,64;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;1.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;True;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;1;0;5;0\nWireConnection;1;2;4;0\nWireConnection;6;0;7;0\nWireConnection;13;0;16;0\nWireConnection;7;0;8;0\nWireConnection;7;1;2;0\nWireConnection;8;0;9;0\nWireConnection;8;1;10;0\nWireConnection;5;0;6;0\nWireConnection;11;0;12;0\nWireConnection;9;0;11;0\nWireConnection;9;1;12;1\nWireConnection;10;0;12;1\nWireConnection;14;0;20;0\nWireConnection;14;1;24;0\nWireConnection;15;0;14;0\nWireConnection;24;0;19;1\nWireConnection;24;1;23;0\nWireConnection;23;0;22;0\nWireConnection;22;0;21;0\nWireConnection;21;0;20;0\nWireConnection;16;0;15;0\nWireConnection;19;0;18;0\nWireConnection;18;0;17;0\nWireConnection;18;1;3;0\nWireConnection;12;0;13;0\nWireConnection;20;0;19;0\nWireConnection;0;0;1;0\nASEEND*/\n//CHKSM=3C3A7331726678319E055DBE5F0CE1A326E34C29" + m_functionName: + m_description: Creates a hexagonal lattice pattern. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Hex Lattice.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Hex Lattice.asset.meta new file mode 100644 index 0000000..27875ae --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Hex Lattice.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 56d977fb137832a498dced8436cf6708 +timeCreated: 1586863236 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Houndstooth.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Houndstooth.asset new file mode 100644 index 0000000..ffacb65 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Houndstooth.asset @@ -0,0 +1,39 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Houndstooth + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1451;-120;1004;726;3255.592;1165.008;3.399142;True;False\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;1;-2288,0;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;25;-2240,144;Inherit;False;Tiling;2;0;False;1;0;FLOAT2;5,5;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DynamicAppendNode;68;-1280,0;Inherit;False;FLOAT3;4;0;FLOAT2;0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;24;-2048,0;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;63;-1456,96;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;20;-1600,208;Inherit;False;Teeth;1;1;False;1;0;FLOAT;2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;66;-1600,96;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;65;-1856,96;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;11;-624,0;Inherit;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;16;-480,0;Inherit;False;FLOAT3;1;0;FLOAT3;0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.LerpOp;15;-240,0;Inherit;True;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;10;-848,0;Inherit;False;3;0;FLOAT3;0,0,0;False;1;FLOAT3;0.5,0.5,0;False;2;FLOAT3;0.55,0.55,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.Vector4Node;23;-1184,96;Inherit;False;Constant;_Vector0;Vector + 0;0;0;Create;True;0;0;False;0;0.5,0.55,0.95,1;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FractNode;8;-1088,0;Inherit;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;12;-848,128;Inherit;False;3;0;FLOAT3;0,0,0;False;1;FLOAT3;0.95,0.95,0;False;2;FLOAT3;1,1,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;68;0;24;0\nWireConnection;68;2;63;0\nWireConnection;24;0;1;0\nWireConnection;24;1;25;0\nWireConnection;63;0;66;0\nWireConnection;63;1;20;0\nWireConnection;66;0;65;0\nWireConnection;66;1;65;1\nWireConnection;65;0;24;0\nWireConnection;11;0;10;0\nWireConnection;11;1;12;0\nWireConnection;16;0;11;0\nWireConnection;15;0;16;0\nWireConnection;15;1;16;1\nWireConnection;15;2;16;2\nWireConnection;10;0;8;0\nWireConnection;10;1;23;1\nWireConnection;10;2;23;2\nWireConnection;8;0;68;0\nWireConnection;12;0;8;0\nWireConnection;12;1;23;3\nWireConnection;12;2;23;4\nWireConnection;0;0;15;0\nASEEND*/\n//CHKSM=85441DDEF3C9BF306BA13CF583CEBD72A1CEC9B0" + m_functionName: + m_description: Creates a duotone textile pattern. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Houndstooth.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Houndstooth.asset.meta new file mode 100644 index 0000000..3fc5c8b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Houndstooth.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 179b3e2dbd7f5a247afe15a7315e0707 +timeCreated: 1586788750 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Inverse Lerp.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Inverse Lerp.asset new file mode 100644 index 0000000..8c80dc8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Inverse Lerp.asset @@ -0,0 +1,41 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Inverse Lerp + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17706\n435;95;1527;761;970.3008;288.0356;1;True;False\nNode;AmplifyShaderEditor.FunctionInput;3;-512,160;Inherit;False;Alpha;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;1;-512,0;Inherit;False;A;1;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-512,80;Inherit;False;B;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;5;-320,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;4;-144,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;6;-320,96;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;5;0;3;0\nWireConnection;5;1;1;0\nWireConnection;4;0;5;0\nWireConnection;4;1;6;0\nWireConnection;6;0;2;0\nWireConnection;6;1;1;0\nWireConnection;0;0;4;0\nASEEND*/\n//CHKSM=9FE4353E1EA15E40F1B4D54618C26A1738EFB700" + m_functionName: + m_description: "Returns the linear parameter that produces the interpolant specified + by input Alpha within the range of input A to input B.\r Inverse Lerp is the inverse + operation of the Lerp Node. It can be used to determine what the input to a Lerp + was based on its output. " + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 7 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Inverse Lerp.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Inverse Lerp.asset.meta new file mode 100644 index 0000000..7f71a94 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Inverse Lerp.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 09cbe79402f023141a4dc1fddd4c9511 +timeCreated: 1582898085 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Lerp White To.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Lerp White To.asset new file mode 100644 index 0000000..7b85d32 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Lerp White To.asset @@ -0,0 +1,26 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Lerp White To + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=15308\n7;358;1906;673;1715.98;594.084;1.39994;False;False\nNode;AmplifyShaderEditor.FunctionInput;2;-544,-16;Float;False;T;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;5;48,-128;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DynamicAppendNode;7;-147,-5;Float;False;FLOAT3;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;6;-336,-128;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;1;-544,-160;Float;False;B;3;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.OneMinusNode;3;-352,0;Float;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;224,-128;Float;False;True;Output;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;5;0;6;0\nWireConnection;5;1;7;0\nWireConnection;7;0;3;0\nWireConnection;7;1;3;0\nWireConnection;7;2;3;0\nWireConnection;6;0;1;0\nWireConnection;6;1;2;0\nWireConnection;3;0;2;0\nWireConnection;0;0;5;0\nASEEND*/\n//CHKSM=D1DB2171EF0B926DCE56994508D5E925AFAC6AD5" + m_functionName: + m_description: + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Lerp White To.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Lerp White To.asset.meta new file mode 100644 index 0000000..3a348fb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Lerp White To.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 047d7c189c36a62438973bad9d37b1c2 +timeCreated: 1527498692 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Midtones Control.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Midtones Control.asset new file mode 100644 index 0000000..8a4ee24 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Midtones Control.asset @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Midtones Control + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=14205\n666;208;1066;728;2931.866;781.7222;2.2203;True;False\nNode;AmplifyShaderEditor.RangedFloatNode;3;-1907.899,-289.42;Float;False;Constant;_b;b;5;0;Create;True;0.333;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;5;-1973.299,6.039673;Float;False;Constant;_a;a;5;0;Create;True;0.25;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;20;-1191.009,82.84344;Float;False;Constant;_scale;scale;5;0;Create;True;0.7;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;22;-808.6494,-114.4888;Float;False;4;4;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT3;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;23;-642.6191,-517.399;Float;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT3;0.0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SaturateNode;24;-440.7793,-523.3648;Float;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionInput;26;-1138.585,215.9016;Float;False;Red + Shift;1;1;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;27;-1136.361,311.5068;Float;False;Green + Shift;1;2;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;28;-1092.291,436.1535;Float;False;Blue + Shift;1;3;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;1;-2162.971,-543.0989;Float;True;Property;_TextureSample0;Texture + Sample 0;3;0;Create;True;None;cc818fab9e6e24a40b931f8701ae2c12;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;25;-2376.585,-567.5209;Float;False;Input;9;0;False;1;0;SAMPLER2D;0.0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.DynamicAppendNode;17;-898.4647,265.9574;Float;False;FLOAT3;4;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WireNode;21;-1276.049,-548.8137;Float;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.NegateNode;7;-1550.52,151.5848;Float;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;8;-1535.909,-477.3485;Float;False;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;4;-1724.909,10.69427;Float;False;Constant;_Float1;Float + 1;5;0;Create;True;-1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;6;-1560.319,-92.27643;Float;False;3;3;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;15;-1207.399,-318.7663;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;16;-1161.829,-75.91486;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;10;-1380.099,-330.7704;Float;False;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;18;-1061.339,-331.9753;Float;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;19;-1008.659,-73.86804;Float;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;9;-1363.329,-47.31543;Float;False;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CustomExpressionNode;2;-1772.049,-470.1264;Float;False;float + fmin = min(min(Color.r, Color.g), Color.b)@$float fmax = max(max(Color.r, Color.g), + Color.b)@$return (fmax + fmin) / 2.0@;1;False;1;True;Color;FLOAT3;0,0,0;In;RBGToLuminance;1;0;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;11;-1366.299,-194.0069;Float;False;Constant;_Float3;Float + 3;5;0;Create;True;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;-271.7024,-592.2229;Float;False;True;Output;0;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nWireConnection;22;0;18;0\nWireConnection;22;1;19;0\nWireConnection;22;2;20;0\nWireConnection;22;3;17;0\nWireConnection;23;0;21;0\nWireConnection;23;1;22;0\nWireConnection;24;0;23;0\nWireConnection;1;0;25;0\nWireConnection;17;0;26;0\nWireConnection;17;1;27;0\nWireConnection;17;2;28;0\nWireConnection;21;0;1;0\nWireConnection;7;0;5;0\nWireConnection;8;0;2;0\nWireConnection;8;1;3;0\nWireConnection;6;0;2;0\nWireConnection;6;1;3;0\nWireConnection;6;2;4;0\nWireConnection;15;0;10;0\nWireConnection;15;1;11;0\nWireConnection;16;0;11;0\nWireConnection;16;1;9;0\nWireConnection;10;0;8;0\nWireConnection;10;1;5;0\nWireConnection;18;0;15;0\nWireConnection;19;0;16;0\nWireConnection;9;0;6;0\nWireConnection;9;1;7;0\nWireConnection;2;0;1;0\nWireConnection;0;0;24;0\nASEEND*/\n//CHKSM=75F383819F22C7DE4B23FB26DA48A8B24E31CDAE" + m_functionName: + m_description: Can change midtones but does not preserve luminosity (still under + construction ) + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Midtones Control.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Midtones Control.asset.meta new file mode 100644 index 0000000..03d0250 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Midtones Control.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1862d12003a80d24ab048da83dc4e4d5 +timeCreated: 1516025195 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Noise Sine Wave.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Noise Sine Wave.asset new file mode 100644 index 0000000..e9b8ffa --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Noise Sine Wave.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Noise Sine Wave + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17500\n508;100;994;700;-752.6482;31.0816;1;True;False\nNode;AmplifyShaderEditor.GetLocalVarNode;23;1004.148,255.9184;Inherit;False;7;sinIn;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;7;599.5011,526.1053;Inherit;False;sinIn;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;15;704,256;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SinOpNode;24;576,640;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;1;272,576;Inherit;False;In;1;0;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;5;272,672;Inherit;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;6;704,624;Inherit;False;sinInOffset;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;4;448,624;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FractNode;17;848,224;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SinOpNode;3;448,544;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;12;224,336;Inherit;False;Constant;_Float1;Float + 1;0;0;Create;True;0;0;False;0;91.2228;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;21;1198.957,186.5331;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;599.7036,112.5256;Inherit;False;Min + Max;2;1;False;1;0;FLOAT2;-0.5,0.5;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;9;80,176;Inherit;False;7;sinIn;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LerpOp;20;985.5731,116.8529;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;10;64,256;Inherit;False;6;sinInOffset;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;19;743.0641,109.0836;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.SinOpNode;14;576,256;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;16;416,368;Inherit;False;Constant;_Float2;Float + 2;0;0;Create;True;0;0;False;0;43758.55;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;13;416,256;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;8;272,208;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;1372,141;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;7;0;3;0\nWireConnection;15;0;14;0\nWireConnection;15;1;16;0\nWireConnection;24;0;4;0\nWireConnection;6;0;24;0\nWireConnection;4;0;1;0\nWireConnection;4;1;5;0\nWireConnection;17;0;15;0\nWireConnection;3;0;1;0\nWireConnection;21;0;20;0\nWireConnection;21;1;23;0\nWireConnection;20;0;19;0\nWireConnection;20;1;19;1\nWireConnection;20;2;17;0\nWireConnection;19;0;2;0\nWireConnection;14;0;13;0\nWireConnection;13;0;8;0\nWireConnection;13;1;12;0\nWireConnection;8;0;9;0\nWireConnection;8;1;10;0\nWireConnection;0;0;21;0\nASEEND*/\n//CHKSM=19A53C6E7C22AEDCEB7C9748D639AD32E25A4747" + m_functionName: + m_description: Creates a sine wave from a given input with an added pseudo-random + value + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Noise Sine Wave.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Noise Sine Wave.asset.meta new file mode 100644 index 0000000..30059cb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Noise Sine Wave.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a6eff29f739ced848846e3b648af87bd +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Non Stereo Screen Pos.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Non Stereo Screen Pos.asset new file mode 100644 index 0000000..98af8ee --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Non Stereo Screen Pos.asset @@ -0,0 +1,42 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Non Stereo Screen Pos + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18812\n-2114;98;1601;770;1522.233;357.651;1.3;True;False\nNode;AmplifyShaderEditor.FunctionInput;23;-544,0;Inherit;False;Screen + Pos;4;0;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.CustomExpressionNode;22;-384,0;Inherit;False;#if + UNITY_SINGLE_PASS_STEREO$float4 scaleOffset = unity_StereoScaleOffset[ unity_StereoEyeIndex + ]@$UV.xy = (UV.xy - scaleOffset.zw) / scaleOffset.xy@$#endif$return UV@;2;False;1;True;UV;FLOAT2;0,0;In;;Float;False;UnStereo;False;False;0;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.ScreenPosInputsNode;21;-752,-45.5;Inherit;False;0;False;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionOutput;0;-224,0;Inherit;False;True;-1;UV;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nWireConnection;23;0;21;0\nWireConnection;22;0;23;0\nWireConnection;0;0;22;0\nASEEND*/\n//CHKSM=E2EEB77DC921BFB3883BDF45A4C981ACE85F8ED2" + m_functionName: + m_description: Transforms a screen position value from VR Stereo to non Stereo + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_customEdited: 0 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Non Stereo Screen Pos.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Non Stereo Screen Pos.asset.meta new file mode 100644 index 0000000..ae29d03 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Non Stereo Screen Pos.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1731ee083b93c104880efc701e11b49b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Height.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Height.asset new file mode 100644 index 0000000..a60acb8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Height.asset @@ -0,0 +1,47 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Normal From Height + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity + Asset Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18702\n0;632;1729;727;608.7599;657.7451;1;True;False\nNode;AmplifyShaderEditor.WorldNormalVector;109;109.7551,-549.6889;Inherit;False;False;1;0;FLOAT3;0,0,1;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.WorldPosInputsNode;108;117.2075,-701.2255;Inherit;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.TransformDirectionNode;42;687.678,-435.2692;Inherit;False;World;Tangent;False;Fast;1;0;FLOAT3;0,0,0;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionInput;20;190.7045,-386.7478;Inherit;False;Height;1;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;110;196.2401,-283.7451;Inherit;False;Strength;1;1;False;1;0;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CustomExpressionNode;107;424.2144,-542.7633;Inherit;False;// + \"Bump Mapping Unparametrized Surfaces on the GPU\" by Morten S. Mikkelsen$float3 + vSigmaS = ddx( surf_pos )@$float3 vSigmaT = ddy( surf_pos )@$float3 vN = surf_norm@$float3 + vR1 = cross( vSigmaT , vN )@$float3 vR2 = cross( vN , vSigmaS )@$float fDet = + dot( vSigmaS , vR1 )@$float dBs = ddx( height )@$float dBt = ddy( height )@$float3 + vSurfGrad = scale * 0.05 * sign( fDet ) * ( dBs * vR1 + dBt * vR2 )@$return normalize + ( abs( fDet ) * vN - vSurfGrad )@$;3;False;4;True;surf_pos;FLOAT3;0,0,0;In;;Inherit;False;True;surf_norm;FLOAT3;0,0,0;In;;Inherit;False;True;height;FLOAT;0;In;;Inherit;False;True;scale;FLOAT;0;In;;Inherit;False;PerturbNormal;True;False;0;4;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;40;936.6965,-431.3251;Inherit;False;False;-1;Tangent + Normal;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;709.3525,-542.4827;Inherit;False;True;-1;World + Normal;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;42;0;107;0\nWireConnection;107;0;108;0\nWireConnection;107;1;109;0\nWireConnection;107;2;20;0\nWireConnection;107;3;110;0\nWireConnection;40;0;42;0\nWireConnection;0;0;107;0\nASEEND*/\n//CHKSM=73C78BB6755C01B84C5BF88CEAA7D85C65F7A490" + m_functionName: + m_description: Derive a normal vector from a procedural height value. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Height.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Height.asset.meta new file mode 100644 index 0000000..d8ae7da --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Height.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1942fe2c5f1a1f94881a33d532e4afeb +timeCreated: 1575458539 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Texture.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Texture.asset new file mode 100644 index 0000000..29c536d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Texture.asset @@ -0,0 +1,82 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Normal From Texture + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity + Asset Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18702\n0;411;1729;948;621.1696;-899.756;1.578781;True;False\nNode;AmplifyShaderEditor.WireNode;94;-934.7373,3153.675;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.FunctionSwitch;149;-35.36745,2507.335;Inherit;False;Height + Channel;False;0;4;-1;R;G;B;A;Instance;135;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;148;-173.2692,2512.505;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FunctionSwitch;147;-37.1351,2265.176;Inherit;False;Height + Channel;False;0;4;-1;R;G;B;A;Instance;135;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;146;-175.0368,2270.346;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.SamplerNode;54;-534.2678,2265.954;Inherit;True;Property;_TextureSample3;Texture + Sample 3;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionSwitch;143;-45.9734,2033.621;Inherit;False;Height + Channel;False;0;4;-1;R;G;B;A;Instance;135;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;142;-183.8751,2038.791;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FunctionSwitch;141;-44.20639,1805.602;Inherit;False;Height + Channel;False;0;4;-1;R;G;B;A;Instance;135;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;139;-50.45546,1508.225;Inherit;False;Height + Channel;False;0;4;-1;R;G;B;A;Instance;135;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;151;-33.13635,2759.903;Inherit;False;Height + Channel;False;0;4;-1;R;G;B;A;Instance;135;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;150;-171.0381,2765.073;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.BreakToComponentsNode;140;-182.1081,1810.772;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.BreakToComponentsNode;138;-188.3572,1513.395;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.BreakToComponentsNode;136;-192.5089,1278.04;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.BreakToComponentsNode;134;-200.3653,1049.094;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.WireNode;88;-950.8482,2862.768;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;83;-942.6831,2954.455;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.CustomExpressionNode;46;-1267.346,2170.667;Inherit;False;{$ + float3 pos = float3( TexelSize.xy, 0 )@$ float3 neg = float3( -pos.xy, 0 )@$ + UV0 = UV + neg.xy@$ UV1 = UV + neg.zy@$ UV2 = UV + float2( pos.x, neg.y + )@$ UV3 = UV + neg.xz@$ UV4 = UV@$ UV5 = UV + pos.xz@$ UV6 = UV + + float2( neg.x, pos.y )@$ UV7 = UV + pos.zy@$ UV8 = UV + pos.xy@$ return@$};7;False;11;True;UV;FLOAT2;0,0;In;;Inherit;False;True;TexelSize;FLOAT4;0,0,0,0;In;;Inherit;False;True;UV0;FLOAT2;0,0;Out;;Inherit;False;True;UV1;FLOAT2;0,0;Out;;Inherit;False;True;UV2;FLOAT2;0,0;Out;;Inherit;False;True;UV3;FLOAT2;0,0;Out;;Inherit;False;True;UV4;FLOAT2;0,0;Out;;Inherit;False;True;UV5;FLOAT2;0,0;Out;;Inherit;False;True;UV6;FLOAT2;0,0;Out;;Inherit;False;True;UV7;FLOAT2;0,0;Out;;Inherit;False;True;UV8;FLOAT2;0,0;Out;;Inherit;False;Calculate + UVs Smooth;True;False;0;12;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT4;0,0,0,0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT2;0,0;False;6;FLOAT2;0,0;False;7;FLOAT2;0,0;False;8;FLOAT2;0,0;False;9;FLOAT2;0,0;False;10;FLOAT2;0,0;False;11;FLOAT2;0,0;False;10;FLOAT;0;FLOAT2;4;FLOAT2;5;FLOAT2;6;FLOAT2;7;FLOAT2;8;FLOAT2;9;FLOAT2;10;FLOAT2;11;FLOAT2;12\nNode;AmplifyShaderEditor.WireNode;71;-950.5735,2126.853;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;86;-1725.35,1955.66;Inherit;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionSwitch;137;-54.60703,1271.102;Inherit;False;Height + Channel;False;0;4;-1;R;G;B;A;Instance;135;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;152;-168.3932,3013.224;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FunctionSwitch;153;-30.49147,3008.054;Inherit;False;Height + Channel;False;0;4;-1;R;G;B;A;Instance;135;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSubtitle;109;980.571,1698.853;Inherit;False;Smooth + (Slower);1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WireNode;163;284.3418,2049.237;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.TransformDirectionNode;68;1495.271,1695.723;Inherit;False;Tangent;World;False;Fast;1;0;FLOAT3;0,0,0;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionSubtitle;107;986.7996,1572.163;Inherit;False;Sharp + (Faster);1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;91;451.2825,1651.488;Inherit;False;Strength;1;3;False;1;0;FLOAT;1.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CustomExpressionNode;128;687.2171,1466.29;Inherit;False;{$ + float3 va = float3( 0.13, 0, ( S1 - S0 ) * Strength )@$ float3 vb = float3( + 0, 0.13, ( S2 - S0 ) * Strength )@$ return normalize( cross( va, vb ) )@$};3;False;4;True;S0;FLOAT;0;In;;Inherit;False;True;S1;FLOAT;0;In;;Inherit;False;True;S2;FLOAT;0;In;;Inherit;False;True;Strength;FLOAT;0;In;;Inherit;False;Combine + Samples Sharp;True;False;0;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.CustomExpressionNode;58;683.8669,1781.724;Inherit;False;{$ + float3 normal@$ normal.x = Strength * ( S0 - S2 + 2 * S3 - 2 * S5 + S6 - S8 + )@$ normal.y = Strength * ( S0 + 2 * S1 + S2 - S6 - 2 * S7 - S8 )@$ normal.z + = 1.0@$ return normalize( normal )@$};3;False;10;True;Strength;FLOAT;0;In;;Inherit;False;True;S0;FLOAT;0;In;;Inherit;False;True;S1;FLOAT;0;In;;Inherit;False;True;S2;FLOAT;0;In;;Inherit;False;True;S3;FLOAT;0;In;;Inherit;False;True;S4;FLOAT;0;In;;Inherit;False;True;S5;FLOAT;0;In;;Inherit;False;True;S6;FLOAT;0;In;;Inherit;False;True;S7;FLOAT;0;In;;Inherit;False;True;S8;FLOAT;0;In;;Inherit;False;Combine + Samples Smooth;True;False;0;10;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;9;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WireNode;167;365.7449,2175.053;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;166;341.2415,2147.356;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;165;322.1609,2118.973;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;164;300.2653,2089.528;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;162;266.8397,2013.852;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;161;248.7872,1964.641;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;160;229.3277,1907.705;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;159;-27.41323,3728.875;Inherit;False;Height + Channel;False;0;4;-1;R;G;B;A;Instance;135;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;158;-165.3149,3734.044;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FunctionSwitch;157;-27.81758,3490.377;Inherit;False;Height + Channel;False;0;4;-1;R;G;B;A;Instance;135;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;156;-165.7193,3495.547;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FunctionSwitch;155;-31.35663,3251.417;Inherit;False;Height + Channel;False;0;4;-1;R;G;B;A;Instance;135;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;154;-169.2584,3256.587;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.WireNode;43;-879.6338,1932.672;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;168;262.7348,1474.22;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;135;-62.46368,1043.924;Inherit;False;Height + Channel;False;0;4;-1;R;G;B;A;Object;-1;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;92;-928.7188,3207.844;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;64;-978.6859,2405.781;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;78;-920.438,2056.731;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;72;-939.3794,3058.119;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;119;-1239.437,2845.394;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;59;-873.6181,2000.867;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;62;-972.6644,2535.252;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;80;-548.3456,1807.032;Inherit;True;Property;_TextureSample1;Texture + Sample 1;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;97;-503.1219,3726.325;Inherit;True;Property;_TextureSample7;Texture + Sample 7;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;90;-540.4975,2031.932;Inherit;True;Property;_TextureSample2;Texture + Sample 2;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.CustomExpressionNode;110;-1103.439,1234.901;Inherit;False;{$ + UV.y -= TexelSize.y * 0.5@$ UV0 = UV@$ UV1 = UV + float2( TexelSize.x, + 0 )@$ UV2 = UV + float2( 0, TexelSize.y )@$};7;False;5;True;UV;FLOAT2;0,0;In;;Inherit;False;True;TexelSize;FLOAT4;0,0,0,0;In;;Inherit;False;True;UV0;FLOAT2;0,0;Out;;Inherit;False;True;UV1;FLOAT2;0,0;Out;;Inherit;False;True;UV2;FLOAT2;0,0;Out;;Inherit;False;Calculate + UVs Sharp;True;False;0;6;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT4;0,0,0,0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT2;0,0;False;4;FLOAT;0;FLOAT2;4;FLOAT2;5;FLOAT2;6\nNode;AmplifyShaderEditor.WireNode;117;-865.0287,1683.958;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;120;-2141.424,2414.817;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SamplerNode;113;-558.706,1273.719;Inherit;True;Property;_TextureSample10;Texture + Sample 10;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.TexelSizeNode;89;-1718.808,2243.135;Inherit;False;-1;1;0;SAMPLER2D;;False;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;45;-875.6236,1969.773;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;121;-856.3488,1450.987;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;73;-944.3997,3034.064;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.RelayNode;118;-1535.702,1475.698;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;63;-960.6208,2234.158;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;115;-879.8671,1597.852;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SamplerNode;79;-531.1535,2508.48;Inherit;True;Property;_TextureSample4;Texture + Sample 4;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;96;-966.6425,2188.994;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;111;-1245.284,2052.146;Inherit;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SamplerNode;112;-551.6846,1042.588;Inherit;True;Property;_TextureSample9;Texture + Sample 9;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;48;-512.4654,3249.776;Inherit;True;Property;_TextureSample0;Texture + Sample 0;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionSwitch;108;1233.465,1567.899;Inherit;False;Filtering;False;0;2;-1;Sharp;Smooth;Object;-1;9;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WireNode;65;-879.3245,1845.746;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;67;-969.6533,2279.322;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;82;-524.924,2757.656;Inherit;True;Property;_TextureSample5;Texture + Sample 5;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;133;-863.5597,1493.908;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;66;-932.4942,2095.913;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SamplerNode;114;-565.3553,1507.426;Inherit;True;Property;_TextureSample11;Texture + Sample 11;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;87;-2095.677,1799.138;Inherit;False;Texture;9;0;False;1;0;SAMPLER2D;0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;76;-948.5767,2913.511;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;57;-907.7392,2017.885;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;69;-878.6321,1893.557;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;81;-939.6157,3105.523;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SamplerNode;70;-528.0388,3006.831;Inherit;True;Property;_TextureSample6;Texture + Sample 6;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;44;-975.6751,2360.617;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;47;-972.6643,2327.497;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;84;-503.1212,3489.608;Inherit;True;Property;_TextureSample8;Texture + Sample 8;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;93;-972.6644,2493.099;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;123;-870.4584,1531.294;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;75;-972.6643,2444.924;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;74;-1443.075,2964.874;Inherit;False;SS;13;2;False;1;0;SAMPLERSTATE;0;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;116;-875.6149,1642.134;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;95;-943.1602,3001.948;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.FunctionInput;85;-1457.552,1951.121;Inherit;False;UV;2;1;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;169;281.6801,1420.541;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;127;-2142.816,1680.113;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.FunctionOutput;0;1748.021,1700.925;Inherit;False;True;-1;World + Normal;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;40;1492.221,1570.54;Inherit;False;False;-1;Tangent + Normal;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;94;0;74;0\nWireConnection;149;0;148;0\nWireConnection;149;1;148;1\nWireConnection;149;2;148;2\nWireConnection;149;3;148;3\nWireConnection;148;0;79;0\nWireConnection;147;0;146;0\nWireConnection;147;1;146;1\nWireConnection;147;2;146;2\nWireConnection;147;3;146;3\nWireConnection;146;0;54;0\nWireConnection;54;0;43;0\nWireConnection;54;1;67;0\nWireConnection;54;7;83;0\nWireConnection;143;0;142;0\nWireConnection;143;1;142;1\nWireConnection;143;2;142;2\nWireConnection;143;3;142;3\nWireConnection;142;0;90;0\nWireConnection;141;0;140;0\nWireConnection;141;1;140;1\nWireConnection;141;2;140;2\nWireConnection;141;3;140;3\nWireConnection;139;0;138;0\nWireConnection;139;1;138;1\nWireConnection;139;2;138;2\nWireConnection;139;3;138;3\nWireConnection;151;0;150;0\nWireConnection;151;1;150;1\nWireConnection;151;2;150;2\nWireConnection;151;3;150;3\nWireConnection;150;0;82;0\nWireConnection;140;0;80;0\nWireConnection;138;0;114;0\nWireConnection;136;0;113;0\nWireConnection;134;0;112;0\nWireConnection;88;0;74;0\nWireConnection;83;0;74;0\nWireConnection;46;1;85;0\nWireConnection;46;2;89;0\nWireConnection;71;0;87;0\nWireConnection;86;2;87;0\nWireConnection;137;0;136;0\nWireConnection;137;1;136;1\nWireConnection;137;2;136;2\nWireConnection;137;3;136;3\nWireConnection;152;0;70;0\nWireConnection;153;0;152;0\nWireConnection;153;1;152;1\nWireConnection;153;2;152;2\nWireConnection;153;3;152;3\nWireConnection;109;0;58;0\nWireConnection;163;0;151;0\nWireConnection;68;0;108;0\nWireConnection;107;0;128;0\nWireConnection;128;0;169;0\nWireConnection;128;1;168;0\nWireConnection;128;2;139;0\nWireConnection;128;3;91;0\nWireConnection;58;0;91;0\nWireConnection;58;1;141;0\nWireConnection;58;2;160;0\nWireConnection;58;3;161;0\nWireConnection;58;4;162;0\nWireConnection;58;5;163;0\nWireConnection;58;6;164;0\nWireConnection;58;7;165;0\nWireConnection;58;8;166;0\nWireConnection;58;9;167;0\nWireConnection;167;0;159;0\nWireConnection;166;0;157;0\nWireConnection;165;0;155;0\nWireConnection;164;0;153;0\nWireConnection;162;0;149;0\nWireConnection;161;0;147;0\nWireConnection;160;0;143;0\nWireConnection;159;0;158;0\nWireConnection;159;1;158;1\nWireConnection;159;2;158;2\nWireConnection;159;3;158;3\nWireConnection;158;0;97;0\nWireConnection;157;0;156;0\nWireConnection;157;1;156;1\nWireConnection;157;2;156;2\nWireConnection;157;3;156;3\nWireConnection;156;0;84;0\nWireConnection;155;0;154;0\nWireConnection;155;1;154;1\nWireConnection;155;2;154;2\nWireConnection;155;3;154;3\nWireConnection;154;0;48;0\nWireConnection;43;0;87;0\nWireConnection;168;0;137;0\nWireConnection;135;0;134;0\nWireConnection;135;1;134;1\nWireConnection;135;2;134;2\nWireConnection;135;3;134;3\nWireConnection;92;0;74;0\nWireConnection;64;0;46;9\nWireConnection;78;0;87;0\nWireConnection;72;0;74;0\nWireConnection;119;0;74;0\nWireConnection;59;0;87;0\nWireConnection;62;0;46;12\nWireConnection;80;0;65;0\nWireConnection;80;1;96;0\nWireConnection;80;7;88;0\nWireConnection;97;0;71;0\nWireConnection;97;1;62;0\nWireConnection;97;7;92;0\nWireConnection;90;0;69;0\nWireConnection;90;1;63;0\nWireConnection;90;7;76;0\nWireConnection;110;1;85;0\nWireConnection;110;2;111;0\nWireConnection;117;0;87;0\nWireConnection;120;0;119;0\nWireConnection;113;0;116;0\nWireConnection;113;1;110;5\nWireConnection;113;7;133;0\nWireConnection;89;0;87;0\nWireConnection;45;0;87;0\nWireConnection;121;0;118;0\nWireConnection;73;0;74;0\nWireConnection;118;0;127;0\nWireConnection;63;0;46;5\nWireConnection;115;0;87;0\nWireConnection;79;0;45;0\nWireConnection;79;1;47;0\nWireConnection;79;7;95;0\nWireConnection;96;0;46;4\nWireConnection;111;0;89;0\nWireConnection;112;0;115;0\nWireConnection;112;1;110;4\nWireConnection;112;7;121;0\nWireConnection;48;0;78;0\nWireConnection;48;1;75;0\nWireConnection;48;7;81;0\nWireConnection;108;0;107;0\nWireConnection;108;1;109;0\nWireConnection;65;0;87;0\nWireConnection;67;0;46;6\nWireConnection;82;0;59;0\nWireConnection;82;1;44;0\nWireConnection;82;7;73;0\nWireConnection;133;0;118;0\nWireConnection;66;0;87;0\nWireConnection;114;0;117;0\nWireConnection;114;1;110;6\nWireConnection;114;7;123;0\nWireConnection;76;0;74;0\nWireConnection;57;0;87;0\nWireConnection;69;0;87;0\nWireConnection;81;0;74;0\nWireConnection;70;0;57;0\nWireConnection;70;1;64;0\nWireConnection;70;7;72;0\nWireConnection;44;0;46;8\nWireConnection;47;0;46;7\nWireConnection;84;0;66;0\nWireConnection;84;1;93;0\nWireConnection;84;7;94;0\nWireConnection;93;0;46;11\nWireConnection;123;0;118;0\nWireConnection;75;0;46;10\nWireConnection;116;0;87;0\nWireConnection;95;0;74;0\nWireConnection;85;0;86;0\nWireConnection;169;0;135;0\nWireConnection;127;0;120;0\nWireConnection;0;0;68;0\nWireConnection;40;0;108;0\nASEEND*/\n//CHKSM=31A91DFE3C09739865ECF32FB1E5EB483581411D" + m_functionName: + m_description: Derive a normal vector from a texture. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Texture.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Texture.asset.meta new file mode 100644 index 0000000..38d9749 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Normal From Texture.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9728ee98a55193249b513caf9a0f1676 +timeCreated: 1575458539 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/NormalCreate.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/NormalCreate.asset new file mode 100644 index 0000000..65a41ca --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/NormalCreate.asset @@ -0,0 +1,29 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: NormalCreate + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=14504\n355;526;1066;579;2449.117;567.652;1.195803;True;False\nNode;AmplifyShaderEditor.SimpleAddOpNode;10;-653.5344,187.1665;Float;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.PowerNode;24;-1044.8,149.3853;Float;False;2;0;FLOAT;0;False;1;FLOAT;3;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ScaleNode;25;-863.0129,158.0113;Float;False;0.1;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;12;-300.427,-32.63319;Float;True;Property;_TextureSample1;Texture + Sample 1;0;0;Create;True;0;0;False;0;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;11;-297.0564,-267.8521;Float;True;Property;_TextureSample0;Texture + Sample 0;0;0;Create;True;0;0;False;0;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;14;-289.2554,-557.6742;Float;True;Property;_TextureSample2;Texture + Sample 2;0;0;Create;True;0;0;False;0;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.DynamicAppendNode;9;-510.4005,165.5482;Float;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;1;-1609.853,-367.2421;Float;False;Tex;9;0;False;1;0;SAMPLER2D;0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.TexturePropertyNode;26;-1891.178,-373.9199;Float;True;Property;_Normal;Height;0;0;Create;True;0;0;False;0;None;None;False;white;Auto;0;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;18;248.1256,-271.7343;Float;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;-1194.829,150.4831;Float;False;Offset;1;2;False;1;0;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;4;33.9635,-213.628;Float;False;Strength;1;3;False;1;0;FLOAT;2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CrossProductOpNode;21;591.7831,-218.9246;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DynamicAppendNode;13;430.6205,-320.9595;Float;False;FLOAT3;4;0;FLOAT;1;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;23;-1414.536,38.33293;Float;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;19;232.3673,-128.4985;Float;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;17;50.32483,-85.61093;Float;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;7;-642.9897,42.01196;Float;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;16;457.5351,-92.18595;Float;False;FLOAT3;4;0;FLOAT;0;False;1;FLOAT;1;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;2;-1101.952,36.79971;Float;False;UV;2;1;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;6;-958.3405,44.83144;Float;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;15;56.50588,-318.4448;Float;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.NormalizeNode;22;751.4589,-201.3778;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DynamicAppendNode;8;-490.1855,39.45096;Float;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;0;959.5413,-203.6477;Float;False;True;Output;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;10;0;6;1\nWireConnection;10;1;25;0\nWireConnection;24;0;3;0\nWireConnection;25;0;24;0\nWireConnection;12;0;1;0\nWireConnection;12;1;9;0\nWireConnection;11;0;1;0\nWireConnection;11;1;8;0\nWireConnection;14;0;1;0\nWireConnection;14;1;2;0\nWireConnection;9;0;6;0\nWireConnection;9;1;10;0\nWireConnection;1;0;26;0\nWireConnection;18;0;15;0\nWireConnection;18;1;4;0\nWireConnection;21;0;13;0\nWireConnection;21;1;16;0\nWireConnection;13;2;18;0\nWireConnection;23;2;1;0\nWireConnection;19;0;17;0\nWireConnection;19;1;4;0\nWireConnection;17;0;12;2\nWireConnection;17;1;14;2\nWireConnection;7;0;6;0\nWireConnection;7;1;25;0\nWireConnection;16;2;19;0\nWireConnection;2;0;23;0\nWireConnection;6;0;2;0\nWireConnection;15;0;11;2\nWireConnection;15;1;14;2\nWireConnection;22;0;21;0\nWireConnection;8;0;7;0\nWireConnection;8;1;6;1\nWireConnection;0;0;22;0\nASEEND*/\n//CHKSM=E15D8591709274A59C7536FD5BB9577CCD09C4B4" + m_functionName: + m_description: + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/NormalCreate.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/NormalCreate.asset.meta new file mode 100644 index 0000000..a0802e3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/NormalCreate.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e12f7ae19d416b942820e3932b56220f +timeCreated: 1520619538 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Or.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Or.asset new file mode 100644 index 0000000..6572f7c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Or.asset @@ -0,0 +1,39 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Or + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18101\n468;180;1104;762;810;372;1;True;False\nNode;AmplifyShaderEditor.CustomExpressionNode;1;-160,0;Inherit;False;float + result = A || B@$return result@;1;False;2;True;A;FLOAT;0;In;;Inherit;False;True;B;FLOAT;0;In;;Inherit;False;ASEOr;False;False;0;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-320,0;Inherit;False;A;1;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;-320,80;Inherit;False;B;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;1;0;2;0\nWireConnection;1;1;3;0\nWireConnection;0;0;1;0\nASEEND*/\n//CHKSM=F2AFC1FFB9B7CC9340AFFCC196218CE05C5EF2C1" + m_functionName: + m_description: Returns true if either of the inputs A and B are true + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 6 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Or.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Or.asset.meta new file mode 100644 index 0000000..11812d1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Or.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dcfde22f80031984b87bcc46a052ad1f +timeCreated: 1589816062 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormal.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormal.asset new file mode 100644 index 0000000..a436506 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormal.asset @@ -0,0 +1,29 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: PerturbNormal + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=15103\n344;92;1056;673;575.1386;503.1177;1.033186;True;False\nNode;AmplifyShaderEditor.BreakToComponentsNode;27;760.8596,55.21472;Float;False;FLOAT3;1;0;FLOAT3;0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;24;567.4818,-78.97424;Float;False;2;2;0;FLOAT3x3;0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionNode;31;80,-272;Float;False;CotangentFrame;-1;;7;62ce0f00f1417804bb4f2b38501ba0d0;0;3;4;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;1;FLOAT2;0,0;False;1;FLOAT3x3;5\nNode;AmplifyShaderEditor.FunctionInput;6;-160,48;Float;False;Normal;3;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WorldNormalVector;13;-176,-400;Float;False;True;1;0;FLOAT3;0,0,0;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.NormalizeNode;8;64,112;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.ViewDirInputsCoordNode;12;-160,-256;Float;False;World;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;11;-176,-96;Float;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionSwitch;26;256,48;Float;False;Normalize;True;0;2;-1;In + 0;In 1;Object;-1;9;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;29;1040,80;Float;False;False;Y;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;28;1040,0;Float;False;False;X;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;9;1040,-80;Float;False;True;XYZ;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;30;1040,160;Float;False;False;Z;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;27;0;24;0\nWireConnection;24;0;31;5\nWireConnection;24;1;26;0\nWireConnection;31;4;13;0\nWireConnection;31;2;12;0\nWireConnection;31;1;11;0\nWireConnection;8;0;6;0\nWireConnection;26;0;6;0\nWireConnection;26;1;8;0\nWireConnection;29;0;27;1\nWireConnection;28;0;27;0\nWireConnection;9;0;24;0\nWireConnection;30;0;27;2\nASEEND*/\n//CHKSM=82B74CD48F60956E292CC6A0881ADA96C894E5CD" + m_functionName: + m_description: 'Perturbing normals without Precomputed Tangents + + http://www.thetenthplanet.de/archives/1180' + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormal.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormal.asset.meta new file mode 100644 index 0000000..16594f7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormal.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c8b64dd82fb09f542943a895dffb6c06 +timeCreated: 1522256219 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormalHQ.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormalHQ.asset new file mode 100644 index 0000000..15f7c85 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormalHQ.asset @@ -0,0 +1,44 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: PerturbNormalHQ + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=15901\n262;107;1149;682;1154.028;517.2542;2.484015;False;False\nNode;AmplifyShaderEditor.FunctionInput;3;-416,16;Float;False;Bump + One Pixel Down;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DdxOpNode;9;-122.6414,307.0036;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;2;-416,-96;Float;False;Bump + Center;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;11;259.3586,-190.9964;Float;False;2;2;0;FLOAT;0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;6;-112,-192;Float;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;1;-406.5,-209.5;Float;False;Bump + One Pixel Right;1;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;25;650.9295,79.78731;Float;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DotProductOpNode;21;451.7501,209.2307;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CrossProductOpNode;15;240,528;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;16;323.3586,-7.996399;Float;False;2;2;0;FLOAT;0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WorldNormalVector;5;-569.6414,488.0036;Float;False;False;1;0;FLOAT3;0,0,1;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.CrossProductOpNode;14;90.53894,177.7209;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;12;527.3586,-157.9964;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WorldPosInputsNode;8;-394.6414,238.0036;Float;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionInput;4;-309.4063,534.0479;Float;False;World + Space Normal;3;3;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.ConditionalIfNode;17;843.8935,337.3362;Float;False;False;5;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;18;632.8947,365.3362;Float;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;0;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;20;644.8946,607.3355;Float;False;Constant;_Float2;Float + 2;0;0;Create;True;0;0;False;0;-1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;19;627.8946,497.3361;Float;False;Constant;_Float1;Float + 1;0;0;Create;True;0;0;False;0;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;22;1232,176;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DdyOpNode;10;-113.6414,183.0036;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;7;-112,-16;Float;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;13;1077.014,199.0213;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.NormalizeNode;23;1424,176;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;24;1054.02,41.71672;Float;False;2;2;0;FLOAT;0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;1600,176;Float;False;True;World + Space Normal;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;9;0;8;0\nWireConnection;11;0;6;0\nWireConnection;11;1;14;0\nWireConnection;6;0;1;0\nWireConnection;6;1;2;0\nWireConnection;25;0;21;0\nWireConnection;21;0;14;0\nWireConnection;21;1;9;0\nWireConnection;15;0;4;0\nWireConnection;15;1;9;0\nWireConnection;16;0;7;0\nWireConnection;16;1;15;0\nWireConnection;14;0;10;0\nWireConnection;14;1;4;0\nWireConnection;12;0;11;0\nWireConnection;12;1;16;0\nWireConnection;4;0;5;0\nWireConnection;17;0;21;0\nWireConnection;17;1;18;0\nWireConnection;17;2;19;0\nWireConnection;17;3;18;0\nWireConnection;17;4;20;0\nWireConnection;22;0;24;0\nWireConnection;22;1;13;0\nWireConnection;10;0;8;0\nWireConnection;7;0;3;0\nWireConnection;7;1;2;0\nWireConnection;13;0;12;0\nWireConnection;13;1;17;0\nWireConnection;23;0;22;0\nWireConnection;24;0;25;0\nWireConnection;24;1;4;0\nWireConnection;0;0;23;0\nASEEND*/\n//CHKSM=EDC100B8D8E2AD6CDE38D95EB0F332AE4D644559" + m_functionName: + m_description: Based on Perturb Normal HQ UE4 Material Expression + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormalHQ.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormalHQ.asset.meta new file mode 100644 index 0000000..4884244 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PerturbNormalHQ.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 45dff16e78a0685469fed8b5b46e4d96 +timeCreated: 1542724676 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polar Coordinates.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polar Coordinates.asset new file mode 100644 index 0000000..4e53b3f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polar Coordinates.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Polar Coordinates + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1476;-250;1004;726;2152.682;1112.438;2.835857;True;False\nNode;AmplifyShaderEditor.ATan2OpNode;14;-528,-128;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;17;-832,-128;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FunctionInput;2;-1104,-432;Inherit;False;Center;2;1;False;1;0;FLOAT2;0.5,0.5;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;18;-304,-128;Inherit;True;3;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;16;-1056,-128;Inherit;False;15;CenteredUV;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TauNode;22;-688,64;Inherit;False;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;4;-528,96;Inherit;False;Length + Scale;1;3;False;1;0;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;20;-528,-16;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;21;-736,-16;Inherit;False;Constant;_Float3;Float + 3;0;0;Create;True;0;0;False;0;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;1;-1104,-512;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RangedFloatNode;13;-528,-288;Inherit;False;Constant;_Float2;Float + 2;0;0;Create;True;0;0;False;0;2;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;-544,-384;Inherit;False;Radial + Scale;1;2;False;1;0;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;23;0,-256;Inherit;True;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;10;-304,-384;Inherit;True;3;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;9;-928,-512;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;5;-1328,-512;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.LengthOpNode;11;-544,-512;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;15;-768,-512;Inherit;False;CenteredUV;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;0;256,-256;Inherit;False;True;-1;Out;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nWireConnection;14;0;17;0\nWireConnection;14;1;17;1\nWireConnection;17;0;16;0\nWireConnection;18;0;14;0\nWireConnection;18;1;20;0\nWireConnection;18;2;4;0\nWireConnection;20;0;21;0\nWireConnection;20;1;22;0\nWireConnection;1;0;5;0\nWireConnection;23;0;10;0\nWireConnection;23;1;18;0\nWireConnection;10;0;11;0\nWireConnection;10;1;3;0\nWireConnection;10;2;13;0\nWireConnection;9;0;1;0\nWireConnection;9;1;2;0\nWireConnection;11;0;15;0\nWireConnection;15;0;9;0\nWireConnection;0;0;23;0\nASEEND*/\n//CHKSM=7C36C8C8F3864BFA86D86EABF6E84D60184CCBC6" + m_functionName: + m_description: Transforms the given UVs into polar coordinates and returns both + distance to center (X) and angle(Y) + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 14 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polar Coordinates.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polar Coordinates.asset.meta new file mode 100644 index 0000000..f75fc94 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polar Coordinates.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7dab8e02884cf104ebefaa2e788e4162 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polygon.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polygon.asset new file mode 100644 index 0000000..59fcbf0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polygon.asset @@ -0,0 +1,45 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Polygon + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity + Asset Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17500\n776;81;858;790;607.6838;-337.546;1.3;True;False\nNode;AmplifyShaderEditor.RegisterLocalVarNode;12;-192,-496;Inherit;False;cosSides;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-896.0001,-468.8;Inherit;False;Sides;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;25;576,-112;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.PiNode;9;-600.1328,-531.7235;Inherit;False;1;0;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;43;112.5215,865.7967;Inherit;False;30;polarCoords;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ATan2OpNode;27;606.6644,49.34894;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;29;732.6644,-113.6511;Inherit;False;finalUVs;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;37;-240.4785,767.7967;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;20;-368,-224;Inherit;False;Constant;_Float3;Float + 3;0;0;Create;True;0;0;False;0;2;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;42;314.5215,754.7967;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;30;735.6644,34.34894;Inherit;False;polarCoords;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;38;-117.4785,719.7967;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;21;-368,-144;Inherit;False;Constant;_Float4;Float + 4;0;0;Create;True;0;0;False;0;-1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.ScaleAndOffsetNode;19;-208,-240;Inherit;False;3;0;FLOAT2;0,0;False;1;FLOAT;1;False;2;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;5;-560,-304;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.RangedFloatNode;8;-621.4227,144.4016;Inherit;False;Constant;_Float2;Float + 2;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;28;425.6644,54.34894;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;14;-552.0002,37.50001;Inherit;False;12;cosSides;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;7;-648.0002,-42.49999;Inherit;False;Constant;_Float1;Float + 1;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;15;-369.5999,170.3;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CosOpNode;53;466.3291,788.9124;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;55;-474.633,867.5168;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;6;-1020.8,-468.8;Inherit;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;6;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;52;-641.1151,595.2535;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;16;-529.6003,234.3001;Inherit;False;12;cosSides;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;35;-431.4811,738.2798;Inherit;False;30;polarCoords;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;-504.0001,-42.49999;Inherit;False;Width;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;18;-192.8964,46.80437;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.CosOpNode;11;-304,-496;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;10;-427.0461,-493.8062;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;22;48,-112;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.NegateNode;26;442,-37;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;13;-376,-10.5;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;4;-487.6001,145.3;Inherit;False;Height;1;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FloorOpNode;40;9.521484,720.7967;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;1;-368,-304;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;44;610.5215,816.7967;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FWidthOpNode;50;784,880;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;49;944,816;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;51;1072,816;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;45;224,960;Inherit;False;29;finalUVs;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.LengthOpNode;46;400,960;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;39;-320,656;Inherit;False;Constant;_Float5;Float + 5;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.TauNode;31;-749.1282,559.6296;Inherit;False;0;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;33;-837.237,553.755;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;54;-468.628,792.4522;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;23;161.6644,-112.6511;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.OneMinusNode;48;784,800;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;41;144.5215,747.7967;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;1216,816;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;12;0;11;0\nWireConnection;2;0;6;0\nWireConnection;25;0;23;0\nWireConnection;25;1;26;0\nWireConnection;27;0;28;0\nWireConnection;27;1;26;0\nWireConnection;29;0;25;0\nWireConnection;37;0;35;0\nWireConnection;37;1;54;0\nWireConnection;42;0;41;0\nWireConnection;42;1;43;0\nWireConnection;30;0;27;0\nWireConnection;38;0;39;0\nWireConnection;38;1;37;0\nWireConnection;19;0;1;0\nWireConnection;19;1;20;0\nWireConnection;19;2;21;0\nWireConnection;28;0;23;0\nWireConnection;15;0;4;0\nWireConnection;15;1;16;0\nWireConnection;53;0;42;0\nWireConnection;55;0;52;0\nWireConnection;52;0;31;0\nWireConnection;52;1;33;0\nWireConnection;3;0;7;0\nWireConnection;18;0;13;0\nWireConnection;18;1;15;0\nWireConnection;11;0;10;0\nWireConnection;10;0;9;0\nWireConnection;10;1;2;0\nWireConnection;22;0;19;0\nWireConnection;22;1;18;0\nWireConnection;26;0;23;1\nWireConnection;13;0;3;0\nWireConnection;13;1;14;0\nWireConnection;4;0;8;0\nWireConnection;40;0;38;0\nWireConnection;1;0;5;0\nWireConnection;44;0;53;0\nWireConnection;44;1;46;0\nWireConnection;50;0;44;0\nWireConnection;49;0;48;0\nWireConnection;49;1;50;0\nWireConnection;51;0;49;0\nWireConnection;46;0;45;0\nWireConnection;33;0;2;0\nWireConnection;54;0;52;0\nWireConnection;23;0;22;0\nWireConnection;48;0;44;0\nWireConnection;41;0;40;0\nWireConnection;41;1;55;0\nWireConnection;0;0;51;0\nASEEND*/\n//CHKSM=4217BFEBCCECAD2073A228BB92D684CF54BC2E87" + m_functionName: + m_description: Creates a polygon shape with a specified amount of sides + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polygon.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polygon.asset.meta new file mode 100644 index 0000000..0621162 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Polygon.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6906ef7087298c94c853d6753e182169 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PreparePerturbNormalHQ.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PreparePerturbNormalHQ.asset new file mode 100644 index 0000000..f7e8a70 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PreparePerturbNormalHQ.asset @@ -0,0 +1,39 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: PreparePerturbNormalHQ + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=15901\n262;107;1149;682;1369.136;129.7274;1;True;False\nNode;AmplifyShaderEditor.SimpleAddOpNode;3;-153,-151;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WireNode;5;-365,-117;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DotProductOpNode;10;-109,392;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DdxOpNode;2;-344,-36;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DotProductOpNode;11;-153,564;Float;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;8;-141,142;Float;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SqrtOpNode;13;248,484;Float;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DdyOpNode;7;-368,180;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.ConditionalIfNode;12;54,479;Float;False;False;5;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;1;-653,45;Float;False;Value;3;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;9;401,452;Float;False;False;Filter + Width;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;6;128,158;Float;False;False;Value + One Pixel Down;2;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;4;116,61;Float;False;False;Value;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;46,-150;Float;False;True;Value + One Pixel Right;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;3;0;5;0\nWireConnection;3;1;2;0\nWireConnection;5;0;1;0\nWireConnection;10;0;2;0\nWireConnection;10;1;2;0\nWireConnection;2;0;1;0\nWireConnection;11;0;7;0\nWireConnection;11;1;7;0\nWireConnection;8;0;1;0\nWireConnection;8;1;7;0\nWireConnection;13;0;12;0\nWireConnection;7;0;1;0\nWireConnection;12;0;10;0\nWireConnection;12;1;11;0\nWireConnection;12;2;10;0\nWireConnection;12;4;11;0\nWireConnection;9;0;13;0\nWireConnection;6;0;8;0\nWireConnection;4;0;1;0\nWireConnection;0;0;3;0\nASEEND*/\n//CHKSM=F843D9238DE3D976B8A55531C9D75AAF0B29A25D" + m_functionName: + m_description: Based on Prepare Perturb Normal HQ UE4 Material Expression + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PreparePerturbNormalHQ.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PreparePerturbNormalHQ.asset.meta new file mode 100644 index 0000000..6f9cd75 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/PreparePerturbNormalHQ.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ce0790c3228f3654b818a19dd51453a4 +timeCreated: 1542716511 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Procedural Sample.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Procedural Sample.asset new file mode 100644 index 0000000..9453b81 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Procedural Sample.asset @@ -0,0 +1,200 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Procedural Sample + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18701\n339;100;906;513;-1593.459;91.35236;1;True;False\nNode;AmplifyShaderEditor.CommentaryNode;142;-1295.165,-358.8215;Inherit;False;2404.07;914.0666;;23;293;24;27;28;144;4;10;2;6;7;135;137;136;134;139;140;141;138;23;25;22;26;12;2D;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;160;-1287.924,722.2014;Inherit;False;2400.167;913.1149;;30;185;190;189;171;176;181;179;187;188;186;165;161;164;163;162;182;172;191;173;175;180;178;177;174;170;169;168;167;166;294;2D + Array;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;198;-1266.038,4663.606;Inherit;False;2381.579;2608.276;;94;289;254;253;291;290;292;285;271;277;257;256;288;287;286;250;281;264;263;266;278;283;284;282;274;273;272;279;260;259;237;249;235;218;251;248;246;258;214;247;242;280;275;276;270;269;267;265;262;261;255;252;245;244;243;241;240;239;238;236;234;233;232;231;230;229;228;227;226;225;224;223;222;221;220;219;217;216;215;213;212;211;210;209;208;207;206;205;204;203;202;201;200;199;296;Triplanar + 2D Array;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;297;1268.411,-354.576;Inherit;False;1484.525;902.526;;15;302;303;304;305;301;300;299;298;34;0;35;33;32;157;31;Outputs;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;146;-1281.138,1820.621;Inherit;False;2395.235;2604.375;;83;57;130;48;84;67;58;133;132;131;93;56;91;129;43;46;89;47;55;44;194;87;96;110;109;101;105;103;116;100;115;90;119;118;92;120;126;127;128;86;63;42;125;123;88;62;112;60;65;95;54;45;108;70;121;69;79;106;94;97;99;122;192;111;113;53;83;107;98;193;59;149;148;147;114;152;150;102;155;156;117;85;41;295;Triplanar + 2D;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;143;-2805.996,-359.0244;Inherit;False;1399.204;991.5428;;28;104;309;76;36;68;145;82;184;5;73;159;315;77;75;308;80;306;74;71;50;72;81;78;183;64;307;158;61;Inputs;1,1,1,1;0;0\nNode;AmplifyShaderEditor.SamplerNode;170;-365.7677,1082.383;Inherit;True;Property;_TextureSample13;Texture + Sample 1;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;85;-18.17893,3443.745;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;161;-992.5226,1018.242;Inherit;False;76;Input_SS;1;0;OBJECT;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;45;-64.76524,2521.532;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CustomExpressionNode;83;-970.9571,3339.666;Inherit;False;float2 + vertex1, vertex2, vertex3@$$// Scaling of the input$float2 uv = UV * 3.464@ // + 2 * sqrt (3)$$// Skew input space into simplex triangle grid$const float2x2 gridToSkewedGrid + = float2x2( 1.0, 0.0, -0.57735027, 1.15470054 )@$float2 skewedCoord = mul( gridToSkewedGrid, + uv )@$$// Compute local triangle vertex IDs and local barycentric coordinates$int2 + baseId = int2( floor( skewedCoord ) )@$float3 temp = float3( frac( skewedCoord + ), 0 )@$temp.z = 1.0 - temp.x - temp.y@$if ( temp.z > 0.0 )${$\tW1 = temp.z@$\tW2 + = temp.y@$\tW3 = temp.x@$\tvertex1 = baseId@$\tvertex2 = baseId + int2( 0, 1 )@$\tvertex3 + = baseId + int2( 1, 0 )@$}$else${$\tW1 = -temp.z@$\tW2 = 1.0 - temp.y@$\tW3 = + 1.0 - temp.x@$\tvertex1 = baseId + int2( 1, 1 )@$\tvertex2 = baseId + int2( 1, + 0 )@$\tvertex3 = baseId + int2( 0, 1 )@$}$$UV1 = UV + frac( sin( mul( float2x2( + 127.1, 311.7, 269.5, 183.3 ), vertex1 ) ) * 43758.5453 )@$UV2 = UV + frac( sin( + mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex2 ) ) * 43758.5453 )@$UV3 = + UV + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex3 ) ) * 43758.5453 + )@$return@;7;False;7;True;UV;FLOAT2;0,0;In;;Float;False;True;UV1;FLOAT2;0,0;Out;;Float;False;True;UV2;FLOAT2;0,0;Out;;Float;False;True;UV3;FLOAT2;0,0;Out;;Float;False;True;W1;FLOAT;0;Out;;Float;False;True;W2;FLOAT;0;Out;;Float;False;True;W3;FLOAT;0;Out;;Float;False;Stochastic + Tiling;False;False;0;8;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;7;FLOAT;0;FLOAT2;3;FLOAT2;4;FLOAT2;5;FLOAT;6;FLOAT;7;FLOAT;8\nNode;AmplifyShaderEditor.WireNode;102;-46.64538,4274.229;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;113;-1224.541,3090.587;Inherit;False;64;Triplanar_UV1;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;47;-674.6476,2026.501;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;121;72.30684,4059.421;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.CustomExpressionNode;108;165.3301,2727.335;Inherit;False;half3 + weights = max( abs( WorldNormal.xyz ), 0.000001 )@$weights /= ( weights.x + weights.y + + weights.z ).xxx@$W0 = weights.x@$W1 = weights.y@$W2 = weights.z@$return@;7;False;4;True;WorldNormal;FLOAT3;0,0,0;In;;Inherit;False;True;W0;FLOAT;0;Out;;Inherit;False;True;W1;FLOAT;0;Out;;Inherit;False;True;W2;FLOAT;0;Out;;Inherit;False;Triplanar + Weights;True;False;0;5;0;FLOAT;0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;4;FLOAT;0;FLOAT;3;FLOAT;4;FLOAT;5\nNode;AmplifyShaderEditor.WireNode;141;-687.2004,-56.97699;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;70;702.0071,3020.752;Inherit;False;3;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;194;-172.265,3509.147;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;26;303.8399,385.2554;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CustomExpressionNode;2;-967.7908,239.7245;Inherit;False;float2 + vertex1, vertex2, vertex3@$$// Scaling of the input$float2 uv = UV * 3.464@ // + 2 * sqrt (3)$$// Skew input space into simplex triangle grid$const float2x2 gridToSkewedGrid + = float2x2( 1.0, 0.0, -0.57735027, 1.15470054 )@$float2 skewedCoord = mul( gridToSkewedGrid, + uv )@$$// Compute local triangle vertex IDs and local barycentric coordinates$int2 + baseId = int2( floor( skewedCoord ) )@$float3 temp = float3( frac( skewedCoord + ), 0 )@$temp.z = 1.0 - temp.x - temp.y@$if ( temp.z > 0.0 )${$\tW1 = temp.z@$\tW2 + = temp.y@$\tW3 = temp.x@$\tvertex1 = baseId@$\tvertex2 = baseId + int2( 0, 1 )@$\tvertex3 + = baseId + int2( 1, 0 )@$}$else${$\tW1 = -temp.z@$\tW2 = 1.0 - temp.y@$\tW3 = + 1.0 - temp.x@$\tvertex1 = baseId + int2( 1, 1 )@$\tvertex2 = baseId + int2( 1, + 0 )@$\tvertex3 = baseId + int2( 0, 1 )@$}$$UV1 = UV + frac( sin( mul( float2x2( + 127.1, 311.7, 269.5, 183.3 ), vertex1 ) ) * 43758.5453 )@$UV2 = UV + frac( sin( + mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex2 ) ) * 43758.5453 )@$UV3 = + UV + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex3 ) ) * 43758.5453 + )@$return@;7;False;7;True;UV;FLOAT2;0,0;In;;Float;False;True;UV1;FLOAT2;0,0;Out;;Float;False;True;UV2;FLOAT2;0,0;Out;;Float;False;True;UV3;FLOAT2;0,0;Out;;Float;False;True;W1;FLOAT;0;Out;;Float;False;True;W2;FLOAT;0;Out;;Float;False;True;W3;FLOAT;0;Out;;Float;False;Stochastic + Tiling;False;False;0;8;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;7;FLOAT;0;FLOAT2;3;FLOAT2;4;FLOAT2;5;FLOAT;6;FLOAT;7;FLOAT;8\nNode;AmplifyShaderEditor.WireNode;152;-187.3821,4345.959;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;169;-365.385,1286.126;Inherit;True;Property;_TextureSample12;Texture + Sample 2;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;43;-377.2667,2361.99;Inherit;True;Property;_TextureSample3;Texture + Sample 3;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;119;-519.4247,3719.87;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;163;-740.3662,1072.4;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;25;303.8398,354.8411;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;139;-671.59,-112.4807;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.GetLocalVarNode;130;-951.8373,1870.621;Inherit;False;68;Input_Texture;1;0;OBJECT;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;114;-21.95006,4281.605;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;100;-369.6875,2860.79;Inherit;True;Property;_TextureSample7;Texture + Sample 7;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;56;-374.4885,1954.325;Inherit;True;Property;_TextureSample4;Texture + Sample 4;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;89;-372.4656,3268.457;Inherit;True;Property;_TextureSample6;Texture + Sample 6;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;46;-674.6478,2058.139;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;87;-539.7791,2910.117;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;84;-669.847,2964.604;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;164;-736.9875,1046.247;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;131;-507.7252,1950.13;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SamplerNode;91;-372.8483,3064.712;Inherit;True;Property;_TextureSample5;Texture + Sample 5;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;69;520.7668,2902.641;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SamplerNode;7;-372.6252,205.1037;Inherit;True;Property;_TextureSample2;Texture + Sample 2;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;156;-195.8623,4301.043;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;95;275.6625,3046.13;Inherit;False;3;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;136;-568.3672,-163.3666;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SamplerNode;173;-362.6067,878.461;Inherit;True;Property;_TextureSample14;Texture + Sample 0;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;150;-190.2717,4322.456;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;202;-180.7623,7144.028;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;112;-540.5168,3756.782;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;94;77.9698,3211.89;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;99;65.72094,2930.447;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;186;-641.9001,979.174;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DdxOpNode;10;-960.4671,-5.020669;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;162;-755.9764,1096.683;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;60;16.91692,2162.801;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;122;269.9997,3893.663;Inherit;False;3;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;138;-999.7629,-162.4468;Inherit;False;76;Input_SS;1;0;OBJECT;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;147;-183.8212,2565.917;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSubtitle;303;1604.811,-34.21301;Inherit;False;Planar + 2D Array;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;133;-559.291,1999.009;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;200;-3.078922,6286.73;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DdxOpNode;107;-961.0446,3904.996;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;90;-949.1356,2796.05;Inherit;False;68;Input_Texture;1;0;OBJECT;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;140;-671.5901,-81.25983;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.CustomExpressionNode;53;-969.106,2453.156;Inherit;False;float2 + vertex1, vertex2, vertex3@$$// Scaling of the input$float2 uv = UV * 3.464@ // + 2 * sqrt (3)$$// Skew input space into simplex triangle grid$const float2x2 gridToSkewedGrid + = float2x2( 1.0, 0.0, -0.57735027, 1.15470054 )@$float2 skewedCoord = mul( gridToSkewedGrid, + uv )@$$// Compute local triangle vertex IDs and local barycentric coordinates$int2 + baseId = int2( floor( skewedCoord ) )@$float3 temp = float3( frac( skewedCoord + ), 0 )@$temp.z = 1.0 - temp.x - temp.y@$if ( temp.z > 0.0 )${$\tW1 = temp.z@$\tW2 + = temp.y@$\tW3 = temp.x@$\tvertex1 = baseId@$\tvertex2 = baseId + int2( 0, 1 )@$\tvertex3 + = baseId + int2( 1, 0 )@$}$else${$\tW1 = -temp.z@$\tW2 = 1.0 - temp.y@$\tW3 = + 1.0 - temp.x@$\tvertex1 = baseId + int2( 1, 1 )@$\tvertex2 = baseId + int2( 1, + 0 )@$\tvertex3 = baseId + int2( 0, 1 )@$}$$UV1 = UV + frac( sin( mul( float2x2( + 127.1, 311.7, 269.5, 183.3 ), vertex1 ) ) * 43758.5453 )@$UV2 = UV + frac( sin( + mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex2 ) ) * 43758.5453 )@$UV3 = + UV + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex3 ) ) * 43758.5453 + )@$return@;7;False;7;True;UV;FLOAT2;0,0;In;;Float;False;True;UV1;FLOAT2;0,0;Out;;Float;False;True;UV2;FLOAT2;0,0;Out;;Float;False;True;UV3;FLOAT2;0,0;Out;;Float;False;True;W1;FLOAT;0;Out;;Float;False;True;W2;FLOAT;0;Out;;Float;False;True;W3;FLOAT;0;Out;;Float;False;Stochastic + Tiling;False;False;0;8;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;7;FLOAT;0;FLOAT2;3;FLOAT2;4;FLOAT2;5;FLOAT;6;FLOAT;7;FLOAT;8\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;106;524.8408,3222.355;Inherit;False;2;2;0;FLOAT;0;False;1;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;137;-600.6234,-132.8083;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;192;-180.2166,3486.774;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;116;-948.1158,3727.082;Inherit;False;76;Input_SS;1;0;OBJECT;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;176;67.66106,1501.591;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;111;-570.3969,3770.843;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.FunctionSubtitle;304;1618.694,95.19456;Inherit;False;Triplanar + 2D;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;134;-1003.098,-253.8223;Inherit;False;68;Input_Texture;1;0;OBJECT;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.GetLocalVarNode;44;-1231.138,2184.123;Inherit;False;50;Triplanar_UV0;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;63;222.213,2136.949;Inherit;False;3;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;115;-688.1614,3828.846;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SamplerNode;128;-373.2032,4115.121;Inherit;True;Property;_TextureSample11;Texture + Sample 11;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;120;-670.5846,3811.27;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;294;865.0776,1047.969;Inherit;False;Output_2DArray;-1;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionInput;104;-2531.787,313.7767;Inherit;False;Tiling;2;5;False;1;0;FLOAT2;1,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;149;-183.7648,2612.974;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DdxOpNode;172;-948.1591,1126.679;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;178;487.1229,1080.427;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;42;24.52043,2302.707;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SamplerNode;4;-369.847,-202.5619;Inherit;True;Property;_TextureSample0;Texture + Sample 0;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;168;-547.5455,876.9119;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.GetLocalVarNode;174;-1236.06,1180.329;Inherit;False;145;Input_UV;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;190;-158.0187,1528.828;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;123;64.70333,3919.515;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;188;-659.7223,1049.705;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;118;-670.5844,3779.631;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;191;-158.0863,1551.41;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DdxOpNode;86;-960.3069,3058.33;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;148;-185.7914,2588.942;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;28;689.8213,-14.83985;Inherit;False;3;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;175;692.4185,1054.575;Inherit;False;3;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionSwitch;157;1885.965,-13.69264;Inherit;False;Sample + Mode;False;0;4;-1;Planar 2D;Planar 2D Array;Triplanar 2D;Triplanar 2D Array;Object;-1;9;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;3;COLOR;0,0,0,0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;132;-522.834,1983.267;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;59;-45.21275,2528.454;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;293;865.8185,-18.28572;Inherit;False;Output_2D;-1;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;103;-949.8732,3642.714;Inherit;False;68;Input_Texture;1;0;OBJECT;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;177;494.7263,1220.333;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionSubtitle;305;1583.404,244.2609;Inherit;False;Triplanar + 2D Array;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;24;492.1291,150.9177;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;65;21.47899,2033.54;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;180;491.6849,951.1669;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.DdyOpNode;182;-946.6234,1204.227;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSubtitle;302;1639.862,-181.2332;Inherit;False;Planar + 2D;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;166;-561.127,917.6563;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;193;-184.1203,3463.355;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;300;1336.352,91.59142;Inherit;False;295;Output_Triplanar;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;48;-952.1794,1973.951;Inherit;False;76;Input_SS;1;0;OBJECT;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.DdyOpNode;92;-958.7713,3135.878;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;208;-168.7211,5408.902;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;298;1358.352,-187.2293;Inherit;False;293;Output_2D;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;155;-67.66827,4256.529;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;93;-669.8467,2932.966;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.CustomExpressionNode;171;-942.7695,1359.865;Inherit;False;float2 + vertex1, vertex2, vertex3@$$// Scaling of the input$float2 uv = UV * 3.464@ // + 2 * sqrt (3)$$// Skew input space into simplex triangle grid$const float2x2 gridToSkewedGrid + = float2x2( 1.0, 0.0, -0.57735027, 1.15470054 )@$float2 skewedCoord = mul( gridToSkewedGrid, + uv )@$$// Compute local triangle vertex IDs and local barycentric coordinates$int2 + baseId = int2( floor( skewedCoord ) )@$float3 temp = float3( frac( skewedCoord + ), 0 )@$temp.z = 1.0 - temp.x - temp.y@$if ( temp.z > 0.0 )${$\tW1 = temp.z@$\tW2 + = temp.y@$\tW3 = temp.x@$\tvertex1 = baseId@$\tvertex2 = baseId + int2( 0, 1 )@$\tvertex3 + = baseId + int2( 1, 0 )@$}$else${$\tW1 = -temp.z@$\tW2 = 1.0 - temp.y@$\tW3 = + 1.0 - temp.x@$\tvertex1 = baseId + int2( 1, 1 )@$\tvertex2 = baseId + int2( 1, + 0 )@$\tvertex3 = baseId + int2( 0, 1 )@$}$$UV1 = UV + frac( sin( mul( float2x2( + 127.1, 311.7, 269.5, 183.3 ), vertex1 ) ) * 43758.5453 )@$UV2 = UV + frac( sin( + mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex2 ) ) * 43758.5453 )@$UV3 = + UV + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex3 ) ) * 43758.5453 + )@$return@;7;False;7;True;UV;FLOAT2;0,0;In;;Float;False;True;UV1;FLOAT2;0,0;Out;;Float;False;True;UV2;FLOAT2;0,0;Out;;Float;False;True;UV3;FLOAT2;0,0;Out;;Float;False;True;W1;FLOAT;0;Out;;Float;False;True;W2;FLOAT;0;Out;;Float;False;True;W3;FLOAT;0;Out;;Float;False;Stochastic + Tiling;False;False;0;8;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;7;FLOAT;0;FLOAT2;3;FLOAT2;4;FLOAT2;5;FLOAT;6;FLOAT;7;FLOAT;8\nNode;AmplifyShaderEditor.WireNode;88;-518.6871,2873.205;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.GetLocalVarNode;101;-947.3781,2880.416;Inherit;False;76;Input_SS;1;0;OBJECT;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;199;-18.26203,6268.457;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;189;-159.3294,1507.557;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;79;518.7319,3049.262;Inherit;False;2;2;0;FLOAT;0;False;1;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;125;69.26546,3790.255;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.CustomExpressionNode;117;-976.4214,4183.103;Inherit;False;float2 + vertex1, vertex2, vertex3@$$// Scaling of the input$float2 uv = UV * 3.464@ // + 2 * sqrt (3)$$// Skew input space into simplex triangle grid$const float2x2 gridToSkewedGrid + = float2x2( 1.0, 0.0, -0.57735027, 1.15470054 )@$float2 skewedCoord = mul( gridToSkewedGrid, + uv )@$$// Compute local triangle vertex IDs and local barycentric coordinates$int2 + baseId = int2( floor( skewedCoord ) )@$float3 temp = float3( frac( skewedCoord + ), 0 )@$temp.z = 1.0 - temp.x - temp.y@$if ( temp.z > 0.0 )${$\tW1 = temp.z@$\tW2 + = temp.y@$\tW3 = temp.x@$\tvertex1 = baseId@$\tvertex2 = baseId + int2( 0, 1 )@$\tvertex3 + = baseId + int2( 1, 0 )@$}$else${$\tW1 = -temp.z@$\tW2 = 1.0 - temp.y@$\tW3 = + 1.0 - temp.x@$\tvertex1 = baseId + int2( 1, 1 )@$\tvertex2 = baseId + int2( 1, + 0 )@$\tvertex3 = baseId + int2( 0, 1 )@$}$$UV1 = UV + frac( sin( mul( float2x2( + 127.1, 311.7, 269.5, 183.3 ), vertex1 ) ) * 43758.5453 )@$UV2 = UV + frac( sin( + mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex2 ) ) * 43758.5453 )@$UV3 = + UV + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex3 ) ) * 43758.5453 + )@$return@;7;False;7;True;UV;FLOAT2;0,0;In;;Float;False;True;UV1;FLOAT2;0,0;Out;;Float;False;True;UV2;FLOAT2;0,0;Out;;Float;False;True;UV3;FLOAT2;0,0;Out;;Float;False;True;W1;FLOAT;0;Out;;Float;False;True;W2;FLOAT;0;Out;;Float;False;True;W3;FLOAT;0;Out;;Float;False;Stochastic + Tiling;False;False;0;8;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;7;FLOAT;0;FLOAT2;3;FLOAT2;4;FLOAT2;5;FLOAT;6;FLOAT;7;FLOAT;8\nNode;AmplifyShaderEditor.SamplerNode;6;-373.0079,1.359925;Inherit;True;Property;_TextureSample1;Texture + Sample 1;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;126;-373.5859,3911.377;Inherit;True;Property;_TextureSample9;Texture + Sample 9;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;181;61.0726,1469.656;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CustomExpressionNode;201;-961.3214,7026.089;Inherit;False;float2 + vertex1, vertex2, vertex3@$$// Scaling of the input$float2 uv = UV * 3.464@ // + 2 * sqrt (3)$$// Skew input space into simplex triangle grid$const float2x2 gridToSkewedGrid + = float2x2( 1.0, 0.0, -0.57735027, 1.15470054 )@$float2 skewedCoord = mul( gridToSkewedGrid, + uv )@$$// Compute local triangle vertex IDs and local barycentric coordinates$int2 + baseId = int2( floor( skewedCoord ) )@$float3 temp = float3( frac( skewedCoord + ), 0 )@$temp.z = 1.0 - temp.x - temp.y@$if ( temp.z > 0.0 )${$\tW1 = temp.z@$\tW2 + = temp.y@$\tW3 = temp.x@$\tvertex1 = baseId@$\tvertex2 = baseId + int2( 0, 1 )@$\tvertex3 + = baseId + int2( 1, 0 )@$}$else${$\tW1 = -temp.z@$\tW2 = 1.0 - temp.y@$\tW3 = + 1.0 - temp.x@$\tvertex1 = baseId + int2( 1, 1 )@$\tvertex2 = baseId + int2( 1, + 0 )@$\tvertex3 = baseId + int2( 0, 1 )@$}$$UV1 = UV + frac( sin( mul( float2x2( + 127.1, 311.7, 269.5, 183.3 ), vertex1 ) ) * 43758.5453 )@$UV2 = UV + frac( sin( + mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex2 ) ) * 43758.5453 )@$UV3 = + UV + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex3 ) ) * 43758.5453 + )@$return@;7;False;7;True;UV;FLOAT2;0,0;In;;Float;False;True;UV1;FLOAT2;0,0;Out;;Float;False;True;UV2;FLOAT2;0,0;Out;;Float;False;True;UV3;FLOAT2;0,0;Out;;Float;False;True;W1;FLOAT;0;Out;;Float;False;True;W2;FLOAT;0;Out;;Float;False;True;W3;FLOAT;0;Out;;Float;False;Stochastic + Tiling;False;False;0;8;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;7;FLOAT;0;FLOAT2;3;FLOAT2;4;FLOAT2;5;FLOAT;6;FLOAT;7;FLOAT;8\nNode;AmplifyShaderEditor.WireNode;167;-593.3832,948.2145;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.SamplerNode;127;-370.425,3707.456;Inherit;True;Property;_TextureSample10;Texture + Sample 10;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.DdyOpNode;12;-958.9313,72.52722;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;165;-1044.845,828.8899;Inherit;False;159;Input_TextureArray;1;0;OBJECT;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;41;-33.36201,3425.471;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;187;-645.2793,997.7559;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;299;1331.738,-38.71012;Inherit;False;294;Output_2DArray;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;129;-362.8989,2887.883;Inherit;False;68;Input_Texture;1;0;OBJECT;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.DdyOpNode;58;-963.5724,2229.414;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WorldNormalVector;62;-31.00317,2723.179;Inherit;False;False;1;0;FLOAT3;0,0,1;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.WireNode;54;-92.78294,2504.121;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DdxOpNode;57;-965.1083,2151.866;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;251;-733.1257,6786.954;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.CustomExpressionNode;216;-954.0061,5296.142;Inherit;False;float2 + vertex1, vertex2, vertex3@$$// Scaling of the input$float2 uv = UV * 3.464@ // + 2 * sqrt (3)$$// Skew input space into simplex triangle grid$const float2x2 gridToSkewedGrid + = float2x2( 1.0, 0.0, -0.57735027, 1.15470054 )@$float2 skewedCoord = mul( gridToSkewedGrid, + uv )@$$// Compute local triangle vertex IDs and local barycentric coordinates$int2 + baseId = int2( floor( skewedCoord ) )@$float3 temp = float3( frac( skewedCoord + ), 0 )@$temp.z = 1.0 - temp.x - temp.y@$if ( temp.z > 0.0 )${$\tW1 = temp.z@$\tW2 + = temp.y@$\tW3 = temp.x@$\tvertex1 = baseId@$\tvertex2 = baseId + int2( 0, 1 )@$\tvertex3 + = baseId + int2( 1, 0 )@$}$else${$\tW1 = -temp.z@$\tW2 = 1.0 - temp.y@$\tW3 = + 1.0 - temp.x@$\tvertex1 = baseId + int2( 1, 1 )@$\tvertex2 = baseId + int2( 1, + 0 )@$\tvertex3 = baseId + int2( 0, 1 )@$}$$UV1 = UV + frac( sin( mul( float2x2( + 127.1, 311.7, 269.5, 183.3 ), vertex1 ) ) * 43758.5453 )@$UV2 = UV + frac( sin( + mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex2 ) ) * 43758.5453 )@$UV3 = + UV + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex3 ) ) * 43758.5453 + )@$return@;7;False;7;True;UV;FLOAT2;0,0;In;;Float;False;True;UV1;FLOAT2;0,0;Out;;Float;False;True;UV2;FLOAT2;0,0;Out;;Float;False;True;UV3;FLOAT2;0,0;Out;;Float;False;True;W1;FLOAT;0;Out;;Float;False;True;W2;FLOAT;0;Out;;Float;False;True;W3;FLOAT;0;Out;;Float;False;Stochastic + Tiling;False;False;0;8;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;7;FLOAT;0;FLOAT2;3;FLOAT2;4;FLOAT2;5;FLOAT;6;FLOAT;7;FLOAT;8\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;240;39.62043,5145.692;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.DdxOpNode;242;-927.6881,5993.915;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;279;-998.8414,4745.661;Inherit;False;159;Input_TextureArray;1;0;OBJECT;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;224;539.9408,6065.341;Inherit;False;2;2;0;FLOAT;0;False;1;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;261;-157.165,6352.133;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;105;-377.6494,2158.247;Inherit;True;Property;_TextureSample8;Texture + Sample 8;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleAddOpNode;232;290.7627,5889.115;Inherit;False;3;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;227;87.40696,6902.406;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;213;-33.87604,6253.656;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;231;-77.68291,5347.106;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;284;-605.3763,4924.135;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;239;84.36546,6633.24;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.DdxOpNode;214;-933.4313,6855.596;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;205;-175.1717,7165.441;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;245;-358.4859,6754.362;Inherit;True;Property;_TextureSample17;Texture + Sample 9;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;288;-603.3726,5839.669;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;277;-693.7852,5897.679;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;260;-494.6287,5761.116;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;218;-533.2599,6622.33;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;257;-711.3621,5915.255;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.FunctionInput;183;-2522.189,101.5914;Inherit;False;Index;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;212;-169.0203,6306.341;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;243;-358.1031,6958.106;Inherit;True;Property;_TextureSample15;Texture + Sample 11;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;233;36.57905,4876.525;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WorldNormalVector;236;-15.90314,5566.165;Inherit;False;False;1;0;FLOAT3;0,0,1;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.WireNode;271;-676.2661,5873.548;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;234;32.01691,5005.787;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;185;-1005.769,928.8007;Inherit;False;184;Input_Index;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DdyOpNode;275;-915.9375,5175.009;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;238;79.80344,6762.5;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;254;-1037.831,6514.394;Inherit;False;159;Input_TextureArray;1;0;OBJECT;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;97;70.36629,3071.982;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;203;-52.56817,7099.515;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;230;-49.66521,5364.518;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;207;-6.85004,7124.591;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;259;-524.509,5775.177;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;109;-687.4238,2982.181;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.CustomExpressionNode;229;180.4301,5570.32;Inherit;False;half3 + weights = max( abs( WorldNormal.xyz ), 0.000001 )@$weights /= ( weights.x + weights.y + + weights.z ).xxx@$W0 = weights.x@$W1 = weights.y@$W2 = weights.z@$return@;7;False;4;True;WorldNormal;FLOAT3;0,0,0;In;;Inherit;False;True;W0;FLOAT;0;Out;;Inherit;False;True;W1;FLOAT;0;Out;;Inherit;False;True;W2;FLOAT;0;Out;;Inherit;False;Triplanar + Weights;True;False;0;5;0;FLOAT;0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;4;FLOAT;0;FLOAT;3;FLOAT;4;FLOAT;5\nNode;AmplifyShaderEditor.DdyOpNode;247;-926.1526,6071.462;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;27;305.3607,417.1903;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;264;-677.0543,4964.566;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;241;237.3129,4979.935;Inherit;False;3;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.DdyOpNode;258;-931.8958,6933.145;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;255;-362.5493,5001.232;Inherit;True;Property;_TextureSample19;Texture + Sample 8;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;246;-715.549,6769.378;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;237;-473.5366,5724.204;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.SamplerNode;252;-354.5874,5703.775;Inherit;True;Property;_TextureSample18;Texture + Sample 7;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;248;-715.5488,6737.739;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;223;93.0698,6054.875;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;281;-964.0038,4829.952;Inherit;False;184;Input_Index;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;250;-1022.183,5639.036;Inherit;False;159;Input_TextureArray;1;0;OBJECT;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;228;717.1071,5863.737;Inherit;False;3;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;204;-31.54535,7117.215;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;296;870.2289,5857.978;Inherit;False;Output_TriplanarArray;-1;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;273;-475.6802,4856.304;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;22;489.0877,-118.2482;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;287;-589.3491,5819.636;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;144;-1257.727,32.94259;Inherit;False;145;Input_UV;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;158;-2590.266,-3.661018;Inherit;False;Texture + Array;12;1;False;1;0;SAMPLER2DARRAY;0;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;274;-512.1373,4872.046;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.GetLocalVarNode;253;-984.0741,6702.991;Inherit;False;76;Input_SS;1;0;OBJECT;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.GetLocalVarNode;256;-972.3212,5842.516;Inherit;False;76;Input_SS;1;0;OBJECT;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;272;-460.5714,4823.167;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;290;-615.3917,6651.026;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DdyOpNode;110;-959.5091,3982.545;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;67;-1225.278,3937.253;Inherit;False;71;Triplanar_UV2;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;265;-357.3655,6111.442;Inherit;True;Property;_TextureSample20;Texture + Sample 6;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;283;-597.3629,4908.108;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;291;-613.3883,6679.072;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;179;44.18006,1435.864;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;292;-619.3984,6699.106;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;217;-1206.556,6060.53;Inherit;False;64;Triplanar_UV1;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;276;-1230.178,6903.238;Inherit;False;71;Triplanar_UV2;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;220;285.0999,6736.648;Inherit;False;3;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SamplerNode;269;-357.7482,5907.697;Inherit;True;Property;_TextureSample22;Texture + Sample 5;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;222;85.46629,5914.968;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;219;-165.1165,6329.76;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;226;535.8668,5745.627;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;266;-694.5734,4988.696;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;221;80.82102,5773.433;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;289;-998.0596,6606.927;Inherit;False;184;Input_Index;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;267;-362.1667,5204.976;Inherit;True;Property;_TextureSample21;Texture + Sample 3;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;74;-2575.694,186.7092;Inherit;False;SS;13;6;False;1;0;SAMPLERSTATE;0;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;225;533.8319,5892.248;Inherit;False;2;2;0;FLOAT;0;False;1;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.DdxOpNode;280;-917.4734,5097.461;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;235;-503.3798,6608.269;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.WireNode;55;-692.2244,2075.716;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;98;-48.9761,3410.671;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;210;-168.6647,5455.96;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;308;-2149.554,321.281;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;211;-30.11273,5371.439;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;263;-699.6365,5013.781;Inherit;False;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.SamplerNode;244;-355.325,6550.441;Inherit;True;Property;_TextureSample16;Texture + Sample 10;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;286;-589.3489,5787.583;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;209;-170.6913,5431.928;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;206;-172.282,7188.944;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;96;-569.6593,2924.178;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.GetLocalVarNode;278;-946.5848,4931.528;Inherit;False;76;Input_SS;1;0;OBJECT;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.WireNode;135;-554.7857,-204.111;Inherit;False;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;36;-2384.665,-215.9967;Inherit;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WireNode;249;-482.2875,6571.357;Inherit;False;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;145;-1629.496,-192.1966;Inherit;False;Input_UV;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;68;-1637.527,-288.2665;Inherit;False;Input_Texture;-1;True;1;0;SAMPLER2D;;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SamplerNode;270;-359.3885,4797.311;Inherit;True;Property;_TextureSample23;Texture + Sample 4;0;0;Create;True;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Object;-1;Derivative;Texture2DArray;8;0;SAMPLER2DARRAY;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.TextureCoordinatesNode;309;-2384.424,-81.31772;Inherit;False;0;-1;2;3;2;SAMPLER2DARRAY;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;23;484.5256,11.0122;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;262;-1204.496,5159.837;Inherit;False;50;Triplanar_UV0;1;0;OBJECT;;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.CustomExpressionNode;215;-955.8572,6182.651;Inherit;False;float2 + vertex1, vertex2, vertex3@$$// Scaling of the input$float2 uv = UV * 3.464@ // + 2 * sqrt (3)$$// Skew input space into simplex triangle grid$const float2x2 gridToSkewedGrid + = float2x2( 1.0, 0.0, -0.57735027, 1.15470054 )@$float2 skewedCoord = mul( gridToSkewedGrid, + uv )@$$// Compute local triangle vertex IDs and local barycentric coordinates$int2 + baseId = int2( floor( skewedCoord ) )@$float3 temp = float3( frac( skewedCoord + ), 0 )@$temp.z = 1.0 - temp.x - temp.y@$if ( temp.z > 0.0 )${$\tW1 = temp.z@$\tW2 + = temp.y@$\tW3 = temp.x@$\tvertex1 = baseId@$\tvertex2 = baseId + int2( 0, 1 )@$\tvertex3 + = baseId + int2( 1, 0 )@$}$else${$\tW1 = -temp.z@$\tW2 = 1.0 - temp.y@$\tW3 = + 1.0 - temp.x@$\tvertex1 = baseId + int2( 1, 1 )@$\tvertex2 = baseId + int2( 1, + 0 )@$\tvertex3 = baseId + int2( 0, 1 )@$}$$UV1 = UV + frac( sin( mul( float2x2( + 127.1, 311.7, 269.5, 183.3 ), vertex1 ) ) * 43758.5453 )@$UV2 = UV + frac( sin( + mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex2 ) ) * 43758.5453 )@$UV3 = + UV + frac( sin( mul( float2x2( 127.1, 311.7, 269.5, 183.3 ), vertex3 ) ) * 43758.5453 + )@$return@;7;False;7;True;UV;FLOAT2;0,0;In;;Float;False;True;UV1;FLOAT2;0,0;Out;;Float;False;True;UV2;FLOAT2;0,0;Out;;Float;False;True;UV3;FLOAT2;0,0;Out;;Float;False;True;W1;FLOAT;0;Out;;Float;False;True;W2;FLOAT;0;Out;;Float;False;True;W3;FLOAT;0;Out;;Float;False;Stochastic + Tiling;False;False;0;8;0;FLOAT;0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;7;FLOAT;0;FLOAT2;3;FLOAT2;4;FLOAT2;5;FLOAT;6;FLOAT;7;FLOAT;8\nNode;AmplifyShaderEditor.FunctionInput;5;-1772.503,-191.8328;Inherit;False;UV;2;3;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitch;315;-2116.706,-191.1189;Inherit;False;Option;False;0;4;-1;2D;2D + Array;Triplanar;Triplanar Array;Instance;157;9;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;FLOAT2;0,0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;159;-1638.465,-4.046509;Inherit;False;Input_TextureArray;-1;True;1;0;SAMPLER2DARRAY;;False;1;SAMPLER2DARRAY;0\nNode;AmplifyShaderEditor.FunctionInput;82;-2562.134,-290.8169;Inherit;False;Texture;9;0;False;1;0;SAMPLER2D;0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.WireNode;282;-591.3529,4882.065;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;301;1327.809,238.6714;Inherit;False;296;Output_TriplanarArray;1;0;OBJECT;;False;1;COLOR;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;184;-1632.055,101.7441;Inherit;False;Input_Index;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SwizzleNode;61;-2258.47,364.7153;Inherit;False;FLOAT2;2;1;2;3;1;0;FLOAT3;0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;306;-2196.85,294.618;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;307;-2138.884,347.3101;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;77;-1994.028,329.8235;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SwizzleNode;73;-2257.888,435.678;Inherit;False;FLOAT2;2;0;2;3;1;0;FLOAT3;0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;285;-984.0376,5741.479;Inherit;False;184;Input_Index;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;31;2294.798,132.5219;Inherit;False;COLOR;1;0;COLOR;0,0,0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.RegisterLocalVarNode;76;-1632.419,184.9388;Inherit;False;Input_SS;-1;True;1;0;SAMPLERSTATE;;False;1;SAMPLERSTATE;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;295;873.6226,3015.605;Inherit;False;Output_Triplanar;-1;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WorldPosInputsNode;81;-2760.234,421.0934;Inherit;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;72;-1993.533,507.2687;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;64;-1632.479,418.3403;Inherit;False;Triplanar_UV1;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;78;-1994.079,417.5941;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;80;-2574.644,415.9991;Inherit;False;World + Position;3;4;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SwizzleNode;75;-2257.687,506.5578;Inherit;False;FLOAT2;0;1;2;3;1;0;FLOAT3;0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;50;-1630.848,341.5698;Inherit;False;Triplanar_UV0;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;71;-1630.916,494.2191;Inherit;False;Triplanar_UV2;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;33;2573.17,133.5936;Inherit;False;False;-1;G;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;2573.008,-6.675806;Inherit;False;True;-1;RGBA;0;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionOutput;34;2576.37,208.7937;Inherit;False;False;-1;B;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;35;2577.97,287.1936;Inherit;False;False;-1;A;4;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;32;2573.17,63.19369;Inherit;False;False;-1;R;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;170;0;166;0\nWireConnection;170;1;171;4\nWireConnection;170;3;172;0\nWireConnection;170;4;182;0\nWireConnection;170;6;187;0\nWireConnection;170;7;163;0\nWireConnection;85;0;194;0\nWireConnection;45;0;148;0\nWireConnection;83;1;113;0\nWireConnection;102;0;150;0\nWireConnection;47;0;48;0\nWireConnection;121;0;128;0\nWireConnection;121;1;114;0\nWireConnection;108;1;62;0\nWireConnection;141;0;138;0\nWireConnection;70;0;69;0\nWireConnection;70;1;79;0\nWireConnection;70;2;106;0\nWireConnection;194;0;83;8\nWireConnection;26;0;2;7\nWireConnection;2;1;144;0\nWireConnection;152;0;117;8\nWireConnection;169;0;167;0\nWireConnection;169;1;171;5\nWireConnection;169;3;172;0\nWireConnection;169;4;182;0\nWireConnection;169;6;188;0\nWireConnection;169;7;162;0\nWireConnection;43;0;133;0\nWireConnection;43;1;53;5\nWireConnection;43;3;57;0\nWireConnection;43;4;58;0\nWireConnection;43;7;55;0\nWireConnection;119;0;103;0\nWireConnection;163;0;161;0\nWireConnection;25;0;2;6\nWireConnection;139;0;138;0\nWireConnection;114;0;152;0\nWireConnection;100;0;88;0\nWireConnection;100;1;83;3\nWireConnection;100;3;86;0\nWireConnection;100;4;92;0\nWireConnection;100;7;93;0\nWireConnection;56;0;131;0\nWireConnection;56;1;53;3\nWireConnection;56;3;57;0\nWireConnection;56;4;58;0\nWireConnection;56;7;47;0\nWireConnection;89;0;96;0\nWireConnection;89;1;83;5\nWireConnection;89;3;86;0\nWireConnection;89;4;92;0\nWireConnection;89;7;109;0\nWireConnection;46;0;48;0\nWireConnection;87;0;90;0\nWireConnection;84;0;101;0\nWireConnection;164;0;161;0\nWireConnection;131;0;130;0\nWireConnection;91;0;87;0\nWireConnection;91;1;83;4\nWireConnection;91;3;86;0\nWireConnection;91;4;92;0\nWireConnection;91;7;84;0\nWireConnection;69;0;63;0\nWireConnection;69;1;108;3\nWireConnection;7;0;137;0\nWireConnection;7;1;2;5\nWireConnection;7;3;10;0\nWireConnection;7;4;12;0\nWireConnection;7;7;141;0\nWireConnection;156;0;117;6\nWireConnection;95;0;99;0\nWireConnection;95;1;97;0\nWireConnection;95;2;94;0\nWireConnection;136;0;134;0\nWireConnection;173;0;168;0\nWireConnection;173;1;171;3\nWireConnection;173;3;172;0\nWireConnection;173;4;182;0\nWireConnection;173;6;186;0\nWireConnection;173;7;164;0\nWireConnection;150;0;117;7\nWireConnection;202;0;201;6\nWireConnection;112;0;103;0\nWireConnection;94;0;89;0\nWireConnection;94;1;85;0\nWireConnection;99;0;100;0\nWireConnection;99;1;98;0\nWireConnection;186;0;185;0\nWireConnection;10;0;144;0\nWireConnection;162;0;161;0\nWireConnection;60;0;105;0\nWireConnection;60;1;45;0\nWireConnection;122;0;125;0\nWireConnection;122;1;123;0\nWireConnection;122;2;121;0\nWireConnection;147;0;53;6\nWireConnection;303;0;299;0\nWireConnection;133;0;130;0\nWireConnection;200;0;261;0\nWireConnection;107;0;67;0\nWireConnection;140;0;138;0\nWireConnection;53;1;44;0\nWireConnection;106;0;108;5\nWireConnection;106;1;122;0\nWireConnection;137;0;134;0\nWireConnection;192;0;83;7\nWireConnection;176;0;191;0\nWireConnection;111;0;103;0\nWireConnection;304;0;300;0\nWireConnection;63;0;65;0\nWireConnection;63;1;60;0\nWireConnection;63;2;42;0\nWireConnection;115;0;116;0\nWireConnection;128;0;111;0\nWireConnection;128;1;117;5\nWireConnection;128;3;107;0\nWireConnection;128;4;110;0\nWireConnection;128;7;115;0\nWireConnection;120;0;116;0\nWireConnection;294;0;175;0\nWireConnection;149;0;53;8\nWireConnection;172;0;174;0\nWireConnection;178;0;170;0\nWireConnection;178;1;181;0\nWireConnection;42;0;43;0\nWireConnection;42;1;59;0\nWireConnection;4;0;135;0\nWireConnection;4;1;2;3\nWireConnection;4;3;10;0\nWireConnection;4;4;12;0\nWireConnection;4;7;139;0\nWireConnection;168;0;165;0\nWireConnection;190;0;171;7\nWireConnection;123;0;126;0\nWireConnection;123;1;102;0\nWireConnection;188;0;185;0\nWireConnection;118;0;116;0\nWireConnection;191;0;171;8\nWireConnection;86;0;113;0\nWireConnection;148;0;53;7\nWireConnection;28;0;22;0\nWireConnection;28;1;23;0\nWireConnection;28;2;24;0\nWireConnection;175;0;180;0\nWireConnection;175;1;178;0\nWireConnection;175;2;177;0\nWireConnection;157;0;302;0\nWireConnection;157;1;303;0\nWireConnection;157;2;304;0\nWireConnection;157;3;305;0\nWireConnection;132;0;130;0\nWireConnection;59;0;149;0\nWireConnection;293;0;28;0\nWireConnection;177;0;169;0\nWireConnection;177;1;176;0\nWireConnection;305;0;301;0\nWireConnection;24;0;7;0\nWireConnection;24;1;27;0\nWireConnection;65;0;56;0\nWireConnection;65;1;54;0\nWireConnection;180;0;173;0\nWireConnection;180;1;179;0\nWireConnection;182;0;174;0\nWireConnection;302;0;298;0\nWireConnection;166;0;165;0\nWireConnection;193;0;83;6\nWireConnection;92;0;113;0\nWireConnection;208;0;216;6\nWireConnection;155;0;156;0\nWireConnection;93;0;101;0\nWireConnection;171;1;174;0\nWireConnection;88;0;90;0\nWireConnection;199;0;219;0\nWireConnection;189;0;171;6\nWireConnection;79;0;108;4\nWireConnection;79;1;95;0\nWireConnection;125;0;127;0\nWireConnection;125;1;155;0\nWireConnection;117;1;67;0\nWireConnection;6;0;136;0\nWireConnection;6;1;2;4\nWireConnection;6;3;10;0\nWireConnection;6;4;12;0\nWireConnection;6;7;140;0\nWireConnection;126;0;112;0\nWireConnection;126;1;117;4\nWireConnection;126;3;107;0\nWireConnection;126;4;110;0\nWireConnection;126;7;120;0\nWireConnection;181;0;190;0\nWireConnection;201;1;276;0\nWireConnection;167;0;165;0\nWireConnection;127;0;119;0\nWireConnection;127;1;117;3\nWireConnection;127;3;107;0\nWireConnection;127;4;110;0\nWireConnection;127;7;118;0\nWireConnection;12;0;144;0\nWireConnection;41;0;192;0\nWireConnection;187;0;185;0\nWireConnection;58;0;44;0\nWireConnection;54;0;147;0\nWireConnection;57;0;44;0\nWireConnection;251;0;253;0\nWireConnection;216;1;262;0\nWireConnection;240;0;267;0\nWireConnection;240;1;211;0\nWireConnection;242;0;217;0\nWireConnection;224;0;229;5\nWireConnection;224;1;220;0\nWireConnection;261;0;215;8\nWireConnection;105;0;132;0\nWireConnection;105;1;53;4\nWireConnection;105;3;57;0\nWireConnection;105;4;58;0\nWireConnection;105;7;46;0\nWireConnection;232;0;221;0\nWireConnection;232;1;222;0\nWireConnection;232;2;223;0\nWireConnection;227;0;243;0\nWireConnection;227;1;207;0\nWireConnection;213;0;212;0\nWireConnection;231;0;208;0\nWireConnection;284;0;281;0\nWireConnection;239;0;244;0\nWireConnection;239;1;203;0\nWireConnection;214;0;276;0\nWireConnection;205;0;201;7\nWireConnection;245;0;235;0\nWireConnection;245;1;201;4\nWireConnection;245;3;214;0\nWireConnection;245;4;258;0\nWireConnection;245;6;291;0\nWireConnection;245;7;246;0\nWireConnection;288;0;285;0\nWireConnection;277;0;256;0\nWireConnection;260;0;250;0\nWireConnection;218;0;254;0\nWireConnection;257;0;256;0\nWireConnection;212;0;215;6\nWireConnection;243;0;218;0\nWireConnection;243;1;201;5\nWireConnection;243;3;214;0\nWireConnection;243;4;258;0\nWireConnection;243;6;292;0\nWireConnection;243;7;251;0\nWireConnection;233;0;270;0\nWireConnection;233;1;231;0\nWireConnection;271;0;256;0\nWireConnection;234;0;255;0\nWireConnection;234;1;230;0\nWireConnection;275;0;262;0\nWireConnection;238;0;245;0\nWireConnection;238;1;204;0\nWireConnection;97;0;91;0\nWireConnection;97;1;41;0\nWireConnection;203;0;202;0\nWireConnection;230;0;209;0\nWireConnection;207;0;206;0\nWireConnection;259;0;250;0\nWireConnection;109;0;101;0\nWireConnection;229;1;236;0\nWireConnection;247;0;217;0\nWireConnection;27;0;2;8\nWireConnection;264;0;278;0\nWireConnection;241;0;233;0\nWireConnection;241;1;234;0\nWireConnection;241;2;240;0\nWireConnection;258;0;276;0\nWireConnection;255;0;273;0\nWireConnection;255;1;216;4\nWireConnection;255;3;280;0\nWireConnection;255;4;275;0\nWireConnection;255;6;283;0\nWireConnection;255;7;266;0\nWireConnection;246;0;253;0\nWireConnection;237;0;250;0\nWireConnection;252;0;237;0\nWireConnection;252;1;215;3\nWireConnection;252;3;242;0\nWireConnection;252;4;247;0\nWireConnection;252;6;286;0\nWireConnection;252;7;271;0\nWireConnection;248;0;253;0\nWireConnection;223;0;265;0\nWireConnection;223;1;200;0\nWireConnection;228;0;226;0\nWireConnection;228;1;225;0\nWireConnection;228;2;224;0\nWireConnection;204;0;205;0\nWireConnection;296;0;228;0\nWireConnection;273;0;279;0\nWireConnection;22;0;4;0\nWireConnection;22;1;25;0\nWireConnection;287;0;285;0\nWireConnection;274;0;279;0\nWireConnection;272;0;279;0\nWireConnection;290;0;289;0\nWireConnection;110;0;67;0\nWireConnection;265;0;259;0\nWireConnection;265;1;215;5\nWireConnection;265;3;242;0\nWireConnection;265;4;247;0\nWireConnection;265;6;288;0\nWireConnection;265;7;257;0\nWireConnection;283;0;281;0\nWireConnection;291;0;289;0\nWireConnection;179;0;189;0\nWireConnection;292;0;289;0\nWireConnection;220;0;239;0\nWireConnection;220;1;238;0\nWireConnection;220;2;227;0\nWireConnection;269;0;260;0\nWireConnection;269;1;215;4\nWireConnection;269;3;242;0\nWireConnection;269;4;247;0\nWireConnection;269;6;287;0\nWireConnection;269;7;277;0\nWireConnection;222;0;269;0\nWireConnection;222;1;199;0\nWireConnection;219;0;215;7\nWireConnection;226;0;241;0\nWireConnection;226;1;229;3\nWireConnection;266;0;278;0\nWireConnection;221;0;252;0\nWireConnection;221;1;213;0\nWireConnection;267;0;274;0\nWireConnection;267;1;216;5\nWireConnection;267;3;280;0\nWireConnection;267;4;275;0\nWireConnection;267;6;284;0\nWireConnection;267;7;263;0\nWireConnection;225;0;229;4\nWireConnection;225;1;232;0\nWireConnection;280;0;262;0\nWireConnection;235;0;254;0\nWireConnection;55;0;48;0\nWireConnection;98;0;193;0\nWireConnection;210;0;216;8\nWireConnection;308;0;104;0\nWireConnection;211;0;210;0\nWireConnection;263;0;278;0\nWireConnection;244;0;249;0\nWireConnection;244;1;201;3\nWireConnection;244;3;214;0\nWireConnection;244;4;258;0\nWireConnection;244;6;290;0\nWireConnection;244;7;248;0\nWireConnection;286;0;285;0\nWireConnection;209;0;216;7\nWireConnection;206;0;201;8\nWireConnection;96;0;90;0\nWireConnection;135;0;134;0\nWireConnection;36;2;82;0\nWireConnection;249;0;254;0\nWireConnection;145;0;5;0\nWireConnection;68;0;82;0\nWireConnection;270;0;272;0\nWireConnection;270;1;216;3\nWireConnection;270;3;280;0\nWireConnection;270;4;275;0\nWireConnection;270;6;282;0\nWireConnection;270;7;264;0\nWireConnection;309;2;158;0\nWireConnection;23;0;6;0\nWireConnection;23;1;26;0\nWireConnection;215;1;217;0\nWireConnection;5;0;315;0\nWireConnection;315;0;36;0\nWireConnection;315;1;309;0\nWireConnection;315;2;36;0\nWireConnection;315;3;309;0\nWireConnection;159;0;158;0\nWireConnection;282;0;281;0\nWireConnection;184;0;183;0\nWireConnection;61;0;80;0\nWireConnection;306;0;104;0\nWireConnection;307;0;104;0\nWireConnection;77;0;306;0\nWireConnection;77;1;61;0\nWireConnection;73;0;80;0\nWireConnection;31;0;157;0\nWireConnection;76;0;74;0\nWireConnection;295;0;70;0\nWireConnection;72;0;307;0\nWireConnection;72;1;75;0\nWireConnection;64;0;78;0\nWireConnection;78;0;308;0\nWireConnection;78;1;73;0\nWireConnection;80;0;81;0\nWireConnection;75;0;80;0\nWireConnection;50;0;77;0\nWireConnection;71;0;72;0\nWireConnection;33;0;31;1\nWireConnection;0;0;157;0\nWireConnection;34;0;31;2\nWireConnection;35;0;31;3\nWireConnection;32;0;31;0\nASEEND*/\n//CHKSM=DC3AB08472A21A32907C6A155EB8627E743376BD" + m_functionName: + m_description: Based on "Procedural Stochastic Textures by Tiling and Blending" + by Thomas Deliot and Eric Heitz + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 1 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 12 + m_customNodeCategory: Rust + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Procedural Sample.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Procedural Sample.asset.meta new file mode 100644 index 0000000..060ad5a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Procedural Sample.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f5379ff72769e2b4495e5ce2f004d8d4 +timeCreated: 1602845933 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Projection.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Projection.asset new file mode 100644 index 0000000..7e81b27 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Projection.asset @@ -0,0 +1,39 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Projection + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18101\n468;180;1104;762;1212.968;431.7589;1.20154;True;False\nNode;AmplifyShaderEditor.DotProductOpNode;1;-592,-80;Inherit;False;2;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;3;-416,-80;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DotProductOpNode;2;-592,96;Inherit;False;2;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;5;-848,-80;Inherit;False;A;4;0;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;4;-256,0;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionInput;6;-848,16;Inherit;False;B;4;1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;Out;0;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nWireConnection;1;0;5;0\nWireConnection;1;1;6;0\nWireConnection;3;0;1;0\nWireConnection;3;1;2;0\nWireConnection;2;0;6;0\nWireConnection;2;1;6;0\nWireConnection;4;0;3;0\nWireConnection;4;1;6;0\nWireConnection;0;0;4;0\nASEEND*/\n//CHKSM=B9F0AEDF37A53545406238C555E2DAE90B6FC153" + m_functionName: + m_description: Returns the result of projecting the value of input A onto a straight + line parallel to the value of input B + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 16 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Projection.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Projection.asset.meta new file mode 100644 index 0000000..d34e340 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Projection.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3249e2c8638c9ef4bbd1902a2d38a67c +timeCreated: 1589968069 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Radial Shear.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Radial Shear.asset new file mode 100644 index 0000000..eac209d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Radial Shear.asset @@ -0,0 +1,42 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Radial Shear + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity + Asset Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17500\n747;81;640;789;142.1275;882.7152;1.3;True;False\nNode;AmplifyShaderEditor.FunctionInput;1;-114,-240.5;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;4;816,-48;Inherit;False;Offset;2;3;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.Vector2Node;10;624,-16;Inherit;False;Constant;_Vector2;Vector + 2;0;0;Create;True;0;0;False;0;0,0;0,0;0;3;FLOAT2;0;FLOAT;1;FLOAT;2\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;21;823.5911,-159.5089;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;23;868.5839,-379.9765;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;22;301.9583,-397.5442;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.Vector2Node;9;128,-64;Inherit;False;Constant;_Vector1;Vector + 1;0;0;Create;True;0;0;False;0;10,10;0,0;0;3;FLOAT2;0;FLOAT;1;FLOAT;2\nNode;AmplifyShaderEditor.FunctionInput;3;304,-64;Inherit;False;Strength;2;2;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;16;1024,-224;Inherit;False;3;3;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;2;-130,-121.5;Inherit;False;Center;2;1;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.Vector2Node;6;-288,-128;Inherit;False;Constant;_Vector0;Vector + 0;0;0;Create;True;0;0;False;0;0.5,0.5;0,0;0;3;FLOAT2;0;FLOAT;1;FLOAT;2\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;11;48,-192;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DotProductOpNode;12;272,-207;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;18;272,-304;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.NegateNode;20;533.0646,-334.0239;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;19;684.8169,-283.6713;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;15;480,-128;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;5;-304,-256;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionOutput;0;1168,-224;Inherit;True;True;-1;Out;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nWireConnection;1;0;5;0\nWireConnection;4;0;10;0\nWireConnection;21;0;19;0\nWireConnection;21;1;15;0\nWireConnection;23;0;22;0\nWireConnection;22;0;1;0\nWireConnection;3;0;9;0\nWireConnection;16;0;23;0\nWireConnection;16;1;21;0\nWireConnection;16;2;4;0\nWireConnection;2;0;6;0\nWireConnection;11;0;1;0\nWireConnection;11;1;2;0\nWireConnection;12;0;11;0\nWireConnection;12;1;11;0\nWireConnection;18;0;11;0\nWireConnection;20;0;18;0\nWireConnection;19;0;18;1\nWireConnection;19;1;20;0\nWireConnection;15;0;12;0\nWireConnection;15;1;3;0\nWireConnection;0;0;16;0\nASEEND*/\n//CHKSM=A89AF2681F84C95F847B2DABF2152AEDA506C9E8" + m_functionName: + m_description: Creates a radial shear warp based on given UVs + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 14 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Radial Shear.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Radial Shear.asset.meta new file mode 100644 index 0000000..ae5f48f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Radial Shear.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c6dc9fc7fa9b08c4d95138f2ae88b526 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/RadialUVDistortion.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/RadialUVDistortion.asset new file mode 100644 index 0000000..ee08750 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/RadialUVDistortion.asset @@ -0,0 +1,37 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: RadialUVDistortion + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=13706\n234;92;1307;805;1057.718;-728.6741;2.742884;True;False\nNode;AmplifyShaderEditor.CommentaryNode;59;277.4049,1612.7;Float;False;1535;395;;11;47;50;53;52;51;48;55;54;58;56;57;Ring + Panner;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;27;-1156.5,-315;Float;False;1765;958;;20;19;12;15;1;11;13;16;18;17;3;5;8;9;10;21;23;24;25;80;81;Normal + map 1 Panner/Size;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;46;-1152,800;Float;False;1692;591.2493;;13;32;34;39;38;36;33;31;29;70;69;78;79;86;Radial + Math;1,1,1,1;0;0\nNode;AmplifyShaderEditor.PannerNode;18;-218.5,203;Float;False;3;0;FLOAT2;0,0;False;2;FLOAT2;1,0;False;1;FLOAT;1.0;False;1;FLOAT2\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;16;-499.5,260;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT\nNode;AmplifyShaderEditor.ComponentMaskNode;3;-713.5,-240;Float;False;True;False;True;True;1;0;FLOAT2;0,0,0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.DynamicAppendNode;10;16,-80;Float;False;FLOAT2;4;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;1;FLOAT2\nNode;AmplifyShaderEditor.PannerNode;19;-213.5,487;Float;False;3;0;FLOAT2;0,0;False;2;FLOAT2;0,1;False;1;FLOAT;1.0;False;1;FLOAT2\nNode;AmplifyShaderEditor.DynamicAppendNode;24;271.5,348;Float;False;FLOAT2;4;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;1;FLOAT2\nNode;AmplifyShaderEditor.ComponentMaskNode;23;10.5,476;Float;False;False;True;True;True;1;0;FLOAT2;0,0,0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;17;-518.5,501;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT\nNode;AmplifyShaderEditor.ComponentMaskNode;5;-709.5,65;Float;False;False;True;True;True;1;0;FLOAT2;0,0,0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.ComponentMaskNode;21;-0.5,205;Float;False;True;False;True;True;1;0;FLOAT2;0,0,0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.TextureCoordinatesNode;81;-515.3643,364.2482;Float;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;FLOAT;FLOAT;FLOAT;FLOAT\nNode;AmplifyShaderEditor.SimpleAddOpNode;25;454.5,190;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0.0,0;False;1;FLOAT2\nNode;AmplifyShaderEditor.PannerNode;54;1156.405,1662.7;Float;False;3;0;FLOAT2;0,0;False;2;FLOAT2;1,0;False;1;FLOAT;1.0;False;1;FLOAT2\nNode;AmplifyShaderEditor.PannerNode;55;1151.405,1851.699;Float;False;3;0;FLOAT2;0,0;False;2;FLOAT2;0,1;False;1;FLOAT;1.0;False;1;FLOAT2\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;52;919.5789,1859.739;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT\nNode;AmplifyShaderEditor.TextureCoordinatesNode;80;-490.1459,-126.2656;Float;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;FLOAT;FLOAT;FLOAT;FLOAT\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;8;-168,-227;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;9;-157,48;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT\nNode;AmplifyShaderEditor.FractNode;38;208,944;Float;False;1;0;FLOAT;0.0;False;1;FLOAT\nNode;AmplifyShaderEditor.FunctionInput;29;-736,960;Float;False;UV + Channel;2;6;False;1;0;FLOAT2;0,0;False;1;FLOAT2\nNode;AmplifyShaderEditor.SimpleDivideOpNode;36;24.17026,866.1562;Float;False;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT\nNode;AmplifyShaderEditor.TextureCoordinatesNode;78;-976,1024;Float;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;FLOAT;FLOAT;FLOAT;FLOAT\nNode;AmplifyShaderEditor.TauNode;70;-134.649,977.495;Float;False;0;1;FLOAT\nNode;AmplifyShaderEditor.Vector2Node;79;-1136,1040;Float;False;Constant;_Vector1;Vector + 1;0;0;2,2;0;3;FLOAT2;FLOAT;FLOAT\nNode;AmplifyShaderEditor.ATan2OpNode;34;-139.461,862.9785;Float;False;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;67;2008.955,1176.914;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2\nNode;AmplifyShaderEditor.FunctionInput;47;327.4049,1740.699;Float;False;Ring + panner speed;2;5;False;1;0;FLOAT2;1,1;False;1;FLOAT2\nNode;AmplifyShaderEditor.ComponentMaskNode;63;1601.903,863.11;Float;False;True;True;False;False;1;0;COLOR;0,0,0,0;False;1;FLOAT2\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;64;1860.937,863.1101;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT;0,0;False;1;FLOAT2\nNode;AmplifyShaderEditor.ComponentMaskNode;50;572.5789,1870.739;Float;False;False;True;True;True;1;0;FLOAT2;0,0,0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.Vector2Node;69;-750.9933,1135.168;Float;False;Constant;_Vector0;Vector + 0;0;0;1,1;0;3;FLOAT2;FLOAT;FLOAT\nNode;AmplifyShaderEditor.SimpleAddOpNode;66;2122.934,960.8027;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2\nNode;AmplifyShaderEditor.ComponentMaskNode;57;1396.404,1844.699;Float;False;False;True;True;True;1;0;FLOAT2;0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.WireNode;62;881.3285,841.1897;Float;False;1;0;FLOAT2;0,0;False;1;FLOAT2\nNode;AmplifyShaderEditor.ComponentMaskNode;56;1395.404,1666.7;Float;False;True;False;True;True;1;0;FLOAT2;0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.ComponentMaskNode;48;556.5789,1678.739;Float;False;True;False;True;True;1;0;FLOAT2;0,0,0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.SamplerNode;61;1273.3,858.6689;Float;True;Property;_TextureSample0;Texture + Sample 0;0;0;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;FLOAT;FLOAT;FLOAT;FLOAT\nNode;AmplifyShaderEditor.FunctionInput;11;-1097.5,295;Float;False;Noise + map panner speed;2;2;False;1;0;FLOAT2;0,0;False;1;FLOAT2\nNode;AmplifyShaderEditor.FunctionInput;65;1581.182,996.3248;Float;False;Combined + Noise Map Strength;1;3;False;1;0;FLOAT;1.0;False;1;FLOAT\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;31;-593.5078,943.7484;Float;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0.0,0;False;1;FLOAT2\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;51;929.3787,1738.541;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT\nNode;AmplifyShaderEditor.ComponentMaskNode;33;-384,944;Float;False;False;True;True;True;1;0;FLOAT2;0,0,0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.SimpleTimeNode;15;-773.5,372;Float;False;1;0;FLOAT;1.0;False;1;FLOAT\nNode;AmplifyShaderEditor.DynamicAppendNode;58;1645.404,1804.699;Float;False;FLOAT2;4;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;1;FLOAT2\nNode;AmplifyShaderEditor.FunctionInput;1;-1106.5,-75;Float;False;Noise + map size;2;1;False;1;0;FLOAT2;1,1;False;1;FLOAT2\nNode;AmplifyShaderEditor.SimpleTimeNode;53;652.579,1790.739;Float;False;1;0;FLOAT;1.0;False;1;FLOAT\nNode;AmplifyShaderEditor.DynamicAppendNode;39;339.0049,1105.292;Float;False;FLOAT2;4;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;1;FLOAT2\nNode;AmplifyShaderEditor.ComponentMaskNode;32;-384,864;Float;False;True;False;True;True;1;0;FLOAT2;0,0,0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.FunctionInput;60;974.1886,744.1376;Float;False;Noise + Map;9;0;False;1;0;SAMPLER2D;0.0;False;1;SAMPLER2D\nNode;AmplifyShaderEditor.LengthOpNode;86;-146.1864,1204.794;Float;False;1;0;FLOAT2;0,0,0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.ComponentMaskNode;12;-814,240;Float;False;True;False;True;True;1;0;FLOAT2;0,0,0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.FunctionInput;68;1781.573,1218.733;Float;False;Texture + Coordination;2;4;False;1;0;FLOAT2;1,1;False;1;FLOAT2\nNode;AmplifyShaderEditor.ComponentMaskNode;13;-800,512;Float;False;False;True;True;True;1;0;FLOAT2;0,0;False;1;FLOAT\nNode;AmplifyShaderEditor.FunctionOutput;0;2475.644,909.1371;Float;False;True;UV + Output;0;1;0;FLOAT2;0,0;False;0\nWireConnection;18;0;81;0\nWireConnection;18;1;16;0\nWireConnection;16;0;12;0\nWireConnection;16;1;15;0\nWireConnection;3;0;1;0\nWireConnection;10;0;8;0\nWireConnection;10;1;9;0\nWireConnection;19;0;81;0\nWireConnection;19;1;17;0\nWireConnection;24;0;21;0\nWireConnection;24;1;23;0\nWireConnection;23;0;19;0\nWireConnection;17;0;15;0\nWireConnection;17;1;13;0\nWireConnection;5;0;1;0\nWireConnection;21;0;18;0\nWireConnection;25;0;10;0\nWireConnection;25;1;24;0\nWireConnection;54;0;39;0\nWireConnection;54;1;51;0\nWireConnection;55;0;39;0\nWireConnection;55;1;52;0\nWireConnection;52;0;53;0\nWireConnection;52;1;50;0\nWireConnection;8;0;3;0\nWireConnection;8;1;80;1\nWireConnection;9;0;80;2\nWireConnection;9;1;5;0\nWireConnection;38;0;36;0\nWireConnection;29;0;78;0\nWireConnection;36;0;34;0\nWireConnection;36;1;70;0\nWireConnection;78;0;79;0\nWireConnection;34;0;32;0\nWireConnection;34;1;33;0\nWireConnection;67;0;68;0\nWireConnection;67;1;58;0\nWireConnection;63;0;61;0\nWireConnection;64;0;63;0\nWireConnection;64;1;65;0\nWireConnection;50;0;47;0\nWireConnection;66;0;64;0\nWireConnection;66;1;67;0\nWireConnection;57;0;55;0\nWireConnection;62;0;25;0\nWireConnection;56;0;54;0\nWireConnection;48;0;47;0\nWireConnection;61;0;60;0\nWireConnection;61;1;62;0\nWireConnection;31;0;29;0\nWireConnection;31;1;69;0\nWireConnection;51;0;48;0\nWireConnection;51;1;53;0\nWireConnection;33;0;31;0\nWireConnection;58;0;56;0\nWireConnection;58;1;57;0\nWireConnection;39;0;38;0\nWireConnection;39;1;86;0\nWireConnection;32;0;31;0\nWireConnection;86;0;31;0\nWireConnection;12;0;11;0\nWireConnection;13;0;11;0\nWireConnection;0;0;66;0\nASEEND*/\n//CHKSM=6E93501F5310904D0620611C1184B482F2F90DC7" + m_functionName: + m_description: "Radial UV Distortion originally created by:\nYoeri - Luos_83 - Vleer\r\n + Luos@woodenswordstudios.com" + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_nodeCategory: 3 + m_customNodeCategory: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/RadialUVDistortion.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/RadialUVDistortion.asset.meta new file mode 100644 index 0000000..4c5e3c3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/RadialUVDistortion.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 051d65e7699b41a4c800363fd0e822b2 +timeCreated: 1510748744 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Random Range.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Random Range.asset new file mode 100644 index 0000000..e13bf2b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Random Range.asset @@ -0,0 +1,41 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Random Range + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17803\n388;132;1046;800;1433.178;491.644;1.608637;True;False\nNode;AmplifyShaderEditor.SinOpNode;6;-544,176;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;8;-640,272;Inherit;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;43758.55;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.DotProductOpNode;4;-704,176;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;1;-928,176;Inherit;False;Seed;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.Vector2Node;5;-976,256;Inherit;False;Constant;_Vector0;Vector + 0;0;0;Create;True;0;0;False;0;12.9898,78.233;0,0;0;3;FLOAT2;0;FLOAT;1;FLOAT;2\nNode;AmplifyShaderEditor.FunctionInput;3;-256,80;Inherit;False;Max;1;2;False;1;0;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LerpOp;10;-64,0;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-256,0;Inherit;False;Min;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;7;-400,176;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FractNode;9;-256,176;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;128,0;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;6;0;4;0\nWireConnection;4;0;1;0\nWireConnection;4;1;5;0\nWireConnection;10;0;2;0\nWireConnection;10;1;3;0\nWireConnection;10;2;9;0\nWireConnection;7;0;6;0\nWireConnection;7;1;8;0\nWireConnection;9;0;7;0\nWireConnection;0;0;10;0\nASEEND*/\n//CHKSM=66CE582F1B0E5425FE558D38A8279477232CEB3A" + m_functionName: + m_description: Returns a pseudo-random number value based on input Seed that is + between the minimum and maximum values defined by inputs Min and Max respectively + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Random Range.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Random Range.asset.meta new file mode 100644 index 0000000..bfb6cb3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Random Range.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7b754edb8aebbfb4a9ace907af661cfc +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Reconstruct World Position From Depth.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Reconstruct World Position From Depth.asset new file mode 100644 index 0000000..470c293 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Reconstruct World Position From Depth.asset @@ -0,0 +1,52 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Reconstruct World Position From Depth + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity + Asset Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18810\n-1974;79;1023;876;1214.631;642.8694;1;True;False\nNode;AmplifyShaderEditor.ComponentMaskNode;44;-1216,-480;Inherit;False;True;True;True;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.CustomExpressionNode;72;-818,-477;Inherit;False;float3 + result = In@$#if !defined(ASE_SRP_VERSION) || ASE_SRP_VERSION <= 70301$result + *= float3(1,1,-1)@$#endif$return result@;3;False;1;True;In;FLOAT3;0,0,0;In;;Inherit;False;InvertDepthDir;True;False;0;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;74;-545.1306,-416.3694;Inherit;False;4;0;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionNode;67;-2576,-384;Inherit;False;Non + Stereo Screen Pos;-1;;3;1731ee083b93c104880efc701e11b49b;0;1;23;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.ComponentMaskNode;45;-1216,-368;Inherit;False;False;False;False;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;39;-1936,-384;Inherit;False;FLOAT3;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;1;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;43;-1376,-416;Inherit;False;2;2;0;FLOAT4x4;0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1;False;1;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.StaticSwitch;38;-2208,-208;Float;False;Property;_Keyword0;Keyword + 0;3;0;Fetch;True;0;0;0;False;0;False;0;0;0;False;UNITY_REVERSED_Z;Toggle;2;Key0;Key1;Fetch;False;True;9;1;FLOAT;0;False;0;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ScaleAndOffsetNode;40;-1776,-384;Inherit;False;3;0;FLOAT3;0,0,0;False;1;FLOAT;2;False;2;FLOAT;-1;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.CustomExpressionNode;75;-764.631,-319.8694;Inherit;False;float3 + result = In@$#if !defined(ASE_SRP_VERSION) || ASE_SRP_VERSION <= 70301 || ASE_SRP_VERSION + == 70503 || ASE_SRP_VERSION >= 80301 $result *= float3(1,1,-1)@$#endif$return + result@;3;False;1;True;In;FLOAT3;0,0,0;In;;Inherit;False;InvertDepthDirURP;True;False;0;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.ScreenDepthNode;69;-2576,-208;Inherit;False;1;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;64;-2272,-384;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.DynamicAppendNode;42;-1552,-384;Inherit;False;FLOAT4;4;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;1;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.ScreenPosInputsNode;70;-2896,-304;Inherit;False;0;False;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.OneMinusNode;37;-2368,-144;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;50;-125.0509,-462.7967;Inherit;False;2;2;0;FLOAT4x4;0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1;False;1;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.CameraToWorldMatrix;48;-349.0508,-494.7968;Inherit;False;0;1;FLOAT4x4;0\nNode;AmplifyShaderEditor.DynamicAppendNode;49;-285.0508,-414.7967;Inherit;False;FLOAT4;4;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;1;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.CameraProjectionNode;41;-1664,-480;Inherit;False;unity_CameraInvProjection;0;1;FLOAT4x4;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;46;-976,-432;Inherit;False;2;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.CustomExpressionNode;73;-826.1306,-195.3694;Inherit;False;float3 + result = In@$#if !defined(ASE_SRP_VERSION) || ASE_SRP_VERSION <= 70301 || ASE_SRP_VERSION + == 70503 || ASE_SRP_VERSION >= 80301 $result *= float3(1,1,-1)@$#endif$return + result@;3;False;1;True;In;FLOAT3;0,0,0;In;;Inherit;False;InvertDepthDirHD;True;False;0;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;68,-460;Inherit;False;True;-1;XYZW;0;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nWireConnection;44;0;43;0\nWireConnection;72;0;46;0\nWireConnection;74;0;72;0\nWireConnection;74;3;72;0\nWireConnection;74;1;75;0\nWireConnection;74;2;73;0\nWireConnection;67;23;70;0\nWireConnection;45;0;43;0\nWireConnection;39;0;64;0\nWireConnection;39;1;64;1\nWireConnection;39;2;38;0\nWireConnection;43;0;41;0\nWireConnection;43;1;42;0\nWireConnection;38;1;69;0\nWireConnection;38;0;37;0\nWireConnection;40;0;39;0\nWireConnection;75;0;46;0\nWireConnection;69;0;70;0\nWireConnection;64;0;67;0\nWireConnection;42;0;40;0\nWireConnection;37;0;69;0\nWireConnection;50;0;48;0\nWireConnection;50;1;49;0\nWireConnection;49;0;74;0\nWireConnection;46;0;44;0\nWireConnection;46;1;45;0\nWireConnection;73;0;46;0\nWireConnection;0;0;50;0\nASEEND*/\n//CHKSM=6A4B01665D41BCF1E3EAAF86BFFB414B6783C5E1" + m_functionName: + m_description: Reconstructs world position from the depth of the scene. If depth + is unconnected a default screen depth will be calculated. For best results, zwrite + should be OFF and ztest should be ALWAYS. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_customEdited: 0 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Reconstruct World Position From Depth.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Reconstruct World Position From Depth.asset.meta new file mode 100644 index 0000000..1ff88bc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Reconstruct World Position From Depth.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e7094bcbcc80eb140b2a3dbe6a861de8 +timeCreated: 1507625018 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rectangle.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rectangle.asset new file mode 100644 index 0000000..ce3fc58 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rectangle.asset @@ -0,0 +1,38 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Rectangle + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1462;-64;1004;726;585.2094;505.7291;2.101326;True;False\nNode;AmplifyShaderEditor.FunctionInput;3;-272,80;Inherit;False;Height;1;2;False;1;0;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-272,0;Inherit;False;Width;1;1;False;1;0;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;10;-80,0;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.ScaleAndOffsetNode;7;-288,-128;Inherit;False;3;0;FLOAT2;0,0;False;1;FLOAT;2;False;2;FLOAT;-1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;4;-688,-128;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;1;-464,-128;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.AbsOpNode;18;-80,-128;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;11;96,-64;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;16;720,-64;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.SimpleMinOpNode;15;960,-64;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;17;1088,-64;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FWidthOpNode;14;272,32;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;13;416,-64;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.OneMinusNode;12;560,-64;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;0;1248,-64;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;10;0;2;0\nWireConnection;10;1;3;0\nWireConnection;7;0;1;0\nWireConnection;1;0;4;0\nWireConnection;18;0;7;0\nWireConnection;11;0;18;0\nWireConnection;11;1;10;0\nWireConnection;16;0;12;0\nWireConnection;15;0;16;0\nWireConnection;15;1;16;1\nWireConnection;17;0;15;0\nWireConnection;14;0;11;0\nWireConnection;13;0;11;0\nWireConnection;13;1;14;0\nWireConnection;12;0;13;0\nWireConnection;0;0;17;0\nASEEND*/\n//CHKSM=B118B72CF8CE06CB57B6E2BDED3062642C9B7509" + m_functionName: + m_description: Creates a rectangle shape with a specified size + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rectangle.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rectangle.asset.meta new file mode 100644 index 0000000..d285854 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rectangle.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6b23e0c975270fb4084c354b2c83366a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rejection.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rejection.asset new file mode 100644 index 0000000..a90bbeb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rejection.asset @@ -0,0 +1,41 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Rejection + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18104\n-1705;-353;1296;693;1041;283.5;1;True;False\nNode;AmplifyShaderEditor.FunctionInput;4;-560,96;Inherit;False;B;4;1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionInput;3;-560,0;Inherit;False;A;4;0;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionNode;1;-368,80;Inherit;False;Projection;-1;;1;3249e2c8638c9ef4bbd1902a2d38a67c;0;2;5;FLOAT4;0,0,0,0;False;6;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;2;-176,0;Inherit;False;2;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;Out;0;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nWireConnection;1;5;3;0\nWireConnection;1;6;4;0\nWireConnection;2;0;3;0\nWireConnection;2;1;1;0\nWireConnection;0;0;2;0\nASEEND*/\n//CHKSM=3BD893037EAFB176DD5A4C61C6A15D4B88CB7106" + m_functionName: + m_description: Returns the result of the projection of the value of input A onto + the plane orthogonal, or perpendicular, to the value of input B. The value of + the rejection vector is equal to the original vector, the value of input A, minus + the value of the Projection of the same inputs + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 16 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rejection.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rejection.asset.meta new file mode 100644 index 0000000..6eb73f2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rejection.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ea6ca936e02c9e74fae837451ff893c3 +timeCreated: 1589968229 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Replace Color.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Replace Color.asset new file mode 100644 index 0000000..243f775 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Replace Color.asset @@ -0,0 +1,46 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Replace Color + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity + Asset Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17500\n731;73;658;709;498.7031;575.9198;1.332954;True;False\nNode;AmplifyShaderEditor.FunctionSwitch;12;160,-208;Inherit;False;Compare + Alpha;True;0;2;-1;In 0;In 1;Object;-1;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;24;603.7781,-62.30967;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;20;752,-64;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LerpOp;21;959.2881,-109.705;Inherit;True;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0\nNode;AmplifyShaderEditor.WireNode;23;314.2856,-334.9587;Inherit;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;18;432,48;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;19;304,128;Inherit;False;Constant;_Float2;Float + 2;0;0;Create;True;0;0;False;0;1E-05;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;5;288,16;Inherit;False;Fuzziness;1;4;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;10;144,16;Inherit;False;Constant;_Float1;Float + 1;0;0;Create;True;0;0;False;0;0;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;16;416,-160;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ColorNode;8;528,-432;Inherit;False;Constant;_Color2;Color + 2;0;0;Create;True;0;0;False;0;0,0,0,0;0,0,0,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.ColorNode;6;-608,-192;Inherit;False;Constant;_Color0;Color + 0;0;0;Create;True;0;0;False;0;0,0,0,0;0,0,0,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;1;-416,-192;Inherit;False;In;5;0;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionInput;2;-416,0;Inherit;False;From;5;1;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.ColorNode;7;-608,0;Inherit;False;Constant;_Color1;Color + 1;0;0;Create;True;0;0;False;0;0,0,0,0;0,0,0,0;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.DistanceOpNode;11;-160,-64;Inherit;False;2;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SwizzleNode;14;-176,-176;Inherit;False;FLOAT3;0;1;2;3;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.SwizzleNode;13;-176,-272;Inherit;False;FLOAT3;0;1;2;3;1;0;COLOR;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.DistanceOpNode;15;0,-240;Inherit;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;22;-142.4747,-355.8744;Inherit;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.RangedFloatNode;9;144,-96;Inherit;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;0;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;768,-304;Inherit;False;To;5;2;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionInput;4;272,-96;Inherit;False;Range;1;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;1224.459,-102.2181;Inherit;False;True;-1;Out;0;False;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nWireConnection;12;0;15;0\nWireConnection;12;1;11;0\nWireConnection;24;0;16;0\nWireConnection;24;1;18;0\nWireConnection;20;0;24;0\nWireConnection;21;0;3;0\nWireConnection;21;1;23;0\nWireConnection;21;2;20;0\nWireConnection;23;0;22;0\nWireConnection;18;0;5;0\nWireConnection;18;1;19;0\nWireConnection;5;0;10;0\nWireConnection;16;0;11;0\nWireConnection;16;1;4;0\nWireConnection;1;0;6;0\nWireConnection;2;0;7;0\nWireConnection;11;0;1;0\nWireConnection;11;1;2;0\nWireConnection;14;0;2;0\nWireConnection;13;0;1;0\nWireConnection;15;0;13;0\nWireConnection;15;1;14;0\nWireConnection;22;0;1;0\nWireConnection;3;0;8;0\nWireConnection;4;0;9;0\nWireConnection;0;0;21;0\nASEEND*/\n//CHKSM=6A90827C59AE8E0E59809A229392575842D7BEF8" + m_functionName: + m_description: Replaces colors from given In which are equal to From to color To + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Replace Color.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Replace Color.asset.meta new file mode 100644 index 0000000..53b47d9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Replace Color.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 896dccb3016c847439def376a728b869 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rounded Rectangle.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rounded Rectangle.asset new file mode 100644 index 0000000..9d384bb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rounded Rectangle.asset @@ -0,0 +1,46 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Rounded Rectangle + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity + Asset Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17500\n776;81;858;790;239.8782;396.9632;2.892348;True;False\nNode;AmplifyShaderEditor.FunctionInput;1;616.5462,415.359;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;3;-32,352;Inherit;False;Height;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;21;189.5313,424.008;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;23;482.2314,693.308;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;22;1300.805,516.7463;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.WireNode;36;1147.975,717.6099;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;26;1280,640;Inherit;False;25;Radius;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;24;1472,560;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;27;1648,608;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RangedFloatNode;28;1472,688;Inherit;False;Constant;_Float6;Float + 6;0;0;Create;True;0;0;False;0;0;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.LengthOpNode;29;1776,608;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;30;1936,624;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;31;1744,704;Inherit;False;25;Radius;1;0;OBJECT;;False;1;FLOAT;0\nNode;AmplifyShaderEditor.OneMinusNode;32;2096,576;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FWidthOpNode;34;2096,704;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;33;2288,608;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;7;-192,352;Inherit;False;Constant;_Float1;Float + 1;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;35;2416,624;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;6;-176,240;Inherit;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;8;-256,96;Inherit;False;Constant;_Float2;Float + 2;0;0;Create;True;0;0;False;0;0.1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;5;427.5291,412.736;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.RangedFloatNode;18;624,496;Inherit;False;Constant;_Float4;Float + 4;0;0;Create;True;0;0;False;0;2;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;19;640,592;Inherit;False;Constant;_Float5;Float + 5;0;0;Create;True;0;0;False;0;-1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.ScaleAndOffsetNode;17;800,448;Inherit;False;3;0;FLOAT2;0,0;False;1;FLOAT;1;False;2;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.AbsOpNode;20;1014.086,440.2351;Inherit;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMinOpNode;11;288,128;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;12;160,208;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;13;240,320;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMinOpNode;14;448,192;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMaxOpNode;15;624,224;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;16;464,320;Inherit;False;Constant;_Float3;Float + 3;0;0;Create;True;0;0;False;0;1E-05;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;25;784,272;Inherit;False;Radius;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;9;160,96;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;4;-112,96;Inherit;False;Radius;1;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ScaleNode;10;16,96;Inherit;False;2;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-32,240;Inherit;False;Width;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;2544,624;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;1;0;5;0\nWireConnection;3;0;7;0\nWireConnection;21;0;2;0\nWireConnection;21;1;3;0\nWireConnection;23;0;21;0\nWireConnection;22;0;20;0\nWireConnection;22;1;36;0\nWireConnection;36;0;23;0\nWireConnection;24;0;22;0\nWireConnection;24;1;26;0\nWireConnection;27;0;24;0\nWireConnection;27;1;28;0\nWireConnection;29;0;27;0\nWireConnection;30;0;29;0\nWireConnection;30;1;31;0\nWireConnection;32;0;30;0\nWireConnection;34;0;30;0\nWireConnection;33;0;32;0\nWireConnection;33;1;34;0\nWireConnection;35;0;33;0\nWireConnection;17;0;1;0\nWireConnection;17;1;18;0\nWireConnection;17;2;19;0\nWireConnection;20;0;17;0\nWireConnection;11;0;9;0\nWireConnection;11;1;12;0\nWireConnection;12;0;2;0\nWireConnection;13;0;3;0\nWireConnection;14;0;11;0\nWireConnection;14;1;13;0\nWireConnection;15;0;14;0\nWireConnection;15;1;16;0\nWireConnection;25;0;15;0\nWireConnection;9;0;10;0\nWireConnection;4;0;8;0\nWireConnection;10;0;4;0\nWireConnection;2;0;6;0\nWireConnection;0;0;35;0\nASEEND*/\n//CHKSM=6DC878F2DF725F7361203E76F473DF65D786CAD0" + m_functionName: + m_description: Creates a round rectangle shape from a given size and radius + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rounded Rectangle.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rounded Rectangle.asset.meta new file mode 100644 index 0000000..01c3ee8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Rounded Rectangle.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8679f72f5be758f47babb3ba1d5f51d3 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SRP Additional Light.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SRP Additional Light.asset new file mode 100644 index 0000000..08f0d35 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SRP Additional Light.asset @@ -0,0 +1,117 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: SRP Additional Light + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18903\n-2306;98;1199;1062;1079.951;1299.86;1;True;False\nNode;AmplifyShaderEditor.CommentaryNode;67;-762.7209,462.2619;Inherit;False;1393.582;499.9396;;9;0;30;19;6;39;23;59;62;21;Main + Switch;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;66;-2609.233,465.7281;Inherit;False;581.5553;236.5492;;3;33;32;68;Shadow + Mask;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;65;-920.7385,-584.9739;Inherit;False;1591.506;791.9908;;11;55;49;18;14;15;27;61;13;16;63;64;Specular;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;60;-848.252,-1179.358;Inherit;False;1189.888;419.8453;;7;54;48;56;57;22;26;58;Half + Lambert;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;53;-2619.122,-57.4623;Inherit;False;1141.001;424.3999;;7;12;9;4;10;2;11;50;World + Normal;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;52;-2608.642,-424.6649;Inherit;False;467.4869;233;;2;44;3;World + Pos;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;40;-846.7464,-1664.293;Inherit;False;1082.843;405.3478;;7;38;25;41;51;47;37;5;Lambert;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;36;-844.4141,-2081.018;Inherit;False;987.3232;348.9314;;6;29;24;8;31;35;45;Flat;1,1,1,1;0;0\nNode;AmplifyShaderEditor.FunctionInput;18;-658.4189,-156.4711;Inherit;False;Smoothness;1;4;False;1;0;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;39;-702.373,659.6418;Inherit;False;38;lambertResult;1;0;OBJECT;;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;58;99.63594,-1021.087;Inherit;False;halfLambertResult;-1;True;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;55;-640.7715,-449.6685;Inherit;False;50;worldNormalValue;1;0;OBJECT;;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;64;-504.154,75.26627;Inherit;False;33;shadowMaskValue;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;30;-543.587,512.2619;Inherit;False;29;FlatResult;1;0;OBJECT;;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;14;-658.4189,-236.4712;Inherit;False;Specular + Color;3;3;False;1;0;FLOAT3;1,1,1;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;49;-611.2431,-534.9739;Inherit;False;44;worldPosValue;1;0;OBJECT;;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WorldNormalVector;4;-2409.121,153.5377;Inherit;False;False;1;0;FLOAT3;0,0,1;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionSwitch;26;-137.4143,-1046.044;Inherit;False;Option;False;0;2;-1;In + 0;In 1;Instance;24;9;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;59;-712.7209,760.9056;Inherit;False;58;halfLambertResult;1;0;OBJECT;;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.Vector3Node;10;-2569.122,-6.462288;Inherit;False;Constant;_Vector0;Vector + 0;0;0;Create;True;0;0;0;False;0;False;0,0,1;0,0,0;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.Vector3Node;21;-65.63779,774.2015;Inherit;False;Constant;_Vector1;Vector + 1;0;0;Create;True;0;0;0;False;0;False;0,0,0;0,0,0;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionSwitch;27;98.46796,-286.2599;Inherit;False;Option;False;0;2;-1;In + 0;In 1;Instance;24;9;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionSwitch;9;-1991.121,55.53762;Inherit;False;Normal + Space;False;0;2;1;Tangent Space;World Space;Object;-1;9;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;33;-2241.678,522.2767;Inherit;False;shadowMaskValue;-1;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.GetLocalVarNode;48;-723.7242,-1129.357;Inherit;False;44;worldPosValue;1;0;OBJECT;;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionSwitchByPipeline;19;223.761,651.6014;Inherit;False;4;0;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.CustomExpressionNode;37;-450.795,-1603.666;Inherit;False;float3 + Color = 0@$#ifdef _ADDITIONAL_LIGHTS$int numLights = GetAdditionalLightsCount()@$for(int + i = 0@ i= 100000$\tLight light = GetAdditionalLight(i, + WorldPosition, ShadowMask)@$#else$\tLight light = GetAdditionalLight(i, WorldPosition)@$#endif$\thalf3 + AttLightColor = light.color *(light.distanceAttenuation * light.shadowAttenuation)@$\tColor + +=LightingLambert(AttLightColor, light.direction, WorldNormal)@$\t$}$#endif$return + Color@;3;Create;3;True;WorldPosition;FLOAT3;0,0,0;In;;Float;False;True;WorldNormal;FLOAT3;0,0,0;In;;Float;False;True;ShadowMask;FLOAT4;0,0,0,0;In;;Inherit;False;AdditionalLightsLambertMask;False;False;0;;False;3;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionSwitch;25;-193.5493,-1609.208;Inherit;False;Option;False;0;2;-1;In + 0;In 1;Instance;24;9;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;35;-820.8937,-1817.931;Inherit;False;33;shadowMaskValue;1;0;OBJECT;;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.CustomExpressionNode;13;-191.7135,-336.9496;Inherit;False;float3 + Color = 0@$#ifdef _ADDITIONAL_LIGHTS$Smoothness = exp2(10 * Smoothness + 1)@$int + numLights = GetAdditionalLightsCount()@$for(int i = 0@ i= 100000$\tLight light = GetAdditionalLight(i, + WorldPosition, ShadowMask)@$#else$\tLight light = GetAdditionalLight(i, WorldPosition)@$#endif$\tColor + += light.color *(light.distanceAttenuation * light.shadowAttenuation)@$\t$}$#endif$return + Color@;3;Create;2;True;WorldPosition;FLOAT3;0,0,0;In;;Float;False;True;ShadowMask;FLOAT4;0,0,0,0;In;;Inherit;False;AdditionalLightsFlatMask;False;False;0;;False;2;0;FLOAT3;0,0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.CustomExpressionNode;22;-428.3495,-1080.747;Inherit;False;float3 + Color = 0@$#ifdef _ADDITIONAL_LIGHTS$int numLights = GetAdditionalLightsCount()@$for(int + i = 0@ i= 100000$\tLight light = GetAdditionalLight(i, WorldPosition, + ShadowMask)@$#else$\tLight light = GetAdditionalLight(i, WorldPosition)@$#endif$\thalf3 + AttLightColor = light.color *(light.distanceAttenuation * light.shadowAttenuation)@$\tColor + += LightingSpecular(AttLightColor, light.direction, WorldNormal, WorldView, half4(SpecColor, + 0), Smoothness)@\t$}$#endif$return Color@;3;Create;6;True;WorldPosition;FLOAT3;0,0,0;In;;Float;False;True;WorldNormal;FLOAT3;0,0,0;In;;Float;False;True;WorldView;FLOAT3;0,0,0;In;;Float;False;True;SpecColor;FLOAT3;0,0,0;In;;Float;False;True;Smoothness;FLOAT;0.5;In;;Float;False;True;ShadowMask;FLOAT4;0,0,0,0;In;;Inherit;False;AdditionalLightsSpecularMask;False;False;0;;False;6;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;4;FLOAT;0.5;False;5;FLOAT4;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.CustomExpressionNode;56;-433.6657,-942.9171;Inherit;False;float3 + Color = 0@$#ifdef _ADDITIONAL_LIGHTS$int numLights = GetAdditionalLightsCount()@$for(int + i = 0@ i= 100000$\tLight light = GetAdditionalLight(i, + WorldPosition, ShadowMask)@$#else$\tLight light = GetAdditionalLight(i, WorldPosition)@$#endif$\thalf3 + AttLightColor = light.color *(light.distanceAttenuation * light.shadowAttenuation)@$\tColor + +=(dot(light.direction, WorldNormal)*0.5+0.5 )* AttLightColor@$\t$}$#endif$return + Color@;3;Create;3;True;WorldPosition;FLOAT3;0,0,0;In;;Float;False;True;WorldNormal;FLOAT3;0,0,0;In;;Float;False;True;ShadowMask;FLOAT4;0,0,0,0;In;;Inherit;False;AdditionalLightsHalfLambertMask;False;False;0;;False;3;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.ViewDirInputsCoordNode;16;-870.7385,-332.9706;Inherit;False;World;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionOutput;0;495.8608,669.8015;Inherit;False;True;-1;Out;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;58;0;26;0\nWireConnection;26;0;22;0\nWireConnection;26;1;56;0\nWireConnection;27;0;13;0\nWireConnection;27;1;63;0\nWireConnection;9;0;12;0\nWireConnection;9;1;11;0\nWireConnection;33;0;32;0\nWireConnection;19;0;21;0\nWireConnection;19;3;21;0\nWireConnection;19;1;6;0\nWireConnection;19;2;21;0\nWireConnection;37;0;47;0\nWireConnection;37;1;51;0\nWireConnection;6;0;30;0\nWireConnection;6;1;23;0\nWireConnection;6;2;62;0\nWireConnection;15;0;16;0\nWireConnection;24;0;8;0\nWireConnection;24;1;31;0\nWireConnection;5;0;47;0\nWireConnection;5;1;51;0\nWireConnection;5;2;41;0\nWireConnection;25;0;37;0\nWireConnection;25;1;5;0\nWireConnection;13;0;49;0\nWireConnection;13;1;55;0\nWireConnection;13;2;15;0\nWireConnection;13;3;14;0\nWireConnection;13;4;18;0\nWireConnection;11;0;4;0\nWireConnection;38;0;25;0\nWireConnection;61;0;27;0\nWireConnection;12;0;2;0\nWireConnection;50;0;9;0\nWireConnection;29;0;24;0\nWireConnection;32;0;68;0\nWireConnection;23;0;39;0\nWireConnection;23;1;59;0\nWireConnection;44;0;3;0\nWireConnection;8;0;45;0\nWireConnection;31;0;45;0\nWireConnection;31;1;35;0\nWireConnection;22;0;48;0\nWireConnection;22;1;54;0\nWireConnection;2;0;10;0\nWireConnection;63;0;49;0\nWireConnection;63;1;55;0\nWireConnection;63;2;15;0\nWireConnection;63;3;14;0\nWireConnection;63;4;18;0\nWireConnection;63;5;64;0\nWireConnection;56;0;48;0\nWireConnection;56;1;54;0\nWireConnection;56;2;57;0\nWireConnection;0;0;19;0\nASEEND*/\n//CHKSM=172C975BC4B8265A7736E90F657433DCA22992AA" + m_functionName: + m_description: 'Returns SRP''s additional lights information calculated with the + selected lighting mode. + + Shadow mask option only applied on SRP 10 or greater.' + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 1 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_customEdited: 0 + m_additionalDirectives: + - {fileID: 0} + - {fileID: 0} + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: + - LineType: 2 + LineValue: multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS + GUIDToggle: 0 + GUIDValue: + Origin: 2 + - LineType: 2 + LineValue: multi_compile _ _ADDITIONAL_LIGHT_SHADOWS + GUIDToggle: 0 + GUIDValue: + Origin: 2 + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SRP Additional Light.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SRP Additional Light.asset.meta new file mode 100644 index 0000000..75b7d2b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SRP Additional Light.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6c86746ad131a0a408ca599df5f40861 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Sawtooth Wave.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Sawtooth Wave.asset new file mode 100644 index 0000000..7a9db0d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Sawtooth Wave.asset @@ -0,0 +1,39 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Sawtooth Wave + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17500\n508;100;994;700;746.5329;443.6693;1;True;False\nNode;AmplifyShaderEditor.FunctionInput;1;-591,-88;Inherit;False;In;1;0;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;4;-368,-16;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;3;-528,32;Inherit;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FloorOpNode;2;-240,-16;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;5;-112,-80;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ScaleNode;7;32,-80;Inherit;False;2;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;176,-80;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;4;0;1;0\nWireConnection;4;1;3;0\nWireConnection;2;0;4;0\nWireConnection;5;0;1;0\nWireConnection;5;1;2;0\nWireConnection;7;0;5;0\nWireConnection;0;0;7;0\nASEEND*/\n//CHKSM=CD22F0B45C0FC6CDCBADEDB7C0D7C1285F12B773" + m_functionName: + m_description: Creates a sawtooth wave from a given input + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Sawtooth Wave.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Sawtooth Wave.asset.meta new file mode 100644 index 0000000..9e62bed --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Sawtooth Wave.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 289adb816c3ac6d489f255fc3caf5016 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Simple HUE.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Simple HUE.asset new file mode 100644 index 0000000..0874349 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Simple HUE.asset @@ -0,0 +1,18 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Simple HUE + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=7207\n848;92;1072;626;663.3998;365.3001;1;True;False\nNode;AmplifyShaderEditor.RangedFloatNode;2;-413.5179,6.410728;Float;False;Constant;_Float1;Float + 1;0;0;1;0;0;0;1;FLOAT\nNode;AmplifyShaderEditor.FunctionInput;1;-408.5179,-209.5893;Float;False;Input;1;0;True;1;0;FLOAT;0.0;False;1;FLOAT\nNode;AmplifyShaderEditor.HSVToRGBNode;3;-201.5179,-187.5893;Float;False;3;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;4;FLOAT3;FLOAT;FLOAT;FLOAT\nNode;AmplifyShaderEditor.FunctionOutput;6;110.9821,-215.5893;Float;False;True;RGB;0;1;0;FLOAT3;0.0;False;0\nNode;AmplifyShaderEditor.FunctionOutput;7;111.4821,-128.5893;Float;False;False;R;1;1;0;FLOAT;0.0;False;0\nNode;AmplifyShaderEditor.FunctionOutput;8;114.4821,35.41073;Float;False;True;B;3;1;0;FLOAT;0.0;False;0\nNode;AmplifyShaderEditor.FunctionOutput;5;113.4821,-55.58927;Float;False;False;G;2;1;0;FLOAT;0.0;False;0\nWireConnection;3;0;1;0\nWireConnection;3;1;2;0\nWireConnection;3;2;2;0\nWireConnection;6;0;3;0\nWireConnection;7;0;3;1\nWireConnection;8;0;3;3\nWireConnection;5;0;3;2\nASEEND*/\n//CHKSM=47A5570DFC4487C498F141EA313AD2D9825590BD" + m_functionName: + m_description: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Simple HUE.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Simple HUE.asset.meta new file mode 100644 index 0000000..03b4250 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Simple HUE.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 32abb5f0db087604486c2db83a2e817a +timeCreated: 1497273339 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Smooth Wave.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Smooth Wave.asset new file mode 100644 index 0000000..1abe4b0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Smooth Wave.asset @@ -0,0 +1,40 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Smooth Wave + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1451;-120;1004;726;4133.806;1549.814;4.291845;True;False\nNode;AmplifyShaderEditor.StepOpNode;2;-560,-240;Inherit;True;2;0;FLOAT;0.5;False;1;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;3;-272,0;Inherit;False;Anti + Aliasing;False;1;3;1;None;Smoothstep;Derivative;Object;-1;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionNode;4;-560,224;Inherit;True;Step + Antialiasing;-1;;4;2a825e80dfb3290468194f83380797bd;0;2;1;FLOAT;0.5;False;2;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;1;-560,0;Inherit;True;3;0;FLOAT;0;False;1;FLOAT;0.5;False;2;FLOAT;0.55;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;5;-832,0;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;6;-1008,0;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;7;-1184,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RoundOpNode;8;-1328,80;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;9;-1504,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;19;-1696,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;21;-2672,0;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;18;-1888,64;Inherit;False;Amplitude;1;2;False;1;0;FLOAT;0.25;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ScaleAndOffsetNode;11;-1744,176;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0.5;False;2;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SinOpNode;12;-1904,176;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;13;-2064,176;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;15;-2224,176;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;20;-2912,0;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;16;-2416,256;Inherit;False;Wavelength;1;1;False;1;0;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;22;-2512,0;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.TauNode;14;-2224,288;Inherit;False;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;17;-2864,128;Inherit;False;Tiling;2;0;False;1;0;FLOAT2;1,1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;2;1;5;0\nWireConnection;3;0;2;0\nWireConnection;3;1;1;0\nWireConnection;3;2;4;0\nWireConnection;4;2;5;0\nWireConnection;1;0;5;0\nWireConnection;5;0;6;0\nWireConnection;6;0;7;0\nWireConnection;7;0;9;0\nWireConnection;7;1;8;0\nWireConnection;8;0;9;0\nWireConnection;9;0;19;0\nWireConnection;9;1;11;0\nWireConnection;19;0;22;1\nWireConnection;19;1;18;0\nWireConnection;21;0;20;0\nWireConnection;21;1;17;0\nWireConnection;11;0;12;0\nWireConnection;12;0;13;0\nWireConnection;13;0;15;0\nWireConnection;13;1;14;0\nWireConnection;15;0;22;0\nWireConnection;15;1;16;0\nWireConnection;22;0;21;0\nWireConnection;0;0;3;0\nASEEND*/\n//CHKSM=892F129365FB301F688609519A07B0C40D936DB3" + m_functionName: + m_description: Creates a smooth wave pattern. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Smooth Wave.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Smooth Wave.asset.meta new file mode 100644 index 0000000..55598e8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Smooth Wave.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 45d5b33902fbc0848a1166b32106db74 +timeCreated: 1586862423 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SphereMask.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SphereMask.asset new file mode 100644 index 0000000..4c661d7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SphereMask.asset @@ -0,0 +1,39 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: SphereMask + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17803\n269;89;1530;884;1386.415;349.8481;1;True;False\nNode;AmplifyShaderEditor.SaturateNode;16;-352,0;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DotProductOpNode;8;-496,0;Inherit;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;12;-384,144;Inherit;False;Hardness;1;2;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;14;-816,144;Inherit;False;Radius;1;1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WorldPosInputsNode;1;-1088,0;Float;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;3;-848,0;Inherit;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.PowerNode;11;-176,0;Inherit;False;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;5;-656,0;Inherit;False;2;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;15;-1088,160;Inherit;False;Sphere + Center;3;0;True;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;Output;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;16;0;8;0\nWireConnection;8;0;5;0\nWireConnection;8;1;5;0\nWireConnection;3;0;1;0\nWireConnection;3;1;15;0\nWireConnection;11;0;16;0\nWireConnection;11;1;12;0\nWireConnection;5;0;3;0\nWireConnection;5;1;14;0\nWireConnection;0;0;11;0\nASEEND*/\n//CHKSM=F2ED75A8184A51CCDCD716ADE2ADF2B74D08414C" + m_functionName: + m_description: + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SphereMask.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SphereMask.asset.meta new file mode 100644 index 0000000..5356f25 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SphereMask.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 988803ee12caf5f4690caee3c8c4a5bb +timeCreated: 1497273339 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spherize.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spherize.asset new file mode 100644 index 0000000..7edede3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spherize.asset @@ -0,0 +1,42 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Spherize + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity + Asset Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17500\n747;81;887;789;35.74168;1084.006;1.494906;False;False\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;6;-451,-504.5;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;3;-208,-336;Inherit;False;Center;2;1;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.Vector2Node;7;-448,-336;Inherit;False;Constant;_Vector0;Vector + 0;0;0;Create;True;0;0;False;0;0.5,0.5;0,0;0;3;FLOAT2;0;FLOAT;1;FLOAT;2\nNode;AmplifyShaderEditor.FunctionInput;2;-224,-512;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;11;-48,-448;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DotProductOpNode;12;128,-384;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.Vector2Node;8;-64,-224;Inherit;False;Constant;_Vector1;Vector + 1;0;0;Create;True;0;0;False;0;10,10;0,0;0;3;FLOAT2;0;FLOAT;1;FLOAT;2\nNode;AmplifyShaderEditor.FunctionInput;4;96,-224;Inherit;False;Strength;2;2;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;13;272,-384;Inherit;True;3;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;16;528,-512;Inherit;True;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;14;800,-560;Inherit;False;3;3;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;5;672,-272;Inherit;False;Offset;2;3;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.Vector2Node;9;496,-272;Inherit;False;Constant;_Vector2;Vector + 2;0;0;Create;True;0;0;False;0;0,0;0,0;0;3;FLOAT2;0;FLOAT;1;FLOAT;2\nNode;AmplifyShaderEditor.WireNode;17;475.96,-558.8504;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;0;928,-592;Inherit;False;True;-1;Out;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nWireConnection;3;0;7;0\nWireConnection;2;0;6;0\nWireConnection;11;0;2;0\nWireConnection;11;1;3;0\nWireConnection;12;0;11;0\nWireConnection;12;1;11;0\nWireConnection;4;0;8;0\nWireConnection;13;0;12;0\nWireConnection;13;1;12;0\nWireConnection;13;2;4;0\nWireConnection;16;0;11;0\nWireConnection;16;1;13;0\nWireConnection;14;0;17;0\nWireConnection;14;1;16;0\nWireConnection;14;2;5;0\nWireConnection;5;0;9;0\nWireConnection;17;0;2;0\nWireConnection;0;0;14;0\nASEEND*/\n//CHKSM=D018B0F4362C188C557966F417A11556B9BFFA27" + m_functionName: + m_description: Creates a sphere type warping effect from given UVs + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 14 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spherize.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spherize.asset.meta new file mode 100644 index 0000000..dfd44fe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spherize.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1488bb72d8899174ba0601b595d32b07 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spiral.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spiral.asset new file mode 100644 index 0000000..b672005 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spiral.asset @@ -0,0 +1,41 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Spiral + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1451;-120;1004;726;4246.446;1553.644;4.406295;True;False\nNode;AmplifyShaderEditor.FunctionSwitch;2;-272,0;Inherit;False;Anti + Aliasing;False;1;3;1;None;Smoothstep;Derivative;Object;-1;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.StepOpNode;3;-544,-192;Inherit;True;2;0;FLOAT;0.5;False;1;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionNode;1;-544,256;Inherit;True;Step + Antialiasing;-1;;8;2a825e80dfb3290468194f83380797bd;0;2;1;FLOAT;0.5;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;12;-928,32;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;20;-1744,32;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;4;-544,32;Inherit;True;3;0;FLOAT;0;False;1;FLOAT;0.4;False;2;FLOAT;0.6;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;6;-768,32;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;13;-1088,32;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;14;-1280,32;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RoundOpNode;17;-1424,96;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;19;-1157.289,239.4264;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;10;-928,112;Inherit;False;Width;1;3;False;1;0;FLOAT;0.6;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;18;-1568,32;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.WireNode;26;-1632.98,191.0273;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;22;-1920,96;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;21;-1920,-16;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;24;-2192,32;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.PiNode;25;-2128,-48;Inherit;False;1;0;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;23;-2096,144;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;15;-2272,272;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;11;-2448,272;Inherit;False;Separation;1;4;False;1;0;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.TauNode;16;-2400,352;Inherit;False;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;9;-2258,145;Inherit;False;Number;1;2;False;1;0;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionNode;27;-2512,32;Inherit;False;Polar + Coordinates;-1;;7;7dab8e02884cf104ebefaa2e788e4162;0;4;1;FLOAT2;0,0;False;2;FLOAT2;0.5,0.5;False;3;FLOAT;1;False;4;FLOAT;1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;29;-2720,32;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;28;-2992,32;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;7;-2960,160;Inherit;False;Tiling;2;0;False;1;0;FLOAT2;3,3;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;8;-2720,160;Inherit;False;Position;2;1;False;1;0;FLOAT2;1.5,1.5;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;2;0;3;0\nWireConnection;2;1;4;0\nWireConnection;2;2;1;0\nWireConnection;3;1;6;0\nWireConnection;1;2;6;0\nWireConnection;12;0;13;0\nWireConnection;20;0;21;0\nWireConnection;20;1;22;0\nWireConnection;4;0;6;0\nWireConnection;6;0;12;0\nWireConnection;6;1;10;0\nWireConnection;13;0;14;0\nWireConnection;13;1;19;0\nWireConnection;14;0;18;0\nWireConnection;14;1;17;0\nWireConnection;17;0;18;0\nWireConnection;19;0;15;0\nWireConnection;18;0;20;0\nWireConnection;18;1;26;0\nWireConnection;26;0;15;0\nWireConnection;22;0;24;1\nWireConnection;22;1;23;0\nWireConnection;21;0;25;0\nWireConnection;21;1;24;0\nWireConnection;24;0;27;0\nWireConnection;23;0;9;0\nWireConnection;23;1;15;0\nWireConnection;15;0;11;0\nWireConnection;15;1;16;0\nWireConnection;27;1;29;0\nWireConnection;27;2;8;0\nWireConnection;29;0;28;0\nWireConnection;29;1;7;0\nWireConnection;0;0;2;0\nASEEND*/\n//CHKSM=AE166C1ED4D74A88DA5347C878A6607CE24AB3DC" + m_functionName: + m_description: Creates a duotone spiral. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spiral.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spiral.asset.meta new file mode 100644 index 0000000..fd02fa2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Spiral.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 310c5f1537fa4c44699ebaf10a65d8a2 +timeCreated: 1586860260 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Square Wave.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Square Wave.asset new file mode 100644 index 0000000..e5b0374 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Square Wave.asset @@ -0,0 +1,39 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Square Wave + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17500\n508;100;994;700;447.1031;292.2682;1;True;False\nNode;AmplifyShaderEditor.RangedFloatNode;2;112,-16;Inherit;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;3;240,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ScaleNode;4;96,64;Inherit;False;2;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RoundOpNode;6;-16,64;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FractNode;5;-128,64;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;1;-240,64;Inherit;False;In;1;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;380,1;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;3;0;2;0\nWireConnection;3;1;4;0\nWireConnection;4;0;6;0\nWireConnection;6;0;5;0\nWireConnection;5;0;1;0\nWireConnection;0;0;3;0\nASEEND*/\n//CHKSM=A3216B4840DFB3FEAB230591EBAFD041F839FDD7" + m_functionName: + m_description: Creates a square wave from a given input + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Square Wave.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Square Wave.asset.meta new file mode 100644 index 0000000..802bda6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Square Wave.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6f8df4c09ccca5d42b0d3d422aad9cbd +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Step Antialiasing.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Step Antialiasing.asset new file mode 100644 index 0000000..d50961c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Step Antialiasing.asset @@ -0,0 +1,40 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Step Antialiasing + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18403\n351;92;1482;1034;1514.894;658.248;1.312046;True;False\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;3;-640,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;6;-160,0;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;5;-304,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FWidthOpNode;4;-464,64;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;1;-832,48;Inherit;False;A;1;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-832,-32;Inherit;False;B;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;False;True;-1;;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;3;0;2;0\nWireConnection;3;1;1;0\nWireConnection;6;0;5;0\nWireConnection;5;0;3;0\nWireConnection;5;1;4;0\nWireConnection;4;0;3;0\nWireConnection;0;0;6;0\nASEEND*/\n//CHKSM=71BB29D08447D735C1A7814C9A95F38DB2A1C626" + m_functionName: + m_description: 'Same as Step but provides an antialiased edge. + + (Only valid on fragment type ports)' + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 7 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Step Antialiasing.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Step Antialiasing.asset.meta new file mode 100644 index 0000000..1947ed7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Step Antialiasing.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2a825e80dfb3290468194f83380797bd +timeCreated: 1517571460 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stereo Screen Pos.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stereo Screen Pos.asset new file mode 100644 index 0000000..c48e357 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stereo Screen Pos.asset @@ -0,0 +1,42 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Stereo Screen Pos + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18812\n-2114;98;1601;770;1084.5;514.5;1;True;False\nNode;AmplifyShaderEditor.CustomExpressionNode;4;-224,-160;Inherit;False;#if + defined(UNITY_SINGLE_PASS_STEREO)$ float4 scaleOffset = unity_StereoScaleOffset[unity_StereoEyeIndex]@$ + \ return UV.xy * scaleOffset.xy + scaleOffset.zw@$#else$\treturn UV@$#endif\t;2;False;1;True;UV;FLOAT2;0,0;In;;Inherit;False;ASETransformStereoScreenSpaceTex;True;False;0;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;2;-544,-160;Inherit;False;Screen + Pos;4;0;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.SwizzleNode;3;-382,-155;Inherit;False;FLOAT2;0;1;2;3;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.ScreenPosInputsNode;1;-775.5,-166.5;Inherit;False;0;False;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionOutput;0;80,-160;Inherit;False;True;-1;Output;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nWireConnection;4;0;3;0\nWireConnection;2;0;1;0\nWireConnection;3;0;2;0\nWireConnection;0;0;4;0\nASEEND*/\n//CHKSM=5E1A913A8489DDB98C84EA0657FF57B93EE308A7" + m_functionName: + m_description: Transforms a screen position value from non Stereo to VR Stereo + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_customEdited: 0 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stereo Screen Pos.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stereo Screen Pos.asset.meta new file mode 100644 index 0000000..503d412 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stereo Screen Pos.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 855e05b95c44ab9408194955b1347bed +timeCreated: 1613491445 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stripes.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stripes.asset new file mode 100644 index 0000000..8887616 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stripes.asset @@ -0,0 +1,38 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Stripes + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1451;-120;1004;726;2464.405;901.6481;2.690987;True;False\nNode;AmplifyShaderEditor.RotatorNode;10;-1344,0;Inherit;True;3;0;FLOAT2;0,0;False;1;FLOAT2;0.5,0.5;False;2;FLOAT;1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;4;-1040,176;Inherit;False;Offset;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;9;-864,176;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;12;-1696,128;Inherit;False;Rotation;1;3;False;1;0;FLOAT;45;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RadiansOpNode;13;-1552,128;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;11;-1616,0;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;5;-1056,64;Inherit;False;Frequency;1;0;False;1;0;FLOAT;6;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FractNode;6;-416,0;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionNode;2;-224,0;Inherit;False;Rectangle;-1;;2;6b23e0c975270fb4084c354b2c83366a;0;3;1;FLOAT2;0,0;False;2;FLOAT;0.5;False;3;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;3;-432,80;Inherit;False;Thickness;1;2;False;1;0;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;8;-864,64;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;1;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.ScaleAndOffsetNode;7;-656,0;Inherit;False;3;0;FLOAT2;0,0;False;1;FLOAT2;1,0;False;2;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;True;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;10;0;11;0\nWireConnection;10;2;13;0\nWireConnection;9;0;4;0\nWireConnection;13;0;12;0\nWireConnection;6;0;7;0\nWireConnection;2;1;6;0\nWireConnection;2;2;3;0\nWireConnection;8;0;5;0\nWireConnection;7;0;10;0\nWireConnection;7;1;8;0\nWireConnection;7;2;9;0\nWireConnection;0;0;2;0\nASEEND*/\n//CHKSM=595F81C41E70086403DC08E5F39B901F2C31A726" + m_functionName: + m_description: Creates a stripes pattern. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stripes.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stripes.asset.meta new file mode 100644 index 0000000..207a1c4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Stripes.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8e73a71cdf24db740864b4c3f3357e7f +timeCreated: 1586859731 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SubstanceBlendMetallic.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SubstanceBlendMetallic.asset new file mode 100644 index 0000000..e8449e7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SubstanceBlendMetallic.asset @@ -0,0 +1,55 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: SubstanceBlendMetallic + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=15701\n1927;-171;1755;1044;4944.894;2298.292;3.922265;True;False\nNode;AmplifyShaderEditor.CommentaryNode;75;-2140.3,165.0382;Float;False;1438.676;390.7817;;8;64;25;22;23;7;26;8;50;Blending;0.1089965,0.8235294,0.2026249,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;74;-2122.365,668.0774;Float;False;1089.531;337.4497;;5;37;40;36;52;13;Smoothness;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;73;-2062.092,1136.985;Float;False;815.4429;395.7837;;5;70;69;71;72;41;Metallic;0.6176471,0.6176471,0.6176471,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;76;-913.6868,684.1127;Float;False;1032.627;404.9763;;6;53;29;30;32;33;12;Normal;0,0.2965517,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;79;-2178.365,-418.924;Float;False;1444.215;475.3517;;8;20;1;62;63;68;59;48;60;Height;0.7794118,0.5321501,0,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;78;-644.9852,-402.4992;Float;False;851.1305;427.6555;;5;10;56;27;9;0;Albedo;0.8308824,0.2810338,0.2810338,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;77;-596.2914,188.0575;Float;False;802.3574;335.5521;;5;45;46;54;44;47;Occlusion;0.08088237,0.08088237,0.08088237,1;0;0\nNode;AmplifyShaderEditor.GetLocalVarNode;54;-508.9551,408.6093;Float;False;50;Mask;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LerpOp;46;-266.7092,286.337;Float;False;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;10;-594.9857,-215.7596;Float;False;M2 + Albedo;3;9;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;44;-546.2911,238.0574;Float;False;M1 + Occlusion;1;8;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;45;-537.6957,316.0335;Float;False;M2 + Occlusion;1;13;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;30;-858.4458,974.089;Float;False;M2 + Normal;3;10;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;29;-863.6868,868.3461;Float;False;M1 + Normal;3;4;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.NormalizeNode;33;-308.887,751.9397;Float;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.LayeredBlendNode;32;-626.5039,827.4257;Float;False;6;0;FLOAT;0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;4;FLOAT;0;False;5;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.GetLocalVarNode;56;-470.663,-89.84428;Float;False;50;Mask;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;68;-1565.192,-129.3357;Float;False;Height;1;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;63;-1139.765,-368.924;Float;False;2;2;0;FLOAT;0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.ScaleAndOffsetNode;60;-1692.467,-280.4159;Float;False;3;0;FLOAT;0;False;1;FLOAT;1;False;2;FLOAT;-0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.NormalVertexDataNode;59;-1363.017,-122.572;Float;False;0;5;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;62;-1362.51,-314.935;Float;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;9;-586.3267,-352.4984;Float;False;M1 + Albedo;3;3;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.LerpOp;27;-212.9957,-265.2253;Float;False;3;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;1;-2128.365,-104.1909;Float;False;M1 + Height;3;7;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.ComponentMaskNode;20;-1903.539,-98.68884;Float;False;True;False;False;False;1;0;FLOAT3;0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LerpOp;71;-1693.327,1251.971;Float;False;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;52;-1714.363,890.5271;Float;False;50;Mask;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;64;-1850.772,226.6873;Float;False;Height1;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;69;-2012.092,1186.985;Float;False;M1 + Metallic;1;6;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;40;-2072.365,861.0316;Float;False;M2 + Smoothness;1;11;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;37;-2058.345,730.4346;Float;False;M1 + Smoothness;1;5;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;72;-1953.641,1417.769;Float;False;50;Mask;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LerpOp;36;-1528.141,718.0774;Float;False;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.TFHCRemapNode;25;-1444.829,264.7208;Float;True;5;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;1;False;3;FLOAT;0;False;4;FLOAT;2.69;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;8;-1706.795,440.8203;Float;False;Blend + Hardness;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SaturateNode;26;-1152.618,215.0382;Float;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;53;-857.4697,767.5581;Float;False;50;Mask;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;50;-944.6227,238.2931;Float;False;Mask;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;70;-2007.1,1301.496;Float;False;M2 + Metallic;1;12;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.OneMinusNode;22;-1611.744,230.6643;Float;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.OneMinusNode;23;-1693.643,349.4193;Float;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;7;-2090.301,395.7402;Float;False;Blend + Amount;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;48;-927.1483,-364.2609;Float;False;False;Height + OUT;5;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;47;-8.933975,238.2769;Float;False;False;Occlusion + OUT;4;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;12;-78.05887,734.1125;Float;False;False;Normal + OUT;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;13;-1267.832,719.8586;Float;False;False;Smoothness + OUT;3;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;11.14432,-267.8937;Float;False;True;Albedo + OUT;0;True;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;41;-1447.649,1238.483;Float;False;False;Metallic + OUT;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;46;0;44;0\nWireConnection;46;1;45;0\nWireConnection;46;2;54;0\nWireConnection;33;0;32;0\nWireConnection;32;0;53;0\nWireConnection;32;1;29;0\nWireConnection;32;2;30;0\nWireConnection;63;0;62;0\nWireConnection;63;1;59;0\nWireConnection;60;0;20;0\nWireConnection;62;0;60;0\nWireConnection;62;1;68;0\nWireConnection;27;0;9;0\nWireConnection;27;1;10;0\nWireConnection;27;2;56;0\nWireConnection;20;0;1;0\nWireConnection;71;0;69;0\nWireConnection;71;1;70;0\nWireConnection;71;2;72;0\nWireConnection;64;0;20;0\nWireConnection;36;0;37;0\nWireConnection;36;1;40;0\nWireConnection;36;2;52;0\nWireConnection;25;0;22;0\nWireConnection;25;1;23;0\nWireConnection;25;4;8;0\nWireConnection;26;0;25;0\nWireConnection;50;0;26;0\nWireConnection;22;0;64;0\nWireConnection;23;0;7;0\nWireConnection;48;0;63;0\nWireConnection;47;0;46;0\nWireConnection;12;0;33;0\nWireConnection;13;0;36;0\nWireConnection;0;0;27;0\nWireConnection;41;0;71;0\nASEEND*/\n//CHKSM=CB70D7609C0CE7FF39409B2F5F3B4C63A7232E07" + m_functionName: + m_description: + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SubstanceBlendMetallic.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SubstanceBlendMetallic.asset.meta new file mode 100644 index 0000000..5a1b542 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/SubstanceBlendMetallic.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 48f32255bf4aabb4bb7933a1266a4646 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Animate Vertex.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Animate Vertex.asset new file mode 100644 index 0000000..57b2ea0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Animate Vertex.asset @@ -0,0 +1,44 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Terrain Wind Animate Vertex + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=16103\n279;100;1002;701;934;430;1;True;False\nNode;AmplifyShaderEditor.PosVertexDataNode;5;-706,-228;Float;False;1;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;2;-477,-116;Float;False;Pos;4;0;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.CustomExpressionNode;1;-253,-72;Float;False;return + AnimateVertex(Pos,Normal,AnimParams)@;4;False;3;True;Pos;FLOAT4;0,0,0,0;In;;Float;True;Normal;FLOAT3;0,0,0;In;;Float;True;AnimParams;FLOAT4;0,0,0,0;In;;Float;WindAnimateVertex;True;False;0;3;0;FLOAT4;0,0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.NormalVertexDataNode;6;-712,2;Float;False;0;5;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;3;-491,-27;Float;False;Normal;3;1;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionInput;4;-512,143;Float;False;Anim + Params;4;2;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionOutput;0;-21,-86;Float;False;True;Output;0;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nWireConnection;2;0;5;0\nWireConnection;1;0;2;0\nWireConnection;1;1;3;0\nWireConnection;1;2;4;0\nWireConnection;3;0;6;0\nWireConnection;0;0;1;0\nASEEND*/\n//CHKSM=A559079493ADDD12988F7585C781D01E1B32CCBB" + m_functionName: + m_description: "Uses Unity AnimateVertex(...) function \nAnimation parameters\nx + = branch phase\ny = edge flutter factor\nz = primary factor\nw = secondary factor" + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 1 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: + - {fileID: 0} + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: + - LineType: 0 + LineValue: TerrainEngine.cginc + GUIDToggle: 0 + GUIDValue: + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Animate Vertex.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Animate Vertex.asset.meta new file mode 100644 index 0000000..3b9d084 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Animate Vertex.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3bc81bd4568a7094daabf2ccd6a7e125 +timeCreated: 1544624630 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Value.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Value.asset new file mode 100644 index 0000000..4d107c3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Value.asset @@ -0,0 +1,41 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Terrain Wind Value + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=16103\n282;100;993;689;732.5;318;1;True;False\nNode;AmplifyShaderEditor.Vector4Node;2;-275,-56;Float;False;Global;_Wind;_Wind;0;0;Fetch;True;0;0;False;0;0,0,0,0;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionOutput;0;1,-32;Float;False;True;Value;0;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nWireConnection;0;0;2;0\nASEEND*/\n//CHKSM=BA65DE015BF1BA5B4089E1D34F116B49DF410865" + m_functionName: + m_description: 'Returns terrain current wind value ' + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 1 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: + - {fileID: 0} + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: + - LineType: 0 + LineValue: TerrainEngine.cginc + GUIDToggle: 0 + GUIDValue: + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Value.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Value.asset.meta new file mode 100644 index 0000000..642905a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Terrain Wind Value.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c7f50c5b53423ac408959a9a25532d8c +timeCreated: 1544624092 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Triangle Wave.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Triangle Wave.asset new file mode 100644 index 0000000..4df8a72 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Triangle Wave.asset @@ -0,0 +1,40 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Triangle Wave + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17500\n508;100;994;700;66.71295;546.0343;1;True;False\nNode;AmplifyShaderEditor.FunctionInput;1;-493,-231;Inherit;False;In;1;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;5;-88.3874,-220.5811;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;3;-352,-128;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FloorOpNode;2;-224,-128;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;4;-528,-112;Inherit;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.ScaleNode;6;48,-224;Inherit;False;2;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;7;192,-224;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.ScaleNode;8;304,-224;Inherit;False;2;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;10;320,-144;Inherit;False;Constant;_Float1;Float + 1;0;0;Create;True;0;0;False;0;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;9;464,-224;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;608,-224;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;5;0;1;0\nWireConnection;5;1;2;0\nWireConnection;3;0;1;0\nWireConnection;3;1;4;0\nWireConnection;2;0;3;0\nWireConnection;6;0;5;0\nWireConnection;7;0;6;0\nWireConnection;8;0;7;0\nWireConnection;9;0;8;0\nWireConnection;9;1;10;0\nWireConnection;0;0;9;0\nASEEND*/\n//CHKSM=590E74ADE111A4C2E167952E95AB6AA949211EC5" + m_functionName: + m_description: Creates a triangle wave from a given input + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Triangle Wave.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Triangle Wave.asset.meta new file mode 100644 index 0000000..706bce3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Triangle Wave.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 51ec3c8d117f3ec4fa3742c3e00d535b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Truchet.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Truchet.asset new file mode 100644 index 0000000..af05af9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Truchet.asset @@ -0,0 +1,40 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Truchet + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1451;-120;1004;726;4353.539;1501.093;4.613734;True;False\nNode;AmplifyShaderEditor.CosOpNode;17;-2128,0;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CeilOpNode;22;-2624,0;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.LengthOpNode;8;-1136,0;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;25;-2992,256;Inherit;False;Tiling;2;0;False;1;0;FLOAT2;8,8;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.LengthOpNode;9;-1136,96;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SignOpNode;16;-1984,0;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.OneMinusNode;10;-1312,96;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.DynamicAppendNode;12;-1616,0;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;34;-864,448;Inherit;False;Line + Edge;1;3;False;1;0;FLOAT;0.1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.OneMinusNode;32;-864,352;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;33;-1040,272;Inherit;False;Line + Width;1;2;False;1;0;FLOAT;0.7;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;31;-608,448;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;28;-592,128;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;27;-592,240;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;30;-592,336;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;18;-2304,0;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;14;-2096,128;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.LengthOpNode;21;-2480,0;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;19;-2480,96;Inherit;False;Seed;1;4;False;1;0;FLOAT;163;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;13;-1824,0;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FractNode;4;-592,0;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;23;-3040,128;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;24;-2784,128;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;3;-384,128;Inherit;False;3;0;FLOAT;0.4;False;1;FLOAT;0.4;False;2;FLOAT;0.2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;2;-384,0;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0.8;False;2;FLOAT;0.6;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FractNode;11;-1456,0;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;6;-944,128;Inherit;False;Repetition;1;1;False;1;0;FLOAT;3;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMinOpNode;7;-928,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;5;-752,0;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;1;-160,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;True;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;17;0;18;0\nWireConnection;22;0;24;0\nWireConnection;8;0;11;0\nWireConnection;9;0;10;0\nWireConnection;16;0;17;0\nWireConnection;10;0;11;0\nWireConnection;12;0;13;0\nWireConnection;12;1;14;1\nWireConnection;32;0;33;0\nWireConnection;31;0;32;0\nWireConnection;31;1;34;0\nWireConnection;28;0;33;0\nWireConnection;28;1;34;0\nWireConnection;27;0;33;0\nWireConnection;27;1;34;0\nWireConnection;30;0;32;0\nWireConnection;30;1;34;0\nWireConnection;18;0;21;0\nWireConnection;18;1;19;0\nWireConnection;14;0;24;0\nWireConnection;21;0;22;0\nWireConnection;13;0;16;0\nWireConnection;13;1;14;0\nWireConnection;4;0;5;0\nWireConnection;24;0;23;0\nWireConnection;24;1;25;0\nWireConnection;3;0;4;0\nWireConnection;3;1;30;0\nWireConnection;3;2;31;0\nWireConnection;2;0;4;0\nWireConnection;2;1;28;0\nWireConnection;2;2;27;0\nWireConnection;11;0;12;0\nWireConnection;7;0;8;0\nWireConnection;7;1;9;0\nWireConnection;5;0;7;0\nWireConnection;5;1;6;0\nWireConnection;1;0;2;0\nWireConnection;1;1;3;0\nWireConnection;0;0;1;0\nASEEND*/\n//CHKSM=71BCBEAE6BE593A152630FFE597CDB7E884F9637" + m_functionName: + m_description: Creates a circular truchet pattern + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Truchet.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Truchet.asset.meta new file mode 100644 index 0000000..6bad17b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Truchet.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 600b4e63537aa56498ba8983340930ed +timeCreated: 1586859036 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Twirl.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Twirl.asset new file mode 100644 index 0000000..c651418 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Twirl.asset @@ -0,0 +1,41 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Twirl + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17402\n283;92;1224;567;1716.085;694.8059;1;True;False\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;26;-229.45,1014.038;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;23;126.1965,470.1173;Float;False;x;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;4;-141.4665,141.677;Inherit;False;Offset;2;3;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;30;-544.0643,1393.266;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.BreakToComponentsNode;40;27.03977,43.70857;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.SimpleAddOpNode;36;-42.68103,1196.398;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;31;-222.9422,1321.077;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;41;18.78442,147.4395;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.GetLocalVarNode;32;-641.9422,1255.077;Inherit;False;10;angle;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CosOpNode;28;-419.744,1284.469;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SinOpNode;33;-421.45,979.0385;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;2;-1094.728,-436.1572;Inherit;False;Center;2;1;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.Vector2Node;48;-1273.182,-434.3912;Float;False;Constant;_Vector0;Vector + 0;0;0;Create;True;0;0;False;0;0.5,0.5;0,0;0;3;FLOAT2;0;FLOAT;1;FLOAT;2\nNode;AmplifyShaderEditor.TextureCoordinatesNode;47;-1177.182,-594.3912;Inherit;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.RangedFloatNode;49;-940.182,-10.39124;Float;False;Constant;_Float0;Float + 0;0;0;Create;True;0;0;False;0;0;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;9;-598.4258,-82.49329;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;38;347.1208,5.87381;Inherit;False;3;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;46;-169.4436,36.13173;Inherit;False;45;center;1;0;OBJECT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;37;85.72414,-54.41926;Inherit;False;23;x;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;42;345.0738,199.996;Inherit;False;3;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;43;79.00623,250.3625;Inherit;False;35;y;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;35;124.55,1199.038;Float;False;y;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.DynamicAppendNode;44;503.8386,114.5915;Inherit;False;FLOAT2;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;5;-692.6281,-495.1572;Inherit;False;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;12;-581.9256,372.3068;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.GetLocalVarNode;14;-679.8035,234.1173;Inherit;False;10;angle;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;16;-788.419,674.3449;Inherit;False;6;delta;1;0;OBJECT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;27;-648.45,948.0384;Inherit;False;10;angle;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;24;-763.5733,1081.228;Inherit;False;6;delta;1;0;OBJECT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;7;-964.4258,-150.4933;Inherit;False;6;delta;1;0;OBJECT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;3;-776,-11.5;Inherit;False;Strength;1;2;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.LengthOpNode;8;-758.4258,-144.4933;Inherit;False;1;0;FLOAT2;0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;11;-794.9268,367.3068;Inherit;False;6;delta;1;0;OBJECT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;10;-432.4258,-86.49329;Float;False;angle;-1;True;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;18;-254.2957,607.1554;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;17;-575.4178,679.3449;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FunctionInput;1;-901.6281,-546.1571;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;6;-514.6281,-499.1572;Float;False;delta;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;29;-757.0655,1388.266;Inherit;False;6;delta;1;0;OBJECT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;25;-550.5721,1086.228;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.RegisterLocalVarNode;45;-919.5434,-437.0681;Float;False;center;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SinOpNode;21;-445.8035,549.1173;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;19;-673.2957,541.1554;Inherit;False;10;angle;1;0;OBJECT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;22;-54.80347,475.1173;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.CosOpNode;13;-469.0975,241.5478;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;15;-260.8035,300.1173;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;755.2719,118.0862;Inherit;False;True;-1;Out;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nWireConnection;26;0;33;0\nWireConnection;26;1;25;0\nWireConnection;23;0;22;0\nWireConnection;30;0;29;0\nWireConnection;40;0;46;0\nWireConnection;36;0;26;0\nWireConnection;36;1;31;0\nWireConnection;31;0;28;0\nWireConnection;31;1;30;1\nWireConnection;41;0;4;0\nWireConnection;28;0;32;0\nWireConnection;33;0;27;0\nWireConnection;2;0;48;0\nWireConnection;9;0;8;0\nWireConnection;9;1;3;0\nWireConnection;38;0;37;0\nWireConnection;38;1;40;0\nWireConnection;38;2;41;0\nWireConnection;42;0;40;1\nWireConnection;42;1;41;1\nWireConnection;42;2;43;0\nWireConnection;35;0;36;0\nWireConnection;44;0;38;0\nWireConnection;44;1;42;0\nWireConnection;5;0;1;0\nWireConnection;5;1;45;0\nWireConnection;12;0;11;0\nWireConnection;3;0;49;0\nWireConnection;8;0;7;0\nWireConnection;10;0;9;0\nWireConnection;18;0;21;0\nWireConnection;18;1;17;1\nWireConnection;17;0;16;0\nWireConnection;1;0;47;0\nWireConnection;6;0;5;0\nWireConnection;25;0;24;0\nWireConnection;45;0;2;0\nWireConnection;21;0;19;0\nWireConnection;22;0;15;0\nWireConnection;22;1;18;0\nWireConnection;13;0;14;0\nWireConnection;15;0;13;0\nWireConnection;15;1;12;0\nWireConnection;0;0;44;0\nASEEND*/\n//CHKSM=F53C1E2142313F47DAA6F7B6F1940C955AD15150" + m_functionName: + m_description: Sets a twirl effect to a given input UV. Created by The C.reator + @cayou66 + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Twirl.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Twirl.asset.meta new file mode 100644 index 0000000..c1d44ba --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Twirl.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 90936742ac32db8449cd21ab6dd337c8 +timeCreated: 1575562904 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/UI-Sprite Effect Layer.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/UI-Sprite Effect Layer.asset new file mode 100644 index 0000000..6902d2f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/UI-Sprite Effect Layer.asset @@ -0,0 +1,71 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: UI-Sprite Effect Layer + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=14301\n487;594;979;424;3607.895;518.2078;1.589382;True;False\nNode;AmplifyShaderEditor.CommentaryNode;223;-6464.406,-405.0316;Float;False;1173;245;Comment;5;221;219;218;222;225;UVs;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;133;-3799.791,-542.9508;Float;False;2592.219;432.9557;Comment;14;33;43;228;14;18;199;203;92;93;20;72;248;249;250;Flow;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;141;-4706.676,155.4364;Float;False;4042.436;693;Comment;35;114;122;130;129;30;99;115;116;126;98;125;100;102;101;103;57;6;2;3;8;13;11;4;7;12;17;97;205;200;236;237;239;240;242;246;Rotate;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;86;-4791.083,-1656.615;Float;False;4027.944;807.3318;Comment;31;229;230;80;190;183;198;184;182;75;83;202;224;185;187;179;84;71;65;181;188;96;189;77;82;186;177;234;233;232;235;231;Distortion;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;209;-6158.292,-709.5029;Float;False;714.7412;175.0351;Comment;3;59;40;197;Time;1,1,1,1;0;0\nNode;AmplifyShaderEditor.CommentaryNode;208;-6188.004,-1135.091;Float;False;775.5483;285.9527;Comment;3;37;201;207;Main + FX Texture;1,1,1,1;0;0\nNode;AmplifyShaderEditor.ComponentMaskNode;6;-4144.676,573.4364;Float;False;True;True;False;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitch;191;128,-800;Float;False;Tint + Effect;True;0;2;1;In 0;In 1;Object;-1;8;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;COLOR;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;228;-3264,-400;Float;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.DynamicAppendNode;82;-3060.073,-1576.615;Float;False;FLOAT4;4;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.StepOpNode;115;-2640.676,653.4366;Float;False;2;0;FLOAT;0.0;False;1;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.TexturePropertyNode;77;-4745.313,-1609.291;Float;True;Property;_DistortionNormal;Distortion + Normal;2;2;[NoScaleOffset];[Normal];Create;True;dd2fd2df93418444c8e280f1d34deeb5;9f3c58d3e4da749499d5cf376feb6225;True;bump;Auto;0;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.FunctionInput;192;128,-688;Float;False;Color;5;0;False;1;0;COLOR;1,1,1,1;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;71;-1780.073,-1160.615;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;14;-3008,-480;Float;True;Property;_FlowandMaskSampler;Flow + and Mask Sampler;11;1;[NoScaleOffset];Create;True;None;db10d612ce611ae47a896290b6c40f26;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.ComponentMaskNode;27;320,-512;Float;False;False;False;False;True;1;0;COLOR;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;30;-2170.379,545.9249;Float;False;Opacity;1;17;False;1;0;FLOAT;1.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.OneMinusNode;122;-2448.676,733.4366;Float;False;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SamplerNode;96;-1588.073,-1336.615;Float;True;Property;_DistortionSampler;Distortion + Sampler;0;1;[NoScaleOffset];Create;True;None;None;True;0;False;black;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;188;-3700.073,-1320.615;Float;False;Distortion + Mask;9;9;False;1;0;SAMPLER2D;0.0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.FunctionInput;181;-4132.074,-968.615;Float;False;Move + Vector;2;5;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;57;-4432.676,605.4365;Float;False;Position + Scale;4;14;False;1;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0\nNode;AmplifyShaderEditor.FunctionInput;33;-3536,-480;Float;False;Flow + (RG) Mask (A);9;10;False;1;0;SAMPLER2D;0.0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.FunctionInput;101;-2688.676,429.4364;Float;False;Rotation + Mask;9;13;False;1;0;SAMPLER2D;0.0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.ScaleNode;7;-3712.676,685.4366;Float;False;0.5;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexturePropertyNode;43;-3776,-480;Float;True;Property;_FlowandMask;Flow + and Mask;3;1;[NoScaleOffset];Create;True;90cbb44e451af6f44acb32a4c63486ec;db10d612ce611ae47a896290b6c40f26;False;white;Auto;0;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;193;752,-608;Float;False;2;2;0;COLOR;0,0,0,0;False;1;COLOR;0.0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionSwitch;186;-2116.073,-1368.615;Float;False;Use + Distortion Mask;True;0;2;6;In 0;In 1;Object;-1;8;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.GetLocalVarNode;203;-2304,-480;Float;False;201;0;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.ComponentMaskNode;84;-2596.073,-1576.615;Float;True;True;True;False;False;1;0;FLOAT3;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;195;560,-528;Float;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0.0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionInput;39;-320,-608;Float;False;Tint + Color;5;1;False;1;0;COLOR;1,1,1,1;False;1;COLOR;0\nNode;AmplifyShaderEditor.SamplerNode;102;-2480.676,429.4364;Float;True;Property;_RotateMaskSampler;Rotate + Mask Sampler;11;1;[NoScaleOffset];Create;True;None;db10d612ce611ae47a896290b6c40f26;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleAddOpNode;196;752,-720;Float;False;2;2;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionInput;37;-5881.824,-1082.837;Float;False;Tex;9;2;False;1;0;SAMPLER2D;0.0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.FunctionSwitch;242;-2326.053,204.1207;Float;False;Vertex + UVs;False;0;2;3;Fragment;Vertex;Object;-1;8;0;FLOAT2;0.0;False;1;FLOAT2;0.0;False;2;FLOAT2;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RotatorNode;17;-3216,208;Float;False;3;0;FLOAT2;0,0;False;1;FLOAT2;0.5,0.5;False;2;FLOAT;1.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitch;74;-400,-800;Float;False;Effect;False;0;3;0;Distortion;Flow;Rotate;Object;-1;8;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;224;-4464,-1120;Float;False;222;0;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;236;-4480,368;Float;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleTimeNode;250;-2976,-192;Float;False;1;0;FLOAT;1.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;13;-3376.676,365.4364;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;239;-4432,496;Float;False;UV;2;4;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.VertexToFragmentNode;246;-2592,272;Float;False;1;0;FLOAT2;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitch;31;976,-800;Float;False;Blend + Mode;False;0;3;16;None;Additive;Additive With Alpha Blend;Object;-1;8;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;COLOR;0,0,0,0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;COLOR;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;222;-5536,-352;Float;False;MainUvs;-1;True;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;65;-3412.073,-1608.615;Float;True;Property;_DistortionNormalSampler;Distortion + Normal Sampler;3;1;[NoScaleOffset];Create;True;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleAddOpNode;8;-3792.676,365.4364;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexturePropertyNode;100;-2976.676,301.4365;Float;True;Property;_RotateMask;Rotate + Mask;5;1;[NoScaleOffset];Create;True;800ff50c9cc42bb4c99ea4b57ccd019e;db10d612ce611ae47a896290b6c40f26;False;white;Auto;0;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;26;-96,-688;Float;False;2;2;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionSwitch;98;-944.6762,205.4365;Float;False;Use + Mask;True;0;2;11;In 0;In 1;Object;-1;8;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionSwitch;126;-1984.676,477.4364;Float;False;Mask + Type;False;0;2;13;Texture;Color;Object;-1;8;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;99;-1168,320;Float;False;3;3;0;COLOR;0,0,0,0;False;1;FLOAT;0,0,0,0;False;2;FLOAT;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionSwitch;204;-368,-240;Float;False;Option;False;0;2;-1;In + 0;In 1;Instance;74;8;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT2;0,0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.PannerNode;179;-3860.073,-1032.615;Float;False;3;0;FLOAT2;0,0;False;2;FLOAT2;0,-0.1;False;1;FLOAT;1.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;72;-2004.572,-476.025;Float;True;Property;_FlowSampler;Flow + Sampler;0;1;[NoScaleOffset];Create;True;None;None;True;0;False;black;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.Vector4Node;103;-4656.676,605.4365;Float;False;Constant;_Vector0;Vector + 0;4;0;Create;True;0,0,1,1;0,0,0,0;0;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.LerpOp;125;-1715.194,611.3666;Float;False;3;0;FLOAT;1.0;False;1;FLOAT;1.0;False;2;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;130;-2224.676,653.4366;Float;False;Invert + Middle Point;True;0;2;15;In 0;In 1;Object;-1;8;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;201;-5655.456,-1085.091;Float;False;FxTexVar;-1;True;1;0;SAMPLER2D;0.0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.SamplerNode;187;-3428.073,-1320.615;Float;True;Property;_DistortionMaskSampler;Distortion + Mask Sampler;3;1;[NoScaleOffset];Create;True;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;40;-5900.292,-649.4677;Float;False;Time;1;15;False;1;0;FLOAT;0.01;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;185;-4164.074,-1432.615;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;116;-2832.676,653.4366;Float;False;2;2;0;FLOAT;0.0;False;1;FLOAT;-0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;205;-1840.676,301.4365;Float;False;201;0;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.GetLocalVarNode;202;-1802.593,-1350.938;Float;False;201;0;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.ComponentMaskNode;114;-3152.676,653.4366;Float;False;False;True;True;True;1;0;FLOAT2;0,0,0,0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.UnpackScaleNormalNode;83;-2852.073,-1576.615;Float;False;2;0;FLOAT4;0,0,0,0;False;1;FLOAT;1.0;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionSwitch;225;-5792,-352;Float;False;Custom + UVs;True;0;2;2;In 0;In 1;Object;-1;8;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RegisterLocalVarNode;197;-5686.55,-659.5028;Float;False;TimeVar;-1;True;1;0;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;75;-3700.073,-1608.615;Float;False;Distortion + Normal;9;6;False;1;0;SAMPLER2D;0.0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.FunctionSwitch;182;-3700.073,-1464.615;Float;False;Move + Distortion;True;0;2;8;In 0;In 1;Object;-1;8;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleAddOpNode;184;-3924.073,-1432.615;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitch;92;-1444.572,-476.025;Float;False;Use + Mask;True;0;2;10;In 0;In 1;Object;-1;8;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;COLOR;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;93;-1652.572,-300.025;Float;False;2;2;0;COLOR;0,0,0,0;False;1;FLOAT;0.0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;198;-4471.64,-1349.006;Float;False;197;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;183;-4484.074,-1432.615;Float;False;Move + Distortion Vector;2;8;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;190;-2324.073,-1304.615;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT;0.0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleTimeNode;59;-6108.292,-649.4677;Float;False;1;0;FLOAT;1.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;80;-3124.073,-1416.615;Float;False;Distortion + Amount;1;7;False;1;0;FLOAT;1.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;177;-3600,-1120;Float;False;Move + Background;True;0;2;7;Simple;Moving Background;Object;-1;8;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexturePropertyNode;235;-2688,-1056;Float;True;Property;_DistortionBlendMask;Distortion + Blend Mask;4;1;[NoScaleOffset];Create;True;800ff50c9cc42bb4c99ea4b57ccd019e;db10d612ce611ae47a896290b6c40f26;False;white;Auto;0;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.NegateNode;12;-3552.676,685.4366;Float;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;230;-1184,-1184;Float;False;3;3;0;COLOR;0,0,0,0;False;1;FLOAT;0.0,0,0,0;False;2;FLOAT;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.GetLocalVarNode;200;-3601.361,241.9365;Float;False;197;0;1;FLOAT;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;219;-6219.89,-355.0316;Float;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;11;-3568.676,365.4364;Float;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexturePropertyNode;207;-6138.004,-1079.138;Float;True;Property;_FXTexture;FX + Texture;0;1;[NoScaleOffset];Create;True;84508b93f15f2b64386ec07486afc7a3;f7e96904e8667e1439548f0f86389447;False;white;Auto;0;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.ComponentMaskNode;2;-4144.676,653.4366;Float;False;False;False;True;True;1;0;FLOAT4;0,0,0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitch;129;-1504.676,477.4364;Float;False;Use + Middle Point Cut;True;1;2;14;In 0;In 1;Object;-1;8;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;231;-1792,-944;Float;False;Opacity;1;16;False;1;0;FLOAT;1.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;4;-3872.676,685.4366;Float;False;2;0;FLOAT2;0,0;False;1;FLOAT;0.0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitch;234;-1584,-1008;Float;False;Mask + Type;False;0;2;12;Texture;Color;Object;-1;8;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;221;-6414.406,-355.0316;Float;False;201;0;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.FunctionSwitch;229;-1008,-1328;Float;False;Use + Mask;True;0;2;9;In 0;In 1;Object;-1;8;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;COLOR;0\nNode;AmplifyShaderEditor.TexturePropertyNode;189;-4745.313,-1321.291;Float;True;Property;_DistortionMask;Distortion + Mask;1;1;[NoScaleOffset];Create;True;23d106e42b09f48ecb609eb2d6032f0a;9f3c58d3e4da749499d5cf376feb6225;False;white;Auto;0;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.FunctionInput;218;-5968,-256;Float;False;UV;2;3;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;97;-1520.676,205.4365;Float;True;Property;_RotateSampler;Rotate + Sampler;4;1;[NoScaleOffset];Create;True;None;None;True;0;False;black;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionInput;248;-2788.04,-193.6505;Float;False;Move + Dir;2;11;False;1;0;FLOAT2;1,1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitch;237;-4144,464;Float;False;Custom + UVs;True;0;2;4;In 0;In 1;Object;-1;8;0;FLOAT2;0.0;False;1;FLOAT2;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.RelayNode;240;-1897.553,209.827;Float;False;1;0;FLOAT2;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;233;-2448,-1056;Float;False;Distortion + Blend Mask;9;12;False;1;0;SAMPLER2D;0.0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.DynamicAppendNode;20;-2496.058,-413.0761;Float;False;FLOAT2;4;0;FLOAT;0.0;False;1;FLOAT;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;18;-2312.529,-412.6489;Float;False;2;0;FLOAT2;0.0;False;1;FLOAT;0.0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SamplerNode;232;-2176,-1056;Float;True;Property;_DistortionBlendMaskSampler;Distortion + Blend Mask Sampler;11;1;[NoScaleOffset];Create;True;None;db10d612ce611ae47a896290b6c40f26;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0.0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1.0;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionSwitch;249;-2592,-272;Float;False;Separate + XY Time;True;0;2;5;In 0;In 1;Object;-1;8;0;FLOAT;0.0;False;1;FLOAT2;0.0;False;2;FLOAT;0.0;False;3;FLOAT;0.0;False;4;FLOAT;0.0;False;5;FLOAT;0.0;False;6;FLOAT;0.0;False;7;FLOAT;0.0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.GetLocalVarNode;199;-2979.91,-269.36;Float;False;197;0;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;3;-4096.676,733.4366;Float;False;Constant;_Float0;Float + 0;3;0;Create;True;1;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;1344,-800;Float;False;True;RGBA;0;True;1;0;COLOR;0,0,0,0;False;1;COLOR;0\nNode;AmplifyShaderEditor.FunctionOutput;172;16,-240;Float;False;False;UV;1;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nWireConnection;6;0;57;0\nWireConnection;191;0;74;0\nWireConnection;191;1;26;0\nWireConnection;228;2;33;0\nWireConnection;82;1;65;2\nWireConnection;82;3;65;1\nWireConnection;115;0;116;0\nWireConnection;71;0;186;0\nWireConnection;71;1;177;0\nWireConnection;14;0;33;0\nWireConnection;14;1;228;0\nWireConnection;27;0;192;0\nWireConnection;122;0;115;0\nWireConnection;96;0;202;0\nWireConnection;96;1;71;0\nWireConnection;188;0;189;0\nWireConnection;57;0;103;0\nWireConnection;33;0;43;0\nWireConnection;101;0;100;0\nWireConnection;7;0;4;0\nWireConnection;193;0;192;0\nWireConnection;193;1;195;0\nWireConnection;186;0;84;0\nWireConnection;186;1;190;0\nWireConnection;84;0;83;0\nWireConnection;195;0;191;0\nWireConnection;195;1;27;0\nWireConnection;102;0;101;0\nWireConnection;102;1;237;0\nWireConnection;196;0;191;0\nWireConnection;196;1;192;0\nWireConnection;37;0;207;0\nWireConnection;242;0;17;0\nWireConnection;242;1;246;0\nWireConnection;17;0;13;0\nWireConnection;17;2;200;0\nWireConnection;74;0;229;0\nWireConnection;74;1;92;0\nWireConnection;74;2;98;0\nWireConnection;13;0;11;0\nWireConnection;13;1;12;0\nWireConnection;246;0;17;0\nWireConnection;31;0;191;0\nWireConnection;31;1;196;0\nWireConnection;31;2;193;0\nWireConnection;222;0;225;0\nWireConnection;65;0;75;0\nWireConnection;65;1;182;0\nWireConnection;8;0;237;0\nWireConnection;8;1;6;0\nWireConnection;26;0;74;0\nWireConnection;26;1;39;0\nWireConnection;98;0;97;0\nWireConnection;98;1;99;0\nWireConnection;126;0;102;2\nWireConnection;126;1;30;0\nWireConnection;99;0;97;0\nWireConnection;99;1;129;0\nWireConnection;99;2;97;4\nWireConnection;204;0;71;0\nWireConnection;204;1;18;0\nWireConnection;204;2;240;0\nWireConnection;179;0;224;0\nWireConnection;179;2;181;0\nWireConnection;72;0;203;0\nWireConnection;72;1;18;0\nWireConnection;125;1;126;0\nWireConnection;125;2;130;0\nWireConnection;130;0;115;0\nWireConnection;130;1;122;0\nWireConnection;201;0;37;0\nWireConnection;187;0;188;0\nWireConnection;187;1;182;0\nWireConnection;40;0;59;0\nWireConnection;185;0;183;0\nWireConnection;185;1;198;0\nWireConnection;116;0;114;0\nWireConnection;114;0;13;0\nWireConnection;83;0;82;0\nWireConnection;83;1;80;0\nWireConnection;225;0;219;0\nWireConnection;225;1;218;0\nWireConnection;197;0;40;0\nWireConnection;75;0;77;0\nWireConnection;182;0;224;0\nWireConnection;182;1;184;0\nWireConnection;184;0;185;0\nWireConnection;184;1;224;0\nWireConnection;92;0;72;0\nWireConnection;92;1;93;0\nWireConnection;93;0;72;0\nWireConnection;93;1;14;4\nWireConnection;190;0;84;0\nWireConnection;190;1;187;2\nWireConnection;177;0;224;0\nWireConnection;177;1;179;0\nWireConnection;12;0;7;0\nWireConnection;230;0;96;0\nWireConnection;230;1;96;4\nWireConnection;230;2;234;0\nWireConnection;219;2;221;0\nWireConnection;11;0;8;0\nWireConnection;11;1;2;0\nWireConnection;2;0;57;0\nWireConnection;129;0;126;0\nWireConnection;129;1;125;0\nWireConnection;4;0;2;0\nWireConnection;4;1;3;0\nWireConnection;234;0;232;2\nWireConnection;234;1;231;0\nWireConnection;229;0;96;0\nWireConnection;229;1;230;0\nWireConnection;218;0;219;0\nWireConnection;97;0;205;0\nWireConnection;97;1;240;0\nWireConnection;248;0;250;0\nWireConnection;237;0;236;0\nWireConnection;237;1;239;0\nWireConnection;240;0;242;0\nWireConnection;233;0;235;0\nWireConnection;20;0;14;1\nWireConnection;20;1;14;2\nWireConnection;18;0;20;0\nWireConnection;18;1;249;0\nWireConnection;232;0;233;0\nWireConnection;249;0;199;0\nWireConnection;249;1;248;0\nWireConnection;0;0;31;0\nWireConnection;172;0;204;0\nASEEND*/\n//CHKSM=3897411E214292FD4588680A344DD01F3BE97598" + m_functionName: + m_description: + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/UI-Sprite Effect Layer.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/UI-Sprite Effect Layer.asset.meta new file mode 100644 index 0000000..fcf96cc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/UI-Sprite Effect Layer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 789bf62641c5cfe4ab7126850acc22b8 +timeCreated: 1516025397 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Whirl.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Whirl.asset new file mode 100644 index 0000000..7a06b52 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Whirl.asset @@ -0,0 +1,42 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Whirl + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18004\n447;214;1178;691;4557.838;1918.107;5.505805;True;True\nNode;AmplifyShaderEditor.FunctionNode;6;-1968,-16;Inherit;False;Polar + Coordinates;-1;;3;7dab8e02884cf104ebefaa2e788e4162;0;4;1;FLOAT2;0,0;False;2;FLOAT2;0.5,0.5;False;3;FLOAT;1;False;4;FLOAT;1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;3;-2192,-16;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;10;-1744,-176;Inherit;False;Rotation;1;5;False;1;0;FLOAT;1;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;9;-1552,-160;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.TauNode;8;-1712,-96;Inherit;False;0;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;7;-2192,112;Inherit;False;Position;2;2;False;1;0;FLOAT2;0.5,0.5;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionSwitch;25;64,0;Inherit;False;Anti + Aliasing;False;1;3;1;None;Smoothstep;Derivative;Object;-1;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionNode;23;-224,224;Inherit;True;Step + Antialiasing;-1;;4;2a825e80dfb3290468194f83380797bd;0;2;1;FLOAT;0.5;False;2;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.StepOpNode;24;-224,-240;Inherit;True;2;0;FLOAT;0.5;False;1;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;21;-560,80;Inherit;False;Width;1;4;False;1;0;FLOAT;2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;1;-2432,112;Inherit;False;Tiling;2;1;False;1;0;FLOAT2;1,1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.AbsOpNode;19;-560,0;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;22;-224,0;Inherit;True;3;0;FLOAT;0;False;1;FLOAT;0.45;False;2;FLOAT;0.55;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;20;-400,0;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;17;-736,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;15;-1040,0;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;11;-1392,-112;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.BreakToComponentsNode;12;-1669.078,-23.10936;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.FunctionInput;16;-1216,96;Inherit;False;Number;1;3;False;1;0;FLOAT;8;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RoundOpNode;18;-880,64;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;14;-1216,0;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;27;-2656,64;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;28;-2880,-16;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionSwitch;26;-2464,-16;Inherit;False;Custom + UVs;True;0;2;0;In 0;In 1;Object;-1;9;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionOutput;0;352,0;Inherit;False;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;6;1;3;0\nWireConnection;6;2;7;0\nWireConnection;3;0;26;0\nWireConnection;3;1;1;0\nWireConnection;9;0;10;0\nWireConnection;9;1;8;0\nWireConnection;25;0;24;0\nWireConnection;25;1;22;0\nWireConnection;25;2;23;0\nWireConnection;23;2;20;0\nWireConnection;24;1;20;0\nWireConnection;19;0;17;0\nWireConnection;22;0;20;0\nWireConnection;20;0;19;0\nWireConnection;20;1;21;0\nWireConnection;17;0;15;0\nWireConnection;17;1;18;0\nWireConnection;15;0;14;0\nWireConnection;15;1;16;0\nWireConnection;11;0;9;0\nWireConnection;11;1;12;0\nWireConnection;12;0;6;0\nWireConnection;18;0;15;0\nWireConnection;14;0;12;1\nWireConnection;14;1;11;0\nWireConnection;27;0;28;0\nWireConnection;26;0;28;0\nWireConnection;26;1;27;0\nWireConnection;0;0;25;0\nASEEND*/\n//CHKSM=524C524527FFD24280A66E7E271E61FCDCEBCBFD" + m_functionName: + m_description: Creates a duotone whirl. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Whirl.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Whirl.asset.meta new file mode 100644 index 0000000..3853666 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Whirl.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7d75aee9e4d352a4299928ac98404afc +timeCreated: 1586858124 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Zig Zag.asset b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Zig Zag.asset new file mode 100644 index 0000000..eaa142d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Zig Zag.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: Zig Zag + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity Asset + Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=17902\n-1451;-120;1004;726;3953.281;1395.555;3.991293;True;False\nNode;AmplifyShaderEditor.BreakToComponentsNode;20;-2336,-32;Inherit;False;FLOAT2;1;0;FLOAT2;0,0;False;16;FLOAT;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4;FLOAT;5;FLOAT;6;FLOAT;7;FLOAT;8;FLOAT;9;FLOAT;10;FLOAT;11;FLOAT;12;FLOAT;13;FLOAT;14;FLOAT;15\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;11;-912,32;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionNode;4;-1824,144;Inherit;False;Triangle + Wave;-1;;5;51ec3c8d117f3ec4fa3742c3e00d535b;0;1;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;7;-1600,32;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;16;-2032,64;Inherit;False;Amplitude;1;3;False;1;0;FLOAT;0.2;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;2;-1984,160;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;15;-2208,176;Inherit;False;Wavelength;1;2;False;1;0;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SmoothstepOpNode;14;-656,32;Inherit;True;3;0;FLOAT;0;False;1;FLOAT;0.5;False;2;FLOAT;0.55;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RoundOpNode;9;-1408,144;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.AbsOpNode;10;-1088,32;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleDivideOpNode;5;-1792,-16;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.RangedFloatNode;18;-1104,144;Inherit;False;Constant;_Float2;Float + 2;0;0;Create;True;0;0;False;0;2;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.StepOpNode;12;-656,-192;Inherit;True;2;0;FLOAT;0.5;False;1;FLOAT;0.5;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;17;-304,0;Inherit;False;Anti + Aliasing;False;1;3;1;None;Smoothstep;Derivative;Object;-1;9;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;8;-1264,32;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionNode;13;-656,256;Inherit;True;Step + Antialiasing;-1;;4;2a825e80dfb3290468194f83380797bd;0;2;1;FLOAT;0.5;False;2;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionSwitch;24;-2560,-32;Inherit;False;Custom + UVs;True;0;2;0;In 0;In 1;Object;-1;9;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT;0;False;7;FLOAT;0;False;8;FLOAT;0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;22;-2944,112;Inherit;False;Tiling;2;1;False;1;0;FLOAT2;1,1;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.SimpleMultiplyOpNode;25;-2752,96;Inherit;False;2;2;0;FLOAT2;0,0;False;1;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.FunctionInput;19;-2752,-32;Inherit;False;UV;2;0;False;1;0;FLOAT2;0,0;False;1;FLOAT2;0\nNode;AmplifyShaderEditor.TexCoordVertexDataNode;1;-3024,-32;Inherit;False;0;2;0;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.FunctionOutput;0;0,0;Inherit;True;True;-1;Out;0;False;1;0;FLOAT;0;False;1;FLOAT;0\nWireConnection;20;0;24;0\nWireConnection;11;0;10;0\nWireConnection;11;1;18;0\nWireConnection;4;1;2;0\nWireConnection;7;0;5;0\nWireConnection;7;1;4;0\nWireConnection;2;0;20;0\nWireConnection;2;1;15;0\nWireConnection;14;0;11;0\nWireConnection;9;0;7;0\nWireConnection;10;0;8;0\nWireConnection;5;0;20;1\nWireConnection;5;1;16;0\nWireConnection;12;1;11;0\nWireConnection;17;0;12;0\nWireConnection;17;1;14;0\nWireConnection;17;2;13;0\nWireConnection;8;0;7;0\nWireConnection;8;1;9;0\nWireConnection;13;2;11;0\nWireConnection;24;0;25;0\nWireConnection;24;1;19;0\nWireConnection;25;0;1;0\nWireConnection;25;1;22;0\nWireConnection;19;0;1;0\nWireConnection;0;0;17;0\nASEEND*/\n//CHKSM=81E39E7D2F7FF85E045BB45FDBBBB9CFD0B58BC3" + m_functionName: + m_description: Creates a zig zag pattern. + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 0 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 9 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Zig Zag.asset.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Zig Zag.asset.meta new file mode 100644 index 0000000..79e99a9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderFunctions/Zig Zag.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8cd734fbcae021148a58931ed7d68679 +timeCreated: 1586786476 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderLibrary.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderLibrary.meta new file mode 100644 index 0000000..11a87f3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderLibrary.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c7d59e8c9057675458e07a7d532c321b +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderLibrary/ShaderLibrary.txt b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderLibrary/ShaderLibrary.txt new file mode 100644 index 0000000..b3bd797 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderLibrary/ShaderLibrary.txt @@ -0,0 +1 @@ +CustomCategory/ricardo#Hidden/CubeMapReflection#Hidden/DoLSimpleTexture \ No newline at end of file diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderLibrary/ShaderLibrary.txt.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderLibrary/ShaderLibrary.txt.meta new file mode 100644 index 0000000..92684e7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/ShaderLibrary/ShaderLibrary.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 608872e34785abb4aa0eafeb5515ec3b +timeCreated: 1481127071 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders.meta new file mode 100644 index 0000000..5fce785 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: dd999f0c55d995740a0376d84237f80c +folderAsset: yes +timeCreated: 1481126945 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/ASESShaderSelectorUnlit.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/ASESShaderSelectorUnlit.shader new file mode 100644 index 0000000..a0a93f4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/ASESShaderSelectorUnlit.shader @@ -0,0 +1,39 @@ +Shader "Hidden/ASESShaderSelectorUnlit" +{ + SubShader + { + Tags { "RenderType"="Opaque" } + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + + struct appdata + { + float4 vertex : POSITION; + }; + + struct v2f + { + float4 vertex : SV_POSITION; + }; + + uniform fixed4 _Color; + + v2f vert (appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + return o; + } + + fixed4 frag (v2f i) : SV_Target + { + return _Color; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/ASESShaderSelectorUnlit.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/ASESShaderSelectorUnlit.shader.meta new file mode 100644 index 0000000..1a85ab1 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/ASESShaderSelectorUnlit.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b83de440f4e137948bdb40a67a2f6dbe +timeCreated: 1490375492 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/Unlit-ColoredAlpha.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/Unlit-ColoredAlpha.shader new file mode 100644 index 0000000..7638151 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/Unlit-ColoredAlpha.shader @@ -0,0 +1,165 @@ +Shader "Unlit/Colored Transparent" { + Properties { + _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {} + _SecondTex ("Second (RGB) Trans (A)", 2D) = "white" {} + _ThirdTex ("Third (RGB) Trans (A)", 2D) = "white" {} + _FourthTex ("Fourth (RGB) Trans (A)", 2D) = "white" {} + _Color ("Color", Color) = (1,1,1,1) + } + + SubShader { + Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} + LOD 100 + + ZWrite Off + Blend SrcAlpha OneMinusSrcAlpha + + Pass { // SINGLE LINE + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 2.0 + #include "UnityCG.cginc" + + struct appdata_t { + float4 vertex : POSITION; + float4 color : COLOR; + float2 texcoord : TEXCOORD0; + }; + + struct v2f { + float4 vertex : SV_Position; + fixed4 color : COLOR; + half2 texcoord : TEXCOORD0; + float2 clipUV : TEXCOORD1; + }; + + sampler2D _MainTex; + float4 _MainTex_ST; + float4 _Color; + uniform float4x4 unity_GUIClipTextureMatrix; + sampler2D _GUIClipTexture; + + v2f vert (appdata_t v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.color = v.color * _Color; + o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); + float3 eyePos = UnityObjectToViewPos( v.vertex ); + o.clipUV = mul( unity_GUIClipTextureMatrix, float4( eyePos.xy, 0, 1.0 ) ); + return o; + } + + fixed4 frag( v2f i ) : SV_Target + { + float4 l1 = tex2D( _MainTex, i.texcoord); + float clipAlpha = tex2D( _GUIClipTexture, i.clipUV ).a; + l1.rgb *= i.color.rgb; + l1.a *= clipAlpha; + return l1; + } + ENDCG + } + + Pass { // MULTI LINE + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 2.0 + #include "UnityCG.cginc" + + struct appdata_t { + float4 vertex : POSITION; + float4 color : COLOR; + float2 texcoord : TEXCOORD0; + }; + + struct v2f { + float4 vertex : SV_Position; + fixed4 color : COLOR; + half2 texcoord : TEXCOORD0; + float2 clipUV : TEXCOORD1; + }; + + sampler2D _MainTex; + float4 _MainTex_ST; + sampler2D _SecondTex; + float4 _SecondTex_ST; + sampler2D _ThirdTex; + float4 _ThirdTex_ST; + sampler2D _FourthTex; + float4 _FourthTex_ST; + float4 _Color; + uniform float4x4 unity_GUIClipTextureMatrix; + sampler2D _GUIClipTexture; + float _InvertedZoom; + + v2f vert (appdata_t v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.color = v.color * _Color; + o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); + float3 eyePos = UnityObjectToViewPos( v.vertex ); + o.clipUV = mul( unity_GUIClipTextureMatrix, float4( eyePos.xy, 0, 1.0 ) ); + return o; + } + + fixed4 frag( v2f i ) : SV_Target + { + float4 l1 = tex2D( _MainTex, i.texcoord); + float clipAlpha = tex2D( _GUIClipTexture, i.clipUV ).a; + l1.rgb *= i.color.rgb; + l1.a *= clipAlpha; + + float4 l2 = tex2D( _SecondTex, i.texcoord); + float4 l3 = tex2D( _ThirdTex, i.texcoord); + float4 l4 = tex2D( _FourthTex, i.texcoord); + + float2 coords2 = i.texcoord; + coords2.y *= 2; + float4 m2 = tex2D( _MainTex, coords2 ); + m2 = pow( m2, 0.9 ); + + float2 coords3 = i.texcoord; + coords3.y *= 3; + float4 m3 = tex2D( _MainTex, coords3 ); + m3 = pow( m3, 0.8 ); + + float2 coords4 = i.texcoord; + coords4.y *= 4; + float4 m4 = tex2D( _MainTex, coords4 ); + m4 = pow( m4, 0.7 ); + + l2.rgb *= i.color.rgb; + l3.rgb *= i.color.rgb; + l4.rgb *= i.color.rgb; + + m2.rgb *= i.color.rgb; + m3.rgb *= i.color.rgb; + m4.rgb *= i.color.rgb; + + l2.a *= clipAlpha; + l3.a *= clipAlpha; + l4.a *= clipAlpha; + + m2.a *= clipAlpha; + m3.a *= clipAlpha; + m4.a *= clipAlpha; + + float zoomLerp = saturate( ( ( _InvertedZoom ) * 2 ) - 0.0 ); + + if ( i.color.a >= 1 ) + return lerp( l4, m4, zoomLerp ); + else if ( i.color.a >= 0.75 ) + return lerp( l3, m3, zoomLerp ); + else if ( i.color.a >= 0.5 ) + return lerp( l2, m2, zoomLerp ); + else + return l1; + } + ENDCG + } + } +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/Unlit-ColoredAlpha.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/Unlit-ColoredAlpha.shader.meta new file mode 100644 index 0000000..528ef29 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Shaders/Unlit-ColoredAlpha.shader.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 50fc796413bac8b40aff70fb5a886273 +timeCreated: 1491397480 +licenseType: Store +ShaderImporter: + defaultTextures: + - _MainTex: {fileID: 2800000, guid: 02f71419854c0d845a930c9e0a0bf775, type: 3} + - _SecondTex: {fileID: 2800000, guid: 03a7d169469c1af41bb03241a7b7e23d, type: 3} + - _ThirdTex: {fileID: 2800000, guid: c3512c25766a40245ac94c6b1722d76e, type: 3} + - _FourthTex: {fileID: 2800000, guid: e0f922c44762291498cc62e0917609be, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates.meta new file mode 100644 index 0000000..f5784b7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 211faf49d0bea6c4081e4e1135d19686 +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/CustomRTTemplates.unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/CustomRTTemplates.unitypackage.meta new file mode 100644 index 0000000..0ca30b9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/CustomRTTemplates.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 191365b4aece81443875ae2bb7243b55 +timeCreated: 1539791396 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/HDSRPTemplates.unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/HDSRPTemplates.unitypackage.meta new file mode 100644 index 0000000..f46c626 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/HDSRPTemplates.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9a5e61a8b3421b944863d0946e32da0a +timeCreated: 1531836588 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/LWSRPTemplates.unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/LWSRPTemplates.unitypackage.meta new file mode 100644 index 0000000..89ca7fe --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/LWSRPTemplates.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4c816894a3147d343891060451241bfe +timeCreated: 1520621352 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy.meta new file mode 100644 index 0000000..55a974e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6e848a1cd56b4c4489af03626db2de58 +folderAsset: yes +timeCreated: 1527085590 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/DefaultUnlit.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/DefaultUnlit.shader new file mode 100644 index 0000000..3af44f2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/DefaultUnlit.shader @@ -0,0 +1,86 @@ +Shader /*ase_name*/ "Hidden/Templates/Legacy/DefaultUnlit" /*end*/ +{ + Properties + { + _MainTex ("Sprite Texture", 2D) = "white" {} + _Color ("Tint", Color) = (1,1,1,1) + /*ase_props*/ + } + + SubShader + { + Tags { "RenderType"="Opaque" } + LOD 100 + Cull Off + + /*ase_pass*/ + Pass + { + CGPROGRAM + #ifndef UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX + //only defining to not throw compilation error over Unity 5.5 + #define UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input) + #endif + + #pragma target 3.0 + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + /*ase_pragma*/ + + struct appdata + { + float4 vertex : POSITION; + float4 texcoord : TEXCOORD0; + float4 texcoord1 : TEXCOORD1; + UNITY_VERTEX_INPUT_INSTANCE_ID + /*ase_vdata:p=p;uv0=tc0.xy;uv1=tc1.xy*/ + }; + + struct v2f + { + float4 vertex : SV_POSITION; + float4 texcoord : TEXCOORD0; + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + /*ase_interp(1,):sp=sp.xyzw;uv0=tc0.xy;uv1=tc0.zw*/ + }; + + uniform sampler2D _MainTex; + uniform fixed4 _Color; + /*ase_globals*/ + + v2f vert ( appdata v /*ase_vert_input*/) + { + v2f o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + UNITY_TRANSFER_INSTANCE_ID(v, o); + o.texcoord.xy = v.texcoord.xy; + o.texcoord.zw = v.texcoord1.xy; + + // ase common template code + /*ase_vert_code:v=appdata;o=v2f*/ + + v.vertex.xyz += /*ase_vert_out:Local Vertex;Float3*/ float3(0,0,0) /*end*/; + o.vertex = UnityObjectToClipPos(v.vertex); + return o; + } + + fixed4 frag (v2f i /*ase_frag_input*/) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(i); + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); + + fixed4 myColorVar; + // ase common template code + /*ase_frag_code:i=v2f*/ + + myColorVar = /*ase_frag_out:Frag Color;Float4*/fixed4(1,0,0,1)/*end*/; + return myColorVar; + } + ENDCG + } + } + CustomEditor "ASEMaterialInspector" +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/DefaultUnlit.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/DefaultUnlit.shader.meta new file mode 100644 index 0000000..0548163 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/DefaultUnlit.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6e114a916ca3e4b4bb51972669d463bf +timeCreated: 1496328687 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Lit.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Lit.shader new file mode 100644 index 0000000..eed3b73 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Lit.shader @@ -0,0 +1,2302 @@ +Shader /*ase_name*/ "Hidden/Legacy/Lit" /*end*/ +{ + Properties + { + /*ase_props*/ + //_TransmissionShadow( "Transmission Shadow", Range( 0, 1 ) ) = 0.5 + //_TransStrength( "Trans Strength", Range( 0, 50 ) ) = 1 + //_TransNormal( "Trans Normal Distortion", Range( 0, 1 ) ) = 0.5 + //_TransScattering( "Trans Scattering", Range( 1, 50 ) ) = 2 + //_TransDirect( "Trans Direct", Range( 0, 1 ) ) = 0.9 + //_TransAmbient( "Trans Ambient", Range( 0, 1 ) ) = 0.1 + //_TransShadow( "Trans Shadow", Range( 0, 1 ) ) = 0.5 + //_TessPhongStrength( "Tess Phong Strength", Range( 0, 1 ) ) = 0.5 + //_TessValue( "Tess Max Tessellation", Range( 1, 32 ) ) = 16 + //_TessMin( "Tess Min Distance", Float ) = 10 + //_TessMax( "Tess Max Distance", Float ) = 25 + //_TessEdgeLength ( "Tess Edge length", Range( 2, 50 ) ) = 16 + //_TessMaxDisp( "Tess Max Displacement", Float ) = 25 + //_SpecularHighlights("Specular Highlights", Float) = 1.0 + //_GlossyReflections("Reflections", Float) = 1.0 + } + + SubShader + { + /*ase_subshader_options:Name=Additional Options + Option:Workflow,InvertActionOnDeselection:Specular,Metallic:Metallic + Metallic:ShowPort:Metallic + Specular:ShowPort:Specular + Specular:SetDefine:_SPECULAR_SETUP 1 + Option:Surface:Opaque,Transparent:Opaque + Opaque:SetPropertyOnSubShader:RenderType,Opaque + Opaque:SetPropertyOnSubShader:RenderQueue,Geometry + Opaque:SetPropertyOnSubShader:ZWrite,On + Opaque:HideOption: Blend + Opaque:HideOption: Dither Shadows + Opaque:HideOption: Refraction Model + Transparent:SetPropertyOnSubShader:RenderType,Transparent + Transparent:SetPropertyOnSubShader:RenderQueue,Transparent + Transparent:SetPropertyOnSubShader:ZWrite,Off + Transparent:ShowOption: Blend + Transparent:ShowOption: Dither Shadows + Transparent:ShowOption: Refraction Model + Option: Blend:Alpha,Premultiply,Additive,Multiply,Translucent,Custom:Alpha + Alpha:SetPropertyOnPass:ForwardBase:BlendRGB,SrcAlpha,OneMinusSrcAlpha + Alpha:SetPropertyOnPass:ForwardAdd:BlendRGB,SrcAlpha,One + Alpha:SetDefine:_ALPHABLEND_ON 1 + Premultiply:SetPropertyOnPass:ForwardBase:BlendRGB,One,OneMinusSrcAlpha + disable,Premultiply,Additive,Multiply,Translucent,Custom:SetPropertyOnPass:ForwardAdd:BlendRGB,One,One + Premultiply:SetDefine:_ALPHAPREMULTIPLY_ON 1 + Additive:SetPropertyOnPass:ForwardBase:BlendRGB,One,One + Multiply:SetPropertyOnPass:ForwardBase:BlendRGB,DstColor,Zero + disable,Premultiply,Additive,Multiply,Translucent,Custom:RemoveDefine:_ALPHABLEND_ON 1 + disable,Alpha,Additive,Multiply,Translucent,Custom:RemoveDefine:_ALPHAPREMULTIPLY_ON 1 + disable,Translucent:SetPropertyOnPass:ForwardBase:BlendRGB,One,Zero + Option: Refraction Model:None:None + None,disable:HidePort:ForwardBase:Refraction Index + None,disable:HidePort:ForwardBase:Refraction Color + None,disable:RemoveDefine:_REFRACTION_ASE 1 + None,disable:RemoveDefine:ASE_NEEDS_FRAG_SCREEN_POSITION + Legacy:ShowPort:ForwardBase:Refraction Index + Legacy:ShowPort:ForwardBase:Refraction Color + Legacy:SetDefine:_REFRACTION_ASE 1 + Legacy:SetDefine:ASE_NEEDS_FRAG_SCREEN_POSITION + Option: Dither Shadows:false,true:true + true:SetDefine:UNITY_STANDARD_USE_DITHER_MASK 1 + false,disable:RemoveDefine:UNITY_STANDARD_USE_DITHER_MASK 1 + Option:Two Sided:On,Cull Back,Cull Front:Cull Back + On:SetPropertyOnSubShader:CullMode,Off + Cull Back:SetPropertyOnSubShader:CullMode,Back + Cull Front:SetPropertyOnSubShader:CullMode,Front + Option:Deferred Pass:false,true:true + true:IncludePass:Deferred + false:ExcludePass:Deferred + Option:Transmission:false,true:false + false:RemoveDefine:_TRANSMISSION_ASE 1 + false:HidePort:ForwardBase:Transmission + false:HideOption: Transmission Shadow + true:SetDefine:_TRANSMISSION_ASE 1 + true:ShowPort:ForwardBase:Transmission + true:ShowOption: Transmission Shadow + true:SetOption:Deferred Pass,0 + Field: Transmission Shadow:Float:0.5:0:1:_TransmissionShadow + Change:SetMaterialProperty:_TransmissionShadow + Change:SetShaderProperty:_TransmissionShadow,_TransmissionShadow( "Transmission Shadow", Range( 0, 1 ) ) = 0.5 + Inline,disable:SetShaderProperty:_TransmissionShadow,//_TransmissionShadow( "Transmission Shadow", Range( 0, 1 ) ) = 0.5 + Option:Translucency:false,true:false + false:RemoveDefine:_TRANSLUCENCY_ASE 1 + false:HidePort:ForwardBase:Translucency + false:HideOption: Translucency Strength + false:HideOption: Normal Distortion + false:HideOption: Scattering + false:HideOption: Direct + false:HideOption: Ambient + false:HideOption: Shadow + true:SetDefine:_TRANSLUCENCY_ASE 1 + true:ShowPort:ForwardBase:Translucency + true:ShowOption: Translucency Strength + true:ShowOption: Normal Distortion + true:ShowOption: Scattering + true:ShowOption: Direct + true:ShowOption: Ambient + true:ShowOption: Shadow + true:SetOption:Deferred Pass,0 + Field: Translucency Strength:Float:1:0:50:_TransStrength + Change:SetMaterialProperty:_TransStrength + Change:SetShaderProperty:_TransStrength,_TransStrength( "Strength", Range( 0, 50 ) ) = 1 + Inline,disable:SetShaderProperty:_TransStrength,//_TransStrength( "Strength", Range( 0, 50 ) ) = 1 + Field: Normal Distortion:Float:0.5:0:1:_TransNormal + Change:SetMaterialProperty:_TransNormal + Change:SetShaderProperty:_TransNormal,_TransNormal( "Normal Distortion", Range( 0, 1 ) ) = 0.5 + Inline,disable:SetShaderProperty:_TransNormal,//_TransNormal( "Normal Distortion", Range( 0, 1 ) ) = 0.5 + Field: Scattering:Float:2:1:50:_TransScattering + Change:SetMaterialProperty:_TransScattering + Change:SetShaderProperty:_TransScattering,_TransScattering( "Scattering", Range( 1, 50 ) ) = 2 + Inline,disable:SetShaderProperty:_TransScattering,//_TransScattering( "Scattering", Range( 1, 50 ) ) = 2 + Field: Direct:Float:0.9:0:1:_TransDirect + Change:SetMaterialProperty:_TransDirect + Change:SetShaderProperty:_TransDirect,_TransDirect( "Direct", Range( 0, 1 ) ) = 0.9 + Inline,disable:SetShaderProperty:_TransDirect,//_TransDirect( "Direct", Range( 0, 1 ) ) = 0.9 + Field: Ambient:Float:0.1:0:1:_TransAmbient + Change:SetMaterialProperty:_TransAmbient + Change:SetShaderProperty:_TransAmbient,_TransAmbient( "Ambient", Range( 0, 1 ) ) = 0.1 + Inline,disable:SetShaderProperty:_TransAmbient,//_TransAmbient( "Ambient", Range( 0, 1 ) ) = 0.1 + Field: Shadow:Float:0.5:0:1:_TransShadow + Change:SetMaterialProperty:_TransShadow + Change:SetShaderProperty:_TransShadow,_TransShadow( "Shadow", Range( 0, 1 ) ) = 0.5 + Inline,disable:SetShaderProperty:_TransShadow,//_TransShadow( "Shadow", Range( 0, 1 ) ) = 0.5 + Option:Cast Shadows:false,true:true + true:IncludePass:ShadowCaster + false,disable:ExcludePass:ShadowCaster + true:ShowOption: Use Shadow Threshold + false:HideOption: Use Shadow Threshold + Option: Use Shadow Threshold:false,true:false + true:ShowPort:ForwardBase:Alpha Clip Threshold Shadow + false,disable:HidePort:ForwardBase:Alpha Clip Threshold Shadow + Option:Receive Shadows:false,true:true + true:SetDefine:ASE_NEEDS_FRAG_SHADOWCOORDS + false:RemoveDefine:ASE_NEEDS_FRAG_SHADOWCOORDS + Option:GPU Instancing:false,true:true + true:SetDefine:pragma multi_compile_instancing + false:RemoveDefine:pragma multi_compile_instancing + Option:LOD CrossFade:false,true:true + true:SetDefine:pragma multi_compile __ LOD_FADE_CROSSFADE + false:RemoveDefine:pragma multi_compile __ LOD_FADE_CROSSFADE + Option:Built-in Fog:false,true:true + true:SetDefine:pragma multi_compile_fog + false:RemoveDefine:pragma multi_compile_fog + true:SetDefine:ASE_FOG 1 + false:RemoveDefine:ASE_FOG 1 + Option:Ambient Light:false,true:true + true:RemoveDefine:ASE_NO_AMBIENT 1 + false:SetDefine:ASE_NO_AMBIENT 1 + Option:Meta Pass:false,true:true + true:IncludePass:Meta + false,disable:ExcludePass:Meta + Option:Add Pass:false,true:true + true:IncludePass:ForwardAdd + false,disable:ExcludePass:ForwardAdd + Option:Override Baked GI:false,true:false + true:ShowPort:ForwardBase:Baked GI + false:HidePort:ForwardBase:Baked GI + true:SetDefine:ASE_BAKEDGI 1 + false:RemoveDefine:ASE_BAKEDGI 1 + Option:Extra Pre Pass:false,true:false + true:IncludePass:ExtraPrePass + false,disable:ExcludePass:ExtraPrePass + Option:Tessellation:false,true:false + true:SetDefine:TESSELLATION_ON 1 + true:SetDefine:pragma require tessellation tessHW + true:SetDefine:pragma hull HullFunction + true:SetDefine:pragma domain DomainFunction + true:ShowOption: Phong + true:ShowOption: Type + false,disable:RemoveDefine:TESSELLATION_ON 1 + false,disable:RemoveDefine:pragma require tessellation tessHW + false,disable:RemoveDefine:pragma hull HullFunction + false,disable:RemoveDefine:pragma domain DomainFunction + false,disable:HideOption: Phong + false,disable:HideOption: Type + Option: Phong:false,true:false + true:SetDefine:ASE_PHONG_TESSELLATION + false,disable:RemoveDefine:ASE_PHONG_TESSELLATION + true:ShowOption: Strength + false,disable:HideOption: Strength + Field: Strength:Float:0.5:0:1:_TessPhongStrength + Change:SetMaterialProperty:_TessPhongStrength + Change:SetShaderProperty:_TessPhongStrength,_TessPhongStrength( "Phong Tess Strength", Range( 0, 1 ) ) = 0.5 + Inline,disable:SetShaderProperty:_TessPhongStrength,//_TessPhongStrength( "Phong Tess Strength", Range( 0, 1 ) ) = 0.5 + Option: Type:Fixed,Distance Based,Edge Length,Edge Length Cull:Fixed + Fixed:SetDefine:ASE_FIXED_TESSELLATION + Fixed,Distance Based:ShowOption: Tess + Distance Based:SetDefine:ASE_DISTANCE_TESSELLATION + Distance Based:ShowOption: Min + Distance Based:ShowOption: Max + Edge Length:SetDefine:ASE_LENGTH_TESSELLATION + Edge Length,Edge Length Cull:ShowOption: Edge Length + Edge Length Cull:SetDefine:ASE_LENGTH_CULL_TESSELLATION + Edge Length Cull:ShowOption: Max Displacement + disable,Distance Based,Edge Length,Edge Length Cull:RemoveDefine:ASE_FIXED_TESSELLATION + disable,Fixed,Edge Length,Edge Length Cull:RemoveDefine:ASE_DISTANCE_TESSELLATION + disable,Fixed,Distance Based,Edge Length Cull:RemoveDefine:ASE_LENGTH_TESSELLATION + disable,Fixed,Distance Based,Edge Length:RemoveDefine:ASE_LENGTH_CULL_TESSELLATION + disable,Edge Length,Edge Length Cull:HideOption: Tess + disable,Fixed,Edge Length,Edge Length Cull:HideOption: Min + disable,Fixed,Edge Length,Edge Length Cull:HideOption: Max + disable,Fixed,Distance Based:HideOption: Edge Length + disable,Fixed,Distance Based,Edge Length:HideOption: Max Displacement + Field: Tess:Float:16:1:32:_TessValue + Change:SetMaterialProperty:_TessValue + Change:SetShaderProperty:_TessValue,_TessValue( "Max Tessellation", Range( 1, 32 ) ) = 16 + Inline,disable:SetShaderProperty:_TessValue,//_TessValue( "Max Tessellation", Range( 1, 32 ) ) = 16 + Field: Min:Float:10:_TessMin + Change:SetMaterialProperty:_TessMin + Change:SetShaderProperty:_TessMin,_TessMin( "Tess Min Distance", Float ) = 10 + Inline,disable:SetShaderProperty:_TessMin,//_TessMin( "Tess Min Distance", Float ) = 10 + Field: Max:Float:25:_TessMax + Change:SetMaterialProperty:_TessMax + Change:SetShaderProperty:_TessMax,_TessMax( "Tess Max Distance", Float ) = 25 + Inline,disable:SetShaderProperty:_TessMax,//_TessMax( "Tess Max Distance", Float ) = 25 + Field: Edge Length:Float:16:2:50:_TessEdgeLength + Change:SetMaterialProperty:_TessEdgeLength + Change:SetShaderProperty:_TessEdgeLength,_TessEdgeLength ( "Edge length", Range( 2, 50 ) ) = 16 + Inline,disable:SetShaderProperty:_TessEdgeLength,//_TessEdgeLength ( "Edge length", Range( 2, 50 ) ) = 16 + Field: Max Displacement:Float:25:_TessMaxDisp + Change:SetMaterialProperty:_TessMaxDisp + Change:SetShaderProperty:_TessMaxDisp,_TessMaxDisp( "Max Displacement", Float ) = 25 + Inline,disable:SetShaderProperty:_TessMaxDisp,//_TessMaxDisp( "Max Displacement", Float ) = 25 + Option:Fwd Specular Highlights Toggle:false,true:false + true:SetShaderProperty:_SpecularHighlights,[ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0 + false:SetShaderProperty:_SpecularHighlights,//[ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0 + true:SetDefine:pragma shader_feature _SPECULARHIGHLIGHTS_OFF + false:RemoveDefine:pragma shader_feature _SPECULARHIGHLIGHTS_OFF + Option:Fwd Reflections Toggle:false,true:false + true:SetShaderProperty:_GlossyReflections,[ToggleOff] _GlossyReflections("Reflections", Float) = 1.0 + false:SetShaderProperty:_GlossyReflections,//[ToggleOff] _GlossyReflections("Reflections", Float) = 1.0 + true:SetDefine:pragma shader_feature _GLOSSYREFLECTIONS_OFF + false:RemoveDefine:pragma shader_feature _GLOSSYREFLECTIONS_OFF + Option:Disable Batching:False,True,LOD Fading:False + False:SetPropertyOnSubShader:DisableBatching,False + True:SetPropertyOnSubShader:DisableBatching,True + LOD Fading:SetPropertyOnSubShader:DisableBatching,LODFading + Option:Vertex Position,InvertActionOnDeselection:Absolute,Relative:Relative + Absolute:SetDefine:ASE_ABSOLUTE_VERTEX_POS 1 + Absolute:SetPortName:ForwardBase:15,Vertex Position + Relative:SetPortName:ForwardBase:15,Vertex Offset + Absolute:SetPortName:ExtraPrePass:3,Vertex Position + Relative:SetPortName:ExtraPrePass:3,Vertex Offset + Port:ForwardBase:Alpha Clip Threshold + On:SetDefine:_ALPHATEST_ON 1 + Port:ForwardBase:Alpha Clip Threshold Shadow + On:SetDefine:_ALPHATEST_SHADOW_ON 1 + */ + Tags{ "RenderType" = "Opaque" "Queue" = "Geometry+0" "DisableBatching" = "False" } + LOD 0 + + Cull Back + AlphaToMask Off + ZWrite On + ZTest LEqual + ColorMask RGBA + /*ase_stencil*/ + /*ase_all_modules*/ + + CGINCLUDE + #pragma target 3.0 + + float4 FixedTess( float tessValue ) + { + return tessValue; + } + + float CalcDistanceTessFactor (float4 vertex, float minDist, float maxDist, float tess, float4x4 o2w, float3 cameraPos ) + { + float3 wpos = mul(o2w,vertex).xyz; + float dist = distance (wpos, cameraPos); + float f = clamp(1.0 - (dist - minDist) / (maxDist - minDist), 0.01, 1.0) * tess; + return f; + } + + float4 CalcTriEdgeTessFactors (float3 triVertexFactors) + { + float4 tess; + tess.x = 0.5 * (triVertexFactors.y + triVertexFactors.z); + tess.y = 0.5 * (triVertexFactors.x + triVertexFactors.z); + tess.z = 0.5 * (triVertexFactors.x + triVertexFactors.y); + tess.w = (triVertexFactors.x + triVertexFactors.y + triVertexFactors.z) / 3.0f; + return tess; + } + + float CalcEdgeTessFactor (float3 wpos0, float3 wpos1, float edgeLen, float3 cameraPos, float4 scParams ) + { + float dist = distance (0.5 * (wpos0+wpos1), cameraPos); + float len = distance(wpos0, wpos1); + float f = max(len * scParams.y / (edgeLen * dist), 1.0); + return f; + } + + float DistanceFromPlane (float3 pos, float4 plane) + { + float d = dot (float4(pos,1.0f), plane); + return d; + } + + bool WorldViewFrustumCull (float3 wpos0, float3 wpos1, float3 wpos2, float cullEps, float4 planes[6] ) + { + float4 planeTest; + planeTest.x = (( DistanceFromPlane(wpos0, planes[0]) > -cullEps) ? 1.0f : 0.0f ) + + (( DistanceFromPlane(wpos1, planes[0]) > -cullEps) ? 1.0f : 0.0f ) + + (( DistanceFromPlane(wpos2, planes[0]) > -cullEps) ? 1.0f : 0.0f ); + planeTest.y = (( DistanceFromPlane(wpos0, planes[1]) > -cullEps) ? 1.0f : 0.0f ) + + (( DistanceFromPlane(wpos1, planes[1]) > -cullEps) ? 1.0f : 0.0f ) + + (( DistanceFromPlane(wpos2, planes[1]) > -cullEps) ? 1.0f : 0.0f ); + planeTest.z = (( DistanceFromPlane(wpos0, planes[2]) > -cullEps) ? 1.0f : 0.0f ) + + (( DistanceFromPlane(wpos1, planes[2]) > -cullEps) ? 1.0f : 0.0f ) + + (( DistanceFromPlane(wpos2, planes[2]) > -cullEps) ? 1.0f : 0.0f ); + planeTest.w = (( DistanceFromPlane(wpos0, planes[3]) > -cullEps) ? 1.0f : 0.0f ) + + (( DistanceFromPlane(wpos1, planes[3]) > -cullEps) ? 1.0f : 0.0f ) + + (( DistanceFromPlane(wpos2, planes[3]) > -cullEps) ? 1.0f : 0.0f ); + return !all (planeTest); + } + + float4 DistanceBasedTess( float4 v0, float4 v1, float4 v2, float tess, float minDist, float maxDist, float4x4 o2w, float3 cameraPos ) + { + float3 f; + f.x = CalcDistanceTessFactor (v0,minDist,maxDist,tess,o2w,cameraPos); + f.y = CalcDistanceTessFactor (v1,minDist,maxDist,tess,o2w,cameraPos); + f.z = CalcDistanceTessFactor (v2,minDist,maxDist,tess,o2w,cameraPos); + + return CalcTriEdgeTessFactors (f); + } + + float4 EdgeLengthBasedTess( float4 v0, float4 v1, float4 v2, float edgeLength, float4x4 o2w, float3 cameraPos, float4 scParams ) + { + float3 pos0 = mul(o2w,v0).xyz; + float3 pos1 = mul(o2w,v1).xyz; + float3 pos2 = mul(o2w,v2).xyz; + float4 tess; + tess.x = CalcEdgeTessFactor (pos1, pos2, edgeLength, cameraPos, scParams); + tess.y = CalcEdgeTessFactor (pos2, pos0, edgeLength, cameraPos, scParams); + tess.z = CalcEdgeTessFactor (pos0, pos1, edgeLength, cameraPos, scParams); + tess.w = (tess.x + tess.y + tess.z) / 3.0f; + return tess; + } + + float4 EdgeLengthBasedTessCull( float4 v0, float4 v1, float4 v2, float edgeLength, float maxDisplacement, float4x4 o2w, float3 cameraPos, float4 scParams, float4 planes[6] ) + { + float3 pos0 = mul(o2w,v0).xyz; + float3 pos1 = mul(o2w,v1).xyz; + float3 pos2 = mul(o2w,v2).xyz; + float4 tess; + + if (WorldViewFrustumCull(pos0, pos1, pos2, maxDisplacement, planes)) + { + tess = 0.0f; + } + else + { + tess.x = CalcEdgeTessFactor (pos1, pos2, edgeLength, cameraPos, scParams); + tess.y = CalcEdgeTessFactor (pos2, pos0, edgeLength, cameraPos, scParams); + tess.z = CalcEdgeTessFactor (pos0, pos1, edgeLength, cameraPos, scParams); + tess.w = (tess.x + tess.y + tess.z) / 3.0f; + } + return tess; + } + ENDCG + + /*ase_pass*/ + Pass + { + Name "ExtraPrePass" + Tags { "LightMode" = "ForwardBase" } + + Blend One Zero + Cull Back + ZWrite On + ZTest LEqual + Offset 0,0 + ColorMask RGBA + /*ase_stencil*/ + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_fwdbase + #ifndef UNITY_PASS_FORWARDBASE + #define UNITY_PASS_FORWARDBASE + #endif + #include "HLSLSupport.cginc" + #ifndef UNITY_INSTANCED_LOD_FADE + #define UNITY_INSTANCED_LOD_FADE + #endif + #ifndef UNITY_INSTANCED_SH + #define UNITY_INSTANCED_SH + #endif + #ifndef UNITY_INSTANCED_LIGHTMAPSTS + #define UNITY_INSTANCED_LIGHTMAPSTS + #endif + #include "UnityShaderVariables.cginc" + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + #include "AutoLight.cginc" + + /*ase_pragma*/ + struct appdata { + float4 vertex : POSITION; + float4 tangent : TANGENT; + float3 normal : NORMAL; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + /*ase_vdata:p=p;t=t;n=n;uv1=tc1.xyzw;uv2=tc2.xyzw*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct v2f { + #if UNITY_VERSION >= 201810 + UNITY_POSITION(pos); + #else + float4 pos : SV_POSITION; + #endif + #if defined(UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS) && UNITY_VERSION >= 201810 && defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + UNITY_LIGHTING_COORDS(2,3) + #elif defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + #if UNITY_VERSION >= 201710 + UNITY_SHADOW_COORDS(2) + #else + SHADOW_COORDS(2) + #endif + #endif + #ifdef ASE_FOG + UNITY_FOG_COORDS(4) + #endif + float4 tSpace0 : TEXCOORD5; + float4 tSpace1 : TEXCOORD6; + float4 tSpace2 : TEXCOORD7; + /*ase_interp(8,):sp=sp.xyzw;sc=tc2;wn.xyz=tc5.xyz;wt.xyz=tc6.xyz;wbt.xyz=tc7.xyz;wp.x=tc5.w;wp.y=tc6.w;wp.z=tc7.w*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + }; + + #ifdef TESSELLATION_ON + float _TessPhongStrength; + float _TessValue; + float _TessMin; + float _TessMax; + float _TessEdgeLength; + float _TessMaxDisp; + #endif + /*ase_globals*/ + + /*ase_funcs*/ + + v2f VertexFunction (appdata v /*ase_vert_input*/ ) { + UNITY_SETUP_INSTANCE_ID(v); + v2f o; + UNITY_INITIALIZE_OUTPUT(v2f,o); + UNITY_TRANSFER_INSTANCE_ID(v,o); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + + /*ase_vert_code:v=appdata;o=v2f*/ + #ifdef ASE_ABSOLUTE_VERTEX_POS + float3 defaultVertexValue = v.vertex.xyz; + #else + float3 defaultVertexValue = float3(0, 0, 0); + #endif + float3 vertexValue = /*ase_vert_out:Vertex Offset;Float3;3;-1;_VertexP*/defaultVertexValue/*end*/; + #ifdef ASE_ABSOLUTE_VERTEX_POS + v.vertex.xyz = vertexValue; + #else + v.vertex.xyz += vertexValue; + #endif + v.vertex.w = 1; + v.normal = /*ase_vert_out:Vertex Normal;Float3;4;-1;_VertexNormalP*/v.normal/*end*/; + v.tangent = /*ase_vert_out:Vertex Tangent;Float4;5;-1;_VertexTangentP*/v.tangent/*end*/; + + o.pos = UnityObjectToClipPos(v.vertex); + float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; + fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); + fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz); + fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w; + fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign; + o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); + o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); + o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); + + #if UNITY_VERSION >= 201810 && defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + UNITY_TRANSFER_LIGHTING(o, v.texcoord1.xy); + #elif defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + #if UNITY_VERSION >= 201710 + UNITY_TRANSFER_SHADOW(o, v.texcoord1.xy); + #else + TRANSFER_SHADOW(o); + #endif + #endif + + #ifdef ASE_FOG + UNITY_TRANSFER_FOG(o,o.pos); + #endif + return o; + } + + #if defined(TESSELLATION_ON) + struct VertexControl + { + float4 vertex : INTERNALTESSPOS; + float4 tangent : TANGENT; + float3 normal : NORMAL; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + /*ase_vcontrol*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct TessellationFactors + { + float edge[3] : SV_TessFactor; + float inside : SV_InsideTessFactor; + }; + + VertexControl vert ( appdata v ) + { + VertexControl o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_TRANSFER_INSTANCE_ID(v, o); + o.vertex = v.vertex; + o.tangent = v.tangent; + o.normal = v.normal; + o.texcoord1 = v.texcoord1; + o.texcoord2 = v.texcoord2; + /*ase_control_code:v=appdata;o=VertexControl*/ + return o; + } + + TessellationFactors TessellationFunction (InputPatch v) + { + TessellationFactors o; + float4 tf = 1; + float tessValue = /*ase_inline_begin*/_TessValue/*ase_inline_end*/; float tessMin = /*ase_inline_begin*/_TessMin/*ase_inline_end*/; float tessMax = /*ase_inline_begin*/_TessMax/*ase_inline_end*/; + float edgeLength = /*ase_inline_begin*/_TessEdgeLength/*ase_inline_end*/; float tessMaxDisp = /*ase_inline_begin*/_TessMaxDisp/*ase_inline_end*/; + #if defined(ASE_FIXED_TESSELLATION) + tf = FixedTess( tessValue ); + #elif defined(ASE_DISTANCE_TESSELLATION) + tf = DistanceBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, tessValue, tessMin, tessMax, UNITY_MATRIX_M, _WorldSpaceCameraPos ); + #elif defined(ASE_LENGTH_TESSELLATION) + tf = EdgeLengthBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, UNITY_MATRIX_M, _WorldSpaceCameraPos, _ScreenParams ); + #elif defined(ASE_LENGTH_CULL_TESSELLATION) + tf = EdgeLengthBasedTessCull(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, tessMaxDisp, UNITY_MATRIX_M, _WorldSpaceCameraPos, _ScreenParams, unity_CameraWorldClipPlanes ); + #endif + o.edge[0] = tf.x; o.edge[1] = tf.y; o.edge[2] = tf.z; o.inside = tf.w; + return o; + } + + [domain("tri")] + [partitioning("fractional_odd")] + [outputtopology("triangle_cw")] + [patchconstantfunc("TessellationFunction")] + [outputcontrolpoints(3)] + VertexControl HullFunction(InputPatch patch, uint id : SV_OutputControlPointID) + { + return patch[id]; + } + + [domain("tri")] + v2f DomainFunction(TessellationFactors factors, OutputPatch patch, float3 bary : SV_DomainLocation) + { + appdata o = (appdata) 0; + o.vertex = patch[0].vertex * bary.x + patch[1].vertex * bary.y + patch[2].vertex * bary.z; + o.tangent = patch[0].tangent * bary.x + patch[1].tangent * bary.y + patch[2].tangent * bary.z; + o.normal = patch[0].normal * bary.x + patch[1].normal * bary.y + patch[2].normal * bary.z; + o.texcoord1 = patch[0].texcoord1 * bary.x + patch[1].texcoord1 * bary.y + patch[2].texcoord1 * bary.z; + o.texcoord2 = patch[0].texcoord2 * bary.x + patch[1].texcoord2 * bary.y + patch[2].texcoord2 * bary.z; + /*ase_domain_code:patch=VertexControl;o=appdata;bary=SV_DomainLocation*/ + #if defined(ASE_PHONG_TESSELLATION) + float3 pp[3]; + for (int i = 0; i < 3; ++i) + pp[i] = o.vertex.xyz - patch[i].normal * (dot(o.vertex.xyz, patch[i].normal) - dot(patch[i].vertex.xyz, patch[i].normal)); + float phongStrength = /*ase_inline_begin*/_TessPhongStrength/*ase_inline_end*/; + o.vertex.xyz = phongStrength * (pp[0]*bary.x + pp[1]*bary.y + pp[2]*bary.z) + (1.0f-phongStrength) * o.vertex.xyz; + #endif + UNITY_TRANSFER_INSTANCE_ID(patch[0], o); + return VertexFunction(o); + } + #else + v2f vert ( appdata v ) + { + return VertexFunction( v ); + } + #endif + + fixed4 frag (v2f IN /*ase_frag_input*/ + #ifdef _DEPTHOFFSET_ON + , out float outputDepth : SV_Depth + #endif + ) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(IN); + + #ifdef LOD_FADE_CROSSFADE + UNITY_APPLY_DITHER_CROSSFADE(IN.pos.xy); + #endif + + #if defined(_SPECULAR_SETUP) + SurfaceOutputStandardSpecular o = (SurfaceOutputStandardSpecular)0; + #else + SurfaceOutputStandard o = (SurfaceOutputStandard)0; + #endif + /*ase_local_var:wt*/float3 WorldTangent = float3(IN.tSpace0.x,IN.tSpace1.x,IN.tSpace2.x); + /*ase_local_var:wbt*/float3 WorldBiTangent = float3(IN.tSpace0.y,IN.tSpace1.y,IN.tSpace2.y); + /*ase_local_var:wn*/float3 WorldNormal = float3(IN.tSpace0.z,IN.tSpace1.z,IN.tSpace2.z); + /*ase_local_var:wp*/float3 worldPos = float3(IN.tSpace0.w,IN.tSpace1.w,IN.tSpace2.w); + /*ase_local_var:wvd*/float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos)); + #if defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + UNITY_LIGHT_ATTENUATION(atten, IN, worldPos) + #else + /*ase_local_var:sc*/half atten = 1; + #endif + + /*ase_frag_code:IN=v2f*/ + float3 Color = /*ase_frag_out:Color;Float3;0;-1;_ColorP*/fixed3( 0, 0, 0 )/*end*/; + float Alpha = /*ase_frag_out:Alpha;Float;1;-1;_AlphaP*/1/*end*/; + float AlphaClipThreshold = /*ase_frag_out:Alpha Clip Threshold;Float;2;-1;_AlphaClipP*/0.5/*end*/; + + float4 c = float4( Color, Alpha ); + + #ifdef _ALPHATEST_ON + clip( Alpha - AlphaClipThreshold ); + #endif + + #ifdef _DEPTHOFFSET_ON + outputDepth = IN.pos.z; + #endif + + #ifdef ASE_FOG + UNITY_APPLY_FOG(IN.fogCoord, c); + #endif + return c; + } + ENDCG + } + + /*ase_pass*/ + Pass + { + /*ase_main_pass*/ + Name "ForwardBase" + Tags { "LightMode" = "ForwardBase" } + + Blend One Zero + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_fwdbase + #ifndef UNITY_PASS_FORWARDBASE + #define UNITY_PASS_FORWARDBASE + #endif + #include "HLSLSupport.cginc" + #ifndef UNITY_INSTANCED_LOD_FADE + #define UNITY_INSTANCED_LOD_FADE + #endif + #ifndef UNITY_INSTANCED_SH + #define UNITY_INSTANCED_SH + #endif + #ifndef UNITY_INSTANCED_LIGHTMAPSTS + #define UNITY_INSTANCED_LIGHTMAPSTS + #endif + #include "UnityShaderVariables.cginc" + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + #include "AutoLight.cginc" + + /*ase_pragma*/ + struct appdata { + float4 vertex : POSITION; + float4 tangent : TANGENT; + float3 normal : NORMAL; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + /*ase_vdata:p=p;t=t;n=n;uv1=tc1.xyzw;uv2=tc2.xyzw*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct v2f { + #if UNITY_VERSION >= 201810 + UNITY_POSITION(pos); + #else + float4 pos : SV_POSITION; + #endif + #if defined(LIGHTMAP_ON) || (!defined(LIGHTMAP_ON) && SHADER_TARGET >= 30) + float4 lmap : TEXCOORD0; + #endif + #if !defined(LIGHTMAP_ON) && UNITY_SHOULD_SAMPLE_SH + half3 sh : TEXCOORD1; + #endif + #if defined(UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS) && UNITY_VERSION >= 201810 && defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + UNITY_LIGHTING_COORDS(2,3) + #elif defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + #if UNITY_VERSION >= 201710 + UNITY_SHADOW_COORDS(2) + #else + SHADOW_COORDS(2) + #endif + #endif + #ifdef ASE_FOG + UNITY_FOG_COORDS(4) + #endif + float4 tSpace0 : TEXCOORD5; + float4 tSpace1 : TEXCOORD6; + float4 tSpace2 : TEXCOORD7; + #if defined(ASE_NEEDS_FRAG_SCREEN_POSITION) + float4 screenPos : TEXCOORD8; + #endif + /*ase_interp(9,):sp=sp.xyzw;sc=tc2;wn.xyz=tc5.xyz;wt.xyz=tc6.xyz;wbt.xyz=tc7.xyz;wp.x=tc5.w;wp.y=tc6.w;wp.z=tc7.w;spu=tc8*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + }; + + #ifdef _TRANSMISSION_ASE + float _TransmissionShadow; + #endif + #ifdef _TRANSLUCENCY_ASE + float _TransStrength; + float _TransNormal; + float _TransScattering; + float _TransDirect; + float _TransAmbient; + float _TransShadow; + #endif + #ifdef TESSELLATION_ON + float _TessPhongStrength; + float _TessValue; + float _TessMin; + float _TessMax; + float _TessEdgeLength; + float _TessMaxDisp; + #endif + /*ase_globals*/ + + /*ase_funcs*/ + + v2f VertexFunction (appdata v /*ase_vert_input*/ ) { + UNITY_SETUP_INSTANCE_ID(v); + v2f o; + UNITY_INITIALIZE_OUTPUT(v2f,o); + UNITY_TRANSFER_INSTANCE_ID(v,o); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + + /*ase_vert_code:v=appdata;o=v2f*/ + #ifdef ASE_ABSOLUTE_VERTEX_POS + float3 defaultVertexValue = v.vertex.xyz; + #else + float3 defaultVertexValue = float3(0, 0, 0); + #endif + float3 vertexValue = /*ase_vert_out:Vertex Offset;Float3;15;-1;_Vertex*/defaultVertexValue/*end*/; + #ifdef ASE_ABSOLUTE_VERTEX_POS + v.vertex.xyz = vertexValue; + #else + v.vertex.xyz += vertexValue; + #endif + v.vertex.w = 1; + v.normal = /*ase_vert_out:Vertex Normal;Float3;16;-1;_VertexNormal*/v.normal/*end*/; + v.tangent = /*ase_vert_out:Vertex Tangent;Float4;17;-1;_VertexTangent*/v.tangent/*end*/; + + o.pos = UnityObjectToClipPos(v.vertex); + float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; + fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); + fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz); + fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w; + fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign; + o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); + o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); + o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); + + #ifdef DYNAMICLIGHTMAP_ON + o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; + #endif + #ifdef LIGHTMAP_ON + o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw; + #endif + + #ifndef LIGHTMAP_ON + #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL + o.sh = 0; + #ifdef VERTEXLIGHT_ON + o.sh += Shade4PointLights ( + unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0, + unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb, + unity_4LightAtten0, worldPos, worldNormal); + #endif + o.sh = ShadeSHPerVertex (worldNormal, o.sh); + #endif + #endif + + #if UNITY_VERSION >= 201810 && defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + UNITY_TRANSFER_LIGHTING(o, v.texcoord1.xy); + #elif defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + #if UNITY_VERSION >= 201710 + UNITY_TRANSFER_SHADOW(o, v.texcoord1.xy); + #else + TRANSFER_SHADOW(o); + #endif + #endif + + #ifdef ASE_FOG + UNITY_TRANSFER_FOG(o,o.pos); + #endif + #if defined(ASE_NEEDS_FRAG_SCREEN_POSITION) + o.screenPos = ComputeScreenPos(o.pos); + #endif + return o; + } + + #if defined(TESSELLATION_ON) + struct VertexControl + { + float4 vertex : INTERNALTESSPOS; + float4 tangent : TANGENT; + float3 normal : NORMAL; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + /*ase_vcontrol*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct TessellationFactors + { + float edge[3] : SV_TessFactor; + float inside : SV_InsideTessFactor; + }; + + VertexControl vert ( appdata v ) + { + VertexControl o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_TRANSFER_INSTANCE_ID(v, o); + o.vertex = v.vertex; + o.tangent = v.tangent; + o.normal = v.normal; + o.texcoord1 = v.texcoord1; + o.texcoord2 = v.texcoord2; + /*ase_control_code:v=appdata;o=VertexControl*/ + return o; + } + + TessellationFactors TessellationFunction (InputPatch v) + { + TessellationFactors o; + float4 tf = 1; + float tessValue = /*ase_inline_begin*/_TessValue/*ase_inline_end*/; float tessMin = /*ase_inline_begin*/_TessMin/*ase_inline_end*/; float tessMax = /*ase_inline_begin*/_TessMax/*ase_inline_end*/; + float edgeLength = /*ase_inline_begin*/_TessEdgeLength/*ase_inline_end*/; float tessMaxDisp = /*ase_inline_begin*/_TessMaxDisp/*ase_inline_end*/; + #if defined(ASE_FIXED_TESSELLATION) + tf = FixedTess( tessValue ); + #elif defined(ASE_DISTANCE_TESSELLATION) + tf = DistanceBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, tessValue, tessMin, tessMax, UNITY_MATRIX_M, _WorldSpaceCameraPos ); + #elif defined(ASE_LENGTH_TESSELLATION) + tf = EdgeLengthBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, UNITY_MATRIX_M, _WorldSpaceCameraPos, _ScreenParams ); + #elif defined(ASE_LENGTH_CULL_TESSELLATION) + tf = EdgeLengthBasedTessCull(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, tessMaxDisp, UNITY_MATRIX_M, _WorldSpaceCameraPos, _ScreenParams, unity_CameraWorldClipPlanes ); + #endif + o.edge[0] = tf.x; o.edge[1] = tf.y; o.edge[2] = tf.z; o.inside = tf.w; + return o; + } + + [domain("tri")] + [partitioning("fractional_odd")] + [outputtopology("triangle_cw")] + [patchconstantfunc("TessellationFunction")] + [outputcontrolpoints(3)] + VertexControl HullFunction(InputPatch patch, uint id : SV_OutputControlPointID) + { + return patch[id]; + } + + [domain("tri")] + v2f DomainFunction(TessellationFactors factors, OutputPatch patch, float3 bary : SV_DomainLocation) + { + appdata o = (appdata) 0; + o.vertex = patch[0].vertex * bary.x + patch[1].vertex * bary.y + patch[2].vertex * bary.z; + o.tangent = patch[0].tangent * bary.x + patch[1].tangent * bary.y + patch[2].tangent * bary.z; + o.normal = patch[0].normal * bary.x + patch[1].normal * bary.y + patch[2].normal * bary.z; + o.texcoord1 = patch[0].texcoord1 * bary.x + patch[1].texcoord1 * bary.y + patch[2].texcoord1 * bary.z; + o.texcoord2 = patch[0].texcoord2 * bary.x + patch[1].texcoord2 * bary.y + patch[2].texcoord2 * bary.z; + /*ase_domain_code:patch=VertexControl;o=appdata;bary=SV_DomainLocation*/ + #if defined(ASE_PHONG_TESSELLATION) + float3 pp[3]; + for (int i = 0; i < 3; ++i) + pp[i] = o.vertex.xyz - patch[i].normal * (dot(o.vertex.xyz, patch[i].normal) - dot(patch[i].vertex.xyz, patch[i].normal)); + float phongStrength = /*ase_inline_begin*/_TessPhongStrength/*ase_inline_end*/; + o.vertex.xyz = phongStrength * (pp[0]*bary.x + pp[1]*bary.y + pp[2]*bary.z) + (1.0f-phongStrength) * o.vertex.xyz; + #endif + UNITY_TRANSFER_INSTANCE_ID(patch[0], o); + return VertexFunction(o); + } + #else + v2f vert ( appdata v ) + { + return VertexFunction( v ); + } + #endif + + fixed4 frag (v2f IN /*ase_frag_input*/ + #ifdef _DEPTHOFFSET_ON + , out float outputDepth : SV_Depth + #endif + ) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(IN); + + #ifdef LOD_FADE_CROSSFADE + UNITY_APPLY_DITHER_CROSSFADE(IN.pos.xy); + #endif + + #if defined(_SPECULAR_SETUP) + SurfaceOutputStandardSpecular o = (SurfaceOutputStandardSpecular)0; + #else + SurfaceOutputStandard o = (SurfaceOutputStandard)0; + #endif + /*ase_local_var:wt*/float3 WorldTangent = float3(IN.tSpace0.x,IN.tSpace1.x,IN.tSpace2.x); + /*ase_local_var:wbt*/float3 WorldBiTangent = float3(IN.tSpace0.y,IN.tSpace1.y,IN.tSpace2.y); + /*ase_local_var:wn*/float3 WorldNormal = float3(IN.tSpace0.z,IN.tSpace1.z,IN.tSpace2.z); + /*ase_local_var:wp*/float3 worldPos = float3(IN.tSpace0.w,IN.tSpace1.w,IN.tSpace2.w); + /*ase_local_var:wvd*/float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos)); + #if defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + UNITY_LIGHT_ATTENUATION(atten, IN, worldPos) + #else + /*ase_local_var:sc*/half atten = 1; + #endif + #if defined(ASE_NEEDS_FRAG_SCREEN_POSITION) + /*ase_local_var:spu*/float4 ScreenPos = IN.screenPos; + #endif + + /*ase_frag_code:IN=v2f*/ + o.Albedo = /*ase_frag_out:Albedo;Float3;0;-1;_Albedo*/fixed3( 0.5, 0.5, 0.5 )/*end*/; + o.Normal = /*ase_frag_out:Normal;Float3;1;-1;_Normal*/fixed3( 0, 0, 1 )/*end*/; + o.Emission = /*ase_frag_out:Emission;Float3;2;-1;_Emission*/half3( 0, 0, 0 )/*end*/; + #if defined(_SPECULAR_SETUP) + o.Specular = /*ase_frag_out:Specular;Float3;3;-1;_Specular*/fixed3( 0, 0, 0 )/*end*/; + #else + o.Metallic = /*ase_frag_out:Metallic;Float;4;-1;_Metallic*/0/*end*/; + #endif + o.Smoothness = /*ase_frag_out:Smoothness;Float;5;-1;_Smoothness*/0/*end*/; + o.Occlusion = /*ase_frag_out:Occlusion;Float;6;-1;_Occlusion*/1/*end*/; + o.Alpha = /*ase_frag_out:Alpha;Float;7;-1;_Alpha*/1/*end*/; + float AlphaClipThreshold = /*ase_frag_out:Alpha Clip Threshold;Float;8;-1;_AlphaClip*/0.5/*end*/; + float AlphaClipThresholdShadow = /*ase_frag_out:Alpha Clip Threshold Shadow;Float;9;-1;_AlphaClipShadow*/0.5/*end*/; + float3 BakedGI = /*ase_frag_out:Baked GI;Float3;10;-1;_BakedGI*/0/*end*/; + float3 RefractionColor = /*ase_frag_out:Refraction Color;Float3;11;-1;_RefractionColor*/1/*end*/; + float RefractionIndex = /*ase_frag_out:Refraction Index;Float;12;-1;_RefractionIndex*/1/*end*/; + float3 Transmission = /*ase_frag_out:Transmission;Float3;13;-1;_Transmission*/1/*end*/; + float3 Translucency = /*ase_frag_out:Translucency;Float3;14;-1;_Translucency*/1/*end*/; + + #ifdef _ALPHATEST_ON + clip( o.Alpha - AlphaClipThreshold ); + #endif + + #ifdef _DEPTHOFFSET_ON + outputDepth = IN.pos.z; + #endif + + #ifndef USING_DIRECTIONAL_LIGHT + fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos)); + #else + fixed3 lightDir = _WorldSpaceLightPos0.xyz; + #endif + + fixed4 c = 0; + float3 worldN; + worldN.x = dot(IN.tSpace0.xyz, o.Normal); + worldN.y = dot(IN.tSpace1.xyz, o.Normal); + worldN.z = dot(IN.tSpace2.xyz, o.Normal); + worldN = normalize(worldN); + o.Normal = worldN; + + UnityGI gi; + UNITY_INITIALIZE_OUTPUT(UnityGI, gi); + gi.indirect.diffuse = 0; + gi.indirect.specular = 0; + gi.light.color = _LightColor0.rgb; + gi.light.dir = lightDir; + + UnityGIInput giInput; + UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput); + giInput.light = gi.light; + giInput.worldPos = worldPos; + giInput.worldViewDir = worldViewDir; + giInput.atten = atten; + #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON) + giInput.lightmapUV = IN.lmap; + #else + giInput.lightmapUV = 0.0; + #endif + #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL + giInput.ambient = IN.sh; + #else + giInput.ambient.rgb = 0.0; + #endif + giInput.probeHDR[0] = unity_SpecCube0_HDR; + giInput.probeHDR[1] = unity_SpecCube1_HDR; + #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION) + giInput.boxMin[0] = unity_SpecCube0_BoxMin; + #endif + #ifdef UNITY_SPECCUBE_BOX_PROJECTION + giInput.boxMax[0] = unity_SpecCube0_BoxMax; + giInput.probePosition[0] = unity_SpecCube0_ProbePosition; + giInput.boxMax[1] = unity_SpecCube1_BoxMax; + giInput.boxMin[1] = unity_SpecCube1_BoxMin; + giInput.probePosition[1] = unity_SpecCube1_ProbePosition; + #endif + + #if defined(_SPECULAR_SETUP) + LightingStandardSpecular_GI(o, giInput, gi); + #else + LightingStandard_GI( o, giInput, gi ); + #endif + + #ifdef ASE_BAKEDGI + gi.indirect.diffuse = BakedGI; + #endif + + #if UNITY_SHOULD_SAMPLE_SH && !defined(LIGHTMAP_ON) && defined(ASE_NO_AMBIENT) + gi.indirect.diffuse = 0; + #endif + + #if defined(_SPECULAR_SETUP) + c += LightingStandardSpecular (o, worldViewDir, gi); + #else + c += LightingStandard( o, worldViewDir, gi ); + #endif + + #ifdef _TRANSMISSION_ASE + { + float shadow = /*ase_inline_begin*/_TransmissionShadow/*ase_inline_end*/; + #ifdef DIRECTIONAL + float3 lightAtten = lerp( _LightColor0.rgb, gi.light.color, shadow ); + #else + float3 lightAtten = gi.light.color; + #endif + half3 transmission = max(0 , -dot(o.Normal, gi.light.dir)) * lightAtten * Transmission; + c.rgb += o.Albedo * transmission; + } + #endif + + #ifdef _TRANSLUCENCY_ASE + { + float shadow = /*ase_inline_begin*/_TransShadow/*ase_inline_end*/; + float normal = /*ase_inline_begin*/_TransNormal/*ase_inline_end*/; + float scattering = /*ase_inline_begin*/_TransScattering/*ase_inline_end*/; + float direct = /*ase_inline_begin*/_TransDirect/*ase_inline_end*/; + float ambient = /*ase_inline_begin*/_TransAmbient/*ase_inline_end*/; + float strength = /*ase_inline_begin*/_TransStrength/*ase_inline_end*/; + + #ifdef DIRECTIONAL + float3 lightAtten = lerp( _LightColor0.rgb, gi.light.color, shadow ); + #else + float3 lightAtten = gi.light.color; + #endif + half3 lightDir = gi.light.dir + o.Normal * normal; + half transVdotL = pow( saturate( dot( worldViewDir, -lightDir ) ), scattering ); + half3 translucency = lightAtten * (transVdotL * direct + gi.indirect.diffuse * ambient) * Translucency; + c.rgb += o.Albedo * translucency * strength; + } + #endif + + //#ifdef _REFRACTION_ASE + // float4 projScreenPos = ScreenPos / ScreenPos.w; + // float3 refractionOffset = ( RefractionIndex - 1.0 ) * mul( UNITY_MATRIX_V, WorldNormal ).xyz * ( 1.0 - dot( WorldNormal, WorldViewDirection ) ); + // projScreenPos.xy += refractionOffset.xy; + // float3 refraction = UNITY_SAMPLE_SCREENSPACE_TEXTURE( _GrabTexture, projScreenPos ) * RefractionColor; + // color.rgb = lerp( refraction, color.rgb, color.a ); + // color.a = 1; + //#endif + + c.rgb += o.Emission; + + #ifdef ASE_FOG + UNITY_APPLY_FOG(IN.fogCoord, c); + #endif + return c; + } + ENDCG + } + + /*ase_pass*/ + Pass + { + /*ase_hide_pass*/ + Name "ForwardAdd" + Tags { "LightMode"="ForwardAdd" } + ZWrite Off + Blend One One + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma skip_variants INSTANCING_ON + #pragma multi_compile_fwdadd_fullshadows + #ifndef UNITY_PASS_FORWARDADD + #define UNITY_PASS_FORWARDADD + #endif + #include "HLSLSupport.cginc" + #if !defined( UNITY_INSTANCED_LOD_FADE ) + #define UNITY_INSTANCED_LOD_FADE + #endif + #if !defined( UNITY_INSTANCED_SH ) + #define UNITY_INSTANCED_SH + #endif + #if !defined( UNITY_INSTANCED_LIGHTMAPSTS ) + #define UNITY_INSTANCED_LIGHTMAPSTS + #endif + #include "UnityShaderVariables.cginc" + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + #include "AutoLight.cginc" + + /*ase_pragma*/ + struct appdata { + float4 vertex : POSITION; + float4 tangent : TANGENT; + float3 normal : NORMAL; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + /*ase_vdata:p=p;t=t;n=n;uv1=tc1.xyzw;uv2=tc2.xyzw*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + struct v2f { + #if UNITY_VERSION >= 201810 + UNITY_POSITION(pos); + #else + float4 pos : SV_POSITION; + #endif + #if UNITY_VERSION >= 201810 && defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + UNITY_LIGHTING_COORDS(1,2) + #elif defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + #if UNITY_VERSION >= 201710 + UNITY_SHADOW_COORDS(1) + #else + SHADOW_COORDS(1) + #endif + #endif + #ifdef ASE_FOG + UNITY_FOG_COORDS(3) + #endif + float4 tSpace0 : TEXCOORD5; + float4 tSpace1 : TEXCOORD6; + float4 tSpace2 : TEXCOORD7; + #if defined(ASE_NEEDS_FRAG_SCREEN_POSITION) + float4 screenPos : TEXCOORD8; + #endif + /*ase_interp(9,):sp=sp.xyzw;sc=tc1;wn.xyz=tc5.xyz;wt.xyz=tc6.xyz;wbt.xyz=tc7.xyz;wp.x=tc5.w;wp.y=tc6.w;wp.z=tc7.w;spu=tc8*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + }; + + #ifdef _TRANSMISSION_ASE + float _TransmissionShadow; + #endif + #ifdef _TRANSLUCENCY_ASE + float _TransStrength; + float _TransNormal; + float _TransScattering; + float _TransDirect; + float _TransAmbient; + float _TransShadow; + #endif + #ifdef TESSELLATION_ON + float _TessPhongStrength; + float _TessValue; + float _TessMin; + float _TessMax; + float _TessEdgeLength; + float _TessMaxDisp; + #endif + /*ase_globals*/ + + /*ase_funcs*/ + + v2f VertexFunction (appdata v /*ase_vert_input*/ ) { + UNITY_SETUP_INSTANCE_ID(v); + v2f o; + UNITY_INITIALIZE_OUTPUT(v2f,o); + UNITY_TRANSFER_INSTANCE_ID(v,o); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + + /*ase_vert_code:v=appdata;o=v2f*/ + #ifdef ASE_ABSOLUTE_VERTEX_POS + float3 defaultVertexValue = v.vertex.xyz; + #else + float3 defaultVertexValue = float3(0, 0, 0); + #endif + float3 vertexValue = /*ase_vert_out:Vertex Offset;Float3;11;-1;_Vertex*/defaultVertexValue/*end*/; + #ifdef ASE_ABSOLUTE_VERTEX_POS + v.vertex.xyz = vertexValue; + #else + v.vertex.xyz += vertexValue; + #endif + v.vertex.w = 1; + v.normal = /*ase_vert_out:Vertex Normal;Float3;12;-1;_VertexNormal*/v.normal/*end*/; + v.tangent = /*ase_vert_out:Vertex Tangent;Float4;13;-1;_VertexTangent*/v.tangent/*end*/; + + o.pos = UnityObjectToClipPos(v.vertex); + float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; + fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); + fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz); + fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w; + fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign; + o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); + o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); + o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); + + #if UNITY_VERSION >= 201810 && defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + UNITY_TRANSFER_LIGHTING(o, v.texcoord1.xy); + #elif defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + #if UNITY_VERSION >= 201710 + UNITY_TRANSFER_SHADOW(o, v.texcoord1.xy); + #else + TRANSFER_SHADOW(o); + #endif + #endif + + #ifdef ASE_FOG + UNITY_TRANSFER_FOG(o,o.pos); + #endif + #if defined(ASE_NEEDS_FRAG_SCREEN_POSITION) + o.screenPos = ComputeScreenPos(o.pos); + #endif + return o; + } + + #if defined(TESSELLATION_ON) + struct VertexControl + { + float4 vertex : INTERNALTESSPOS; + float4 tangent : TANGENT; + float3 normal : NORMAL; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + /*ase_vcontrol*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct TessellationFactors + { + float edge[3] : SV_TessFactor; + float inside : SV_InsideTessFactor; + }; + + VertexControl vert ( appdata v ) + { + VertexControl o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_TRANSFER_INSTANCE_ID(v, o); + o.vertex = v.vertex; + o.tangent = v.tangent; + o.normal = v.normal; + o.texcoord1 = v.texcoord1; + o.texcoord2 = v.texcoord2; + /*ase_control_code:v=appdata;o=VertexControl*/ + return o; + } + + TessellationFactors TessellationFunction (InputPatch v) + { + TessellationFactors o; + float4 tf = 1; + float tessValue = /*ase_inline_begin*/_TessValue/*ase_inline_end*/; float tessMin = /*ase_inline_begin*/_TessMin/*ase_inline_end*/; float tessMax = /*ase_inline_begin*/_TessMax/*ase_inline_end*/; + float edgeLength = /*ase_inline_begin*/_TessEdgeLength/*ase_inline_end*/; float tessMaxDisp = /*ase_inline_begin*/_TessMaxDisp/*ase_inline_end*/; + #if defined(ASE_FIXED_TESSELLATION) + tf = FixedTess( tessValue ); + #elif defined(ASE_DISTANCE_TESSELLATION) + tf = DistanceBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, tessValue, tessMin, tessMax, UNITY_MATRIX_M, _WorldSpaceCameraPos ); + #elif defined(ASE_LENGTH_TESSELLATION) + tf = EdgeLengthBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, UNITY_MATRIX_M, _WorldSpaceCameraPos, _ScreenParams ); + #elif defined(ASE_LENGTH_CULL_TESSELLATION) + tf = EdgeLengthBasedTessCull(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, tessMaxDisp, UNITY_MATRIX_M, _WorldSpaceCameraPos, _ScreenParams, unity_CameraWorldClipPlanes ); + #endif + o.edge[0] = tf.x; o.edge[1] = tf.y; o.edge[2] = tf.z; o.inside = tf.w; + return o; + } + + [domain("tri")] + [partitioning("fractional_odd")] + [outputtopology("triangle_cw")] + [patchconstantfunc("TessellationFunction")] + [outputcontrolpoints(3)] + VertexControl HullFunction(InputPatch patch, uint id : SV_OutputControlPointID) + { + return patch[id]; + } + + [domain("tri")] + v2f DomainFunction(TessellationFactors factors, OutputPatch patch, float3 bary : SV_DomainLocation) + { + appdata o = (appdata) 0; + o.vertex = patch[0].vertex * bary.x + patch[1].vertex * bary.y + patch[2].vertex * bary.z; + o.tangent = patch[0].tangent * bary.x + patch[1].tangent * bary.y + patch[2].tangent * bary.z; + o.normal = patch[0].normal * bary.x + patch[1].normal * bary.y + patch[2].normal * bary.z; + o.texcoord1 = patch[0].texcoord1 * bary.x + patch[1].texcoord1 * bary.y + patch[2].texcoord1 * bary.z; + o.texcoord2 = patch[0].texcoord2 * bary.x + patch[1].texcoord2 * bary.y + patch[2].texcoord2 * bary.z; + /*ase_domain_code:patch=VertexControl;o=appdata;bary=SV_DomainLocation*/ + #if defined(ASE_PHONG_TESSELLATION) + float3 pp[3]; + for (int i = 0; i < 3; ++i) + pp[i] = o.vertex.xyz - patch[i].normal * (dot(o.vertex.xyz, patch[i].normal) - dot(patch[i].vertex.xyz, patch[i].normal)); + float phongStrength = /*ase_inline_begin*/_TessPhongStrength/*ase_inline_end*/; + o.vertex.xyz = phongStrength * (pp[0]*bary.x + pp[1]*bary.y + pp[2]*bary.z) + (1.0f-phongStrength) * o.vertex.xyz; + #endif + UNITY_TRANSFER_INSTANCE_ID(patch[0], o); + return VertexFunction(o); + } + #else + v2f vert ( appdata v ) + { + return VertexFunction( v ); + } + #endif + + fixed4 frag ( v2f IN /*ase_frag_input*/ + #ifdef _DEPTHOFFSET_ON + , out float outputDepth : SV_Depth + #endif + ) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(IN); + + #ifdef LOD_FADE_CROSSFADE + UNITY_APPLY_DITHER_CROSSFADE(IN.pos.xy); + #endif + + #if defined(_SPECULAR_SETUP) + SurfaceOutputStandardSpecular o = (SurfaceOutputStandardSpecular)0; + #else + SurfaceOutputStandard o = (SurfaceOutputStandard)0; + #endif + /*ase_local_var:wt*/float3 WorldTangent = float3(IN.tSpace0.x,IN.tSpace1.x,IN.tSpace2.x); + /*ase_local_var:wbt*/float3 WorldBiTangent = float3(IN.tSpace0.y,IN.tSpace1.y,IN.tSpace2.y); + /*ase_local_var:wn*/float3 WorldNormal = float3(IN.tSpace0.z,IN.tSpace1.z,IN.tSpace2.z); + /*ase_local_var:wp*/float3 worldPos = float3(IN.tSpace0.w,IN.tSpace1.w,IN.tSpace2.w); + /*ase_local_var:wvd*/float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos)); + #if defined(ASE_NEEDS_FRAG_SHADOWCOORDS) + UNITY_LIGHT_ATTENUATION(atten, IN, worldPos) + #else + /*ase_local_var:sc*/half atten = 1; + #endif + #if defined(ASE_NEEDS_FRAG_SCREEN_POSITION) + /*ase_local_var:spu*/float4 ScreenPos = IN.screenPos; + #endif + + + /*ase_frag_code:IN=v2f*/ + o.Albedo = /*ase_frag_out:Albedo;Float3;0;-1;_Albedo*/fixed3( 0.5, 0.5, 0.5 )/*end*/; + o.Normal = /*ase_frag_out:Normal;Float3;1;-1;_Normal*/fixed3( 0, 0, 1 )/*end*/; + o.Emission = /*ase_frag_out:Emission;Float3;2;-1;_Emission*/half3( 0, 0, 0 )/*end*/; + #if defined(_SPECULAR_SETUP) + o.Specular = /*ase_frag_out:Specular;Float3;3;-1;_Specular*/fixed3( 0, 0, 0 )/*end*/; + #else + o.Metallic = /*ase_frag_out:Metallic;Float;4;-1;_Metallic*/0/*end*/; + #endif + o.Smoothness = /*ase_frag_out:Smoothness;Float;5;-1;_Smoothness*/0/*end*/; + o.Occlusion = /*ase_frag_out:Occlusion;Float;6;-1;_Occlusion*/1/*end*/; + o.Alpha = /*ase_frag_out:Alpha;Float;7;-1;_Alpha*/1/*end*/; + float AlphaClipThreshold = /*ase_frag_out:Alpha Clip Threshold;Float;8;-1;_AlphaClip*/0.5/*end*/; + float3 Transmission = /*ase_frag_out:Transmission;Float3;9;-1;_Transmission*/1/*end*/; + float3 Translucency = /*ase_frag_out:Translucency;Float3;10;-1;_Translucency*/1/*end*/; + + #ifdef _ALPHATEST_ON + clip( o.Alpha - AlphaClipThreshold ); + #endif + + #ifdef _DEPTHOFFSET_ON + outputDepth = IN.pos.z; + #endif + + #ifndef USING_DIRECTIONAL_LIGHT + fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos)); + #else + fixed3 lightDir = _WorldSpaceLightPos0.xyz; + #endif + + fixed4 c = 0; + float3 worldN; + worldN.x = dot(IN.tSpace0.xyz, o.Normal); + worldN.y = dot(IN.tSpace1.xyz, o.Normal); + worldN.z = dot(IN.tSpace2.xyz, o.Normal); + worldN = normalize(worldN); + o.Normal = worldN; + + UnityGI gi; + UNITY_INITIALIZE_OUTPUT(UnityGI, gi); + gi.indirect.diffuse = 0; + gi.indirect.specular = 0; + gi.light.color = _LightColor0.rgb; + gi.light.dir = lightDir; + gi.light.color *= atten; + + #if defined(_SPECULAR_SETUP) + c += LightingStandardSpecular( o, worldViewDir, gi ); + #else + c += LightingStandard( o, worldViewDir, gi ); + #endif + + #ifdef _TRANSMISSION_ASE + { + float shadow = /*ase_inline_begin*/_TransmissionShadow/*ase_inline_end*/; + #ifdef DIRECTIONAL + float3 lightAtten = lerp( _LightColor0.rgb, gi.light.color, shadow ); + #else + float3 lightAtten = gi.light.color; + #endif + half3 transmission = max(0 , -dot(o.Normal, gi.light.dir)) * lightAtten * Transmission; + c.rgb += o.Albedo * transmission; + } + #endif + + #ifdef _TRANSLUCENCY_ASE + { + float shadow = /*ase_inline_begin*/_TransShadow/*ase_inline_end*/; + float normal = /*ase_inline_begin*/_TransNormal/*ase_inline_end*/; + float scattering = /*ase_inline_begin*/_TransScattering/*ase_inline_end*/; + float direct = /*ase_inline_begin*/_TransDirect/*ase_inline_end*/; + float ambient = /*ase_inline_begin*/_TransAmbient/*ase_inline_end*/; + float strength = /*ase_inline_begin*/_TransStrength/*ase_inline_end*/; + + #ifdef DIRECTIONAL + float3 lightAtten = lerp( _LightColor0.rgb, gi.light.color, shadow ); + #else + float3 lightAtten = gi.light.color; + #endif + half3 lightDir = gi.light.dir + o.Normal * normal; + half transVdotL = pow( saturate( dot( worldViewDir, -lightDir ) ), scattering ); + half3 translucency = lightAtten * (transVdotL * direct + gi.indirect.diffuse * ambient) * Translucency; + c.rgb += o.Albedo * translucency * strength; + } + #endif + + //#ifdef _REFRACTION_ASE + // float4 projScreenPos = ScreenPos / ScreenPos.w; + // float3 refractionOffset = ( RefractionIndex - 1.0 ) * mul( UNITY_MATRIX_V, WorldNormal ).xyz * ( 1.0 - dot( WorldNormal, WorldViewDirection ) ); + // projScreenPos.xy += refractionOffset.xy; + // float3 refraction = UNITY_SAMPLE_SCREENSPACE_TEXTURE( _GrabTexture, projScreenPos ) * RefractionColor; + // color.rgb = lerp( refraction, color.rgb, color.a ); + // color.a = 1; + //#endif + + #ifdef ASE_FOG + UNITY_APPLY_FOG(IN.fogCoord, c); + #endif + return c; + } + ENDCG + } + + /*ase_pass*/ + Pass + { + /*ase_hide_pass*/ + Name "Deferred" + Tags { "LightMode"="Deferred" } + + AlphaToMask Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 3.0 + #pragma exclude_renderers nomrt + #pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2 + #pragma multi_compile_prepassfinal + #ifndef UNITY_PASS_DEFERRED + #define UNITY_PASS_DEFERRED + #endif + #include "HLSLSupport.cginc" + #if !defined( UNITY_INSTANCED_LOD_FADE ) + #define UNITY_INSTANCED_LOD_FADE + #endif + #if !defined( UNITY_INSTANCED_SH ) + #define UNITY_INSTANCED_SH + #endif + #if !defined( UNITY_INSTANCED_LIGHTMAPSTS ) + #define UNITY_INSTANCED_LIGHTMAPSTS + #endif + #include "UnityShaderVariables.cginc" + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + + /*ase_pragma*/ + struct appdata { + float4 vertex : POSITION; + float4 tangent : TANGENT; + float3 normal : NORMAL; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + /*ase_vdata:p=p;t=t;n=n;uv1=tc1.xyzw;uv2=tc2.xyzw*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct v2f { + #if UNITY_VERSION >= 201810 + UNITY_POSITION(pos); + #else + float4 pos : SV_POSITION; + #endif + float4 lmap : TEXCOORD2; + #ifndef LIGHTMAP_ON + #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL + half3 sh : TEXCOORD3; + #endif + #else + #ifdef DIRLIGHTMAP_OFF + float4 lmapFadePos : TEXCOORD4; + #endif + #endif + float4 tSpace0 : TEXCOORD5; + float4 tSpace1 : TEXCOORD6; + float4 tSpace2 : TEXCOORD7; + /*ase_interp(8,):sp=sp.xyzw;wn.xyz=tc5.xyz;wt.xyz=tc6.xyz;wbt.xyz=tc7.xyz;wp.x=tc5.w;wp.y=tc6.w;wp.z=tc7.w*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + }; + + #ifdef LIGHTMAP_ON + float4 unity_LightmapFade; + #endif + fixed4 unity_Ambient; + #ifdef TESSELLATION_ON + float _TessPhongStrength; + float _TessValue; + float _TessMin; + float _TessMax; + float _TessEdgeLength; + float _TessMaxDisp; + #endif + /*ase_globals*/ + + /*ase_funcs*/ + + v2f VertexFunction (appdata v /*ase_vert_input*/ ) { + UNITY_SETUP_INSTANCE_ID(v); + v2f o; + UNITY_INITIALIZE_OUTPUT(v2f,o); + UNITY_TRANSFER_INSTANCE_ID(v,o); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + + /*ase_vert_code:v=appdata;o=v2f*/ + #ifdef ASE_ABSOLUTE_VERTEX_POS + float3 defaultVertexValue = v.vertex.xyz; + #else + float3 defaultVertexValue = float3(0, 0, 0); + #endif + float3 vertexValue = /*ase_vert_out:Vertex Offset;Float3;10;-1;_Vertex*/defaultVertexValue/*end*/; + #ifdef ASE_ABSOLUTE_VERTEX_POS + v.vertex.xyz = vertexValue; + #else + v.vertex.xyz += vertexValue; + #endif + v.vertex.w = 1; + v.normal = /*ase_vert_out:Vertex Normal;Float3;11;-1;_VertexNormal*/v.normal/*end*/; + v.tangent = /*ase_vert_out:Vertex Tangent;Float4;12;-1;_VertexTangent*/v.tangent/*end*/; + + o.pos = UnityObjectToClipPos(v.vertex); + float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; + fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); + fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz); + fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w; + fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign; + o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); + o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); + o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); + + #ifdef DYNAMICLIGHTMAP_ON + o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; + #else + o.lmap.zw = 0; + #endif + #ifdef LIGHTMAP_ON + o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw; + #ifdef DIRLIGHTMAP_OFF + o.lmapFadePos.xyz = (mul(unity_ObjectToWorld, v.vertex).xyz - unity_ShadowFadeCenterAndType.xyz) * unity_ShadowFadeCenterAndType.w; + o.lmapFadePos.w = (-UnityObjectToViewPos(v.vertex).z) * (1.0 - unity_ShadowFadeCenterAndType.w); + #endif + #else + o.lmap.xy = 0; + #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL + o.sh = 0; + o.sh = ShadeSHPerVertex (worldNormal, o.sh); + #endif + #endif + return o; + } + + #if defined(TESSELLATION_ON) + struct VertexControl + { + float4 vertex : INTERNALTESSPOS; + float4 tangent : TANGENT; + float3 normal : NORMAL; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + /*ase_vcontrol*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct TessellationFactors + { + float edge[3] : SV_TessFactor; + float inside : SV_InsideTessFactor; + }; + + VertexControl vert ( appdata v ) + { + VertexControl o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_TRANSFER_INSTANCE_ID(v, o); + o.vertex = v.vertex; + o.tangent = v.tangent; + o.normal = v.normal; + o.texcoord1 = v.texcoord1; + o.texcoord2 = v.texcoord2; + /*ase_control_code:v=appdata;o=VertexControl*/ + return o; + } + + TessellationFactors TessellationFunction (InputPatch v) + { + TessellationFactors o; + float4 tf = 1; + float tessValue = /*ase_inline_begin*/_TessValue/*ase_inline_end*/; float tessMin = /*ase_inline_begin*/_TessMin/*ase_inline_end*/; float tessMax = /*ase_inline_begin*/_TessMax/*ase_inline_end*/; + float edgeLength = /*ase_inline_begin*/_TessEdgeLength/*ase_inline_end*/; float tessMaxDisp = /*ase_inline_begin*/_TessMaxDisp/*ase_inline_end*/; + #if defined(ASE_FIXED_TESSELLATION) + tf = FixedTess( tessValue ); + #elif defined(ASE_DISTANCE_TESSELLATION) + tf = DistanceBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, tessValue, tessMin, tessMax, UNITY_MATRIX_M, _WorldSpaceCameraPos ); + #elif defined(ASE_LENGTH_TESSELLATION) + tf = EdgeLengthBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, UNITY_MATRIX_M, _WorldSpaceCameraPos, _ScreenParams ); + #elif defined(ASE_LENGTH_CULL_TESSELLATION) + tf = EdgeLengthBasedTessCull(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, tessMaxDisp, UNITY_MATRIX_M, _WorldSpaceCameraPos, _ScreenParams, unity_CameraWorldClipPlanes ); + #endif + o.edge[0] = tf.x; o.edge[1] = tf.y; o.edge[2] = tf.z; o.inside = tf.w; + return o; + } + + [domain("tri")] + [partitioning("fractional_odd")] + [outputtopology("triangle_cw")] + [patchconstantfunc("TessellationFunction")] + [outputcontrolpoints(3)] + VertexControl HullFunction(InputPatch patch, uint id : SV_OutputControlPointID) + { + return patch[id]; + } + + [domain("tri")] + v2f DomainFunction(TessellationFactors factors, OutputPatch patch, float3 bary : SV_DomainLocation) + { + appdata o = (appdata) 0; + o.vertex = patch[0].vertex * bary.x + patch[1].vertex * bary.y + patch[2].vertex * bary.z; + o.tangent = patch[0].tangent * bary.x + patch[1].tangent * bary.y + patch[2].tangent * bary.z; + o.normal = patch[0].normal * bary.x + patch[1].normal * bary.y + patch[2].normal * bary.z; + o.texcoord1 = patch[0].texcoord1 * bary.x + patch[1].texcoord1 * bary.y + patch[2].texcoord1 * bary.z; + o.texcoord2 = patch[0].texcoord2 * bary.x + patch[1].texcoord2 * bary.y + patch[2].texcoord2 * bary.z; + /*ase_domain_code:patch=VertexControl;o=appdata;bary=SV_DomainLocation*/ + #if defined(ASE_PHONG_TESSELLATION) + float3 pp[3]; + for (int i = 0; i < 3; ++i) + pp[i] = o.vertex.xyz - patch[i].normal * (dot(o.vertex.xyz, patch[i].normal) - dot(patch[i].vertex.xyz, patch[i].normal)); + float phongStrength = /*ase_inline_begin*/_TessPhongStrength/*ase_inline_end*/; + o.vertex.xyz = phongStrength * (pp[0]*bary.x + pp[1]*bary.y + pp[2]*bary.z) + (1.0f-phongStrength) * o.vertex.xyz; + #endif + UNITY_TRANSFER_INSTANCE_ID(patch[0], o); + return VertexFunction(o); + } + #else + v2f vert ( appdata v ) + { + return VertexFunction( v ); + } + #endif + + void frag (v2f IN /*ase_frag_input*/ + , out half4 outGBuffer0 : SV_Target0 + , out half4 outGBuffer1 : SV_Target1 + , out half4 outGBuffer2 : SV_Target2 + , out half4 outEmission : SV_Target3 + #if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4) + , out half4 outShadowMask : SV_Target4 + #endif + #ifdef _DEPTHOFFSET_ON + , out float outputDepth : SV_Depth + #endif + ) + { + UNITY_SETUP_INSTANCE_ID(IN); + + #ifdef LOD_FADE_CROSSFADE + UNITY_APPLY_DITHER_CROSSFADE(IN.pos.xy); + #endif + + #if defined(_SPECULAR_SETUP) + SurfaceOutputStandardSpecular o = (SurfaceOutputStandardSpecular)0; + #else + SurfaceOutputStandard o = (SurfaceOutputStandard)0; + #endif + /*ase_local_var:wt*/float3 WorldTangent = float3(IN.tSpace0.x,IN.tSpace1.x,IN.tSpace2.x); + /*ase_local_var:wbt*/float3 WorldBiTangent = float3(IN.tSpace0.y,IN.tSpace1.y,IN.tSpace2.y); + /*ase_local_var:wn*/float3 WorldNormal = float3(IN.tSpace0.z,IN.tSpace1.z,IN.tSpace2.z); + /*ase_local_var:wp*/float3 worldPos = float3(IN.tSpace0.w,IN.tSpace1.w,IN.tSpace2.w); + /*ase_local_var:wvd*/float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos)); + /*ase_local_var:sc*/half atten = 1; + + /*ase_frag_code:IN=v2f*/ + o.Albedo = /*ase_frag_out:Albedo;Float3;0;-1;_Albedo*/fixed3( 0.5, 0.5, 0.5 )/*end*/; + o.Normal = /*ase_frag_out:Normal;Float3;1;-1;_Normal*/fixed3( 0, 0, 1 )/*end*/; + o.Emission = /*ase_frag_out:Emission;Float3;2;-1;_Emission*/half3( 0, 0, 0 )/*end*/; + #if defined(_SPECULAR_SETUP) + o.Specular = /*ase_frag_out:Specular;Float3;3;-1;_Specular*/fixed3( 0, 0, 0 )/*end*/; + #else + o.Metallic = /*ase_frag_out:Metallic;Float;4;-1;_Metallic*/0/*end*/; + #endif + o.Smoothness = /*ase_frag_out:Smoothness;Float;5;-1;_Smoothness*/0/*end*/; + o.Occlusion = /*ase_frag_out:Occlusion;Float;6;-1;_Occlusion*/1/*end*/; + o.Alpha = /*ase_frag_out:Alpha;Float;7;-1;_Alpha*/1/*end*/; + float AlphaClipThreshold = /*ase_frag_out:Alpha Clip Threshold;Float;8;-1;_AlphaClip*/0.5/*end*/; + float3 BakedGI = /*ase_frag_out:Baked GI;Float3;9;-1;_BakedGI*/0/*end*/; + + #ifdef _ALPHATEST_ON + clip( o.Alpha - AlphaClipThreshold ); + #endif + + #ifdef _DEPTHOFFSET_ON + outputDepth = IN.pos.z; + #endif + + #ifndef USING_DIRECTIONAL_LIGHT + fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos)); + #else + fixed3 lightDir = _WorldSpaceLightPos0.xyz; + #endif + + float3 worldN; + worldN.x = dot(IN.tSpace0.xyz, o.Normal); + worldN.y = dot(IN.tSpace1.xyz, o.Normal); + worldN.z = dot(IN.tSpace2.xyz, o.Normal); + worldN = normalize(worldN); + o.Normal = worldN; + + UnityGI gi; + UNITY_INITIALIZE_OUTPUT(UnityGI, gi); + gi.indirect.diffuse = 0; + gi.indirect.specular = 0; + gi.light.color = 0; + gi.light.dir = half3(0,1,0); + + UnityGIInput giInput; + UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput); + giInput.light = gi.light; + giInput.worldPos = worldPos; + giInput.worldViewDir = worldViewDir; + giInput.atten = atten; + #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON) + giInput.lightmapUV = IN.lmap; + #else + giInput.lightmapUV = 0.0; + #endif + #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL + giInput.ambient = IN.sh; + #else + giInput.ambient.rgb = 0.0; + #endif + giInput.probeHDR[0] = unity_SpecCube0_HDR; + giInput.probeHDR[1] = unity_SpecCube1_HDR; + #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION) + giInput.boxMin[0] = unity_SpecCube0_BoxMin; + #endif + #ifdef UNITY_SPECCUBE_BOX_PROJECTION + giInput.boxMax[0] = unity_SpecCube0_BoxMax; + giInput.probePosition[0] = unity_SpecCube0_ProbePosition; + giInput.boxMax[1] = unity_SpecCube1_BoxMax; + giInput.boxMin[1] = unity_SpecCube1_BoxMin; + giInput.probePosition[1] = unity_SpecCube1_ProbePosition; + #endif + + #if defined(_SPECULAR_SETUP) + LightingStandardSpecular_GI( o, giInput, gi ); + #else + LightingStandard_GI( o, giInput, gi ); + #endif + + #ifdef ASE_BAKEDGI + gi.indirect.diffuse = BakedGI; + #endif + + #if UNITY_SHOULD_SAMPLE_SH && !defined(LIGHTMAP_ON) && defined(ASE_NO_AMBIENT) + gi.indirect.diffuse = 0; + #endif + + #if defined(_SPECULAR_SETUP) + outEmission = LightingStandardSpecular_Deferred( o, worldViewDir, gi, outGBuffer0, outGBuffer1, outGBuffer2 ); + #else + outEmission = LightingStandard_Deferred( o, worldViewDir, gi, outGBuffer0, outGBuffer1, outGBuffer2 ); + #endif + + #if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4) + outShadowMask = UnityGetRawBakedOcclusions (IN.lmap.xy, float3(0, 0, 0)); + #endif + #ifndef UNITY_HDR_ON + outEmission.rgb = exp2(-outEmission.rgb); + #endif + } + ENDCG + } + + /*ase_pass*/ + Pass + { + /*ase_hide_pass*/ + Name "Meta" + Tags { "LightMode"="Meta" } + Cull Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2 + #pragma shader_feature EDITOR_VISUALIZATION + #ifndef UNITY_PASS_META + #define UNITY_PASS_META + #endif + #include "HLSLSupport.cginc" + #if !defined( UNITY_INSTANCED_LOD_FADE ) + #define UNITY_INSTANCED_LOD_FADE + #endif + #if !defined( UNITY_INSTANCED_SH ) + #define UNITY_INSTANCED_SH + #endif + #if !defined( UNITY_INSTANCED_LIGHTMAPSTS ) + #define UNITY_INSTANCED_LIGHTMAPSTS + #endif + #include "UnityShaderVariables.cginc" + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + #include "UnityMetaPass.cginc" + + /*ase_pragma*/ + struct appdata { + float4 vertex : POSITION; + float4 tangent : TANGENT; + float3 normal : NORMAL; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + /*ase_vdata:p=p;t=t;n=n;uv1=tc1.xyzw;uv2=tc2.xyzw*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + struct v2f { + #if UNITY_VERSION >= 201810 + UNITY_POSITION(pos); + #else + float4 pos : SV_POSITION; + #endif + #ifdef EDITOR_VISUALIZATION + float2 vizUV : TEXCOORD1; + float4 lightCoord : TEXCOORD2; + #endif + /*ase_interp(3,):sp=sp.xyzw*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + }; + + #ifdef TESSELLATION_ON + float _TessPhongStrength; + float _TessValue; + float _TessMin; + float _TessMax; + float _TessEdgeLength; + float _TessMaxDisp; + #endif + /*ase_globals*/ + + /*ase_funcs*/ + + v2f VertexFunction (appdata v /*ase_vert_input*/ ) { + UNITY_SETUP_INSTANCE_ID(v); + v2f o; + UNITY_INITIALIZE_OUTPUT(v2f,o); + UNITY_TRANSFER_INSTANCE_ID(v,o); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + + /*ase_vert_code:v=appdata;o=v2f*/ + #ifdef ASE_ABSOLUTE_VERTEX_POS + float3 defaultVertexValue = v.vertex.xyz; + #else + float3 defaultVertexValue = float3(0, 0, 0); + #endif + float3 vertexValue = /*ase_vert_out:Vertex Offset;Float3;4;-1;_Vertex*/defaultVertexValue/*end*/; + #ifdef ASE_ABSOLUTE_VERTEX_POS + v.vertex.xyz = vertexValue; + #else + v.vertex.xyz += vertexValue; + #endif + v.vertex.w = 1; + v.normal = /*ase_vert_out:Vertex Normal;Float3;5;-1;_VertexNormal*/v.normal/*end*/; + v.tangent = /*ase_vert_out:Vertex Tangent;Float4;6;-1;_VertexTangent*/v.tangent/*end*/; + + #ifdef EDITOR_VISUALIZATION + o.vizUV = 0; + o.lightCoord = 0; + if (unity_VisualizationMode == EDITORVIZ_TEXTURE) + o.vizUV = UnityMetaVizUV(unity_EditorViz_UVIndex, v.texcoord.xy, v.texcoord1.xy, v.texcoord2.xy, unity_EditorViz_Texture_ST); + else if (unity_VisualizationMode == EDITORVIZ_SHOWLIGHTMASK) + { + o.vizUV = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw; + o.lightCoord = mul(unity_EditorViz_WorldToLight, mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1))); + } + #endif + + o.pos = UnityMetaVertexPosition(v.vertex, v.texcoord1.xy, v.texcoord2.xy, unity_LightmapST, unity_DynamicLightmapST); + + return o; + } + + #if defined(TESSELLATION_ON) + struct VertexControl + { + float4 vertex : INTERNALTESSPOS; + float4 tangent : TANGENT; + float3 normal : NORMAL; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + /*ase_vcontrol*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct TessellationFactors + { + float edge[3] : SV_TessFactor; + float inside : SV_InsideTessFactor; + }; + + VertexControl vert ( appdata v ) + { + VertexControl o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_TRANSFER_INSTANCE_ID(v, o); + o.vertex = v.vertex; + o.tangent = v.tangent; + o.normal = v.normal; + o.texcoord1 = v.texcoord1; + o.texcoord2 = v.texcoord2; + /*ase_control_code:v=appdata;o=VertexControl*/ + return o; + } + + TessellationFactors TessellationFunction (InputPatch v) + { + TessellationFactors o; + float4 tf = 1; + float tessValue = /*ase_inline_begin*/_TessValue/*ase_inline_end*/; float tessMin = /*ase_inline_begin*/_TessMin/*ase_inline_end*/; float tessMax = /*ase_inline_begin*/_TessMax/*ase_inline_end*/; + float edgeLength = /*ase_inline_begin*/_TessEdgeLength/*ase_inline_end*/; float tessMaxDisp = /*ase_inline_begin*/_TessMaxDisp/*ase_inline_end*/; + #if defined(ASE_FIXED_TESSELLATION) + tf = FixedTess( tessValue ); + #elif defined(ASE_DISTANCE_TESSELLATION) + tf = DistanceBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, tessValue, tessMin, tessMax, UNITY_MATRIX_M, _WorldSpaceCameraPos ); + #elif defined(ASE_LENGTH_TESSELLATION) + tf = EdgeLengthBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, UNITY_MATRIX_M, _WorldSpaceCameraPos, _ScreenParams ); + #elif defined(ASE_LENGTH_CULL_TESSELLATION) + tf = EdgeLengthBasedTessCull(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, tessMaxDisp, UNITY_MATRIX_M, _WorldSpaceCameraPos, _ScreenParams, unity_CameraWorldClipPlanes ); + #endif + o.edge[0] = tf.x; o.edge[1] = tf.y; o.edge[2] = tf.z; o.inside = tf.w; + return o; + } + + [domain("tri")] + [partitioning("fractional_odd")] + [outputtopology("triangle_cw")] + [patchconstantfunc("TessellationFunction")] + [outputcontrolpoints(3)] + VertexControl HullFunction(InputPatch patch, uint id : SV_OutputControlPointID) + { + return patch[id]; + } + + [domain("tri")] + v2f DomainFunction(TessellationFactors factors, OutputPatch patch, float3 bary : SV_DomainLocation) + { + appdata o = (appdata) 0; + o.vertex = patch[0].vertex * bary.x + patch[1].vertex * bary.y + patch[2].vertex * bary.z; + o.tangent = patch[0].tangent * bary.x + patch[1].tangent * bary.y + patch[2].tangent * bary.z; + o.normal = patch[0].normal * bary.x + patch[1].normal * bary.y + patch[2].normal * bary.z; + o.texcoord1 = patch[0].texcoord1 * bary.x + patch[1].texcoord1 * bary.y + patch[2].texcoord1 * bary.z; + o.texcoord2 = patch[0].texcoord2 * bary.x + patch[1].texcoord2 * bary.y + patch[2].texcoord2 * bary.z; + /*ase_domain_code:patch=VertexControl;o=appdata;bary=SV_DomainLocation*/ + #if defined(ASE_PHONG_TESSELLATION) + float3 pp[3]; + for (int i = 0; i < 3; ++i) + pp[i] = o.vertex.xyz - patch[i].normal * (dot(o.vertex.xyz, patch[i].normal) - dot(patch[i].vertex.xyz, patch[i].normal)); + float phongStrength = /*ase_inline_begin*/_TessPhongStrength/*ase_inline_end*/; + o.vertex.xyz = phongStrength * (pp[0]*bary.x + pp[1]*bary.y + pp[2]*bary.z) + (1.0f-phongStrength) * o.vertex.xyz; + #endif + UNITY_TRANSFER_INSTANCE_ID(patch[0], o); + return VertexFunction(o); + } + #else + v2f vert ( appdata v ) + { + return VertexFunction( v ); + } + #endif + + fixed4 frag (v2f IN /*ase_frag_input*/ + #ifdef _DEPTHOFFSET_ON + , out float outputDepth : SV_Depth + #endif + ) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(IN); + + #ifdef LOD_FADE_CROSSFADE + UNITY_APPLY_DITHER_CROSSFADE(IN.pos.xy); + #endif + + #if defined(_SPECULAR_SETUP) + SurfaceOutputStandardSpecular o = (SurfaceOutputStandardSpecular)0; + #else + SurfaceOutputStandard o = (SurfaceOutputStandard)0; + #endif + + /*ase_frag_code:IN=v2f*/ + o.Albedo = /*ase_frag_out:Albedo;Float3;0;-1;_Albedo*/fixed3( 0.5, 0.5, 0.5 )/*end*/; + o.Normal = fixed3( 0, 0, 1 ); + o.Emission = /*ase_frag_out:Emission;Float3;1;-1;_Emission*/half3( 0, 0, 0 )/*end*/; + o.Alpha = /*ase_frag_out:Alpha;Float;2;-1;_Alpha*/1/*end*/; + float AlphaClipThreshold = /*ase_frag_out:Alpha Clip Threshold;Float;3;-1;_AlphaClip*/0.5/*end*/; + + #ifdef _ALPHATEST_ON + clip( o.Alpha - AlphaClipThreshold ); + #endif + + #ifdef _DEPTHOFFSET_ON + outputDepth = IN.pos.z; + #endif + + UnityMetaInput metaIN; + UNITY_INITIALIZE_OUTPUT(UnityMetaInput, metaIN); + metaIN.Albedo = o.Albedo; + metaIN.Emission = o.Emission; + #ifdef EDITOR_VISUALIZATION + metaIN.VizUV = IN.vizUV; + metaIN.LightCoord = IN.lightCoord; + #endif + return UnityMetaFragment(metaIN); + } + ENDCG + } + + /*ase_pass*/ + Pass + { + /*ase_hide_pass*/ + Name "ShadowCaster" + Tags { "LightMode"="ShadowCaster" } + ZWrite On + ZTest LEqual + AlphaToMask Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2 + #pragma multi_compile_shadowcaster + #ifndef UNITY_PASS_SHADOWCASTER + #define UNITY_PASS_SHADOWCASTER + #endif + #include "HLSLSupport.cginc" + #ifndef UNITY_INSTANCED_LOD_FADE + #define UNITY_INSTANCED_LOD_FADE + #endif + #ifndef UNITY_INSTANCED_SH + #define UNITY_INSTANCED_SH + #endif + #ifndef UNITY_INSTANCED_LIGHTMAPSTS + #define UNITY_INSTANCED_LIGHTMAPSTS + #endif + #if ( SHADER_API_D3D11 || SHADER_API_GLCORE || SHADER_API_GLES || SHADER_API_GLES3 || SHADER_API_METAL || SHADER_API_VULKAN ) + #define CAN_SKIP_VPOS + #endif + #include "UnityShaderVariables.cginc" + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + + /*ase_pragma*/ + struct appdata { + float4 vertex : POSITION; + float4 tangent : TANGENT; + float3 normal : NORMAL; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + /*ase_vdata:p=p;t=t;n=n;uv1=tc1.xyzw;uv2=tc2.xyzw*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct v2f { + V2F_SHADOW_CASTER; + /*ase_interp(2,):sp=sp.xyzw*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + }; + + #ifdef UNITY_STANDARD_USE_DITHER_MASK + sampler3D _DitherMaskLOD; + #endif + #ifdef TESSELLATION_ON + float _TessPhongStrength; + float _TessValue; + float _TessMin; + float _TessMax; + float _TessEdgeLength; + float _TessMaxDisp; + #endif + /*ase_globals*/ + + /*ase_funcs*/ + + v2f VertexFunction (appdata v /*ase_vert_input*/ ) { + UNITY_SETUP_INSTANCE_ID(v); + v2f o; + UNITY_INITIALIZE_OUTPUT(v2f,o); + UNITY_TRANSFER_INSTANCE_ID(v,o); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + + /*ase_vert_code:v=appdata;o=v2f*/ + #ifdef ASE_ABSOLUTE_VERTEX_POS + float3 defaultVertexValue = v.vertex.xyz; + #else + float3 defaultVertexValue = float3(0, 0, 0); + #endif + float3 vertexValue = /*ase_vert_out:Vertex Offset;Float3;3;-1;_Vertex*/defaultVertexValue/*end*/; + #ifdef ASE_ABSOLUTE_VERTEX_POS + v.vertex.xyz = vertexValue; + #else + v.vertex.xyz += vertexValue; + #endif + v.vertex.w = 1; + v.normal = /*ase_vert_out:Vertex Normal;Float3;4;-1;_VertexNormal*/v.normal/*end*/; + v.tangent = /*ase_vert_out:Vertex Tangent;Float4;5;-1;_VertexTangent*/v.tangent/*end*/; + + TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) + return o; + } + + #if defined(TESSELLATION_ON) + struct VertexControl + { + float4 vertex : INTERNALTESSPOS; + float4 tangent : TANGENT; + float3 normal : NORMAL; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + /*ase_vcontrol*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct TessellationFactors + { + float edge[3] : SV_TessFactor; + float inside : SV_InsideTessFactor; + }; + + VertexControl vert ( appdata v ) + { + VertexControl o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_TRANSFER_INSTANCE_ID(v, o); + o.vertex = v.vertex; + o.tangent = v.tangent; + o.normal = v.normal; + o.texcoord1 = v.texcoord1; + o.texcoord2 = v.texcoord2; + /*ase_control_code:v=appdata;o=VertexControl*/ + return o; + } + + TessellationFactors TessellationFunction (InputPatch v) + { + TessellationFactors o; + float4 tf = 1; + float tessValue = /*ase_inline_begin*/_TessValue/*ase_inline_end*/; float tessMin = /*ase_inline_begin*/_TessMin/*ase_inline_end*/; float tessMax = /*ase_inline_begin*/_TessMax/*ase_inline_end*/; + float edgeLength = /*ase_inline_begin*/_TessEdgeLength/*ase_inline_end*/; float tessMaxDisp = /*ase_inline_begin*/_TessMaxDisp/*ase_inline_end*/; + #if defined(ASE_FIXED_TESSELLATION) + tf = FixedTess( tessValue ); + #elif defined(ASE_DISTANCE_TESSELLATION) + tf = DistanceBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, tessValue, tessMin, tessMax, UNITY_MATRIX_M, _WorldSpaceCameraPos ); + #elif defined(ASE_LENGTH_TESSELLATION) + tf = EdgeLengthBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, UNITY_MATRIX_M, _WorldSpaceCameraPos, _ScreenParams ); + #elif defined(ASE_LENGTH_CULL_TESSELLATION) + tf = EdgeLengthBasedTessCull(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, tessMaxDisp, UNITY_MATRIX_M, _WorldSpaceCameraPos, _ScreenParams, unity_CameraWorldClipPlanes ); + #endif + o.edge[0] = tf.x; o.edge[1] = tf.y; o.edge[2] = tf.z; o.inside = tf.w; + return o; + } + + [domain("tri")] + [partitioning("fractional_odd")] + [outputtopology("triangle_cw")] + [patchconstantfunc("TessellationFunction")] + [outputcontrolpoints(3)] + VertexControl HullFunction(InputPatch patch, uint id : SV_OutputControlPointID) + { + return patch[id]; + } + + [domain("tri")] + v2f DomainFunction(TessellationFactors factors, OutputPatch patch, float3 bary : SV_DomainLocation) + { + appdata o = (appdata) 0; + o.vertex = patch[0].vertex * bary.x + patch[1].vertex * bary.y + patch[2].vertex * bary.z; + o.tangent = patch[0].tangent * bary.x + patch[1].tangent * bary.y + patch[2].tangent * bary.z; + o.normal = patch[0].normal * bary.x + patch[1].normal * bary.y + patch[2].normal * bary.z; + o.texcoord1 = patch[0].texcoord1 * bary.x + patch[1].texcoord1 * bary.y + patch[2].texcoord1 * bary.z; + o.texcoord2 = patch[0].texcoord2 * bary.x + patch[1].texcoord2 * bary.y + patch[2].texcoord2 * bary.z; + /*ase_domain_code:patch=VertexControl;o=appdata;bary=SV_DomainLocation*/ + #if defined(ASE_PHONG_TESSELLATION) + float3 pp[3]; + for (int i = 0; i < 3; ++i) + pp[i] = o.vertex.xyz - patch[i].normal * (dot(o.vertex.xyz, patch[i].normal) - dot(patch[i].vertex.xyz, patch[i].normal)); + float phongStrength = /*ase_inline_begin*/_TessPhongStrength/*ase_inline_end*/; + o.vertex.xyz = phongStrength * (pp[0]*bary.x + pp[1]*bary.y + pp[2]*bary.z) + (1.0f-phongStrength) * o.vertex.xyz; + #endif + UNITY_TRANSFER_INSTANCE_ID(patch[0], o); + return VertexFunction(o); + } + #else + v2f vert ( appdata v ) + { + return VertexFunction( v ); + } + #endif + + fixed4 frag (v2f IN /*ase_frag_input*/ + #ifdef _DEPTHOFFSET_ON + , out float outputDepth : SV_Depth + #endif + #if !defined( CAN_SKIP_VPOS ) + , UNITY_VPOS_TYPE vpos : VPOS + #endif + ) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(IN); + + #ifdef LOD_FADE_CROSSFADE + UNITY_APPLY_DITHER_CROSSFADE(IN.pos.xy); + #endif + + #if defined(_SPECULAR_SETUP) + SurfaceOutputStandardSpecular o = (SurfaceOutputStandardSpecular)0; + #else + SurfaceOutputStandard o = (SurfaceOutputStandard)0; + #endif + + /*ase_frag_code:IN=v2f*/ + o.Normal = fixed3( 0, 0, 1 ); + o.Occlusion = 1; + o.Alpha = /*ase_frag_out:Alpha;Float;0;-1;_Alpha*/1/*end*/; + float AlphaClipThreshold = /*ase_frag_out:Alpha Clip Threshold;Float;1;-1;_AlphaClip*/0.5/*end*/; + float AlphaClipThresholdShadow = /*ase_frag_out:Alpha Clip Threshold Shadow;Float;2;-1;_AlphaClipShadow*/0.5/*end*/; + + #ifdef _ALPHATEST_SHADOW_ON + if (unity_LightShadowBias.z != 0.0) + clip(o.Alpha - AlphaClipThresholdShadow); + #ifdef _ALPHATEST_ON + else + clip(o.Alpha - AlphaClipThreshold); + #endif + #else + #ifdef _ALPHATEST_ON + clip(o.Alpha - AlphaClipThreshold); + #endif + #endif + + #if defined( CAN_SKIP_VPOS ) + float2 vpos = IN.pos; + #endif + + #ifdef UNITY_STANDARD_USE_DITHER_MASK + half alphaRef = tex3D(_DitherMaskLOD, float3(vpos.xy*0.25,o.Alpha*0.9375)).a; + clip(alphaRef - 0.01); + #endif + + #ifdef _DEPTHOFFSET_ON + outputDepth = IN.pos.z; + #endif + + SHADOW_CASTER_FRAGMENT(IN) + } + ENDCG + } + /*ase_pass_end*/ + } + CustomEditor "ASEMaterialInspector" +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Lit.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Lit.shader.meta new file mode 100644 index 0000000..39509d8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Lit.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ed95fe726fd7b4644bb42f4d1ddd2bcd +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/MultiPassUnlit.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/MultiPassUnlit.shader new file mode 100644 index 0000000..43c244e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/MultiPassUnlit.shader @@ -0,0 +1,297 @@ +Shader /*ase_name*/ "Hidden/Templates/Legacy/Multi Pass Unlit" /*end*/ +{ + Properties + { + /*ase_props*/ + } + + SubShader + { + Tags { "RenderType"="Opaque" } + LOD 100 + + Cull Off + CGINCLUDE + #pragma target 3.0 + ENDCG + + /*ase_pass*/ + Pass + { + /*ase_main_pass*/ + Name "ForwardBase" + Tags { "LightMode"="ForwardBase" } + + /*ase_all_modules*/ + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_fwdbase + #ifndef UNITY_PASS_FORWARDBASE + #define UNITY_PASS_FORWARDBASE + #endif + #include "UnityCG.cginc" + /*ase_pragma*/ + /*ase_globals*/ + + struct appdata + { + float4 vertex : POSITION; + float3 normal : NORMAL; + UNITY_VERTEX_INPUT_INSTANCE_ID + /*ase_vdata:p=p;n=n*/ + }; + + struct v2f + { + float4 pos : SV_POSITION; + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + /*ase_interp(1,):sp=sp.xyzw*/ + }; + + v2f vert ( appdata v /*ase_vert_input*/) + { + v2f o; + UNITY_INITIALIZE_OUTPUT(v2f,o); + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + UNITY_TRANSFER_INSTANCE_ID(v, o); + + /*ase_vert_code:v=appdata;o=v2f*/ + + v.vertex.xyz += /*ase_vert_out:Local Vertex;Float3;_Vertex*/ float3(0,0,0) /*end*/; + o.pos = UnityObjectToClipPos(v.vertex); + #if ASE_SHADOWS + #if UNITY_VERSION >= 560 + UNITY_TRANSFER_SHADOW( o, v.texcoord ); + #else + TRANSFER_SHADOW( o ); + #endif + #endif + return o; + } + + float4 frag (v2f i /*ase_frag_input*/) : SV_Target + { + float3 outColor; + float outAlpha; + + /*ase_frag_code:i=v2f*/ + + outColor = /*ase_frag_out:Color;Float3;_Color*/float3(1,1,1)/*end*/; + outAlpha = /*ase_frag_out:Alpha;Float;_Alpha*/1/*end*/; + clip(outAlpha); + return float4(outColor,outAlpha); + } + ENDCG + } + + /*ase_pass*/ + Pass + { + Name "ForwardAdd" + Tags { "LightMode" = "ForwardAdd" } + ZWrite Off + Blend One One + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_fwdadd_fullshadows + #ifndef UNITY_PASS_FORWARDADD + #define UNITY_PASS_FORWARDADD + #endif + #include "UnityCG.cginc" + /*ase_pragma*/ + /*ase_globals*/ + + struct appdata + { + float4 vertex : POSITION; + float3 normal : NORMAL; + UNITY_VERTEX_INPUT_INSTANCE_ID + /*ase_vdata:p=p;n=n*/ + }; + + struct v2f + { + float4 pos : SV_POSITION; + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + /*ase_interp(1,):sp=sp.xyzw*/ + }; + + v2f vert ( appdata v /*ase_vert_input*/) + { + v2f o; + UNITY_INITIALIZE_OUTPUT(v2f,o); + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + UNITY_TRANSFER_INSTANCE_ID(v, o); + + /*ase_vert_code:v=appdata;o=v2f*/ + + v.vertex.xyz += /*ase_vert_out:Local Vertex;Float3;_Vertex*/ float3(0,0,0) /*end*/; + o.pos = UnityObjectToClipPos(v.vertex); + #if ASE_SHADOWS + #if UNITY_VERSION >= 560 + UNITY_TRANSFER_SHADOW( o, v.texcoord ); + #else + TRANSFER_SHADOW( o ); + #endif + #endif + return o; + } + + float4 frag (v2f i /*ase_frag_input*/) : SV_Target + { + float3 outColor; + float outAlpha; + + /*ase_frag_code:i=v2f*/ + + outColor = /*ase_frag_out:Color;Float3;_Color*/float3(1,1,1)/*end*/; + outAlpha = /*ase_frag_out:Alpha;Float;_Alpha*/1/*end*/; + clip(outAlpha); + return float4(outColor,outAlpha); + } + ENDCG + } + + /*ase_pass*/ + Pass + { + Name "Deferred" + Tags { "LightMode" = "Deferred" } + + /*ase_all_modules*/ + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_prepassfinal + #ifndef UNITY_PASS_DEFERRED + #define UNITY_PASS_DEFERRED + #endif + #include "UnityCG.cginc" + /*ase_pragma*/ + /*ase_globals*/ + + struct appdata + { + float4 vertex : POSITION; + float3 normal : NORMAL; + UNITY_VERTEX_INPUT_INSTANCE_ID + /*ase_vdata:p=p;n=n*/ + }; + + struct v2f + { + float4 pos : SV_POSITION; + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + /*ase_interp(1,):sp=sp.xyzw*/ + }; + + v2f vert ( appdata v /*ase_vert_input*/) + { + v2f o; + UNITY_INITIALIZE_OUTPUT(v2f,o); + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + UNITY_TRANSFER_INSTANCE_ID(v, o); + + /*ase_vert_code:v=appdata;o=v2f*/ + + v.vertex.xyz += /*ase_vert_out:Local Vertex;Float3;_Vertex*/ float3(0,0,0) /*end*/; + o.pos = UnityObjectToClipPos(v.vertex); + #if ASE_SHADOWS + #if UNITY_VERSION >= 560 + UNITY_TRANSFER_SHADOW( o, v.texcoord ); + #else + TRANSFER_SHADOW( o ); + #endif + #endif + return o; + } + + void frag (v2f i /*ase_frag_input*/, out half4 outGBuffer0 : SV_Target0, out half4 outGBuffer1 : SV_Target1, out half4 outGBuffer2 : SV_Target2, out half4 outGBuffer3 : SV_Target3) + { + /*ase_frag_code:i=v2f*/ + + outGBuffer0 = /*ase_frag_out:GBuffer0;Float4*/0/*end*/; + outGBuffer1 = /*ase_frag_out:GBuffer1;Float4*/0/*end*/; + outGBuffer2 = /*ase_frag_out:GBuffer2;Float4*/0/*end*/; + outGBuffer3 = /*ase_frag_out:GBuffer3;Float4*/0/*end*/; + } + ENDCG + } + + /*ase_pass*/ + Pass + { + /*ase_hide_pass:SyncP*/ + Name "ShadowCaster" + Tags { "LightMode"="ShadowCaster" } + ZWrite On + ZTest LEqual + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_shadowcaster + #ifndef UNITY_PASS_SHADOWCASTER + #define UNITY_PASS_SHADOWCASTER + #endif + #include "UnityCG.cginc" + /*ase_pragma*/ + /*ase_globals*/ + + struct appdata + { + float4 vertex : POSITION; + float3 normal : NORMAL; + UNITY_VERTEX_INPUT_INSTANCE_ID + /*ase_vdata:p=p;n=n*/ + }; + + struct v2f + { + V2F_SHADOW_CASTER; + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + /*ase_interp(1,):sp=sp.xyzw*/ + }; + + + v2f vert ( appdata v /*ase_vert_input*/) + { + v2f o; + UNITY_INITIALIZE_OUTPUT(v2f,o); + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + UNITY_TRANSFER_INSTANCE_ID(v, o); + + /*ase_vert_code:v=appdata;o=v2f*/ + + v.vertex.xyz += /*ase_vert_out:Local Vertex;Float3;_Vertex*/ float3(0,0,0) /*end*/; + TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) + return o; + } + + float4 frag (v2f i /*ase_frag_input*/) : SV_Target + { + float3 outColor; + float outAlpha; + + /*ase_frag_code:i=v2f*/ + + outColor = /*ase_frag_out:Color;Float3;_Color*/float3(1,1,1)/*end*/; + outAlpha = /*ase_frag_out:Alpha;Float;_Alpha*/1/*end*/; + clip(outAlpha); + SHADOW_CASTER_FRAGMENT(i) + } + ENDCG + } + /*ase_pass_end*/ + } + CustomEditor "ASEMaterialInspector" +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/MultiPassUnlit.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/MultiPassUnlit.shader.meta new file mode 100644 index 0000000..aab11e9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/MultiPassUnlit.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e1de45c0d41f68c41b2cc20c8b9c05ef +timeCreated: 1496328687 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Particle Alpha Blend.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Particle Alpha Blend.shader new file mode 100644 index 0000000..c501235 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Particle Alpha Blend.shader @@ -0,0 +1,123 @@ +Shader /*ase_name*/ "Hidden/Templates/Legacy/Particles Alpha Blended" /*end*/ +{ + Properties + { + _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5) + _MainTex ("Particle Texture", 2D) = "white" {} + _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0 + /*ase_props*/ + } + + + Category + { + SubShader + { + Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" } + Blend SrcAlpha OneMinusSrcAlpha + ColorMask RGB + Cull Off + Lighting Off + ZWrite Off + ZTest LEqual + /*ase_pass*/ + Pass { + + CGPROGRAM + #ifndef UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX + #define UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input) + #endif + + #pragma vertex vert + #pragma fragment frag + #pragma target 2.0 + #pragma multi_compile_instancing + #pragma multi_compile_particles + #pragma multi_compile_fog + /*ase_pragma*/ + + #include "UnityCG.cginc" + + struct appdata_t + { + float4 vertex : POSITION; + fixed4 color : COLOR; + float4 texcoord : TEXCOORD0; + UNITY_VERTEX_INPUT_INSTANCE_ID + /*ase_vdata:p=p;uv0=tc0;c=c*/ + }; + + struct v2f + { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float4 texcoord : TEXCOORD0; + UNITY_FOG_COORDS(1) + #ifdef SOFTPARTICLES_ON + float4 projPos : TEXCOORD2; + #endif + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + /*ase_interp(3,):sp=sp.xyzw;uv0=tc0;c=c*/ + }; + + + #if UNITY_VERSION >= 560 + UNITY_DECLARE_DEPTH_TEXTURE( _CameraDepthTexture ); + #else + uniform sampler2D_float _CameraDepthTexture; + #endif + + //Don't delete this comment + // uniform sampler2D_float _CameraDepthTexture; + + uniform sampler2D _MainTex; + uniform fixed4 _TintColor; + uniform float4 _MainTex_ST; + uniform float _InvFade; + /*ase_globals*/ + + v2f vert ( appdata_t v /*ase_vert_input*/ ) + { + v2f o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + UNITY_TRANSFER_INSTANCE_ID(v, o); + /*ase_vert_code:v=appdata_t;o=v2f*/ + + v.vertex.xyz += /*ase_vert_out:Offset;Float3*/ float3( 0, 0, 0 ) /*end*/; + o.vertex = UnityObjectToClipPos(v.vertex); + #ifdef SOFTPARTICLES_ON + o.projPos = ComputeScreenPos (o.vertex); + COMPUTE_EYEDEPTH(o.projPos.z); + #endif + o.color = v.color; + o.texcoord = v.texcoord; + UNITY_TRANSFER_FOG(o,o.vertex); + return o; + } + + fixed4 frag ( v2f i /*ase_frag_input*/ ) : SV_Target + { + UNITY_SETUP_INSTANCE_ID( i ); + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX( i ); + + #ifdef SOFTPARTICLES_ON + float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos))); + float partZ = i.projPos.z; + float fade = saturate (_InvFade * (sceneZ-partZ)); + i.color.a *= fade; + #endif + + /*ase_frag_code:i=v2f*/ + + fixed4 col = /*ase_frag_out:Color;Float4*/2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord.xy*_MainTex_ST.xy + _MainTex_ST.zw )/*end*/; + UNITY_APPLY_FOG(i.fogCoord, col); + return col; + } + ENDCG + } + } + } + CustomEditor "ASEMaterialInspector" +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Particle Alpha Blend.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Particle Alpha Blend.shader.meta new file mode 100644 index 0000000..8880a98 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Particle Alpha Blend.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0b6a9f8b4f707c74ca64c0be8e590de0 +timeCreated: 1496654572 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/PostProcess.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/PostProcess.shader new file mode 100644 index 0000000..e862731 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/PostProcess.shader @@ -0,0 +1,94 @@ +Shader /*ase_name*/ "Hidden/Templates/Legacy/PostProcess" /*end*/ +{ + Properties + { + _MainTex ( "Screen", 2D ) = "black" {} + /*ase_props*/ + } + + SubShader + { + Tags{ } + + ZTest Always + Cull Off + ZWrite Off + + /*ase_pass*/ + Pass + { + CGPROGRAM + + #pragma vertex vert_img_custom + #pragma fragment frag + #pragma target 3.0 + #include "UnityCG.cginc" + /*ase_pragma*/ + + struct appdata_img_custom + { + float4 vertex : POSITION; + half2 texcoord : TEXCOORD0; + /*ase_vdata:p=p;uv0=tc0*/ + }; + + struct v2f_img_custom + { + float4 pos : SV_POSITION; + half2 uv : TEXCOORD0; + half2 stereoUV : TEXCOORD2; + #if UNITY_UV_STARTS_AT_TOP + half4 uv2 : TEXCOORD1; + half4 stereoUV2 : TEXCOORD3; + #endif + /*ase_interp(4,):sp=sp.xyzw;uv0=tc0.xy;uv1=tc1;uv2=tc2;uv3=tc3*/ + }; + + uniform sampler2D _MainTex; + uniform half4 _MainTex_TexelSize; + uniform half4 _MainTex_ST; + + /*ase_globals*/ + + v2f_img_custom vert_img_custom ( appdata_img_custom v /*ase_vert_input*/ ) + { + v2f_img_custom o; + /*ase_vert_code:v=appdata_img_custom;o=v2f_img_custom*/ + o.pos = UnityObjectToClipPos( v.vertex ); + o.uv = float4( v.texcoord.xy, 1, 1 ); + + #if UNITY_UV_STARTS_AT_TOP + o.uv2 = float4( v.texcoord.xy, 1, 1 ); + o.stereoUV2 = UnityStereoScreenSpaceUVAdjust ( o.uv2, _MainTex_ST ); + + if ( _MainTex_TexelSize.y < 0.0 ) + o.uv.y = 1.0 - o.uv.y; + #endif + o.stereoUV = UnityStereoScreenSpaceUVAdjust ( o.uv, _MainTex_ST ); + return o; + } + + half4 frag ( v2f_img_custom i /*ase_frag_input*/) : SV_Target + { + #ifdef UNITY_UV_STARTS_AT_TOP + half2 uv = i.uv2; + half2 stereoUV = i.stereoUV2; + #else + half2 uv = i.uv; + half2 stereoUV = i.stereoUV; + #endif + + half4 finalColor; + + // ase common template code + /*ase_frag_code:i=v2f_img_custom*/ + + finalColor = /*ase_frag_out:Frag Color;Float4*/half4( 1, 1, 1, 1 )/*end*/; + + return finalColor; + } + ENDCG + } + } + CustomEditor "ASEMaterialInspector" +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/PostProcess.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/PostProcess.shader.meta new file mode 100644 index 0000000..010915c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/PostProcess.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c71b220b631b6344493ea3cf87110c93 +timeCreated: 1499337997 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Sprites-Default.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Sprites-Default.shader new file mode 100644 index 0000000..555eba9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Sprites-Default.shader @@ -0,0 +1,114 @@ +Shader /*ase_name*/"Hidden/Templates/Legacy/Sprites Default"/*end*/ +{ + Properties + { + [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} + _Color ("Tint", Color) = (1,1,1,1) + [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 + [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {} + /*ase_props*/ + } + + SubShader + { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + "PreviewType"="Plane" + "CanUseSpriteAtlas"="True" + } + + Cull Off + Lighting Off + ZWrite Off + Blend One OneMinusSrcAlpha + + /*ase_pass*/ + Pass + { + CGPROGRAM + #ifndef UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX + #define UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input) + #endif + #pragma vertex vert + #pragma fragment frag + #pragma target 3.0 + #pragma multi_compile _ PIXELSNAP_ON + #pragma multi_compile _ ETC1_EXTERNAL_ALPHA + #include "UnityCG.cginc" + /*ase_pragma*/ + + struct appdata_t + { + float4 vertex : POSITION; + float4 color : COLOR; + float2 texcoord : TEXCOORD0; + UNITY_VERTEX_INPUT_INSTANCE_ID + /*ase_vdata:p=p;uv0=tc0.xy;c=c*/ + }; + + struct v2f + { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float2 texcoord : TEXCOORD0; + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + /*ase_interp(1,):sp=sp.xyzw;uv0=tc0.xy;c=c*/ + }; + + uniform fixed4 _Color; + uniform float _EnableExternalAlpha; + uniform sampler2D _MainTex; + uniform sampler2D _AlphaTex; + /*ase_globals*/ + + v2f vert( appdata_t IN /*ase_vert_input*/ ) + { + v2f OUT; + UNITY_SETUP_INSTANCE_ID(IN); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); + UNITY_TRANSFER_INSTANCE_ID(IN, OUT); + /*ase_vert_code:IN=appdata_t;OUT=v2f*/ + + IN.vertex.xyz += /*ase_vert_out:Offset;Float3*/ float3(0,0,0) /*end*/; + OUT.vertex = UnityObjectToClipPos(IN.vertex); + OUT.texcoord = IN.texcoord; + OUT.color = IN.color * _Color; + #ifdef PIXELSNAP_ON + OUT.vertex = UnityPixelSnap (OUT.vertex); + #endif + + return OUT; + } + + fixed4 SampleSpriteTexture (float2 uv) + { + fixed4 color = tex2D (_MainTex, uv); + +#if ETC1_EXTERNAL_ALPHA + // get the color from an external texture (usecase: Alpha support for ETC1 on android) + fixed4 alpha = tex2D (_AlphaTex, uv); + color.a = lerp (color.a, alpha.r, _EnableExternalAlpha); +#endif //ETC1_EXTERNAL_ALPHA + + return color; + } + + fixed4 frag(v2f IN /*ase_frag_input*/ ) : SV_Target + { + UNITY_SETUP_INSTANCE_ID( IN ); + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX( IN ); + + /*ase_frag_code:IN=v2f*/ + fixed4 c = /*ase_frag_out:Color;Float4*/SampleSpriteTexture (IN.texcoord) * IN.color/*end*/; + c.rgb *= c.a; + return c; + } + ENDCG + } + } + CustomEditor "ASEMaterialInspector" +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Sprites-Default.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Sprites-Default.shader.meta new file mode 100644 index 0000000..560e691 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Sprites-Default.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0f8ba0101102bb14ebf021ddadce9b49 +timeCreated: 1500572363 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UIDefault.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UIDefault.shader new file mode 100644 index 0000000..d537951 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UIDefault.shader @@ -0,0 +1,133 @@ +Shader /*ase_name*/"Hidden/Templates/Legacy/UIDefault"/*end*/ +{ + Properties + { + [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} + _Color ("Tint", Color) = (1,1,1,1) + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _ColorMask ("Color Mask", Float) = 15 + + [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0 + /*ase_props*/ + } + + SubShader + { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + "PreviewType"="Plane" + "CanUseSpriteAtlas"="True" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull Off + Lighting Off + ZWrite Off + ZTest [unity_GUIZTestMode] + Blend SrcAlpha OneMinusSrcAlpha + ColorMask [_ColorMask] + + /*ase_pass*/ + Pass + { + Name "Default" + CGPROGRAM + #ifndef UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX + #define UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input) + #endif + #pragma vertex vert + #pragma fragment frag + #pragma target 3.0 + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + /*ase_pragma*/ + + struct appdata_t + { + float4 vertex : POSITION; + float4 color : COLOR; + float2 texcoord : TEXCOORD0; + UNITY_VERTEX_INPUT_INSTANCE_ID + /*ase_vdata:p=p;uv0=tc0.xy;c=c*/ + }; + + struct v2f + { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + half2 texcoord : TEXCOORD0; + float4 worldPosition : TEXCOORD1; + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + /*ase_interp(2,):sp=sp.xyzw;uv0=tc0.xy;c=c;uv1=tc1.xyzw*/ + }; + + uniform fixed4 _Color; + uniform fixed4 _TextureSampleAdd; + uniform float4 _ClipRect; + uniform sampler2D _MainTex; + /*ase_globals*/ + + v2f vert( appdata_t IN /*ase_vert_input*/ ) + { + v2f OUT; + UNITY_SETUP_INSTANCE_ID( IN ); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); + UNITY_TRANSFER_INSTANCE_ID(IN, OUT); + OUT.worldPosition = IN.vertex; + /*ase_vert_code:IN=appdata_t;OUT=v2f*/ + + OUT.worldPosition.xyz += /*ase_vert_out:Offset;Float3*/ float3( 0, 0, 0 ) /*end*/; + OUT.vertex = UnityObjectToClipPos(OUT.worldPosition); + + OUT.texcoord = IN.texcoord; + + OUT.color = IN.color * _Color; + return OUT; + } + + fixed4 frag(v2f IN /*ase_frag_input*/ ) : SV_Target + { + UNITY_SETUP_INSTANCE_ID( IN ); + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX( IN ); + + /*ase_frag_code:IN=v2f*/ + half4 color = /*ase_frag_out:Color;Float4*/(tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color/*end*/; + + #ifdef UNITY_UI_CLIP_RECT + color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); + #endif + + #ifdef UNITY_UI_ALPHACLIP + clip (color.a - 0.001); + #endif + + return color; + } + ENDCG + } + } + CustomEditor "ASEMaterialInspector" +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UIDefault.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UIDefault.shader.meta new file mode 100644 index 0000000..0d8bdf7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UIDefault.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5056123faa0c79b47ab6ad7e8bf059a4 +timeCreated: 1496313583 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Unlit.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Unlit.shader new file mode 100644 index 0000000..46cd41e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Unlit.shader @@ -0,0 +1,103 @@ +Shader /*ase_name*/ "Hidden/Templates/Unlit" /*end*/ +{ + Properties + { + /*ase_props*/ + } + + SubShader + { + /*ase_subshader_options:Name=Additional Options + Option:Vertex Position,InvertActionOnDeselection:Absolute,Relative:Relative + Absolute:SetDefine:ASE_ABSOLUTE_VERTEX_POS 1 + Absolute:SetPortName:1,Vertex Position + Relative:SetPortName:1,Vertex Offset + */ + + Tags { "RenderType"="Opaque" } + LOD 100 + + /*ase_all_modules*/ + + /*ase_pass*/ + Pass + { + Name "Unlit" + Tags { "LightMode" = "ForwardBase" } + CGPROGRAM + + #ifndef UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX + //only defining to not throw compilation error over Unity 5.5 + #define UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input) + #endif + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_instancing + #include "UnityCG.cginc" + /*ase_pragma*/ + + struct appdata + { + float4 vertex : POSITION; + float4 color : COLOR; + /*ase_vdata:p=p;c=c*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct v2f + { + float4 vertex : SV_POSITION; + #ifdef ASE_NEEDS_FRAG_WORLD_POSITION + float3 worldPos : TEXCOORD0; + #endif + /*ase_interp(1,):sp=sp.xyzw;wp=tc0*/ + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + }; + + /*ase_globals*/ + + v2f vert ( appdata v /*ase_vert_input*/) + { + v2f o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + UNITY_TRANSFER_INSTANCE_ID(v, o); + + /*ase_vert_code:v=appdata;o=v2f*/ + float3 vertexValue = float3(0, 0, 0); + #if ASE_ABSOLUTE_VERTEX_POS + vertexValue = v.vertex.xyz; + #endif + vertexValue = /*ase_vert_out:Vertex Offset;Float3*/vertexValue/*end*/; + #if ASE_ABSOLUTE_VERTEX_POS + v.vertex.xyz = vertexValue; + #else + v.vertex.xyz += vertexValue; + #endif + o.vertex = UnityObjectToClipPos(v.vertex); + + #ifdef ASE_NEEDS_FRAG_WORLD_POSITION + o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; + #endif + return o; + } + + fixed4 frag (v2f i /*ase_frag_input*/) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(i); + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); + fixed4 finalColor; + #ifdef ASE_NEEDS_FRAG_WORLD_POSITION + /*ase_local_var:wp*/float3 WorldPosition = i.worldPos; + #endif + /*ase_frag_code:i=v2f*/ + + finalColor = /*ase_frag_out:Frag Color;Float4*/fixed4(1,1,1,1)/*end*/; + return finalColor; + } + ENDCG + } + } + CustomEditor "ASEMaterialInspector" +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Unlit.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Unlit.shader.meta new file mode 100644 index 0000000..0c928b0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/Unlit.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0770190933193b94aaa3065e307002fa +timeCreated: 1496328687 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UnlitLightmap.shader b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UnlitLightmap.shader new file mode 100644 index 0000000..236a6ab --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UnlitLightmap.shader @@ -0,0 +1,127 @@ +Shader /*ase_name*/ "Hidden/Templates/Legacy/UnlitLightmap" /*end*/ +{ + Properties + { + /*ase_props*/ + } + + SubShader + { + Tags { "RenderType"="Opaque" } + LOD 100 + /*ase_all_modules*/ + CGINCLUDE + #ifndef UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX + #define UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input) + #endif + ENDCG + Pass + { + /*ase_main_pass*/ + Tags{ "LightMode" = "VertexLMRGBM" "RenderType" = "Opaque" } + Name "Unlit LM" + CGPROGRAM + #pragma target 2.0 + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + /*ase_pragma*/ + + struct appdata + { + float4 vertex : POSITION; + UNITY_VERTEX_INPUT_INSTANCE_ID + /*ase_vdata:p=p*/ + }; + + struct v2f + { + float4 vertex : SV_POSITION; + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + /*ase_interp(0,):sp=sp.xyzw*/ + }; + + /*ase_globals*/ + + v2f vert ( appdata v /*ase_vert_input*/) + { + v2f o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + UNITY_TRANSFER_INSTANCE_ID(v, o); + /*ase_vert_code:v=appdata;o=v2f*/ + + v.vertex.xyz += /*ase_vert_out:Local Vertex;Float3;_Vertex*/ float3(0,0,0) /*end*/; + o.vertex = UnityObjectToClipPos(v.vertex); + return o; + } + + fixed4 frag (v2f i /*ase_frag_input*/) : SV_Target + { + UNITY_SETUP_INSTANCE_ID( i ); + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX( i ); + fixed4 finalColor; + /*ase_frag_code:i=v2f*/ + + finalColor = /*ase_frag_out:Frag Color;Float4;_Color*/fixed4(1,1,1,1)/*end*/; + return finalColor; + } + ENDCG + } + + Pass + { + /*ase_hide_pass*/ + Tags{ "LightMode" = "VertexLM" "RenderType" = "Opaque" } + Name "Unlit LM Mobile" + CGPROGRAM + #pragma target 2.0 + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + /*ase_pragma*/ + + struct appdata + { + float4 vertex : POSITION; + UNITY_VERTEX_INPUT_INSTANCE_ID + /*ase_vdata:p=p*/ + }; + + struct v2f + { + float4 vertex : SV_POSITION; + UNITY_VERTEX_OUTPUT_STEREO + /*ase_interp(0,):sp=sp.xyzw*/ + }; + + /*ase_globals*/ + + v2f vert ( appdata v /*ase_vert_input*/) + { + v2f o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + /*ase_vert_code:v=appdata;o=v2f*/ + + v.vertex.xyz += /*ase_vert_out:Local Vertex;Float3;_Vertex*/ float3(0,0,0) /*end*/; + o.vertex = UnityObjectToClipPos(v.vertex); + return o; + } + + fixed4 frag (v2f i /*ase_frag_input*/) : SV_Target + { + UNITY_SETUP_INSTANCE_ID( i ); + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX( i ); + fixed4 finalColor; + /*ase_frag_code:i=v2f*/ + + finalColor = /*ase_frag_out:Frag Color;Float4;_Color*/fixed4(1,1,1,1)/*end*/; + return finalColor; + } + ENDCG + } + } + CustomEditor "ASEMaterialInspector" +} diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UnlitLightmap.shader.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UnlitLightmap.shader.meta new file mode 100644 index 0000000..38c7e30 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/Legacy/UnlitLightmap.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 899e609c083c74c4ca567477c39edef0 +timeCreated: 1528987785 +licenseType: Store +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/PPStackTemplates.unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/PPStackTemplates.unitypackage.meta new file mode 100644 index 0000000..d2aa6b0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/PPStackTemplates.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f86c907c9d9e85846835ba31e656bd60 +timeCreated: 1550245105 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy).meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy).meta new file mode 100644 index 0000000..1d7537c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy).meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: cc9e432e1a0a4764f80870c080173cb7 +folderAsset: yes +timeCreated: 1520621311 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 3xx (Legacy).unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 3xx (Legacy).unitypackage.meta new file mode 100644 index 0000000..36f907a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 3xx (Legacy).unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4dc1afbcc68875c4780502f5e6b80158 +timeCreated: 1540292246 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: \ No newline at end of file diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 4xx (Legacy).unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 4xx (Legacy).unitypackage.meta new file mode 100644 index 0000000..723e586 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 4xx (Legacy).unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5d615bf612f33364e96fb9fd2959ae9c +timeCreated: 1555497476 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 572 (Legacy).unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 572 (Legacy).unitypackage.meta new file mode 100644 index 0000000..e1e2fdf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 572 (Legacy).unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f51b7b861facbc3429fcc5f1f6f91183 +timeCreated: 1557327368 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 5xx (Legacy).unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 5xx (Legacy).unitypackage.meta new file mode 100644 index 0000000..7083290 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 5xx (Legacy).unitypackage.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2d7fe4f7c19e90f41b893bc01fc17230 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 6xx (Legacy).unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 6xx (Legacy).unitypackage.meta new file mode 100644 index 0000000..152e7ef --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 6xx (Legacy).unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e137dba02f4d0f542ab09dcedea27314 +timeCreated: 1583243128 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 718 - 743 (Legacy).unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 718 - 743 (Legacy).unitypackage.meta new file mode 100644 index 0000000..f990e17 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 718 - 743 (Legacy).unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 38b4bfd7c725505409f8f4d944961db4 +timeCreated: 1622209077 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 7xx - 9xx (Legacy).unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 7xx - 9xx (Legacy).unitypackage.meta new file mode 100644 index 0000000..3c74694 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/HDSRPTemplates 7xx - 9xx (Legacy).unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3aeabe705b70b154ea99893f91351100 +timeCreated: 1607957446 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/LWSRPTemplates 3xx (Legacy).unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/LWSRPTemplates 3xx (Legacy).unitypackage.meta new file mode 100644 index 0000000..e46ecb3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/LWSRPTemplates 3xx (Legacy).unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b53d2f3b156ff104f90d4d7693d769c8 +timeCreated: 1540215707 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/LWSRPTemplates 4xx (Legacy).unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/LWSRPTemplates 4xx (Legacy).unitypackage.meta new file mode 100644 index 0000000..5dc9074 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/LWSRPTemplates 4xx (Legacy).unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3e8eabcfae1e5aa4397de89fedeb48db +timeCreated: 1555497476 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/README.txt b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/README.txt new file mode 100644 index 0000000..e2c4956 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/README.txt @@ -0,0 +1,36 @@ +Both High Definition and Lightweight rendering pipelines are in development and in a preview state, so Amplify Shader Editor may have some nodes that are not fully updated for them. +At the moment there are, for each SRP, two separate packages inside Amplify Shader Editor. They contemplate two major SRP versions that exist at the moment. +For Unity 2018.2 and below, users can only install v3.x.x for both HD and LW rendering pipelines and as such they will need to unpack the unity packages containing the 3xx (Legacy) tag. +For Unity 2018.3, users can only install v4.x.x for both HD and LW rendering pipelines and as such they will need to unpack the unity packages containing the 4xx (Legacy) tag. +For Unity 2019.1 and above, users can only install v5.x.x for both HD and LW rendering pipelines and as such they will need to unpack the unity packages NOT containing the (Legacy) tag. + +Unity 2018.2.x, HD and LW v3.x.x: +* HDSRPTemplates 3xx (Legacy).unitypackage + * HD PBR + * HD Unlit + +* LWSRPTemplates 3xx (Legacy).unitypackage + * Lightweight PBR + * Lightweight Unlit + +Unity 2018.3.x, HD and LW v4.x.x: +* HDSRPTemplates 4xx (Legacy).unitypackage + * HD Lit + * HD PBR + * HD Unlit + +* LWSRPTemplates 4xx (Legacy).unitypackage + * Lightweight PBR + * Lightweight Unlit + +Unity 2019.1.x, HD and LW v5.x.x: +* HDSRPTemplates.unitypackage + * HD Lit + * HD PBR + * HD Unlit + +* LWSRPTemplates.unitypackage + * Lightweight PBR + * Lightweight Unlit + +Upon unpacking, the templates they may not be instantly available at the ( Create > Amplify Shader > ... ) menu over you project view, but a user can create p.e. a new Amplify Surface Shader, go to its Shader Type menu over the left Node Properties window and select its newly installed template. \ No newline at end of file diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/README.txt.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/README.txt.meta new file mode 100644 index 0000000..0357e65 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/README.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2700348f89ce70c45a61d215e6999fee +timeCreated: 1541774040 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/USRPTemplates 7xx - 9xx (Legacy).unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/USRPTemplates 7xx - 9xx (Legacy).unitypackage.meta new file mode 100644 index 0000000..a042bad --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/SRP (Legacy)/USRPTemplates 7xx - 9xx (Legacy).unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f54faaaf4faf8784183ede7f87dfeb23 +timeCreated: 1608224299 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/USRPTemplates.unitypackage.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/USRPTemplates.unitypackage.meta new file mode 100644 index 0000000..cc3f5dd --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Templates/USRPTemplates.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 57fcea0ed8b5eb347923c4c21fa31b57 +timeCreated: 1569420442 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures.meta new file mode 100644 index 0000000..f2b28c6 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c7eb84ba37e424945bd8c7221dc5b55a +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/About.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/About.png new file mode 100644 index 0000000000000000000000000000000000000000..55b5017baef01e37d85cb8c88122d5599e31d810 GIT binary patch literal 57164 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 KMNUMnLSTaJGD55X literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/About.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/About.png.meta new file mode 100644 index 0000000..1caa32d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/About.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 8aba6bb20faf8824d9d81946542f1ce1 +timeCreated: 1481127003 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/Icon64.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/Icon64.png new file mode 100644 index 0000000000000000000000000000000000000000..d8f46d3884b754bcd9ce954c056e16a466df61a1 GIT binary patch literal 46810 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/Icon64.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/Icon64.png.meta new file mode 100644 index 0000000..0ca0e8c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/Icon64.png.meta @@ -0,0 +1,82 @@ +fileFormatVersion: 2 +guid: 2c6536772776dd84f872779990273bfc +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: -100 + 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: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 64 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 64 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: WebGL + maxTextureSize: 64 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/black.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/black.png new file mode 100644 index 0000000000000000000000000000000000000000..bc9d9b91166e3a33adb947a900ab3e44cd7427f7 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1SHiab7}%9&H|6fVg?3oVGw3ym^DWND9B#o z>Fdh=fJ1^ulj)9plL1gjHZvrm#5q4VH#M&W$Yo$~E=o--Nlj5G&n(GMaQE~LNYP7W l2a5A}x;Tb#Tu)9=kOlHg7#Nq=Zkz+s;OXk;vd$@?2>`?PA29#` literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/black.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/black.png.meta new file mode 100644 index 0000000..47736ae --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/black.png.meta @@ -0,0 +1,59 @@ +fileFormatVersion: 2 +guid: 7a170cdb7cc88024cb628cfcdbb6705c +timeCreated: 1481126998 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + 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 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/blue.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/blue.png new file mode 100644 index 0000000000000000000000000000000000000000..3d77530c8a8f9c67b796b6372e654b0ec5670a99 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1SHiab7}%9&H|6fVg?3oVGw3ym^DWND9B#o z>Fdh=fJ1^uTkOkclk-3!+02lL66gHf+|;}hAeVu`xhOTUBsE2$JhLQ2!QIn0AVn{g v9Vjm1>Eal|aXmRD;m3IfW*;6826J`>!^@29#b$QTKpH(={an^LB{Ts5U6><| literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/blue.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/blue.png.meta new file mode 100644 index 0000000..bf20fa3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/blue.png.meta @@ -0,0 +1,59 @@ +fileFormatVersion: 2 +guid: 826f80ee0ad07444c8558af826a4df2e +timeCreated: 1481127000 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + 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 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/flat.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/flat.png new file mode 100644 index 0000000000000000000000000000000000000000..ce71188cf309a0bb6c9953a8b0cf018084139b28 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1SHiab7}%9&H|6fVg?3oVGw3ym^DWND9B#o z>Fdh=fJ1^ui@&pZtshWGHZvrm#5q4VH#M&W$Yo$~E=o--Nlj5G&n(GMaQE~LNYP7W v2a1b$x;Tb#Tu)xJ{{MLfW*;6826J|X{an^LB{Ts59-t!Y literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/flat.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/flat.png.meta new file mode 100644 index 0000000..723b460 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/flat.png.meta @@ -0,0 +1,59 @@ +fileFormatVersion: 2 +guid: 194a51ad3c0179644abea3f196c5ebe6 +timeCreated: 1481126977 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + 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 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/green.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/green.png new file mode 100644 index 0000000000000000000000000000000000000000..2128cfbf163befa94a4cb9552a08d082158185d0 GIT binary patch literal 156 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1SHiab7}%9&H|6fVg?3oVGw3ym^DWND9B#o z>Fdh=fJ1^u%fir(!x1PXn;8;O;+&tGo0?YwFdh=fJ1^u)9ml+vR0swY-UJAiF1B#Zfaf$kjuc}T$GwvlA5AWo>`Ki;O^-gkfN8$ v4ip#hba4#fxSqUb{rdCFdh=fJ1^uOMQlUDpY-UJAiF1B#Zfaf$kjuc}T$GwvlA5AWo>`Ki;O^-gkfN8$ r4ip#gba4#fxSssyd;^0Ik4qtg@kK`Vk8cB%K$<*V{an^LB{Ts5joBi~ literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/red.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/red.png.meta new file mode 100644 index 0000000..d3d0d16 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/red.png.meta @@ -0,0 +1,59 @@ +fileFormatVersion: 2 +guid: af5ab63a69b074347be0e4c17fb9dc1b +timeCreated: 1481127009 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + 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 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/white.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/white.png new file mode 100644 index 0000000000000000000000000000000000000000..393b83bf2ddf860179ad3fceb7719863b66625de GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1SHiab7}%9&H|6fVg?3oVGw3ym^DWND9B#o z>Fdh=fJ1^u!|3td=DR>4+02lL66gHf+|;}hAeVu`xhOTUBsE2$JhLQ2!QIn0AVn{g v9Vjm1>Eal|aXtCZ|Nr*PJO+jejCW)hrsXlS-jbMf6r|D9)z4*}Q$iB}rq(5| literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/white.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/white.png.meta new file mode 100644 index 0000000..d361ab0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/Textures/white.png.meta @@ -0,0 +1,59 @@ +fileFormatVersion: 2 +guid: 37e6f91f3efb0954cbdce254638862ea +timeCreated: 1481126984 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + 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 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI.meta new file mode 100644 index 0000000..a5bdca4 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b4971ff9c9d7bfd488d84e355318f683 +folderAsset: yes +timeCreated: 1481126944 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons.meta new file mode 100644 index 0000000..2652961 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f0f8f4a0c1ef2d14d975ace997712605 +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/AddToList.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/AddToList.png new file mode 100644 index 0000000000000000000000000000000000000000..996a7146d1964d80afd665a49004eb155636fdfb GIT binary patch literal 18832 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 E1rqqPwEzGB literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/AddToList.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/AddToList.png.meta new file mode 100644 index 0000000..3596781 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/AddToList.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: cccc116a6334dc1428687697c5a11d58 +timeCreated: 1481127016 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Checkmark.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Checkmark.png new file mode 100644 index 0000000000000000000000000000000000000000..fa6b9dcfdad2f06b23b99d2a620f5df927052f8d GIT binary patch literal 461 zcmV;;0W$uHP)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ-Q%OWYRCwCd);~)eVGzghS%s5a5gXHpWfT+JipjupCc3!|11`_ZJekS05FdxZeY?Hntw-3NUUu@Mm$5wYIRS)TR!x8-R7N<|ASAo;5X00000NkvXXu0mjf DXob0t literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Checkmark.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Checkmark.png.meta new file mode 100644 index 0000000..8c8f28f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Checkmark.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: e9c4642eaa083a54ab91406d8449e6ac +timeCreated: 1506956323 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 1 + 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: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: 5 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_OFF_Dark.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_OFF_Dark.png new file mode 100644 index 0000000000000000000000000000000000000000..af81db4e4acf7c9a11d3e7bf52404e3ea54b1dd4 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*XJZ3p^r=85p>QL70(Y)*K0-phB`o zkS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0x&hTHd%8G=RNPAX^Z&m+ uv)O?o4a^2^uC9O8ec4Zz0i_xK|7T_pN#qb*IjPSA#P@Xdb6Mw<&;$UAH7HI1 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_OFF_Dark.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_OFF_Dark.png.meta new file mode 100644 index 0000000..10bde39 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_OFF_Dark.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 1aaca50d084b0bb43854f075ce2f302b +timeCreated: 1526466929 +licenseType: Store +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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_ON_Dark.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_ON_Dark.png new file mode 100644 index 0000000000000000000000000000000000000000..da7b066297e7b2788e8badb9f01f50463cbd1236 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*XJZ3p^r=85p>QL70(Y)*K0-phB`o zkS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0x&hTXd%8G=RNN{#;mGCS zAi{7V-G}dIc$VJ6jvei@rWQv9h*g}v?&8uex!3#Xw2et0Brd9ndam+uF+c^bj9D}E;pUXO@geCwpWI1vG literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_ON_Dark.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_ON_Dark.png.meta new file mode 100644 index 0000000..17e618a --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CircularToggle_ON_Dark.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: ac0860a6a77e29d4091ba790a17daa0f +timeCreated: 1526466092 +licenseType: Store +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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFF.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFF.png new file mode 100644 index 0000000000000000000000000000000000000000..18a8f62d68ecf5c3f5d6b69aafd764037bf84e28 GIT binary patch literal 24764 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 Fe*p!Z?*;$> literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFF.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFF.png.meta new file mode 100644 index 0000000..6dc17c9 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFF.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: f62c0c3a5ddcd844e905fb2632fdcb15 +timeCreated: 1481127028 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFFNew.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFFNew.png new file mode 100644 index 0000000000000000000000000000000000000000..f3d4d94d9e05aa41fbf43b577cae9ae0fc7e0e1f GIT binary patch literal 19719 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFFNew.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFFNew.png.meta new file mode 100644 index 0000000..9a6ba5e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupOFFNew.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: df0f2e2030492c14d9237317aef419cd +timeCreated: 1481127018 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupON.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupON.png new file mode 100644 index 0000000000000000000000000000000000000000..b5f6667d2521db1938113910d7b456913e5fc192 GIT binary patch literal 24813 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 Dap**) literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupONNew.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupONNew.png.meta new file mode 100644 index 0000000..6d1f63f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CleanupONNew.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: e86ba70d2363b9443beac28a6a370b87 +timeCreated: 1481127021 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpAddIconActive.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpAddIconActive.png new file mode 100644 index 0000000000000000000000000000000000000000..ce67536d01c4ec06959db6a4c7438f8435b92310 GIT binary patch literal 373 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@KN#5=*4F5rJ!QSPQfg+p*9+AZi z4BWyX%*Zfnjs#GUy~NYkmHi=`7(b_Z=iOuS3=E7+o-U3d8t128GW2S86kvUj?{vZG zh+c$-hL+$Oot7!v+U}pO5ZLQEOGNH~+r|rS21^100xoq%WEhM2xioR`>AcxjnScM> zo0hIKF-Q2eZHW0`d~8Q&M|j38x7{qVG6}NpD>N^1nO!)0=5ogjht)E_RCgR@xW1LG zb?xH#n6*`xq}(Ljj&Rt1$+BN_C#rDksy6-@wYP{KG5q)9ZqWKq2o^d|X|4c@) zFmTS(m6!J~j?Ild8tF3UPl15o@zQ%o?BtgDC7(&uHx^IJ*UedP@p$EB-fb6;CZ@$b z+`|(4ChXn59r3RJKkoFNaa`67swqUUv(Hn%)_9*MOh%0JKOLM0#R#BXtxoOcc73tN>k3YL-Gf#B?uDR!SKCk}g z8aeH;hCwIatr@P&&R;&Zl)v~|<*Lkh+2VlQG{aU-odovw3|AM$(Ah`y!v4JAdM;Wo z_d7Mx%=pT|N%yM``08FelGb+XYE&USS-zG%I=znYuQrwPt8$w zK3uYrcg^zilUZc0cJ&zDT+gDsch~&n<~uJ9=T@(qv}f+IwXcNBcV6ZYuUMVW{>Vh91ahuPybX*XB=X2QC4{aCu8CTp|VX=2+usHvVlxK;1f5~=sKPp-H zR6ZkoO}0gM$KuK*XYL%5dzbE)tdlTdrgt%mw}eQ#P4TWnWlM`^%$z=>X7=U0yLUyu zFMb){w!6vo&Lb10W%H#41uvhGITyM37sn8d^HVR_dOJG`v_4GNOG?(! z;Spm~bmNRzvA1{Xicb5`H@RlrsZRBhgOUoL6-PjtD zD*2CD|=7E~hJS8PZ9yaFxSLGv>bhnD~ Snau+FkipZ{&t;ucLK6TZ)OULT literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpRemoveIconNormal.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpRemoveIconNormal.png.meta new file mode 100644 index 0000000..ca97280 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/CustomExpRemoveIconNormal.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 839cb1530f95ad14ab58762161a9cb06 +timeCreated: 1498144034 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FitView.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FitView.png new file mode 100644 index 0000000000000000000000000000000000000000..b3b1dd9188bdb518d1cae04afa9856e7e23260ec GIT binary patch literal 19122 zcmeI4e{2)i9l#w}fd(1~Eg}O(Ju_*g>&5rOKA%sH!9R)7oP{Km5E$ir_Z+UVeaGD; zaUg0(0YM7lk9MUSAcUy4GBzj-RcpsuG>t-6%BHSRmH}Nirj=G*S=lCmfNt;n^Vu<6 zT2ie@XC=-z?|t9*`99z8``&xsC^yjDH1D43Y1I~s<(^1mum%2{0l%k=8w1}Lj@q&m z{-{!0=J_rAe>dX;_{-gL<6_lf8Go<-U1iy}qYgHX)gsZ**b8GOPqNPj=k`Wm(^M_g zu7$+}ur_f?US*xJSqpk3bApO0$Nu!wehREc(-7iS!Zm?zSvQXBW?KW#hMeAy?`Sb~`?a^jyKvIC!Sx;d+P7qd_t|uH$nkF8y zk~l%yari}JgoAa`Ea|f5UN&zvlst+MXIp~d+;s4_2HOfvlUcjHx3{;xm#UYPPCMat zyLB@pi9roa?MrD~8cV6OvPSZDfg4CL%D1gv&n(KRYy=U66vrL(_6T23Y|o zDS@JKjB@c#j35AwF>VKiafHJqP;pY=;*R`8h_N9PeMb>tzTgswj(!~ioGeBWZUN8? z255@HNXo%r3N{E?Y zk~u{Mx?>w`dC#H?Hfu>AlL-)(wfM2hhlxX7IXnbe`^fN{&(XUA zq;8c4vZgXxH#ee6ajlnAfUgrq$k6N*(DSep%}`mZrNhe2XP0+E`~n=Iay_@_2HqKW zaRg3cg3IZ`+ztnaF%G92qj*7Za(K)Yh=l0mp-StT1mOI^Jh2)T53%Si!`7$rY8IlV!`NSZF=vk(a za`KZPHp(aZ0{1N=mqYKIYrg#zX?XfES0r2FkA~Shdsx3W z>nCrxHVh6&@K^*-uPm~^DjZdZkv_|YmaM;=Wq3FpiPLKKV%P2dAIwENz8-nIk_uXa)mtVy6=i z2g9VxMbKd%?RUB15rM%e!r=%RW%f+LMK4q^4hoh&Xg5U>Oo%23KTR`!SJ;IU?qCS+ z-zpo*ww8WC^zv_dc_S7A0$=dG+^r-swNHV!g9Ok^KPvP*QCgT3cs4F6Nlx=3cgSL6 z&PyZq`7|+plM{kpOvT1U;_ziB^!MCQ zw7Y!h;#&_zyUT|bM=nf>nwQMYR@OYyKtWo(2~fRfC{VpMyU1H%bsy+F%bSo3%XBr1 zX^?0SiZFsyy$D7!xiRG(6$dUx2IeQr3`9C^2_+kQu)+`jxL_~*bzw*f$YzKUelK3p z2pdMtnUkP23}q9SAtF@4#D&r@lucZQh)@L+7fQoWHgOpuLKRG0C=El|#AS#GRWNa( zGz?`Emmwll!Ni5qFqBPPhKNuF6BkOuP&RQHB0?2RTqq4g*~Ddt2vsm~p)?F-6PF<( zRKdiB(lC@wT!x5H1rrxa!%#MH86rXzOk5}pL)pY-hzM0MaiKH}WfPYnB2>Y|h0-vT zOFma(Y3}q9SAtF@4#D&r@lucZQh)@L+ z7fQoWHgOpuLKRG0C=EmTmbj{m&+7px_>i7n_%xpS-i}A%lYHv*=K!_lp73BPd-ROs z#FkE|Gf~%Bq=@j}wJojPGEm?{iC#PU!g=`Up&OB)udVU;$*r$+wQ_Z@JuZ2xcL(Rs zU$9~Irk4ho>6_n~{f%8uk6X{oljYYZ{i0*)%8S;o&1iXjmvb%ivO8Ek)j#+8=-}5~ zo1SaAe(}btnHwHkzU@-`zOf%)UiR*4=6!kR`_s;JpO|p$!CA`}Km7Z}&%gcED<|vz zTQ?9nwR!xBpFceIC*GFzmisRK?8R4(-nHcPu4zvM_l((-p7Hj?k2n42+V~CgFMiYh zr#VkQ+g#h$@3_3+lS!V9N4?tmL!XZM;J}uR|MncKd++b}*TN|d*UbOXQ^#TlUtPCp zlT`KY=;zlQKXJk{c(`}pfm1aX#3c)B2j-4?>hkIH{r`HD`>=y)s(P>bz*o-QxbfZZ z?>Myfhpkrz`mSG@arU5NXJl{|Hl^0mHf7=YgTJoZOl(YB{=6poy=SKEA9cyH<=Xx3 z+J1j<M#HXA{bL@pJiBC{eIB?pe37ZsL(;FN|I~cIT*w^$me^Y(M$iu9cV1ZEaZn z>G%b^*6o~}S{q!2U$^~pLb}Fd=|8@bJ@$kB=Z^0W&FNBJ-f`EPA5Fe*&Dq22+8%sn z;K@g3I)8O&@S(ZmH;%57N2ePi@2vjKVF|10xWLrB*zu1yU%Dpmp77Jtd#`Rk``5-Z lt$o`b+06Cbm|FdKRp`|8{s%gUPxMDZMM6!%{r=@o{14tMDp~*l literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FitView.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FitView.png.meta new file mode 100644 index 0000000..924177e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FitView.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 1def740f2314c6b4691529cadeee2e9c +timeCreated: 1481126978 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FocusNode.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FocusNode.png new file mode 100644 index 0000000000000000000000000000000000000000..ae4dd1580cf4ebc969fdf3375489cd04d14b96c9 GIT binary patch literal 18938 zcmeI44{RG(8NglEwQIJCriis$D`7nTtlQ4_&v(8%C2sw)> z?i{COXi#8`AtKRv8d71v7*z+|n5KnMgfzsTcec-d z{*%6J^~55b)g)iu``-8Ne&6@Ld+&>SUmF|Uc75MXeIAeJ`r)D2IQ+Q@e!c&iRq*@d zduBfcf2=Uaw?#a2XE(h9e_2x++G%<`*S^pGTH!hH?G3PTwKbfKufDKq-CE+-vlkxP z4V%_m@hK~z<$-rpE&xwLSIXw7t^$9_RG&Yv<|U73+w)p#%9=`UmlVC=msLFt{4<3T z9P9B6Y?&#^$}V7e(;%xA2Ys)f{Hf2Yse`^9T#`zbq9CUY?KQx}-qDn@cb6inzAd4? zff)%JC;&_L&J^-RQ<@p{RqaYpwwph2ifS2>LghJ7@m*@R- zfa7`kb}vKG3`xO%JV6H}j+dCAxBl^k`k*vms2OQImZ(n$e;f4WEUP4uWTjH^S6IJp zWJy{SMcWL+5Kx0K_Y^I8hA5gh*NixJV!%`ktz>C>(QDh4(|Xw&^!eJ@YI z0NJkIoWE%a#AFMEARnHfID(~9G$*mF#0GAoXo;c_BQ?!78%gL3Rkmcuib&Xqg%ll> z0-O|}Q7bLF?RIok%j{W_m8NFh#sFzUMxa+cYV&GqUxG7|$;-Q=P$0Xx(X`^z(8KkJ z>FP)`wWkEgabW6YLjmz=P_%CDZfYDfgKr6@pn5a@>QRzRO2b9dl8Xu$j)h2QLg!(y1>A_*ZHi_=wSw+?M}6YPt@bjgW9 zNu?N8WqFEVg9=B`G~fwA46uYu2ZAb_VN^L2a3(^GbxiazLxcH3&LcYZeW-A|ntf#W;&W7T zpm@17P%~B4THJ`KXRL~BfN&N@NN0A6+Ig5mGgQrL>#%n7wdI}H-T_CL^7NItLE$n% znWh**4RS$33cn+;&>PFhh!7oCXHWoZgI~7ra_Q&H}Pj%z7=|E0;=nO_A;VN=_Hm`cA6xSaMv6 zSX)lf8WZAdA{q}cOzp`ngd==}3dDkp7>_4t_&|LdslK*X3#Mp6qTybT?`5R6ZbX-o z=HFdWdc{wMFooM|y={+m?yh^0Tb8@W8p**~3-!%b`!a9F8IlXC`2>?f>@3qrInE@A zjrNJ&!F@~ba_I88=PO^4*wc@@BH`kwermDXdirrrRGp_KyP9Ah4Qo&Kg#B!`Pu_5C zU=By{SOib660*N)995T)KHG-2tiQTtcsT9FX|;Blh_P;S=~sGStO{*Nr4B5{B3TvRgB9OU>@#XmrfbGqBVcvI~{o;dqp% zMILUa{jfICRj;cZr(_U@Boegr&|k?sv>1{qaa%$s`gFU6`g#!TCoW-6#S61{k=XE?QS2s^YTN{ z?)IV0k&{Ku3NiKB+M0U}6wGLg0JVEMf!eLLMLq$m`@rVe-h|v(wQEe90r{zz1|!I{ zi(rgUAJg8^b>L29pfg!@AkuMJD7Dyw6@K`~1+wwig^m6AC84nLqGr39Z!zTZ(aMJ>HfKorxsQ}{Mudjq(1oYvH6P& zYqr0>@yHKPChl7K_1o^B8WLXgo%;03@V=Am4UdPv`I2$*&zE*(e*2XhpL$5o-jSO8 z*5QqtZ`iu|9~X|!y?XY+bsL{~pz@L2bLFciN4|UK(f`iMADHu#_kHQf*M|C5Y+IT6 zS^pRBJ@v~U%r3m~=Jeg>KM((A|3dEWk4oYnuI_)j|CG3|eCS;N`4=S041DO^;r%0< zyn?6OdOUYv71%j@hI;nz`Xe_U`|2lNJ@?sT{r8+d z@nPb=M~)vnf9sn2zw`ZagE9LBul(KX%ckYRU oH*McP`P7Eb|NG7L*KP4!svH@5Vtw*YkhNzxJ{p^gd}iPO0PhOd!vFvP literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FocusNode.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FocusNode.png.meta new file mode 100644 index 0000000..78dc8da --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/FocusNode.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: da673e6179c67d346abb220a6935e359 +timeCreated: 1481127018 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help.png new file mode 100644 index 0000000000000000000000000000000000000000..6c55f1ad5ae7caea53eb1f49cb15943f76e4c3a3 GIT binary patch literal 23168 zcmeI42{@E%`@mn3Jxh^PIzuJNn0>VyYeJT?Rhr#o8JQ_duivLwXObYGZKoTj$Al)}nr z^%KvO9V!*g&BYenN{<$ei3!`U?4TpNSNf^MEA^8x5vQW}-uc+J?UZ*z>2T-$@k>t( zyK;w83u+}QBxR3Up&T$_vS&>fDZYrfdA+*rm9BBP^b&tSL9&3R&KX-Q0*r*}>#xwL zkhltn1U;0I1S)J(D&PxuPssO}Can_*ixjEg#^G%w!;}EykQmc5fU$*0SZboC6Ob+j zY`jaQv;(W5z{X|2c0L5cQb&@ui2xpl)s;ok;{eDUdbAnfr3d8JuH9=6xWWM?hRt;X z@DvKbtz8&a!1*GeqDDdH0w5_1z#XEamIGqjfQ`2nFAf4ClK>@)K^OfuEAkb(v_Voy z7xasl5X{3pB%zxnTwHV)Y1LS(tWd&|XONSPb*}{{sUpMC@-K$&0YG}3GC10yv7j2c z{F)kUOre}7w5MErLW4qSAMdEm@izv5Hg0I$xDKpfewdzknD6+>rTt=F8)VYA4DVxH zkT<>rq<24e8S>|`F+Xvz_}R0LSFfI~yl(12zT>iEoO#W&!ez|oL#Y1f@VggRUoHtp zt`D~q8+mc<-rH3f3u_NaMN*nNV=YIEWF|({9%@{-rWCtsE44e!-W+3=ynhIpp|QvG z(DEBg>nCV0TXjB)8n$A9^P3Dsw#7lS)>B2_+bmOX3m zi2;hg_Sd#DrH7DVk1qL zT)$?jU@A=uTNto$dG1bAtzGxet7&h9Ju+59S2%d>iuae(y|(7EoPodmpJd6jO0Cjx zDKV2 zj+gxNSVPiHc*W~^5~%AwaNX)E)8FtqQt{NgziH&k=2Xu=zcyF2WY0Tl?Qel%v%}3R zq_ARvrV#QX6D!wMu69qYvLFkWpcS7>;iN<(9j-0Yh|jXQsCh;4!}WO-Bx1L#mCoXZ z*|BqA3frPd*Ktc`?;#B;wsiw@6n8#ENoOdp9)fv@?`&4f_!*Ph-#I7XyB=#Ct?LzJC%5it3 zkE}eRd1Qe$%=v8gne3KqnKeUe?mEYw-Qct%-(n5Qsr{_fqoX-%vQt<0IxTQwp4H3R zoz2W*I~$!2bsO6w?pC#`%AR!EA^kVc_R?yI3{|xtNJrg!R?e<1;h5{1zukYfeXDj! z;+R^=K7;JDCkQ0eN|Z~1>Ea0b1q7(rj> zoqaUnsB4Z@jzf-RZy7efFEjN_nR$uZ$8b55n=6;CTV~0Ot(lqH<@C&{Ia4}wuB`#_ zUA}I%cgBJfC1!!;ewqD=X;(LdrLAITwgi`T{kd=lY|MGg_s`6Cma?wm1+q)T8)a+e z>EFO?X6viLZZ^JgAg!-5CS{P1kQ3S>ayH-)zg&lahk?|3TS zm|y5yxP#23s4$CeV2BtyQRfifS*Mb9ec5R;p9VLrbO#vzQYx6uobc&Ca{J35L2U3#yxMmAzWYeYbgi zTS)!8)RcmhYkgUb=lZeztp43i$M2z!FHdtraUN9NBE4|vs56o|egy8_nj30QvJYoo z>RJq=!s1-=o}4er2+STP52zTvHw-x5ZrHAmYeBZSdEUcS6x}MiYhT4q^NeaG{knL9 zHW4yW2V{mV6=90*2{#G%nDKEWWV?EKj1jSs{{F(VK9l|F#U{!ou{-m2c2wr6d)@l| zV4nJLS7J?E4NER+b?EDc2NL8?^1iB2*=13?qg-|w#rQ|N&aXoxU;^u!NSs!)Kh2Js zwWKf+_JniLl^AWqY~4-z&v94KSB$E48E*F;yQaEY``9cb=xXO<{d}&rj`j`hewq4G zrhS`ABJ9?B|KJlf*WN~D&ONI;TZeemcvZ9={_r0r3fft7_b(ls6Sy=+I{2E}HKqov z4qF%fl(bHJk=>w`wr$9v-{VR#!AowSGITnMBbS{$Sh{M~s^%18+T7%=5MQJLu?!J$ zDDL29(`gkGj`dyK-FA3%W^jnF6eI#Zj^3U zp1ESzTJc={%X&3KMMm?juvjv*wA$K%8 zp)*0wZ`QNt7iYDuz1a8ey?G-n;l5U5Nkk#3_*A+6X^zV-wJxYhi3~yg;TqCl^_A%oz{iF5Af?=clJ=xtOM?dy7UUW=iv0UMk;zy6w>J6M7V;ffVTFTx0K{OUS5Y<1g~Z(E4t{ zD~FtKvz~YFd>GFhtlgh_By~rq?uVw0jVBAYbx~_tH_5XHt|)NZ>dhzib?KGr)vO!5 z%pJVY*fGcDvP<$gqNi^Uw?}_G{-OQNl4B*w`NiwJi~B>$E^T8BcP~i8)il2?3w|?q zqTz8G!JxTpD1<$HWB6U`+~&}LWn(pWOP&QT>(48-FZFzD+-LHP)V%w#k;iz`(}AX6 zH&q0t57jkU4vR-c)Q-o!ihy1EF;q~FScTNv7KgO%Z$4`ifCJv2KQP4&JSgFi%cICR-t|C&|zPe-@n?lzO z^7RKdq5z<86y#5)degZO3Z2RFGtd|)Dc69oXa*WC7+bilKZ)+evI+^HJB8ReQ$xI| z1e%7Cp|pMw5p>{7=aL~ozCL~&VvvExC%;5c<~74KAfHsY-Ub>bybd9*wyPl|b^slM z(Zxck2m}IxBj_S9coY(&13|(O7#N%YL%^YM1Q7uzBH@tF9}PokP|^>eF^G<47N5HV z|7W1##pU`FVX(l!K;1x;E<1n;Ll6iA7#s;hBB7uLloRa7B?m$MIEyEpO!+aRbEp9< ze=dvd2jTf8Q`lR$1{xZ?j=p?8kIUEpOGkd3&+I^oupqKO4515${lLi9_V3MneZOnT z;hJv+@8t8yzS|+kIoO{LbEI?FTLP$b^R0A0?&9y=1c&QL=R*>}6{!AQNB&bslJDQw zm&-rIL8E@L^xqQT^C?m^Dva(!_XTgB1KJ_J3xmsI{9pjQD?jXx9>n^A8Sl!Z*{3-* z8ESoSA`?jgbTXG6;LK+G7*0-C{y_{phw-K-M9YQcM`H(amg~d5HQ`SjzBjrVnM*eW zEwNBI28zTvBXC4Gl88aC0B1NHKF!Ib<~KfU!9_$PbIH@ZV4(=KGXgXw5aGD#UcS=( z)(@M;Vgw81g|GRw4_jNJwI7E|_M_6R%?!b@>#|rhB8pBY(CB0W6i+6Tp-3be0i_VI zcqpEZqEjez8V-k^9OT#Le{pTbrf%WQ1JLzk2BER3p!+Y=ipW5tu}A^~4@DsnI4A-^ z$3pQ`3aOk`hZlE!>#J}XOFR6)V^C?ph$y8nvGoK_HTVE_co3Z{HPQegN z`k!Y0<30kt=zf1U{U=?0()zIz4x7OZBnQw z|G!&6|Gy$fW&3TV2mCYX4@|OTaFa?8;21Ij*uD^!FPTY)`TH>;TsDO4@9)E+l6iR* zw$+dJdCT|Z>u4&3(|r6d&QcmZfc4L0m}z(U1ry}oY|KBMQ*mSl84ss`8wd&p4W(1i zR45)r#X{+DG6sjHA_x=|Wh$(~mC4^LOnyuL#J1$8BgcSK(0Dkwea6xWcqk2l26vlq z8V!md<7p@aijHSssXrY#JQ0l)=G1RCls}zQ|3Mn%W!f)kcPfO_vemz3PW|^8^G~l# zI1PuP(^@Zw`0H7pR|DeJA}0507Q7uM@2eEdZvWtD4@Md+!V#zK zL8gi=f_@QxWByeZ{p=kquT0fjrph0JZjgB1r zziicsB(@Jbz?My;8-fL*?=?^J$-fN#;l=97zq>HxI9i%Qtj$SS1ObbMB6Y!|_jmQa z>u0LYWCGUBc;z6@w43BDYu=nNB{RQnow@*4C(KA-#~2LU!ps7R!y&L1CRkG(0guMv z;V1+eZT^qS7(XbdVX-(kmVy9Fl4vCQb2*I+2lvGc1crj5!NEEMxTpI23ds*#lNsRs z(g^6Eay>OE@n{qQjlvR8C#{ z=d&5BngpIkal;FBRbZ)o2(eXG5i6-4)O zHDiHwTn?`u$t%cyvibJHcMaX98BTTf$#B|*&xVuXo%a0Z)9RUQ1)mOq52j#Wo=p8^ zVe!69|K%V4i2miS`3{Ah@L32T32_MkiLWBW#b+UaB*Y~EB)*Ce7oUXyk`R{wkoYP> zTznP+NJ3l!K;o+iaq(FQAPI2^0Ew?6#KmVJfF#5v03^PO5Eq|?0Fn@w0Fd}9LR@?n z0!Tt!0zl%c2yyXQ2p|b@2>^+&BE-dKA%G;rB>*J8iVzo{g#eNemjICXDneX*76M2@ zTmnGis|a!NSqLBraR~s4uOh_7XCZ(j#3cYEzKReRpM?OD5SIXu_$oqNd=>&oLRTznP+NPmk%g}_L8w-awg3>a6ac~^0N}#}_`4ebw!i_PXCnX*6Tz35vJZLQ zumFIWd#%k(oP(bG9Px;5c2TY_zx00Gv$Kg&lSJSklh6r;MCi?{^I8+jS=r}i1#-agU_M{B2)LPY9mYt7rV&UIbKP+fzq zMIBZ9A4WIVrnEjkU;gf+m6`wVb>(eiqzCR1(TY3m=f7KV+%I>-2DoMldF?|DipZmf z=s=d=ctgUSBfhiZ!rlah;q1%z-#)ATzTZgf7yY-t#@&;yBFk5qsC0A_xOxXf`#J~X z8W@4JvLFkGO8TMHELpOs( z%Mcf1DsuB2dt?hXiC$|dnF%8s;yt^!q{Pnr<*LXn6|+|}6vvF#Eiqnx;9Y3flLm%- zhm5&a#`A8owhv2E!8fBOA>?Lgoa`#ylGm0#VXbmwcf|0=(o5%p2Mq1aGRGzI5APbD zYm?CO;c8B0w!joTi@>)z~HV%xv;ObO(qxtKJ7ia0rPtiEStW7)*Xg7=CV&QG(9 z=A0$DTSDbZrJg8WNv*aN?`^g`i4Ko>d1TL?(FDzaIrgq8&1$*3jaw!HM6Axv%y>7z z`EbqBGNMvDEb|n;_(pQwxwZM8qsh@>A`r3IwL?9%VF#-nWHa6-xV=d|_2z{i6{)~d z8Z0P>+V_o)&{*Rso88^zHf%f~f-uT%e;s&_i?r4}NUu6~HE`TBaGm}{r}*~nmwGbQ z4A1@bO1Y0@HqS1XzO`O#r=z0gvaWGgoto{q7|yw_p(B}@nq8ryK#f}vlO20ftoYia z*dq-a*FGR#v1FBruyIENcfUB?pcwu7G)Fwcv9Hp-ud2v72lq?#$+sR23{}VamCq-rV&XN(5sExuRNZ%qpw_ zaSV0b3ky5GQ0@ss-FTsWuHBl>*eJ;5tEG~0f5@-xfs~$8Y}0JH7o-Z2d=Z^B3uvzc z)WxDD6P1tMmCMc5F?=|1iBY!2>d@#NpT5ph9d}|1?(J_oFB5%HN_IvEko@w%{=4(B z_30vq_b7*yiI?Ia8d@23ET~aw%YZZZ&R16FyS^crU-rc}vAnD2<)2fx4geg?6@Xik z2X)yNIl5+&vmq7gK39(hS0Nf=Y??O=y?+xF3Gsj2lYb7?+uNcV#CFK*s~nBlu_|4! zOkPrBg@O(X$Z{_7oG;r@T42XgYpu$)3u2Rhmt?tzan@=dDK5yUzn8DIGEL=VQCT2_ zf?i1vDe;eIK4jac?UxF zx*b1XJ$_wJ#`}Vd!?93yW0T*b!oH@+Z4wzuTl=0(TyCh_qq9K$?uBfzV6uMC#Muqy z+vi0xhi=?fNqY0>&LD*j|J^Xld6b<(Z!K)7P;HcIX@#j@JXUbNrsXwf*RWg^<%3@J z{sg_$$DZzUNH=fq(DW#V+0_@dU-nmz{G)hn@AFvW>n*|a;!U>WW#YD#MGoPl`^AsT z>=ZjaC)lTTbMKn~W+Uo;=i_B%1;?dkA3U(DNQB$CR%K?GQjtykV^1r|*d!mx#sTA3 zqA%2gPO}z)F>9EQD$uKOW^~4&du)zppVRF_X{KB~L0Z5{E*UXVn{WDb=L8dgiHc9S U_s;78GdN&vZfBNnx^d@!0kB1s^Z)<= literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help.png.meta new file mode 100644 index 0000000..dfb1fde --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 066674048bbb1e64e8cdcc6c3b4abbeb +timeCreated: 1481126971 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help2.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help2.png new file mode 100644 index 0000000000000000000000000000000000000000..46b80b3fbe3fccde10598f714597d3d9e9fd159b GIT binary patch literal 21750 zcmeI4e{d969l(zSf%2oRB8r8|^}-)mvblY`d;6=GgIw;8q&ASbgyw>P+1q`atlZrm zcT0XyJ5p+^{vi}asL<9jqtH>NI(5pRoeHg@opwsAW3`}I2DAfCwRFnV4q)-^-R<4J zOTvaG{>ZpDB;md9d*8S3^L_8TZ@=H0{aX9V6?10ZGSlPn%xP_j#L?e{=x5%HY3TRr znr&;*pDFqHim>O&;|tHD!VTG$?!3n{Yp(e-#k1#;`KWTb(b^WBesGI?>Z(O1wbqW_!KexJ9{#Msd2YcdD)CfeG)&3X=c0}V7G zlK^;GwgE5!mId`*iUgFOME_Uj#1$m})4BKrM*;P{xo3iA=t(sKn9}fq6NnWerWwcul=hQr~1W`h4a< z1=tROuobpQS=W=SwCnX{bkLlV-PVBn{!Yy^jxQ|r$WVYNlT?=Nk`CcLbgFKSk&ZIRX+w}w6$H^9O<-w zBs1oXXg{)WX~m3a$b9Ee7W(5buW!o9Fxn3@M%~D&;;^###-Iu{udKh)DrsvITQhk> z%E+)a5<=^sLDLju4vvXY3>8VNB}Yf4=9!;X;opAq&1LD*|33Ds%bsv3DgxuhJh%sk1>P+7%tpOoo^O2}`` z%&M47mSY$NK!KGAK@kLkLZ%}Gp63V-2oeZL0ZI@gYkt>dIgTJ{f~3s*D1&Z-!Wv7< ze`D|bZy8P2Gw9@aJ)RHwS9J0;U@jk0b9&mVrKMizM+Z-@p?jrlHl@ju=~Dgu8Krc1 zD&L7L?lv9&!3Cq*^Bi9gnj+i0YuaFi-=gi28iK|>}<2*|Y(f<%)tgKU(d zJ(KpAJ*j(6E5;o(5r(jl=>J^Wh$OZJ|T- z>;xz)bT|=_2Rtr1mZ(Ez{?^m&q<-85oKxtp2*qaX(N}~OE3#P(3--DeLoq)0gl0aU z;Gfd{(sqt4V=6xD{vVytoP+W1j)2Gb9+u#QT{t*X3xE?(PkD1 zEK5)gz^=yDZbUs+2CE5W;2vdoOhE`DC z%*j%GsZX_F#E#vzj@Dp>jyAzHp%m91`oanNu8Y6?WtU+tz`6lW=-P6v5O1m;ZSmMIRL`NE-svhL&?SE004jsSsy87rFKz2ZZEiB# zbmcVk0wGVwrYy{%H)S6C#Sc%R_hBAvjWl(({OaXhNA9d`y7?$;=i_$>>b2D_dMw|p|5n7SkQ{JdNu_SxEG_|6@{`+DDaJ0vv+Q(d8jsibQW3j;Fd)f*KVKsW@O5vCkJP}KIQvI z<6l0$AX|I!{>SdQT=#g#g12ifFTZ==^d8UqFV-J8xODmYH-b}kH@))grBAf~sIF(; z!=5>(8hn=G5r6Bp*pI*Zt>^E4aq5kKSvsp`>4WQ+yxLWF z{0Hk!q>f!U#O~g`?K|IndY$JFf1Mvao0xsy*MIWry&Kl}6UU`#hi}~c_ohDzQ_t1z z{lcope*LF2xBqtTTdm^N3y0qS=H&~kGFRTXbYN)u{v`))zS`Q|k4)-mjjoJ58SdHo EFVqGEegFUf literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help2.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help2.png.meta new file mode 100644 index 0000000..e499d50 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Help2.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 77af20044e9766840a6be568806dc22e +timeCreated: 1488470300 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ItemCleanupOFF.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ItemCleanupOFF.png new file mode 100644 index 0000000000000000000000000000000000000000..3bf7e28d13e3fe33bef2fc5483b21db1c429aa98 GIT binary patch literal 22515 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Library.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Library.png.meta new file mode 100644 index 0000000..7df33cb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Library.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 9a81d7df8e62c044a9d1cada0c8a2131 +timeCreated: 1481127004 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveOFF.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveOFF.png new file mode 100644 index 0000000000000000000000000000000000000000..52c92d4bdd64ff3bc3170c2e5e055a8b4d5a5a5b GIT binary patch literal 22523 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveOFF.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveOFF.png.meta new file mode 100644 index 0000000..b29c03e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveOFF.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: bb16faf366bcc6c4fbf0d7666b105354 +timeCreated: 1481127011 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveON.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveON.png new file mode 100644 index 0000000000000000000000000000000000000000..d792d28855741d308efbe454b7eda93f0580c9b2 GIT binary patch literal 22677 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveON.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveON.png.meta new file mode 100644 index 0000000..57c5503 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LiveON.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 6a0ae1d7892333142aeb09585572202c +timeCreated: 1481126996 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LivePending.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LivePending.png new file mode 100644 index 0000000000000000000000000000000000000000..524e87a7c1f9d91bfd1df38b130acca1b7c87b9b GIT binary patch literal 22735 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 amj_Z$MNX?iyTpj!3uj|#Ps_Ggz4;%X5$vA; literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LivePending.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LivePending.png.meta new file mode 100644 index 0000000..b146db2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/LivePending.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: e3182200efb67114eb5050f8955e1746 +timeCreated: 1481127019 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MaximizeWindow.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MaximizeWindow.png new file mode 100644 index 0000000000000000000000000000000000000000..27d01c545f1d5563014cd8b2b067a7f8b69da74b GIT binary patch literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPNo46pO-G2co&H|6fVg?3oVGw3ym^DWND5#L^ z5#-CjP^HSi(9q1l@bf>Ae#yX4YQVtoDuIE)Y6b&?c>bjLqi#U86FprVLn>~)xxA6{ zhyhRQ!~Z>szD90r76n}T6W`c7i5WhPJmj#aw^LiY*? z7Wx+{J71GDI=P{A&q2F&pU*$(oH0{+XMOrCwKHd0rv&}rVK`da&$T>7s|e^g22WQ% Jmvv4FO#n9+U>yJe literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOff.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOff.png.meta new file mode 100644 index 0000000..2c2774b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOff.png.meta @@ -0,0 +1,63 @@ +fileFormatVersion: 2 +guid: 9f2d5e61dd9821b44a410f36519781d7 +timeCreated: 1489663385 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -3 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOffHover.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOffHover.png new file mode 100644 index 0000000000000000000000000000000000000000..bc019a8cd79c199520a6b551eca4aaf012ed3bd9 GIT binary patch literal 268 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2co&H|6fVg?3oVGw3ym^DWND5#L^ z5#-CjP^HSi(9q1l@bf>Ae#yX4YQVtoDuIE)Y6b&?c>bjLqi#U8lRRA~axpa{8 zh=M@t!+KX1MNMVa9M&dQmA~<8m0lRXQ=G8-*kM0L`Oo*xu-|BqjgXY#eq(qnzvttI zYkGSfyg0enD7H9XnpC`O>$TP=b2c&@oAK1+GsYgNiy!&G>`UX0o;=y~|WW>3x5 zpi=@$nM$9QO@6)WpUS!5HA}vqm|_w9FNMqK>5+4md%ho@`-hET(*92K{~Fbsfv#il MboFyt=akR{0H+ROp8x;= literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOffHover.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOffHover.png.meta new file mode 100644 index 0000000..473f525 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOffHover.png.meta @@ -0,0 +1,63 @@ +fileFormatVersion: 2 +guid: 6f3901bfd2342774ba74e117e43d6db7 +timeCreated: 1489663938 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -3 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOn.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOn.png new file mode 100644 index 0000000000000000000000000000000000000000..4aec22d4fa7daedea872de7c6da0ea791f7c22eb GIT binary patch literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2co&H|6fVg?3oVGw3ym^DWND5#L^ z5#-CjP^HSi(9q1l@bf>Ae#yX4YQVtoDuIE)Y6b&?c>bjLqi#U86FprVLn>~axqO!M zumMlo!*Kg2PkJsgRvD;ytNiYNAer)5j%nv{-YrrO9Pg{E9N@muIQ3*bT?N^28-XG<5DO=TQG6XACxL9yznl zV#n|Dj+ws7;d73g&3yahrtiPiH}3s@-&Om~>hva`|9!hZOET~(N&Yt4{P!l%aSWcW KelF{r5}E*mon-C+ literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOn.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOn.png.meta new file mode 100644 index 0000000..a3bc748 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOn.png.meta @@ -0,0 +1,63 @@ +fileFormatVersion: 2 +guid: 4c872bb553406fe44a9d0046a0ef9bc5 +timeCreated: 1489662998 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -3 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOnHover.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotLeftOnHover.png new file mode 100644 index 0000000000000000000000000000000000000000..af773f426355cd7413e993da8f67229f833abefa GIT binary patch literal 259 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2co&H|6fVg?3oVGw3ym^DWND5#L^ z5#-CjP^HSi(9q1l@bf>Ae#yX4YQVtoDuIE)Y6b&?c>bjLqi#U8ot`d^Ar-gIT-wOn z>>%KBaldtUheoqNmcn)y){y$xm<? z>gaf09A)>(___UrJp0VtOX8BpH&&iA;Mv2@;P69Z!5zQCRG_06JYD@<);T3K0RZK{ BS!n8&EL#Y7+!>a@a2CEqi4C48d;*Yuk)#iA*IEGZ*dUDyD z>wp0V%LPpi%c5<2^Yjt~=4|Y~cc3KvyWJlH@dj!3(zBM@N>OLCb#L60es_;aiAjxf zQj|mJL64>s?g=Gq6IxQ$j5hO6$YGvjH{-!%(Z2m39!pQC*?fU@6_?qujP{dvKk_he XrFL^o`~JQSXfK1OtDnm{r-UW|ix^5j literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOff.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOff.png.meta new file mode 100644 index 0000000..a010f2f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOff.png.meta @@ -0,0 +1,63 @@ +fileFormatVersion: 2 +guid: eaf512a569994074b9b268ff098b0f03 +timeCreated: 1489663385 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -3 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOffHover.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOffHover.png new file mode 100644 index 0000000000000000000000000000000000000000..2b1e15c3eacd66fe6185dc28be869f02789dbfea GIT binary patch literal 236 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRt!3HF+tk*dLq&N#aB8wRqxP?KOkzv*x380`t zvPY0F14ET614BbI1H;e%K>8&EL#Y7+!>a@a2CEqi4C48d;*Yuk)fRcWIEGZ*I&$eC zr;8y6%Y~l;OfRdnJtk%=oJqFs&;OXk;vd$@?2>|G6P2&In literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOffHover.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOffHover.png.meta new file mode 100644 index 0000000..77daf75 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOffHover.png.meta @@ -0,0 +1,63 @@ +fileFormatVersion: 2 +guid: c86cb249299fb7249b5ee7fb27ef1951 +timeCreated: 1489663938 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -3 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOn.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOn.png new file mode 100644 index 0000000000000000000000000000000000000000..08a870bc1e4817d4b176e394ef1cf273dd2cee64 GIT binary patch literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRt!3HF+tk*dLq&N#aB8wRqxP?KOkzv*x380`t zvPY0F14ET614BbI1H;e%K>8&EL#Y7+!>a@a2CEqi4C48d;*Yuk)n;8&EL#Y7+!>a@a2CEqi4C48d;*Yuk)uwp5IEGZ*I&$eE zFM}cn^93)%b+y74OQKgC+&zCbgU6Ho`ngVw9~26fe*d>_Ys^DKwvzX~mdm*fj5Rzb zlrSnyV(2*Wlx-E4aWSKca6^2juf_8tYIj(J{vEijz@D*or}~wskGu@a)6^f#*DF{F Pw2#5l)z4*}Q$iB}b4Est literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOnHover.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOnHover.png.meta new file mode 100644 index 0000000..8ec7c94 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotMidOnHover.png.meta @@ -0,0 +1,63 @@ +fileFormatVersion: 2 +guid: 542d7546736ddd244a145ef7103678fb +timeCreated: 1489663938 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -3 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOff.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOff.png new file mode 100644 index 0000000000000000000000000000000000000000..1517b42c7c4ec41b3341ad72ea7d619c6b461ada GIT binary patch literal 269 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2co&H|6fVg?3oVGw3ym^DWND5#L^ z5#-CjP^HSi(9q1l@bf>Ae#yX4YQVtoDuIE)Y6b&?c>bjLqi#U8lRaG=Ln>~)nY@wr zumKN?e-n?XoO^YO%+^TF$fnkAoe8=^5e5oID?^r;EHrxa|HJ<_yB#~rY}5@mn9 za8B6lo7K0s&F-)X%I>Yb@6YJOaYW*J&?#4!c_+^p821ZLOO0flv})0+bxv)0d`rIj zy}!#UxogR)yc03%mmm53Jhy-HeT%ebZ9Qj~&e@#Zz+joqu#cJHtHPvi(Zz4lfX-v^ MboFyt=akR{0IPdo^8f$< literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOff.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOff.png.meta new file mode 100644 index 0000000..7a358ff --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOff.png.meta @@ -0,0 +1,63 @@ +fileFormatVersion: 2 +guid: bfcecef29876cc54db85363cf2feebb2 +timeCreated: 1489663385 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -3 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOffHover.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MiniBotRightOffHover.png new file mode 100644 index 0000000000000000000000000000000000000000..9f7e57c32fca647897ba9aea3ea6a33be47e43ec GIT binary patch literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2co&H|6fVg?3oVGw3ym^DWND5#L^ z5#-CjP^HSi(9q1l@bf>Ae#yX4YQVtoDuIE)Y6b&?c>bjLqi#U83q4&NLn>~qxpa`X z*?_0@;r$a`4oT{6FTCb9#NJ}u!^B}Cne}|-G2co&H|6fVg?3oVGw3ym^DWND5#L^ z5#-CjP^HSi(9q1l@bf>Ae#yX4YQVtoDuIE)Y6b&?c>bjLqi#U8U7jwEAr-gIOy0Ak4Tr*hN9fInqOq!6CGD6`y0@^XUrheJYMc zCg<*-)Ob>-UR+`nzH#kV&aS-G2co&H|6fVg?3oVGw3ym^DWND5#L^ z5#-CjP^HSi(9q1l@bf>Ae#yX4YQVtoDuIE)Y6b&?c>bjLqi#U8U7jwEAr-gIOxn$R zRDs8Jy}i(F1829>EItQWCdU1rA}XOOs^GC|N&mtQYw_gTe~DWM4fkhnPi literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MinimizeWindow.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MinimizeWindow.png.meta new file mode 100644 index 0000000..20aa6ed --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/MinimizeWindow.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 2aae9a02747d74d46bf98a15ac5c9b21 +timeCreated: 1481126984 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/New.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/New.png new file mode 100644 index 0000000000000000000000000000000000000000..8dc9857a400b5a1d4b73aff11df4eade17a6d125 GIT binary patch literal 21763 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/New.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/New.png.meta new file mode 100644 index 0000000..4dd2709 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/New.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 1bd93c39ca74ac041b79ae289e9b9f08 +timeCreated: 1481126977 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Open.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Open.png new file mode 100644 index 0000000000000000000000000000000000000000..0d1ba82914efdd3ca7382d5d5fa62a23b66717f0 GIT binary patch literal 22139 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 X&_-`$p4V;RJG^Wy9WC-Hn|A*fPF4JN literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Open.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Open.png.meta new file mode 100644 index 0000000..e7503e3 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Open.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: d8b538796c7980843b59d62dbcdebef5 +timeCreated: 1481127018 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenListedShader.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenListedShader.png new file mode 100644 index 0000000000000000000000000000000000000000..19b5b31f7cbf21e21dd48324db421368524fa8b3 GIT binary patch literal 18999 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 O-qzB=B8R?i>wf`8I|ru# literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenListedShader.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenListedShader.png.meta new file mode 100644 index 0000000..ff29cce --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenListedShader.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: a66917730dccde947a01140dc04b9e59 +timeCreated: 1481127005 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenSourceCodeOFF.PNG b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenSourceCodeOFF.PNG new file mode 100644 index 0000000000000000000000000000000000000000..f93eae3f3d4bba13129714b0b245d479c4c9c9e8 GIT binary patch literal 29269 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 LgPqeIM^E`*swr4Z literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenSourceCodeON.PNG.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenSourceCodeON.PNG.meta new file mode 100644 index 0000000..338ef2d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/OpenSourceCodeON.PNG.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 8b114792ff84f6546880c031eda42bc0 +timeCreated: 1481127003 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Options.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/Options.png new file mode 100644 index 0000000000000000000000000000000000000000..9295dcb4cf178a0c08d7b3595a67b3f8ed585d08 GIT binary patch literal 22418 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 Ta);>fEak7aXI$fMy|#}kz)_ly?z~G zov}vm&@!EM2W2;CPby+8OHC@_3|p-;#q*|)o zcWk*AhI{BJc28a#bEbf+qMcQ5huX3F&4;vk%6q!}>luxBl%sMMYy~=zfx*+&&t;uc GLK6U&TwP!Q literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ResetInspectorIcon.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ResetInspectorIcon.png.meta new file mode 100644 index 0000000..2c9ee1c --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ResetInspectorIcon.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: a51794475a883744db8d524cee84e5fc +timeCreated: 1481127005 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SaveOFF.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SaveOFF.png new file mode 100644 index 0000000000000000000000000000000000000000..99b4558599ca1405621ad6324685e290c2e033e1 GIT binary patch literal 21808 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 vHGt4M#*Ed(T)XBEXR&i^d{+NAn+H8h literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SaveOFF.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SaveOFF.png.meta new file mode 100644 index 0000000..4327db0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SaveOFF.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 4e4a13447ac514c4ca21e7232bac5486 +timeCreated: 1481126990 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SaveON.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/SaveON.png new file mode 100644 index 0000000000000000000000000000000000000000..d98884cd765899ac6cf3d789fe3f4ee7336cdff0 GIT binary patch literal 21907 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 J=a?;D`#&uJ-T43j literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ShaderSelectOFF.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ShaderSelectOFF.png.meta new file mode 100644 index 0000000..e2982cf --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ShaderSelectOFF.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: ce7d95fa4e635f943a73ce1b19312cc5 +timeCreated: 1481127016 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ShaderSelectON.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/ShaderSelectON.png new file mode 100644 index 0000000000000000000000000000000000000000..ceb781ffc0299bd5623c5445542ee2d303a8e4ed GIT binary patch literal 25380 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 EU%JhO*#H0l literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/TakeScreenshotOFF.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/TakeScreenshotOFF.png.meta new file mode 100644 index 0000000..b41d15f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/TakeScreenshotOFF.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 7587de2e3bec8bf4d973109524ccc6b1 +timeCreated: 1560359851 +licenseType: Store +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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/TransparentPixel.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/TransparentPixel.png new file mode 100644 index 0000000000000000000000000000000000000000..427fb75b86287ab01a6feec0c2b402153671b6da GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6UNeMs>Cj+yj;LRsM O7K5j&pUXO@geCx0rwkSV literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/TransparentPixel.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/TransparentPixel.png.meta new file mode 100644 index 0000000..f20de9f --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/TransparentPixel.png.meta @@ -0,0 +1,58 @@ +fileFormatVersion: 2 +guid: 1004d06b4b28f5943abdf2313a22790a +timeCreated: 1496682298 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateOFF.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateOFF.png new file mode 100644 index 0000000000000000000000000000000000000000..485578600a52aea1333045f4bdc3de2ba580d02f GIT binary patch literal 23051 zcmeI43pi9;`@pw|5>Y7>H4Q~-%+-vU2Dy_1DWD9+(KtHpmh(rJ0`snZ+`kKlybMgUzX|qOuM1X`N3IHIvie+fHdi5qY zm+iBO&4HO48p1fwkexoY%DhK`mu1)h=}0*vu&11?Uj5W(XsGEMCi%zy*CG+1e|nhC>nTL zJ)C=Ax9eCjveBB{y&WT)iN7y1mThyd?{ z$mFH)Qi&2k#P`m$DL|=JVkt@~Y((aT!Qu5H!8=7txl!5{Q-bAy75)(hr-2nFBEd=V zi|v48Vt{KEjoJ>ZMgXpA+n?S6f|K4K4iEv>9b7nDf(DiL^q08r)*3^U+-K2TaCJ1rZSA_bsq!gnnJ!~y`<>nbX~z|O;foJpSp`SsE) z*)9!;)ZuJ$fhy5BWZe{mmxP0Z=6v-UbNQumc*-P7!V1lDzr%`{5S+~8{#yWWENV71 z+x{Wnn(0|JHTa0U=^GI*E{l)Asnqu2&e{yl3IKS*4XPVnhRm58yj(okWBA0P9 z(~fN!*vH70S&<7Id;ZX&pEJtF`1pZ>#>UQ$jt48R8myz-bl5h`EZ8Jc@BcGJ-z^|H93mi4%+HGcfMHnUQ z@5iLT_ZUPkxwfc&gx=P=Y*19URSP)3Syv<=3UOuwP4u0Gnye$Yv~2(Y`U=@)ch#qe z25$;|Qp+3Z)f+NBwg?Djm`8g7fQyl;rv1$vy~-&7V00`*+QZhE zDfj7kPa=k`H@OtG{5pWy@o9IFDf(bYwvEnRsa(T?GlaQ2O-@X^P3NK$BIg`SyzTw_ zT%G;+<6XBiHpx7U)HSR`l|ECDz+QDnX;xe@xS+jkY7DLF0{pC0M#bFoYtM=n?s-eA zy}%Qj8Dd;I6)(m!fKle_n>kuKT0by515;AP&3HJKFjaJ?O}QF8=8VPfi!aUia8-ed zL5De-EmLWj8956n8xU@Im7qFvk0C~_;J_sF3#aVsXV#n4d)lfzUzV1LGn=atbK@c1 zEn9+ka2agr^<5oF9alQA9rHRC_N|jlqOR~d_1>;c-S+0@m5QCRow!bMFdn17=466x z^O@uJGqfU|4Kk1C*`BirJ2MNnC4pESI>+21CG*6gJ99V5ZyI2od&a#qqxsN$>$uwv z^;OSJpT#{BeZ!NI-aR|CGMuTdn5ZD3z*OWZoQtKbfbNd(IxKUTy~a@^ zPa|-4)J@4lD-SI`G*1I*pO$_)y(N9xn*KFa_K|5WcH6Q{)?n@0)27~y%~+G3w7T1F zo*gr7`I)eE<{7rV-l-s`p*`YGS1hlrGCXB-?83(Oq6*kFnqrRcvW0Ha8N0WHXkA@= zp}H|}t43k`kaFQZo%FQhL__RKtV51%|3QYHM0>o~`y*WIsa@)+as5GiTjY9|v@Mx; z8fRI62G_f#$Hv7vW|(EzWSDjr%eE_50UnXX^CQfd*YKzT!ND=*{Lml#a$njwjqb?hde%}zBQF{6wi@T z6>pNNQ6OK_@?w*fk(EuaZ45VDSz(w$IYfzjvNNinj(qZ-$!{hy`&kw1+f~~=Dm*Gq zE*4+BaIuBe3#*<4TdRW8OHMDhTy9xeeXIIJb;Dt;L>=^fOjlx8;{C+dd{<{*=Vf_k z@-Bkr*&WWOoqF<$Ja;)0ol+dvIB&=?$xO;z)KHjNm^vf1z&ge{Be{Wj<^1cs8+mE@ zisw5Yh&N^BdE{-QFsbs){A*cPdSZ%Wwq4rx+mMcgbXeo`3}t8KAfMm8X&DV=N zR&w8ZZFu5e|28QxC$aqHnWl3+_#ReI*rTJja7ULUJ7IlpU%77h*ru~iZ`#pAD7V(L zL8}Z`g)nowRFE`eltbqI^Z6;f^Z`n*yzV<)@1yOy?PNj=rp0OFEkbGj_57+;SJ=rL zceNUBR~ey?_>a^9slkgxn4)_^^h4H78hq~`xbSj>9;pd@m)-bMfB&%p{n`4FJ2H24 zmSry7bp4M5nF|NH;%lO6Skrf{4tmybTY~bGvhPZel-jPaT@JhTA~@lWbL-G?TD-bP zhCZ!EAB|#-S`wM)Rm5|Mm0B9Q>6)9#4+)oWm-H$$8BVwEIVL%pyIUv`H8ryEp6(^B zpI-KdwI#JpYY&i*M_%8+@jG5q{$^L|oHWgu%Sf>+EW@p}55Cfu)i^U}|DwKGyhRa` ze&x#LOgOR*Ul;zsaJ|NS>pn9LEC1*}qKdTqRIg!EmUR~FR7*QhWGQXgoJdNZldu)$ zfzcrqqeG*k4tN=)FSLruW4>TMWo)fF3+~DuzUH|vA36V!#0|Hc17{~YAtdt*PCv7E zR==+yk}Fy% z*~_mG?}ZXqsZH+Pifinw)8TO--IYg_lD z`!6@Fazr|{=2AZHPMW7Xd(Yl1xhDCz+1nqeKl1II7skGM`S7EIzo%tfEuhyj>KV_U zwjh$%O^;2Fdm1<0Q@Zit@6xSne}DP*opBQ~u3EjRFf`Aw;N)fU#Ue2EMosl{J^NGk zZ|pzX<9q6xb1C=Vd)D>L3n+Sr`{Q2Ix}t$0-5VuMYed#q-DBJX2h9g_2K2J_q(6Tj zJLs_?)7r!9Wu<7n=#YfU^t}58cke0J>)6{yHZ1KnonE=1WH_mphmgigulemrMVku8 z$gku1z|_`(`O>6^TlWW?eIjvZ!B%CaGIFy)LSKSOqFut^I_kPht8VGmHN0r?|76;< zK;{UJ?Buty-~I;c;qx7LVwiok`;!hOZ41);@W{34L|#A_t)_Le47>M|EcZ#h@yNce z%P)$`~BTua-vuIV(#y2Zo>NgrThuza# zH~i>9@1yOTOL@oo>mHd7i0=xm9gcb%DPuS}@^EC;Zt30K$=bR^Vw;}#(DP5JhPCwC z#mVx+Cx)xC%8^Gj~{V$m*d)(*Zb z<2~Xj_nvH(S=A8;+pa#c>BEJ$cDGXpV-#azM#Mzp`#;gJh$a9qU(B+1fq(W(f_@(rBjK>mO}K74aQ)E^VUAX- zVTNpP5T>PxN6^q{G>kyhL~ChdFkLZe6+6zt0ft}6-sM)syN zNVY~MU%G?-rvu-_<#I?!B#+0_*ve7JUCxF^7Q$_4x)(krErjFO%(DMMpjmW z%{)AQYU#r@-U^N6%glb-p^v>E2SnO}KI|>tG|+e}=*d<2*&uwlw%|8Nf5H{i{HKmM z<42O8kL#=YmpJIOua=xG-tM1QicUj6p-seL5fn6zK*usLbP5AE-q8eSd>yUwWt+W@8TzJ__{J<`9RU+HzCTPSo@s9>_D&YrQ-^B z*5_2jp?Ld%qgS{NeEbssn!CQHrcs;EnSw;2jV3W&+GzNKbTaZg>9=8hwfthn;$O}` zhhWVA1oL0_!P^9S3JU)*SD#z`+KCUF!R1lBL476^A%Et|9P|3U*^lnY$kC+l&iZdy z2p`JUzqbr%6rRGs)A0yA10*8Q6dVIV)uvGqcr1~I!+}IJiVCHU{};>fEsANID4tA^ zu8SO>*|^}Jv~m~_MiNI5Y&5p#R?z#e z5fF3+j)0(03DAZGMAL~h0tFA^zTP+g>U~XkS$^GE{IDVU+slS0Qt?zO3XK3!3=9HK z!=Vt`XcQemAmC683KffE;Gj+4zne|J?xV2;VM6_3EBUt*>c7aLqiObQ&K+OE390HI znNa^ZbN<^`CK^O*$+~baOz#uXW|Jyzp0@=z*s%@_ZPZ8wx$L! zb7Mn1nuv$0aGL0eZYH$*sh{zBlRi{G8!Zd@Oc>y(4$~2!(Pr48yKG~1$9Y;%C?pr>Wum~6w^no4#K%XzB6V*SOItezN zsQ%IPo8=l$7FQSZrMDl%6Rbwd#$z#L2R$kQN2m6q=*QNpS-zmVqY(=#Z2F8A=&)K} zY<^Vy)X?dhA!fX@&xR8eUkt~VcftdW&tWtsg&vncPil}~AJyX;^IRhNFc-|hz_4l zh>H)2Ab}84doWkO&e8aS5WsrxW7hLn25Z#3hIhpH7I24~Zaw z5SJi2d^#a6J|uz!LR^CA@acrO_>c$^2yqFb!>1GC;zJ@xAjBnz4xdhliw}t)fe@D< zI(#}IEX;^IRhNFWfGQ zvFpNB9TY3KZ%n$x9kArFd9_>bEYHBI6v!$bN(z%U61}-uY^r37$?63sDkSQH5Kq_#)@2po^k1LiA*&A_`)I?)mZ-q>MW%#%c6Q5Jc z3sDXT{XusAAIIsGYg~PGr7a2=kC+C zY?(bnaV{+)#ASD5)}-^|fs?~S!mc&k3XQFq^;i!-d-?%@_!wX5RU;aieB?-AVQcSY zHS_3!B`GUE1nO?ta9`CNPEjCL#P6|v!R!CtJI~Y8v!Uh)(Wjxm z=tu+U#lT>5XlN)0r4V>~OS4asb(c?0qx-qF8BYdvq0YE|LyGTpUzt31$t^D4w%`@x z@r=jwVt?zTE>lk#u79}|DI*>_c*u5v8$K~~pFFaqprj-yZ?(GEhd`IitSoUiH@ABx zC+n0VD{FtNY;Q7B)l-m4-rKHF+pjJsd5X0cEnZdsAhvvYaENG8jpy*w$C*Qlk=>URXyNVgD5)iJRXr6I6>cAghA)J#@7p$_NRzsswL$dQ+6+XhB_OTc z6YXs;u4-jRN}6sXcl@Bil3nfEi3RI5Gwn5`X;LM8H?5S zduMf17ZstdEHZAEvt+n$RKlr_DK9(+HL1qm1tH% zi5#re>1HB*#X(!Seb=sec+@HHq&$OS)4Jg(6w?$1h(f$|s*%mkhPgAIbab4WwflI? zX;zhjVXkwE%Q>VYd9v6FrNQ%Ol5VvmRxj@E?$(Ylj8;9x`lukA>zvuZ(Y^~W=aLpl z8Je7&(f%5ug|4{WJFq3=-e$K<8tv90lauPN+W&+=DBwdUvhs?z?yI{2n7#DEmJ0uNnDZVRz8>;L1fiV6NIq!&XK; z@s^A8A6@incgoDQzH|4tc1I}mPBnYx4-5>9G(YFAg!k<;Ir%z?dg1*FrOJ)s^CxE^ zLtcff0($f7gUq(_c(o#WImK;9^Frq%?#+a^4VG-L?;RKk;&M*~wvJE}P7i2D#31D) zO_qSss!{5Djofr*Mr~~9ervk-S{t)nyF}i%6_g~)cnz^nqbD#U%_j%6moO91P_v3mZSJ;@&6k8+)0KiOh zGb4NOQxSa66A=Rc-umR+1Ad5lo4K+9Kzz>FTL4H-T?hbTwoF6A6)W6W92VP+Omz-;!lNPXuCb5EU{vPFYP}RLUYk{z&sY zyYgAa#?xi4AC3@=i3y3GXQw`6x7Y*WF8QM|+mA);zWMp_mSgTsrGw9IkDR}+)1A|w zR!}EgCNkrI8Ojb5GUJrN;#rTjS6{7q+@+xxDyHNONQo3s<=MlE0>DtPmez8GGU3aB zfd5@_5unUEr3@~+YgF=uLDCw5kR1YLoH)FtNXT43FEGa71fXXk5R!IK*#S5_9oSGq zA$I~Rpuh%|ZO`rkA!$QNTLggB`{m~e9F7AZb7&DpfSV?eQ@3)rG2j9R=F%;%5`YI# z0B-I~Hv`TT0cEvP;`xBc3;=Ey5xxwVz6IEDT~W~=*pURxHF@W(^>%rlRJR&PDk)#9 zScza9x>^M4Bkb&~u~@a%e8KX$Skg37vYtjoK$0{v6fOCv{}uooj++Pewtv{aRwA#q z78_G2u^#&3iqNP6ncO+@v@Y9Q4*(u>g6l`rVFimqG=)MuM~*J-o9?zw{P3p1D0;r6 z-g)3~Pm6QE_ZS=FBYTURo1b=dJ+QcHu$pw!IcS7YvA)cC*yCfc)|bJ7N0*-{g(BC6 znob{jRB`LQRfcTcKG7ZIwr8=XUy8&>zsTKHxN1%=c2S$#X*b&^#wa-kgY9UJ8WJ&G-2Lz&ax(4ab`Wy44~8V01WC?To(6`|^eAWkRy$f3%g0f7yWDVW4!i z!a&MEj2a^AyJ1;Qn1Slf+h^p|Ho)%b$)U^a+;+x$OK4O$U69cBmi$B#NiSC|4HccP ze_dn_NxmgQfV|s9F-BxTQuvU3x!LsDQA&^-5p(SnEaNa{2>acR5GOOaciO(w2)ovp zT#VDa4j{w6>?}1!><`Vi)4n(3ykYT4+@c*ON5$_@If&%g`G-^P_?}y&9gRKGeJ9&Z zvL#l>uo_iU{T7}+XmvvRZj^MjBOHf#d9XW4GKuBnqE@K3bza;}u>^|* z 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 G?7slENv+lZ literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateOutdated.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateOutdated.png.meta new file mode 100644 index 0000000..54e5175 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateOutdated.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: cce638be049286c41bcbd0a26c356b18 +timeCreated: 1481127016 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateUpToDated.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateUpToDated.png new file mode 100644 index 0000000000000000000000000000000000000000..a60c4351bc8afa54cf37cbe1a2be03a5120ac7f4 GIT binary patch literal 23084 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 F@n8HtlNJB~ literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateUpToDated.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateUpToDated.png.meta new file mode 100644 index 0000000..db066db --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Buttons/UpdateUpToDated.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: ce30b12fbb3223746bcfef9ea82effe3 +timeCreated: 1481127016 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas.meta new file mode 100644 index 0000000..9cfcde5 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c956b1443ae5df54485c68a775928f3e +folderAsset: yes +timeCreated: 1481126946 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/CircleBackground.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/CircleBackground.png new file mode 100644 index 0000000000000000000000000000000000000000..961d196a6e0643994df952313e043044b0403858 GIT binary patch literal 15526 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 UYtrsN9{sMStgTe6U>W?s0MQ|0wg3PC literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Grid128.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Grid128.png.meta new file mode 100644 index 0000000..211cf27 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Grid128.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 881c304491028ea48b5027ac6c62cf73 +timeCreated: 1481127003 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 1 + 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: 4 + 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: 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 2.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 2.png new file mode 100644 index 0000000000000000000000000000000000000000..4f94e4111fd0c92d3efde6e74f15d7049b545243 GIT binary patch literal 198 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{O!3HEhOmL|OQk(@Ik;M!Q+`=Ht$S`Y;1W-^R z*(1o8fuTy3fuW(9f#K(WApMeoq11qZ;Z*_ygVhWM2J!q!@kiZ&YJEIi978H@^_*QO zdO$&d<>KC_3pEvak6f(hwBYi1;%SnU^l6dtquYWCuh&`_^KZZAcRgyi@*?gXED4^! qPUa>^N!+XEU%z#kifHZWbOtYL#h#b17qkP-W$<+Mb6Mw<&;$S{T0IE> literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 2.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 2.png.meta new file mode 100644 index 0000000..f0ef6b0 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 2.png.meta @@ -0,0 +1,84 @@ +fileFormatVersion: 2 +guid: 03a7d169469c1af41bb03241a7b7e23d +timeCreated: 1486740437 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 1 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 0 + mipMapFadeDistanceEnd: 10 + 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: 4 + 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: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: 5 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + - buildTarget: WebGL + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 3.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 3.png new file mode 100644 index 0000000000000000000000000000000000000000..ef9865bafe105476596618b3be0b80cf73c6dbdb GIT binary patch literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^j6kf&!3HEHb{^ahq&N#aB8wRqxP?KOkzv*x380`t zvPY0F14ET614BbI1H;e%K>8&EL#Y7+!>a@a2CEqi4C48d;*Yuk)%tq6IEGZ*T61op z=m7-*mWz9zF4R=yJ#w+0(}K(6iKj_Y(x)Itw;Effl)a+q&mLa8^)f2E+@*wZI)jd< reX;Zmwzlv04ri~`^mM&{%a~!hq~aVd^I2bk1~YiN`njxgN@xNALdQHh literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 3.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 3.png.meta new file mode 100644 index 0000000..fb6886d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 3.png.meta @@ -0,0 +1,84 @@ +fileFormatVersion: 2 +guid: c3512c25766a40245ac94c6b1722d76e +timeCreated: 1491391706 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 1 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 1 + 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: 4 + 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: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: 5 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + - buildTarget: WebGL + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 4.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 4.png new file mode 100644 index 0000000000000000000000000000000000000000..9e913665c0ff1bdbc924d7b4ad77e992723aad32 GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^%s{Nk!3HEh$WML`q&N#aB8wRqxP?KOkzv*x380`t zvPY0F14ET614BbI1H;e%K>8&EL#Y7+!>a@a2CEqi4C48d;*Yuk)y8^F@}ZyMntI`u@5fC}o&1^=drJRex8@cE*m~T8{#Seu?oYH*8hD617=*=@!eR zp54t$nkStTob~U|j~<2xMIKtpeC;!BGuBSc4BoeFKRZL$YsDjS`TvuF_Aq$5`njxg HN@xNA*qKH6 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 4.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 4.png.meta new file mode 100644 index 0000000..a8c3128 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex 4.png.meta @@ -0,0 +1,84 @@ +fileFormatVersion: 2 +guid: e0f922c44762291498cc62e0917609be +timeCreated: 1491397409 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 1 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 1 + 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: 4 + 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: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: 5 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + - buildTarget: WebGL + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/LineTex.png new file mode 100644 index 0000000000000000000000000000000000000000..69c7e0d9250ff9d7879ffefcd14a520c3c4cd3e4 GIT binary patch literal 470 zcmV;{0V)28P)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ-TuDShRCwC#nN5m>Fc5_+rY7kiZd`hRK8N=|f(LNvM#T0f)@=F!Pk4}?p@rT( zzVB5LA=u8$1bHd}pKp*8bRy!*sI~8V_u=c&=kv+!s9o0;np)eoh1A+K4SDLit}%5= ziL4GGIBqbd1nE^(F{1Y#?uesf(SsYf#5=(UeUA_N=}GjCu~6{N)XIHl?hFGHD>{*{hJ)Pe zHLNaqYZj4$*Zg{DQPB3#OjunXI0siA%)Q<2aIs8HS<>&pIsLx@*FV%`C-0HBa;W=KSdbAE1aYF-JD%fR4Vl$uzQ znxasiS(2gP?&%wlqL<1J6xa21aSVw#{Pvt9FM|OG!$#)+Cw2VU=7%{huadph$H{>L YYD6*_&M#Z6&IB^i)78&qol`;+0B!Cuh5!Hn literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MainCanvasTitleBg.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MainCanvasTitleBg.png.meta new file mode 100644 index 0000000..5fc7030 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MainCanvasTitleBg.png.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: bdb42c87b8801e94e886c5c0d60b3014 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + 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: + serializedVersion: 2 + filterMode: 0 + aniso: -1 + mipBias: -1 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 54 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Material.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Material.png new file mode 100644 index 0000000000000000000000000000000000000000..e73d6b0c0487931add3f66e2d2bd98e28a649982 GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?3oVGw3ym^DWNq$1fP z$d`ekN|k}3p_zf<=YJsml7XSrfPvvv0t1893e}1vA?nMjeYIi!)O0Z@Q=qnvzx5JtA;@K9;<{ajEnhzLK8AY^`(28 j0@*Kc1C3$$|DTy*qBC>-tdAWaCop)r`njxgN@xNAl@&Oj literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Material.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Material.png.meta new file mode 100644 index 0000000..3dd5a98 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Material.png.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: 157b94751c138d84bbe1768c672b5168 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + 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: + serializedVersion: 2 + filterMode: 0 + aniso: -1 + mipBias: -1 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 54 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MaterialModeIcon.PNG b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MaterialModeIcon.PNG new file mode 100644 index 0000000000000000000000000000000000000000..95efd603c053d0bf347a696ff8a653cf79ac53c4 GIT binary patch literal 23223 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 MjI2n723z+37ZpC$lmGw# literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MaterialModeIconOFF.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MaterialModeIconOFF.png.meta new file mode 100644 index 0000000..38d362e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/MaterialModeIconOFF.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 7040748e1c49b9648aeeefef41c8a3d5 +timeCreated: 1481126996 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/SelectionBox.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/SelectionBox.png new file mode 100644 index 0000000000000000000000000000000000000000..8e841e41e79d223e8fd6db2e96b9a92b8b60937e GIT binary patch literal 15302 zcmeI3&u`;I6vxeByW8xpdVoX4$%G3C65C0WZY(EDn;$f2Q>vz`O}T(;Pm@s-+t`yP z?S&sgLWm#Y3`lU~1l&Q3kje>h;>3Xq%bkA!smwUeua|UML^vQ#lwa?C=e@B%Z+`eP z@9k{AcsurFOp>JA)veMl{k_3HHCdvawI4{*&Bxj2G3k@fR;lwksn*KZ zAKi-Gd~Wq~skBaAPmpqhRB#)~+hzwz_Z@;s8`%l%n=gJ?ktF?Byw@O&+CANJJ4w@a z4^Xn-@o1nV8F%}hX&oUVAD||7^6@{v{XQ;ZJ0E|Lsi`%uh+25-)JOHx?LF)C$jaIA zyM>t1*J*+dBBtE$w4Ffj=i^~so&INTB`$|e$WcDN!8(*1wH>+W`bf?s(+Nw}G&!41 zYHOKnR(oDfsai@=={uXy*7QtPPp!+*D_)4ve}-=#>bs>%)E%|*@fIPTt|+};FWE~c zUB9Vlxm=E=Nu?6BMItzHh}lm#!PA2z!#pJvSU&a$b{(1JH4oe_$;acYqtPq6uZ}nB z$O$5Ll%mo%Jw;2Z$|y4pG$<3j=p&Q3{+{c$3xhk~X}QD=TCOJ->sk4k2iURQUhu4; zz~P_(3BOUZZ8OO=4b>V5%8R;oA7{#g` zMAfX-^r{mO)3H#sRG{@rVr=VKt*CC?$rRHSZL_?gX`5=LR9VlKR8_0wGL>{#nd#7J zuv9C#R<}dDjMCaHt$MYz6QMI{U-mJb#b$e=4ZG@pl73E#nQpdlK*#vWu&#qi6IQp5 zUZ3_3%ihLewLQ}h5F?+D57AFfp+P1V6IM_+EjCLF7MoPaHk2vv__AOao>R0-=?-#F zgkGG#*Fw$(lX8$HY;bXW;2x5m>7$J%9Rimv6N8M?Au#n|%C+%-z&CkbtVhu_-J%5HP37BsSTVQQ#v_^Veza4I(wxyspVrx@CcQ|c& zhqEpH(DgeeDd3LTM2hD$4Q1?%?sQ?-=MA^c(Pd68%pAS$4E&zmY3S4|XKoz(E5WXpJ@%aE%-~vGSrohGL15|+v0O6Yg z7oQJM1ug)DZwg#|K0p#peT5feQfPn*tY~4^Raz0EBM}Tzo!26}SKpzA13= z`2bbm0zmktz{TeSRDlZs;hO>%pAS$4E&zmY3S4|XKoz(E5WdO96&s&dMGifr+M}mY zA3pl@Lwb^Rl^ueuM+d7UaP)HRr;nPn%?fMtz{dpnQoZXTpB}>f@$Bp0sPt5|w6VAP zi}ly}`S}}5#+%n(diVE_U;X*)1?kq(wGZC;ZdpQKE-(M_*1dDuSgMw{OJ8li_V(XK CM36K9 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/SelectionBox.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/SelectionBox.png.meta new file mode 100644 index 0000000..6d30ffb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/SelectionBox.png.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: a702c1245d15ddb48b8fba73bf951a65 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + 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: + serializedVersion: 2 + filterMode: 0 + aniso: 1 + mipBias: -1 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 54 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Shader.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Shader.png new file mode 100644 index 0000000000000000000000000000000000000000..4dd6cb38dfc1260225a6713279f59cc17402420e GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?3oVGw3ym^DWNq$1fP z$d`ekN|k}3p_zf<=YJsml7XSrfPvvv0t1893e}1vA?nMjeYIi!)O0Z@Q=qnvzx5JtA;@K9;<{ajEnhzLK8AY^`(28 i0@*Kc1C3$$|DT!RK_+v_QN@GjKzvVEKbLh*2~7Zs7C90C literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Shader.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Shader.png.meta new file mode 100644 index 0000000..0ef85a2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/Shader.png.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: 555b6a287b4121b479d412e6ea92bb2e +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + 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: + serializedVersion: 2 + filterMode: 0 + aniso: -1 + mipBias: -1 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 54 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunction.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunction.png new file mode 100644 index 0000000000000000000000000000000000000000..209277206e290acd509ae810595344d688ab9f24 GIT binary patch literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?3oVGw3ym^DWNq$1fP z$d`ekN|k}3p_zf<=YJsml7XSrfPvvv0t1893H_?9uRv=hF<2a@!3^>bP0l+XkKJx??3 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunction.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunction.png.meta new file mode 100644 index 0000000..f168898 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunction.png.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: 94cd628d3d8e07d40a85d82b3fdad15d +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + 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: + serializedVersion: 2 + filterMode: 0 + aniso: -1 + mipBias: -1 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 54 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionIcon.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..2d13391458d71ee491113cabca960975e9974edd GIT binary patch literal 4615 zcmV+i68P(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRa2jY&j7RCwCtn^}w;=W)k>)yGWF?9Sf1Bt`Q+B~ zd#1a;%0pjY&n~T9d5FNs0OW9nJ>C7)SM{%d{i|A3m0P_;WEpt#pMK)6z8*&r#>Ak2 zP=3GV39RF=jTyN8HxBdhT@*x$uS0|KrC`pFVy0%$YMicKGtx)hoSm-Ol$l z-FHFJE#9B|g%-zUU#fs)7FF>53XUU$VVGNbI2th=4%ygj6o|$FkSBVKm*r;#f^K-m;a9hl6VVK~?E>+svC)js{H*H-?;89I<~P z!f~P96Ixy6(pryan|;oOv-o}`xt0j6&9-yu)cvQpcz~M1wKa8N>-3Vx zf(4SIDIlf*m#$Mq((IX_zNCvcsth_!j=R@*Xt~8(-Y{Tk7V6Vbs|&6tXsm3sg{9e; zGuMD>4g3nYRdBt;g7qnws(=oaw>H=LPIL#VnIVOsRzI1B zL9i18IJ?V&niGrS?{a*r6)#!>eYI_5`KB`H_qeZmnGfIDjI3g%k%Slm<0RSQ(E=ydnFOMVqE^Tm-wO$7&wq zs)a#RA&esSn#+9T&L;O9idk5IYE>~2eBwLz^T*$LfD4yvj5Z)@L)?S750zNCW>ye! z0l}5TLpC>C{+>O152OZ=33-6Ed-fJnEDR(Eyxb7mu!QpdD_;Kwj~%(eod;uP7ldjR zG={HTT;{^Y9H{cw&)&=0%Pzw;7~NFDO=Yw1@#EnhJkP^*U65ocy(13Df6ow)1oV&)O$A`=>LNx##!JrTSeCb4vHCG4I z{NcHW`QV-_9ImxF-Jrr;p7XgfkiPg}UnY#y=1*$-A0wAcUC}M0Pq&cwi zKuC24q>|bxgqwYbo1>s)@ElE4@|rW@Tei-Sb5BeZ0aSLfK5yq~urPZ|Lim2YvvO-G!@MYFFrX+7@6co>!q#2?`@-ac=|_&95VAOvJkg zZ;#!$Kz6Z`#nl4$GTF&qZnVi8E3Xt6_2I!o9fDcKse$+cF&I~9#lo9rUt%;&Vo!nf zuuivf#F8SkjI%Zmd2RatIt*aS`QE+(Dd_|$-A(T_@dV+{+6^8%xQ_1wbqJ>5$U#GO z8XRB1NmHo@_Z=LvTpcp#2&M;72+wbJ_+s<0RZfqUV@eVVVxjCL4WO12fU%^&H2q1j z^D?HxsVZ+>YVqckh{_x|4e+KRXb4`AxIH3B1g--I7GqWdh`L}p5Ve*4(=lIa+L}b3 z2Xlof@kGIp(&ouZVp`IdbUT2^N?K!wLvo`B8iv^#RHwk1N;sMmD2|&(s!=osiJ>Y` z@xW9BQ&FNo_-QN1p-}RoYW!YOOxj%p>;eSUE_||UrmM|8e@x*?kGwKkz>^+ssEA3* zVX<>;41@xGMS7qEkgnnk5~B6g=1O{MlT+$UTNTDr?Cx-2=ODNx<=N$cTGCirvRSgv z=UzI-=UzIN|Ll|R_&)D`ppSUTu{wgdtNhJ3_w$9H93Sf&NSTZ0n;>J%!r~{B#(+d~ z(?l3aO`qw4VDf%|-xR$aA6{nmoN0QKhAw z&nna+6eb-4HUj82%ulsk`&;#&s$CEXQ}G5X^(cvDlZHSDqpomaW7b-wm1;{Gq;AnE zRV{xox>H4bHyBXFzSy}>3PmRg1F@vDf)$DsVRGNhO#&~a&kdX3|dZm-K|ILuAq`xSzqMztCgZMHmdOxOdAMR+t*CUs00wH;rrY-q`0^G=I> zb1|N8X@)U$dcx|Unq&+MXpJ#++8YFMlhgaU+_NyqL+?_{=La|HT<*>>zp#?ui=%oQ zJRplYYgfrDuyV>SL6=oM0=%)Fu6v#kXpcwxP=9qut`y~<;6Smm)3Ev9{_RRl+p zoHQB@`N*ile_n0z`Kt~5N>Jzy6UP9fCB45C7AoZnr+%x9^#)PyUF_ml67d5~7+@U2 zQ?Jf!5gGfv4u5d(Ro;GJ$b17v>hi?(MY@s4hmXF336()8e5f+uiDru{sfM7!P8ve5 zR}s=}dSq(tbm1Lh>jHop!||mNUPaK<0Ae8Q3s0^u6>YWj9B-L@nRg!=vS$fgA3pl{ zDW2b`qXKW5-{4JieF7&DTNdgLSHdDSn_Yx}v-32V$=yYdKq+bjHJS<%+0mwi(4OgY zWYLO$KqD9qmFGK+G-Qg3{sV_vEX_l$0qe2DxmSu5{K+4lq&ajzgmcYC3ZO;F?r>YO zK-L%368j?U_Z2Bj$5K{eg#FbGrs|sV|C9j5%IbzoFLDb?n;NX{3)NKAss)C(EMDeY zFU>JE)!=8Q#(Td0Fw=fSC-e#?kX|gFydI#15s+;JVBL0VrkE9hyBcjO0f?KLEe10Z z&c0f=cz&bWKrL$3_2ak|ceP^@nioGh zwiB7*g1F1U#TeHYEB+xI2+y?|xy+@h8)t~}A1^QQku#_G%K0T)Z5K~rI)J5lxMLZ9 z?P!}}e^9D96mEwHnA{SD1~_(6ONc0SauiNBn)p>n8@XT`Jqoc`KoH1Oyu8amr)6X%=#ol~6ZZqC6n{XB=O^9d# zfO-9$#X=5f$&ENsk7Fw#UL_S!A}~W?*jK*0wm7Eu!NdDPR;FNO2KLOuZ=Bp@{pJmt z&2>7>tGs*vCZ-RjD_m(;`O(Hq!AA8q^#ziJn=Jzql9jAuaW7Wse6)6x#Tmu%Qt*qw z4B*+THG0O)8z|X1zk73q4<5RN4>T(9(7upQ{mM12v|QeCV8FfxI0IM@9scC$6P7?z zmPaSw7}>%Fl8g|A5pf*jxgMV9rGiM}0S3dPds|cka2(RzhhYc4`qJJ!tB5s1_pKXC z{QbotA3c79nMzEZKz1*|Ap~o}L2G6(ZV-shZO=^tK@l3`5lDA|{-rcR4P3~V<<*vDqJ$1vC zPKOH{9iDFO!waT}qL2sY);O>j<9lEt(4jEgR6hC4(eliI7Aj6wZ*(JUzzWSqi&Tmd_nKaE7o)1^rI{&yNzg>&2RD(=B1jKHJBPefM>2qKY%q|O+dQyQ+ z&%iKA3?J_ms1j1OE2np&Y7;VQbl<2xY9$*46}TKq60lQl3f| zxeXp5<-r^kI6R|F1xmG=ba|_;;8o!PFGl=L?p}^)RKXbv;ZQk$wZ_MvK1nxn3dKlt zY{uml6XrI<+@kpC)@JSG`vO}><1Vxs+!=0QLNH-+v#tm;HF)G;j1vo92%|oH^U^Gz z`thM8?OCdiJwUy6s?2V`V_R z%_vy%my{c&TfE%v99sx2rTG>eGgA>EYMsY^0LR|(fV36K- x`xo^9AD9Cgzl0vp1~ybReBB24|M2?X0RVXj&9e%Er_BHW002ovPDHLkV1fyo(jx!> literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionIcon.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionIcon.png.meta new file mode 100644 index 0000000..c84615b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionIcon.png.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: 50be8291f9514914aa55c66c49da67cf +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + 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: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -1 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 5 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + - buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 54 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIcon.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..a7724e96ee4eeb2f8fb38cdd7f58f0cdc262fd82 GIT binary patch literal 4051 zcmV;^4=nJBP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000F3Nkl8Pv=RfpPk~$Hn)3Rn-I2gB#h{l}>kcSL!~_ zx#ym4lf?aa6x^rBeG6Q*Po6vWl91?jyM)liCAbGD%nZ!OqLS8Q-^w6t%z}aO@T6=Z31F|*Ns*WT-J;jMxg?- z4y+y68>YI~RJc<#l|qY6Rp80-c_s&!`F4JsOE){cbK($!u)_PzaX^uQaa>$A<}n%7 zNx7VTotwO}?@K^DGxY;6Z2u`;lV;r`Sz`x7|5nE%DVJ##h)wNdMc~BVuQ`2nA7^GK zxVZ3mO5QO`^93=9BA{S>0tfG{QY{n}nVmB^zH^qbp}_ky)! zPj9@%;i)Q?i4a-%+gkp~?;}hOu5fG@y!*>` z&drWCm1aRP)pW>8Xsk0%p4l5xn_I2R2tT@ciJ=lcoaxjS!GI%M{$gRJIEIRD2WZ+^Fn>G37rdg4-TAmm<;sJr^LTD5F?YO$+nx69c-af9V9 zoV_-ZJ`bEedI5KF^5PVimqwcF}m5fN-`wDt_=%(H9MBBja_}?n?3B= zaFgM(%iEV8jOvwliAsVTyy$~*oH0ayE0YpVjMo28O9h+QxMl< z?yQ+p$iPA$&z0Gykd_1--MYkUk6dQF3Ou`Qo-bx5dFQtc^&;@L>ufEEIM*KSlsm!u zxlGdPL<#SB!~GMByngU!K%Bg=HGS^&&aTNMkIPbdgGCN#m8rOka;>tj24}8zID2h> zIya2GJZigNf2U*^Es2GaQOsmpJ1`zK*7FUsWLnE{HaOF?O;#Eq2kuHDFbtj@m_ zJVx)au}O$q4$JTGCXS*d@b|+s9pb zlsFSOtAbf=Le%brwakgNTxctOcd=?mVE_LW@n1du834ul+6ujB3wQtk002ovPDHLk FV1gd)sP_N> literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIcon.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIcon.png.meta new file mode 100644 index 0000000..d1d0180 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIcon.png.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: 68897d376b60748438e0ae3474ebe558 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + 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: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 54 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIconOFF.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIconOFF.png new file mode 100644 index 0000000000000000000000000000000000000000..5312858691cc2c18c260cae1c20debf1b5b4fa8f GIT binary patch literal 3614 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIconOFF.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIconOFF.png.meta new file mode 100644 index 0000000..9735d2b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderFunctionModeIconOFF.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: ff637d399b504ac4999b770f24ef4d56 +timeCreated: 1494003400 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeIcon.PNG b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeIcon.PNG new file mode 100644 index 0000000000000000000000000000000000000000..fe8ea72f60d1d263c29fda433d74a8c6e67a663e GIT binary patch literal 25967 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeIconOFF.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeIconOFF.png.meta new file mode 100644 index 0000000..aa63312 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeIconOFF.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: df81b9531d8ef704f96072ce6910db68 +timeCreated: 1481127018 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 0 + 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: 0 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeMatIcon.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Canvas/ShaderModeMatIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..a2ac1b0890d95ea9f3e1db55724be997fcb730a2 GIT binary patch literal 927 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBase.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBase.png.meta new file mode 100644 index 0000000..1c13e09 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBase.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 60c283ffa9a758646ab70a2fe7ff5f71 +timeCreated: 1483554830 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: -3 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBaseLeft.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBaseLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..3e25124ebc0425eb26260237c0f7358001ba99c7 GIT binary patch literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?3oVGw3ym^DWNq$1fP z$d`ekN|k}3p_zf<=YJsml7XSrfPvvv0t1893gZ#n?VDJ$(ZDIaw?0>vdkPWMj3-+KdTvILUR{&=;C^|W;j|C Vsobl-;}ww0;OXk;vd$@?2>=OCU!ed1 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBaseLeft.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBaseLeft.png.meta new file mode 100644 index 0000000..ee8cd74 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBaseLeft.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 330fd0c8f074a3c4f8042114a61a73d9 +timeCreated: 1522611116 +licenseType: Store +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: 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: 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: 4 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBaseSquare.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/BlueNormalBaseSquare.png new file mode 100644 index 0000000000000000000000000000000000000000..2ddfe241fdde8d7c5441f536970e4cce7f2016a4 GIT binary patch literal 350 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/CommentNodeBase.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/CommentNodeBase.png.meta new file mode 100644 index 0000000..163cb26 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/CommentNodeBase.png.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: b2be9c55e7e7ba447967677c82b2cb23 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + 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: + serializedVersion: 2 + filterMode: 0 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 54 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/CommentaryResizeIcon.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/CommentaryResizeIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..c4034d019917f6c355f9c211608a5830f2145486 GIT binary patch literal 18758 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/FlatBackground.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/FlatBackground.png.meta new file mode 100644 index 0000000..86eb564 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/FlatBackground.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 44efd0011d6a9bc4fb0b3a82753dac4e +timeCreated: 1481126984 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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: 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: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphButton.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphButton.png new file mode 100644 index 0000000000000000000000000000000000000000..38fe4e6d4914a4cb909a04baf19b1b6c9e5b5251 GIT binary patch literal 383 zcmV-_0f7FAP)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ-1xZ9fRCwB?k}*!hKoCXWE^8ZEiex1zh$v9*0!QEgAbQS1kq*HDxI#n&cd((R z1Se7&c4KBJf+GZic;%6%Sn1E-|No3pRr-_xlC$%R)8TM*_3r&xME)JH*0P^vuXX)) zd3$qx=YUb3=d-e`iV#AlU(+-lPp3yS;NAg~MZGM7_nl=2?^)E#0+={pux=V8GK+Q7 z01O;pRRvXvBKX2vw|OYB+i3Ay0+AjBBEqiq{j3)M&4To>Ac96J(BBIBWT1jXT4?bO z5buLG#%5iEwAK$W^3oKHpbwbld38ofRzCbfMehUI0W`~2>1YA dfH^S#8~`^!sx0BE=E48~002ovPDHLkV1jUZm5~4d literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphButton.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphButton.png.meta new file mode 100644 index 0000000..76350fc --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphButton.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 2b3b7485f95e8a44dab3fa9610f56cbb +timeCreated: 1513873202 +licenseType: Store +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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphButtonActive.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GraphButtonActive.png new file mode 100644 index 0000000000000000000000000000000000000000..67cce68771fc0160f0c72fcb2545af389e3d0d55 GIT binary patch literal 381 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 literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GrayNormalHeader.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GrayNormalHeader.png.meta new file mode 100644 index 0000000..fab11a7 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GrayNormalHeader.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 9e88b336bd16b1e4b99de75f486126c1 +timeCreated: 1481127004 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 5 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GrayNormalHeaderSquare.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/GrayNormalHeaderSquare.png new file mode 100644 index 0000000000000000000000000000000000000000..a150e5bb98c306f21960608e53a6a08b8951d162 GIT binary patch literal 5263 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 TW_C3JLz=-G2co&H|6fVg?3oVGw3ym^DWND5#L^ z5#-CjP^HSi(9q1l@bf>Ae#yX4YQVtoDuIE)Y6b&?c>bjLqi#U8A)YRdAr-fh{`~)M z&%CsuwXw0$(IsR~&g6T0>Q0_$I+Ct(xaU6)5cu$fFz96XDSK}2SYg3@HO46G#0td{ sV;0Ms|JzlQgBX=fPXQgl!0`V+GlSR){-lz*TfTz$p00i_>zopr0Oe6VV*mgE literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/ObjectPickerBackgroundOutline.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/ObjectPickerBackgroundOutline.png.meta new file mode 100644 index 0000000..13ecffb --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/ObjectPickerBackgroundOutline.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: c1912a55d2f211d468ddeb7b1386dd41 +timeCreated: 1487618370 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 1 + 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: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: 5 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PopupPicker.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PopupPicker.png new file mode 100644 index 0000000000000000000000000000000000000000..8c826a9677de0a3276c5cf310078ef6e60ee4f21 GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkEAgXYd<_O1%;x|9#|ww+ z>t#w!(d{mhRJkyXk3B(q4tW7IfLI@*e95OT`=j4 zGQ;hqcBQR)TlWfxotmxH!0@-8y|r9AHqm?5yc0D~_yl;*R6I~#mZtXW`ThdNV{ep{ U53V)r2iniz>FVdQ&MBb@0Qloc`2YX_ literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PopupPicker.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PopupPicker.png.meta new file mode 100644 index 0000000..4d05be2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PopupPicker.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: d2384a227b4ac4943b73c8151393e502 +timeCreated: 1515513996 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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: 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: 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOff.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOff.png new file mode 100644 index 0000000000000000000000000000000000000000..e336ea4ee7d3edae62c1c0cdd6edd591e4be96e0 GIT binary patch literal 243 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP*5S+ zBgmJ5p-Pp3p`n?9;pcxK{gQ#9)PRBERRRNp)eHs(@%%~gN8NyGD?MEtLn>~)xpa{8 zP=G+o!^*flkxh4R1g*Nr$0Rn%FUa}9=T9QMdju-Q`T2BCzdQG5xvob)-^(lcjCr1K zR=j3sJa3h>Y3<5iaXZT$3Xa|3IRAB?u0z4WOD9NzGt krTVRJ{LlSG_74mhdi1;#;zWOl10BKO>FVdQ&MBb@0KKeK@c;k- literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOff.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOff.png.meta new file mode 100644 index 0000000..97da0a2 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOff.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 1f3a46793c375864ab816c0d78061e4e +timeCreated: 1486488219 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 1 + 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: -3 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOn.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOn.png new file mode 100644 index 0000000000000000000000000000000000000000..0b8ed9d3d06be97cd2b22796ccb20b4b2bf06bee GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP*5S+ zBgmJ5p-Pp3p`n?9;pcxK{gQ#9)PRBERRRNp)eHs(@%%~gN8NyGvproLLn>~)nY^2~ z!GMQVR!Yk)L8|PO$xVhCDzj7CJf<^=H^|s|wOgFrlw%*8&hEiI*W^>-K?SAN->e!! z`DWaVC^6e?+W5SqUU^1CjZn(n`&@1ciIcy?iGFc-GHZoput0^|4emStxr5jkE(dyt U{P+1a9cV3sr>mdKI;Vst0B$Eo)Bpeg literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOn.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOn.png.meta new file mode 100644 index 0000000..704441e --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PreviewOn.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: dae54b5aa457b474e8a1599de1073d26 +timeCreated: 1486488219 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 1 + 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: -3 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PropertyPicker.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/PropertyPicker.png new file mode 100644 index 0000000000000000000000000000000000000000..f8bbfe615f57eb1d65c30799cdb5e81a42e0fb3b GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP*5S+ zBgmJ5p-Pp3p`n?9;pcxK{gQ#9)PRBERRRNp)eHs(@%%~gN8NyGtvp>ELn>}1{rUgj zo>{e_v(f25(~&xdMRBZbK;WjLKjD?QTZy3Q< zO-sW-5Zz7EBn^S;AwNP8tl-&;2mejLyCfuf@gzO=>i_UmJoKb^5d=vg%|)bGOGDCp z)c2NF4;h%9-8XM`XWmNjZ!!$S3(K;uG)+4t+_vp=S(f)v6g}d&B__GRv>*tso2H4D z%cUraLV>nzi@{(ZbX^bQIKBng>R6=j`otqchr{91bUIBm z6!c(mmSs8#d-6UKW6m&)8*&XS7LrG+)rvji*fr){*F8qYVu8V1s;Uy(t(vP-A*JM8 zY~NskzzrV&Pd1xPhfDyXx zysACODNNH8i^XC*nM@u){b2zoZScw~lJAb=93r|P7nth>Qr|&NlE2{P-^bzLzz=qA zBhvVT-#gC{+kFA{>eqXSCR~YuSi`AA1y>UO0@cmDiq%_F2><{907*qoM6N<$f>Hap AL;wH) literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/SliderButton.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/SliderButton.png.meta new file mode 100644 index 0000000..f016d54 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/SliderButton.png.meta @@ -0,0 +1,58 @@ +fileFormatVersion: 2 +guid: dd563e33152bb6443b099b4139ceecb9 +timeCreated: 1501088039 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortOutline.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..dcd640db7b4200dddc2e20966c469fc8ef5856b1 GIT binary patch literal 19719 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 YFSXekv%s7LpBUibGTS-dX~~-Z0htf8Gynhq literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortOutline.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortOutline.png.meta new file mode 100644 index 0000000..b16ea8b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortOutline.png.meta @@ -0,0 +1,84 @@ +fileFormatVersion: 2 +guid: 56277f370fb77a448a152bcd2e3a9077 +timeCreated: 1481126991 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 1 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 1 + 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: 5 + maxTextureSize: 2048 + textureSettings: + filterMode: 1 + aniso: 4 + 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: WebGL + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortSolid.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortSolid.png new file mode 100644 index 0000000000000000000000000000000000000000..b755f5e4b2fd69b20285d2594849572cdc8cd6ee GIT binary patch literal 19671 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 V%5Cn~N`)^JaCP)_D6$V)|1WbFobCVs literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortSolid.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortSolid.png.meta new file mode 100644 index 0000000..9ead42d --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WhitePortSolid.png.meta @@ -0,0 +1,84 @@ +fileFormatVersion: 2 +guid: 8113366f9f7cec647878e3af2fb98922 +timeCreated: 1481127000 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 1 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 1 + 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: 5 + maxTextureSize: 2048 + textureSettings: + filterMode: 1 + aniso: 4 + 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: WebGL + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WireNodeSelection.png b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WireNodeSelection.png new file mode 100644 index 0000000000000000000000000000000000000000..9dd1e738510adedd57455ce4076e3635c2f2bba6 GIT binary patch literal 933 zcmV;W16urvP)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZL_H>6+D5R_*G!xjCjl#u@+l5M|1`?gw^umwm z9m!(CF7}ZnyBIMsF)q8pZ9&=4myU)JEMIdYDEvss57mskTQsYg{O?{!( zTz0B$R(7{Ekon|CZUW1z9a`UigO|2e^7f`;`~dL;^hRJXCJ~*^6$QLd=NE*kKy~GE zb4g+YcRBvrIX(um7C>qavH7W;oT^aS3NShaUxy`T7F|PWx$I<_*V9&_dd{YW^0%H^ zsp*eqHO-xaI*L%TEBNp0Tpk){UIOgrTRHs1Hr_IweSSkiQ{7+gZ`Aj#)oy24>6(cz zJomz*;-S;;`#I5ip3^em(cC<37WYN~Yw^%}Fo6Ay`aZ11L%orF&R}?CKrL0MGljvJ zL`tY<3SCM{sAmRa`5`eFsthQa8_g7=)8MpAmkI%$cIlFNS%yOmP-MU%#F_*CpTb}` zWPph|5~dLFLMknq3$~mV%>i%z+hoYV;_w8Mrcmb>IHmZZf-Ot&Lv{ZAt1}pjGNAX3 zF<=UzDj=KO(iv8|)`NA1l`gW$EupG>&S2;kz%n|8{gDcGSC!#(*g$i`A7h!?aMbl` z&!|uIjc=L`-|=WY!^$gtV=Et~l8MLm?hsU{IoQ{uebRWh)BkJE(Mxi zf1IN)?;%v}`^VB)H%2B|{-}rE_kQ3M&<)%-e_R3kiZ3O%7cTyi* zbQEKmXjfgL~%;0KHoBM!uXzkojAHZZ$-!9ExOU&$Sw3Xj-b00000NkvXX Hu0mjf5cRHo literal 0 HcmV?d00001 diff --git a/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WireNodeSelection.png.meta b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WireNodeSelection.png.meta new file mode 100644 index 0000000..44efba8 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Plugins/EditorResources/UI/Nodes/WireNodeSelection.png.meta @@ -0,0 +1,58 @@ +fileFormatVersion: 2 +guid: bfe0b03d5d60cea4f9d4b2d1d121e592 +timeCreated: 1504005445 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 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 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AmplifyShaderEditor/Readme.txt b/Assets/AmplifyShaderEditor/Readme.txt new file mode 100644 index 0000000..9ee1064 --- /dev/null +++ b/Assets/AmplifyShaderEditor/Readme.txt @@ -0,0 +1,90 @@ +About + + Amplify Shader Editor (c) Amplify Creations, Lda. All rights reserved. + + Amplify Shader Editor is a node-based shader creation tool for Unity 5 + + Redistribution of Amplify Shader Editor is frowned upon. If you want to share the + software, please refer others to the official product page: + + http://amplify.pt/unity/amplify-shader-editor/ + +Description + + Amplify Shader Editor is a node-based shader creation tool inspired by industry leading + editors. An open and tightly integrated solution, it provides a familiar and consistent + development environment that seamlessly blends with Unitys UI conventions and Shader use. + +Features + + * Intuitive, familiar interface + * Node based creation + * Full source-code + * Extensive node library + * Growing sample collection + * Open to user requests and contributions + * Integrated Texture Array Creator tool + * Node API + * Custom Shader Templates + * SRP HD and Lightweight support + +Supported Platforms + + * All platforms + +Minimum Requirements + + Software + + Unity 5+ + +Quick Guide Amplify Shader Editor + + 1) Open the editor canvas located in the main menu under Window > Amplify Shader Editor > Open Canvas. + 2) Create an Amplify Shader via the Menu under Assets > Create > Shaders > Amplify Surface shader. + 3) Double-click an ASE shader to open it in the ASE canvas. + 4) Create a new material and set its shader to the newly created Amplify Shader. + 5) Node and shader properties are on the left side, node list on the right. + 6) Drag out nodes from the node palette list on the right, or right-click anywhere in the canvas to open + a simpler searchable node list. + 7) Data flows from left to right, drag wires from node Input/Output ports to create connections. + 8) The 4 buttons on the main canvas next to the node and shader properties on the upper-left area serve as the main + save and update buttons. Button 1: Update and Save shader, Button 2: LIVE mode, automatically updates + and saves the active shader, Button 3: Remove disconnected nodes, Button 4: Open shader in text editor. + 9) Quick access to current shader or material in use by hitting bottom left and or right buttons on main canvas + 10) Consult the Manual below for detailed information. + +Quick Guide Texture Array Creator + + 1) Open the tool in the main menu under Window > Amplify Shader Editor > Texture Array Creator + 2) Specify the desired Width and Height for the Texture Array through the X and Y Size + 3) Configure your texture properties + 4) Set your array Name and Path + 5) Add elements to the array by hitting the (+) button over the Texture List area and assign textures to them + 6) Hit the Build Array button on the top of the window to build your new Texture Array + 7) Please notice that you can't load previously created texture arrays into the tool so maintain it open until all the tweaks on the array are done + +Documentation + + Please refer to the following website for an up-to-date online manual: + + http://amplify.pt/unity/amplify-shader-editor/manual + +Nodes + + Please refer to the following website for a searchable node list: + + http://amplify.pt/unity/amplify-shader-editor/nodes + + +Feedback + + To file error reports, questions or suggestions, you may use + our feedback form online: + + http://amplify.pt/contact + + Or contact us directly: + + For general inquiries - info@amplify.pt + For technical support - support@amplify.pt (customers only) diff --git a/Assets/AmplifyShaderEditor/Readme.txt.meta b/Assets/AmplifyShaderEditor/Readme.txt.meta new file mode 100644 index 0000000..9e4e00b --- /dev/null +++ b/Assets/AmplifyShaderEditor/Readme.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1b2d5cde00ee97c46b03020eb630dc2d +timeCreated: 1481127071 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins.meta b/Assets/Plugins.meta new file mode 100644 index 0000000..99ec3a2 --- /dev/null +++ b/Assets/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 206db24916f23234bb02a7a1204fa077 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant.meta b/Assets/Plugins/Demigiant.meta new file mode 100644 index 0000000..d6dd26b --- /dev/null +++ b/Assets/Plugins/Demigiant.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: be5ec4e65b4c6d04cad2986b66e5a92b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DOTween.meta b/Assets/Plugins/Demigiant/DOTween.meta new file mode 100644 index 0000000..cbebc39 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween.meta @@ -0,0 +1,21 @@ +fileFormatVersion: 2 +guid: a50bd9a009c8dfc4ebd88cc8101225a7 +labels: +- Tween +- Tweening +- Animation +- HOTween +- Paths +- iTween +- DFTween +- LeanTween +- Ease +- Easing +- Shake +- Punch +- 2DToolkit +- TextMeshPro +- Text +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/DOTween.XML b/Assets/Plugins/Demigiant/DOTween/DOTween.XML new file mode 100644 index 0000000..762220e --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/DOTween.XML @@ -0,0 +1,2963 @@ + + + + DOTween + + + +

+ Types of autoPlay behaviours + + + + No tween is automatically played + + + Only Sequences are automatically played + + + Only Tweeners are automatically played + + + All tweens are automatically played + + + + What axis to constrain in case of Vector tweens + + + + Called the first time the tween is set in a playing state, after any eventual delay + + + + Used in place of System.Func, which is not available in mscorlib. + + + + + Used in place of System.Action. + + + + + Public so it can be used by lose scripts related to DOTween (like DOTweenAnimation) + + + + + Used to separate DOTween class from the MonoBehaviour instance (in order to use static constructors on DOTween). + Contains all instance-based methods + + + + Used internally inside Unity Editor, as a trick to update DOTween's inspector at every frame + + + + Directly sets the current max capacity of Tweeners and Sequences + (meaning how many Tweeners and Sequences can be running at the same time), + so that DOTween doesn't need to automatically increase them in case the max is reached + (which might lead to hiccups when that happens). + Sequences capacity must be less or equal to Tweeners capacity + (if you pass a low Tweener capacity it will be automatically increased to match the Sequence's). + Beware: use this method only when there are no tweens running. + + Max Tweeners capacity. + Default: 200 + Max Sequences capacity. + Default: 50 + + + + This class contains a C# port of the easing equations created by Robert Penner (http://robertpenner.com/easing). + + + + + Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in: accelerating from zero velocity. + + + Current time (in frames or seconds). + + + Expected easing duration (in frames or seconds). + + Unused: here to keep same delegate for all ease types. + Unused: here to keep same delegate for all ease types. + + The eased value. + + + + + Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out: decelerating from zero velocity. + + + Current time (in frames or seconds). + + + Expected easing duration (in frames or seconds). + + Unused: here to keep same delegate for all ease types. + Unused: here to keep same delegate for all ease types. + + The eased value. + + + + + Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in/out: acceleration until halfway, then deceleration. + + + Current time (in frames or seconds). + + + Expected easing duration (in frames or seconds). + + Unused: here to keep same delegate for all ease types. + Unused: here to keep same delegate for all ease types. + + The eased value. + + + + + Returns a value between 0 and 1 (inclusive) based on the elapsed time and ease selected + + + + + Returns a value between 0 and 1 (inclusive) based on the elapsed time and ease selected + + + + + Used to interpret AnimationCurves as eases. + Public so it can be used by external ease factories + + + + + Behaviour in case a tween nested inside a Sequence fails and is captured by safe mode + + + + If the Sequence contains other elements, kill the failed tween but preserve the rest + + + Kill the whole Sequence + + + + Log types thrown by errors captured and prevented by safe mode + + + + No logs. NOT RECOMMENDED + + + Throw a normal log + + + Throw a warning log (default) + + + Throw an error log + + + + Additional notices passed to plugins when updating. + Public so it can be used by custom plugins. Internally, only PathPlugin uses it + + + + + None + + + + + Lets the plugin know that we restarted or rewinded + + + + + OnRewind callback behaviour (can only be set via DOTween's Utility Panel) + + + + + When calling Rewind or PlayBackwards/SmoothRewind, OnRewind callbacks will be fired only if the tween isn't already rewinded + + + + + When calling Rewind, OnRewind callbacks will always be fired, even if the tween is already rewinded. + When calling PlayBackwards/SmoothRewind instead, OnRewind callbacks will be fired only if the tween isn't already rewinded + + + + + When calling Rewind or PlayBackwards/SmoothRewind, OnRewind callbacks will always be fired, even if the tween is already rewinded + + + + + Public only so custom shortcuts can access some of these methods + + + + + INTERNAL: used by DO shortcuts and Modules to set special startup mode + + + + + INTERNAL: used by DO shortcuts and Modules to set the tween as blendable + + + + + INTERNAL: used by DO shortcuts and Modules to prevent a tween from using a From setup even if passed + + + + + Used to dispatch commands that need to be captured externally, usually by Modules + + + + + Returns a Vector3 with z = 0 + + + + + Returns the 2D angle between two vectors + + + + + Returns a point on a circle with the given center and radius, + using Unity's circle coordinates (0° points up and increases clockwise) + + + + + Uses approximate equality on each axis instead of Unity's Vector3 equality, + because the latter fails (in some cases) when assigning a Vector3 to a transform.position and then checking it. + + + + + Looks for the type within all possible project assembly names + + + + NO-GC METHOD: changes the start value of a tween and rewinds it (without pausing it). + Has no effect with tweens that are inside Sequences + The new start value + If bigger than 0 applies it as the new tween duration + + + NO-GC METHOD: changes the end value of a tween and rewinds it (without pausing it). + Has no effect with tweens that are inside Sequences + The new end value + If TRUE the start value will become the current target's value, otherwise it will stay the same + + + NO-GC METHOD: changes the end value of a tween and rewinds it (without pausing it). + Has no effect with tweens that are inside Sequences + The new end value + If bigger than 0 applies it as the new tween duration + If TRUE the start value will become the current target's value, otherwise it will stay the same + + + NO-GC METHOD: changes the start and end value of a tween and rewinds it (without pausing it). + Has no effect with tweens that are inside Sequences + The new start value + The new end value + If bigger than 0 applies it as the new tween duration + + + + Struct that stores two colors (used for LineRenderer tweens) + + + + + Used for tween callbacks + + + + + Used for tween callbacks + + + + + Used for custom and animationCurve-based ease functions. Must return a value between 0 and 1. + + + + + Straight Quaternion plugin. Instead of using Vector3 values accepts Quaternion values directly. + Beware: doesn't work with LoopType.Incremental (neither directly nor if inside a LoopType.Incremental Sequence). + To use it, call DOTween.To with the plugin parameter overload, passing it PureQuaternionPlugin.Plug() as first parameter + (do not use any of the other public PureQuaternionPlugin methods): + DOTween.To(PureQuaternionPlugin.Plug(), ()=> myQuaternionProperty, x=> myQuaternionProperty = x, myQuaternionEndValue, duration); + + + + + Plug this plugin inside a DOTween.To call. + Example: + DOTween.To(PureQuaternionPlugin.Plug(), ()=> myQuaternionProperty, x=> myQuaternionProperty = x, myQuaternionEndValue, duration); + + + + INTERNAL: do not use + + + INTERNAL: do not use + + + INTERNAL: do not use + + + INTERNAL: do not use + + + INTERNAL: do not use + + + INTERNAL: do not use + + + INTERNAL: do not use + + + INTERNAL: do not use + + + + Extra non-tweening-related curve methods + + + + + Cubic bezier curve methods + + + + + Calculates a point along the given Cubic Bezier segment-curve. + + Segment start point + Start point's control point/handle + Segment end point + End point's control point/handle + 0-1 percentage along which to retrieve point + + + + Returns an array containing a series of points along the given Cubic Bezier segment-curve. + + Start point + Start point's control point/handle + End point + End point's control point/handle + Cloud resolution (min: 2) + + + + Calculates a series of points along the given Cubic Bezier segment-curve and adds them to the given list. + + Start point + Start point's control point/handle + End point + End point's control point/handle + Cloud resolution (min: 2) + + + + Main DOTween class. Contains static methods to create and control tweens in a generic way + + + + DOTween's version + + + If TRUE (default) makes tweens slightly slower but safer, automatically taking care of a series of things + (like targets becoming null while a tween is playing). + Default: TRUE + + + Log type when safe mode reports capturing an error and preventing it + + + Behaviour in case a tween nested inside a Sequence fails (and is caught by safe mode). + Default: NestedTweenFailureBehaviour.TryToPreserveSequence + + + If TRUE you will get a DOTween report when exiting play mode (only in the Editor). + Useful to know how many max Tweeners and Sequences you reached and optimize your final project accordingly. + Beware, this will slightly slow down your tweens while inside Unity Editor. + Default: FALSE + + + Global DOTween timeScale. + Default: 1 + + + If TRUE, DOTween will use Time.smoothDeltaTime instead of Time.deltaTime for UpdateType.Normal and UpdateType.Late tweens + (unless they're set as timeScaleIndependent, in which case a value between the last timestep + and will be used instead). + Setting this to TRUE will lead to smoother animations. + Default: FALSE + + + If is TRUE, this indicates the max timeStep that an independent update call can last. + Setting this to TRUE will lead to smoother animations. + Default: FALSE + + + DOTween's log behaviour. + Default: LogBehaviour.ErrorsOnly + + + Used to intercept DOTween's logs. If this method isn't NULL, DOTween will call it before writing a log via Unity's own Debug log methods. + Return TRUE if you want DOTween to proceed with the log, FALSE otherwise. + This method must return a bool and accept two parameters: + - LogType: the type of Unity log that DOTween is trying to log + - object: the log message that DOTween wants to log + + + If TRUE draws path gizmos in Unity Editor (if the gizmos button is active). + Deactivate this if you want to avoid gizmos overhead while in Unity Editor + + + If TRUE activates various debug options + + + Stores the target id so it can be used to give more info in case of safeMode error capturing. + Only active if both debugMode and useSafeMode are TRUE + + + Default updateType for new tweens. + Default: UpdateType.Normal + + + Sets whether Unity's timeScale should be taken into account by default or not. + Default: false + + + Default autoPlay behaviour for new tweens. + Default: AutoPlay.All + + + Default autoKillOnComplete behaviour for new tweens. + Default: TRUE + + + Default loopType applied to all new tweens. + Default: LoopType.Restart + + + If TRUE all newly created tweens are set as recyclable, otherwise not. + Default: FALSE + + + Default ease applied to all new Tweeners (not to Sequences which always have Ease.Linear as default). + Default: Ease.InOutQuad + + + Default overshoot/amplitude used for eases + Default: 1.70158f + + + Default period used for eases + Default: 0 + + + Used internally. Assigned/removed by DOTweenComponent.Create/DestroyInstance + + + + Must be called once, before the first ever DOTween call/reference, + otherwise it will be called automatically and will use default options. + Calling it a second time won't have any effect. + You can chain SetCapacity to this method, to directly set the max starting size of Tweeners and Sequences: + DOTween.Init(false, false, LogBehaviour.Default).SetCapacity(100, 20); + + If TRUE all new tweens will be set for recycling, meaning that when killed, + instead of being destroyed, they will be put in a pool and reused instead of creating new tweens. This option allows you to avoid + GC allocations by reusing tweens, but you will have to take care of tween references, since they might result active + even if they were killed (since they might have been respawned and are now being used for other tweens). + If you want to automatically set your tween references to NULL when a tween is killed + you can use the OnKill callback like this: + .OnKill(()=> myTweenReference = null) + You can change this setting at any time by changing the static property, + or you can set the recycling behaviour for each tween separately, using: + SetRecyclable(bool recyclable) + Default: FALSE + If TRUE makes tweens slightly slower but safer, automatically taking care of a series of things + (like targets becoming null while a tween is playing). + You can change this setting at any time by changing the static property. + Default: FALSE + Type of logging to use. + You can change this setting at any time by changing the static property. + Default: ErrorsOnly + + + + Directly sets the current max capacity of Tweeners and Sequences + (meaning how many Tweeners and Sequences can be running at the same time), + so that DOTween doesn't need to automatically increase them in case the max is reached + (which might lead to hiccups when that happens). + Sequences capacity must be less or equal to Tweeners capacity + (if you pass a low Tweener capacity it will be automatically increased to match the Sequence's). + Beware: use this method only when there are no tweens running. + + Max Tweeners capacity. + Default: 200 + Max Sequences capacity. + Default: 50 + + + + Kills all tweens, clears all cached tween pools and plugins and resets the max Tweeners/Sequences capacities to the default values. + + If TRUE also destroys DOTween's gameObject and resets its initializiation, default settings and everything else + (so that next time you use it it will need to be re-initialized) + + + + Clears all cached tween pools. + + + + + Checks all active tweens to find and remove eventually invalid ones (usually because their targets became NULL) + and returns the total number of invalid tweens found and removed. + IMPORTANT: this will cause an error on UWP platform, so don't use it there + BEWARE: this is a slightly expensive operation so use it with care + + + + + Updates all tweens that are set to . + + Manual deltaTime + Unscaled delta time (used with tweens set as timeScaleIndependent) + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a property or field to the given value using a custom plugin + The plugin to use. Each custom plugin implements a static Get() method + you'll need to call to assign the correct plugin in the correct way, like this: + CustomPlugin.Get() + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens only one axis of a Vector3 to the given value using default plugins. + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + The axis to tween + + + Tweens only the alpha of a Color to the given value using default plugins + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end value to reachThe tween's duration + + + Tweens a virtual property from the given start to the given end value + and implements a setter that allows to use that value with an external method or a lambda + Example: + To(MyMethod, 0, 12, 0.5f); + Where MyMethod is a function that accepts a float parameter (which will be the result of the virtual tween) + The action to perform with the tweened value + The value to start from + The end value to reach + The duration of the virtual tween + + + + Punches a Vector3 towards the given direction and then back to the starting one + as if it was connected to the starting position via an elastic. + This tween type generates some GC allocations at startup + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The direction and strength of the punch + The duration of the tween + Indicates how much will the punch vibrate + Represents how much (0 to 1) the vector will go beyond the starting position when bouncing backwards. + 1 creates a full oscillation between the direction and the opposite decaying direction, + while 0 oscillates only between the starting position and the decaying direction + + + Shakes a Vector3 with the given values. + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The duration of the tween + The shake strength + Indicates how much will the shake vibrate + Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + Setting it to 0 will shake along a single direction and behave like a random punch. + If TRUE only shakes on the X Y axis (looks better with things like cameras). + If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + + + Shakes a Vector3 with the given values. + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The duration of the tween + The shake strength on each axis + Indicates how much will the shake vibrate + Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + Setting it to 0 will shake along a single direction and behave like a random punch. + If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + + + Tweens a property or field to the given values using default plugins. + Ease is applied between each segment and not as a whole. + This tween type generates some GC allocations at startup + A getter for the field or property to tween. + Example usage with lambda:()=> myProperty + A setter for the field or property to tween + Example usage with lambda:x=> myProperty = x + The end values to reach for each segment. This array must have the same length as durations + The duration of each segment. This array must have the same length as endValues + + + + Returns a new to be used for tween groups. + Mind that Sequences don't have a target applied automatically like Tweener creation shortcuts, + so if you want to be able to kill this Sequence when calling DOTween.Kill(target) you'll have to add + the target manually; you can do that directly by using the overload instead of this one + + + + + Returns a new to be used for tween groups, and allows to set a target + (because Sequences don't have their target set automatically like Tweener creation shortcuts). + That way killing/controlling tweens by target will apply to this Sequence too. + + The target of the Sequence. Relevant only for static target-based methods like DOTween.Kill(target), + useless otherwise + + + Completes all tweens and returns the number of actual tweens completed + (meaning tweens that don't have infinite loops and were not already complete) + For Sequences only: if TRUE also internal Sequence callbacks will be fired, + otherwise they will be ignored + + + Completes all tweens with the given ID or target and returns the number of actual tweens completed + (meaning the tweens that don't have infinite loops and were not already complete) + For Sequences only: if TRUE internal Sequence callbacks will be fired, + otherwise they will be ignored + + + Flips all tweens (changing their direction to forward if it was backwards and viceversa), + then returns the number of actual tweens flipped + + + Flips the tweens with the given ID or target (changing their direction to forward if it was backwards and viceversa), + then returns the number of actual tweens flipped + + + Sends all tweens to the given position (calculating also eventual loop cycles) and returns the actual tweens involved + + + Sends all tweens with the given ID or target to the given position (calculating also eventual loop cycles) + and returns the actual tweens involved + + + Kills all tweens and returns the number of actual tweens killed + If TRUE completes the tweens before killing them + + + Kills all tweens and returns the number of actual tweens killed + If TRUE completes the tweens before killing them + Eventual IDs or targets to exclude from the killing + + + Kills all tweens with the given ID or target and returns the number of actual tweens killed + If TRUE completes the tweens before killing them + + + Kills all tweens with the given target and the given ID, and returns the number of actual tweens killed + If TRUE completes the tweens before killing them + + + Pauses all tweens and returns the number of actual tweens paused + + + Pauses all tweens with the given ID or target and returns the number of actual tweens paused + (meaning the tweens that were actually playing and have been paused) + + + Plays all tweens and returns the number of actual tweens played + (meaning tweens that were not already playing or complete) + + + Plays all tweens with the given ID or target and returns the number of actual tweens played + (meaning the tweens that were not already playing or complete) + + + Plays all tweens with the given target and the given ID, and returns the number of actual tweens played + (meaning the tweens that were not already playing or complete) + + + Plays backwards all tweens and returns the number of actual tweens played + (meaning tweens that were not already started, playing backwards or rewinded) + + + Plays backwards all tweens with the given ID or target and returns the number of actual tweens played + (meaning the tweens that were not already started, playing backwards or rewinded) + + + Plays backwards all tweens with the given target and ID and returns the number of actual tweens played + (meaning the tweens that were not already started, playing backwards or rewinded) + + + Plays forward all tweens and returns the number of actual tweens played + (meaning tweens that were not already playing forward or complete) + + + Plays forward all tweens with the given ID or target and returns the number of actual tweens played + (meaning the tweens that were not already playing forward or complete) + + + Plays forward all tweens with the given target and ID and returns the number of actual tweens played + (meaning the tweens that were not already started, playing backwards or rewinded) + + + Restarts all tweens, then returns the number of actual tweens restarted + + + Restarts all tweens with the given ID or target, then returns the number of actual tweens restarted + If TRUE includes the eventual tweens delays, otherwise skips them + If >= 0 changes the startup delay of all involved tweens to this value, otherwise doesn't touch it + + + Restarts all tweens with the given target and the given ID, and returns the number of actual tweens played + (meaning the tweens that were not already playing or complete) + If TRUE includes the eventual tweens delays, otherwise skips them + If >= 0 changes the startup delay of all involved tweens to this value, otherwise doesn't touch it + + + Rewinds and pauses all tweens, then returns the number of actual tweens rewinded + (meaning tweens that were not already rewinded) + + + Rewinds and pauses all tweens with the given ID or target, then returns the number of actual tweens rewinded + (meaning the tweens that were not already rewinded) + + + Smoothly rewinds all tweens (delays excluded), then returns the number of actual tweens rewinding/rewinded + (meaning tweens that were not already rewinded). + A "smooth rewind" animates the tween to its start position, + skipping all elapsed loops (except in case of LoopType.Incremental) while keeping the animation fluent. + Note that a tween that was smoothly rewinded will have its play direction flipped + + + Smoothly rewinds all tweens (delays excluded) with the given ID or target, then returns the number of actual tweens rewinding/rewinded + (meaning the tweens that were not already rewinded). + A "smooth rewind" animates the tween to its start position, + skipping all elapsed loops (except in case of LoopType.Incremental) while keeping the animation fluent. + Note that a tween that was smoothly rewinded will have its play direction flipped + + + Toggles the play state of all tweens and returns the number of actual tweens toggled + (meaning tweens that could be played or paused, depending on the toggle state) + + + Toggles the play state of all tweens with the given ID or target and returns the number of actual tweens toggled + (meaning the tweens that could be played or paused, depending on the toggle state) + + + + Returns TRUE if a tween with the given ID or target is active. + You can also use this to know if a shortcut tween is active for a given target. + Example: + transform.DOMoveX(45, 1); // transform is automatically added as the tween target + DOTween.IsTweening(transform); // Returns true + + The target or ID to look for + If FALSE (default) returns TRUE as long as a tween for the given target/ID is active, + otherwise also requires it to be playing + + + + Returns the total number of active tweens. + A tween is considered active if it wasn't killed, regardless if it's playing or paused + + + + + Returns the total number of active and playing tweens. + A tween is considered as playing even if its delay is actually playing + + + + + Returns a list of all active tweens in a playing state. + Returns NULL if there are no active playing tweens. + Beware: each time you call this method a new list is generated, so use it for debug only + + If NULL creates a new list, otherwise clears and fills this one (and thus saves allocations) + + + + Returns a list of all active tweens in a paused state. + Returns NULL if there are no active paused tweens. + Beware: each time you call this method a new list is generated, so use it for debug only + + If NULL creates a new list, otherwise clears and fills this one (and thus saves allocations) + + + + Returns a list of all active tweens with the given id. + Returns NULL if there are no active tweens with the given id. + Beware: each time you call this method a new list is generated + + If TRUE returns only the tweens with the given ID that are currently playing + If NULL creates a new list, otherwise clears and fills this one (and thus saves allocations) + + + + Returns a list of all active tweens with the given target. + Returns NULL if there are no active tweens with the given target. + Beware: each time you call this method a new list is generated + If TRUE returns only the tweens with the given target that are currently playing + If NULL creates a new list, otherwise clears and fills this one (and thus saves allocations) + + + + + Creates virtual tweens that can be used to change other elements via their OnUpdate calls + + + + + Tweens a virtual float. + You can add regular settings to the generated tween, + but do not use SetUpdate or you will overwrite the onVirtualUpdate parameter + + The value to start from + The value to tween to + The duration of the tween + A callback which must accept a parameter of type float, called at each update + + + + Tweens a virtual int. + You can add regular settings to the generated tween, + but do not use SetUpdate or you will overwrite the onVirtualUpdate parameter + + The value to start from + The value to tween to + The duration of the tween + A callback which must accept a parameter of type int, called at each update + + + + Tweens a virtual Vector3. + You can add regular settings to the generated tween, + but do not use SetUpdate or you will overwrite the onVirtualUpdate parameter + + The value to start from + The value to tween to + The duration of the tween + A callback which must accept a parameter of type Vector3, called at each update + + + + Tweens a virtual Color. + You can add regular settings to the generated tween, + but do not use SetUpdate or you will overwrite the onVirtualUpdate parameter + + The value to start from + The value to tween to + The duration of the tween + A callback which must accept a parameter of type Color, called at each update + + + Returns a value based on the given ease and lifetime percentage (0 to 1) + The value to start from when lifetimePercentage is 0 + The value to reach when lifetimePercentage is 1 + The time percentage (0 to 1) at which the value should be taken + The type of ease + + + Returns a value based on the given ease and lifetime percentage (0 to 1) + The value to start from when lifetimePercentage is 0 + The value to reach when lifetimePercentage is 1 + The time percentage (0 to 1) at which the value should be taken + The type of ease + Eventual overshoot to use with Back ease + + + Returns a value based on the given ease and lifetime percentage (0 to 1) + The value to start from when lifetimePercentage is 0 + The value to reach when lifetimePercentage is 1 + The time percentage (0 to 1) at which the value should be taken + The type of ease + Eventual amplitude to use with Elastic easeType + Eventual period to use with Elastic easeType + + + Returns a value based on the given ease and lifetime percentage (0 to 1) + The value to start from when lifetimePercentage is 0 + The value to reach when lifetimePercentage is 1 + The time percentage (0 to 1) at which the value should be taken + The AnimationCurve to use for ease + + + Fires the given callback after the given time. + Callback delay + Callback to fire when the delay has expired + If TRUE (default) ignores Unity's timeScale + + + + Don't assign this! It's assigned automatically when creating 0 duration tweens + + + + + Don't assign this! It's assigned automatically when setting the ease to an AnimationCurve or to a custom ease function + + + + + Allows to wrap ease method in special ways, adding extra features + + + + + Converts the given ease so that it also creates a stop-motion effect, by playing the tween at the given FPS + + FPS at which the tween should be played + Ease type + + + + Converts the given ease so that it also creates a stop-motion effect, by playing the tween at the given FPS + + FPS at which the tween should be played + AnimationCurve to use for the ease + + + + Converts the given ease so that it also creates a stop-motion effect, by playing the tween at the given FPS + + FPS at which the tween should be played + Custom ease function to use + + + + Used to allow method chaining with DOTween.Init + + + + + Directly sets the current max capacity of Tweeners and Sequences + (meaning how many Tweeners and Sequences can be running at the same time), + so that DOTween doesn't need to automatically increase them in case the max is reached + (which might lead to hiccups when that happens). + Sequences capacity must be less or equal to Tweeners capacity + (if you pass a low Tweener capacity it will be automatically increased to match the Sequence's). + Beware: use this method only when there are no tweens running. + + Max Tweeners capacity. + Default: 200 + Max Sequences capacity. + Default: 50 + + + + Behaviour that can be assigned when chaining a SetLink to a tween + + + + Pauses the tween when the link target is disabled + + + Pauses the tween when the link target is disabled, plays it when it's enabled + + + Pauses the tween when the link target is disabled, restarts it when it's enabled + + + Plays the tween when the link target is enabled + + + Restarts the tween when the link target is enabled + + + Kills the tween when the link target is disabled + + + Kills the tween when the link target is destroyed (becomes NULL). This is always active even if another behaviour is chosen + + + Completes the tween when the link target is disabled + + + Completes and kills the tween when the link target is disabled + + + Rewinds the tween (delay excluded) when the link target is disabled + + + Rewinds and kills the tween when the link target is disabled + + + + Path mode (used to determine correct LookAt orientation) + + + + Ignores the path mode (and thus LookAt behaviour) + + + Regular 3D path + + + 2D top-down path + + + 2D side-scroller path + + + + Type of path to use with DOPath tweens + + + + Linear, composed of straight segments between each waypoint + + + Curved path (which uses Catmull-Rom curves) + + + EXPERIMENTAL: Curved path (which uses Cubic Bezier curves, where each point requires two extra control points) + + + + Tweens a Vector2 along a circle. + EndValue represents the center of the circle, start and end value degrees are inside options + ChangeValue x is changeValue°, y is unused + + + + + Path control point + + + + + Path waypoints (modified by PathPlugin when setting relative end/change value or by CubicBezierDecoder) and by DOTweenPathInspector + + + + + Minimum input points necessary to create the path (doesn't correspond to actual waypoints required) + + + + + Gets the point on the path at the given percentage (0 to 1) + + The percentage (0 to 1) at which to get the point + If TRUE constant speed is taken into account, otherwise not + + + + Base interface for all tween plugins options + + + + Resets the plugin + + + + This plugin generates some GC allocations at startup + + + + + Path plugin works exclusively with Transforms + + + + + Rotation mode used with DORotate methods + + + + + Fastest way that never rotates beyond 360° + + + + + Fastest way that rotates beyond 360° + + + + + Adds the given rotation to the transform using world axis and an advanced precision mode + (like when using transform.Rotate(Space.World)). + In this mode the end value is is always considered relative + + + + + Adds the given rotation to the transform's local axis + (like when rotating an object with the "local" switch enabled in Unity's editor or using transform.Rotate(Space.Self)). + In this mode the end value is is always considered relative + + + + + Type of scramble to apply to string tweens + + + + + No scrambling of characters + + + + + A-Z + a-z + 0-9 characters + + + + + A-Z characters + + + + + a-z characters + + + + + 0-9 characters + + + + + Custom characters + + + + + Methods that extend Tween objects and allow to control or get data from them + + + + Completes the tween + + + Completes the tween + For Sequences only: if TRUE also internal Sequence callbacks will be fired, + otherwise they will be ignored + + + Flips the direction of this tween (backwards if it was going forward or viceversa) + + + Forces the tween to initialize its settings immediately + + + Send the tween to the given position in time + Time position to reach + (if higher than the whole tween duration the tween will simply reach its end) + If TRUE will play the tween after reaching the given position, otherwise it will pause it + + + Send the tween to the given position in time while also executing any callback between the previous time position and the new one + Time position to reach + (if higher than the whole tween duration the tween will simply reach its end) + If TRUE will play the tween after reaching the given position, otherwise it will pause it + + + Kills the tween + If TRUE completes the tween before killing it + + + + Forces this tween to update manually, regardless of the set via SetUpdate. + Note that the tween will still be subject to normal tween rules, so if for example it's paused this method will do nothing. + Also note that if you only want to update this tween instance manually you'll have to set it to anyway, + so that it's not updated automatically. + + Manual deltaTime + Unscaled delta time (used with tweens set as timeScaleIndependent) + + + Pauses the tween + + + Plays the tween + + + Sets the tween in a backwards direction and plays it + + + Sets the tween in a forward direction and plays it + + + Restarts the tween from the beginning + Ignored in case of Sequences. If TRUE includes the eventual tween delay, otherwise skips it + Ignored in case of Sequences. If >= 0 changes the startup delay to this value, otherwise doesn't touch it + + + Rewinds and pauses the tween + Ignored in case of Sequences. If TRUE includes the eventual tween delay, otherwise skips it + + + Smoothly rewinds the tween (delays excluded). + A "smooth rewind" animates the tween to its start position, + skipping all elapsed loops (except in case of LoopType.Incremental) while keeping the animation fluent. + If called on a tween who is still waiting for its delay to happen, it will simply set the delay to 0 and pause the tween. + Note that a tween that was smoothly rewinded will have its play direction flipped + + + Plays the tween if it was paused, pauses it if it was playing + + + Send a path tween to the given waypoint. + Has no effect if this is not a path tween. + BEWARE, this is a special utility method: + it works only with Linear eases. Also, the lookAt direction might be wrong after calling this and might need to be set manually + (because it relies on a smooth path movement and doesn't work well with jumps that encompass dramatic direction changes) + Waypoint index to reach + (if higher than the max waypoint index the tween will simply go to the last one) + If TRUE will play the tween after reaching the given waypoint, otherwise it will pause it + + + + Creates a yield instruction that waits until the tween is killed or complete. + It can be used inside a coroutine as a yield. + Example usage:yield return myTween.WaitForCompletion(); + + + + + Creates a yield instruction that waits until the tween is killed or rewinded. + It can be used inside a coroutine as a yield. + Example usage:yield return myTween.WaitForRewind(); + + + + + Creates a yield instruction that waits until the tween is killed. + It can be used inside a coroutine as a yield. + Example usage:yield return myTween.WaitForKill(); + + + + + Creates a yield instruction that waits until the tween is killed or has gone through the given amount of loops. + It can be used inside a coroutine as a yield. + Example usage:yield return myTween.WaitForElapsedLoops(2); + + Elapsed loops to wait for + + + + Creates a yield instruction that waits until the tween is killed or has reached the given position (loops included, delays excluded). + It can be used inside a coroutine as a yield. + Example usage:yield return myTween.WaitForPosition(2.5f); + + Position (loops included, delays excluded) to wait for + + + + Creates a yield instruction that waits until the tween is killed or started + (meaning when the tween is set in a playing state the first time, after any eventual delay). + It can be used inside a coroutine as a yield. + Example usage:yield return myTween.WaitForStart(); + + + + Returns the total number of loops completed by this tween + + + Returns the eventual delay set for this tween + + + Returns the eventual elapsed delay set for this tween + + + Returns the duration of this tween (delays excluded). + NOTE: when using settings like SpeedBased, the duration will be recalculated when the tween starts + If TRUE returns the full duration loops included, + otherwise the duration of a single loop cycle + + + Returns the elapsed time for this tween (delays exluded) + If TRUE returns the elapsed time since startup loops included, + otherwise the elapsed time within the current loop cycle + + + Returns the elapsed percentage (0 to 1) of this tween (delays exluded) + If TRUE returns the elapsed percentage since startup loops included, + otherwise the elapsed percentage within the current loop cycle + + + Returns the elapsed percentage (0 to 1) of this tween (delays exluded), + based on a single loop, and calculating eventual backwards Yoyo loops as 1 to 0 instead of 0 to 1 + + + Returns FALSE if this tween has been killed or is NULL, TRUE otherwise. + BEWARE: if this tween is recyclable it might have been spawned again for another use and thus return TRUE anyway. + When working with recyclable tweens you should take care to know when a tween has been killed and manually set your references to NULL. + If you want to be sure your references are set to NULL when a tween is killed you can use the OnKill callback like this: + .OnKill(()=> myTweenReference = null) + + + Returns TRUE if this tween was reversed and is set to go backwards + + + Returns TRUE if the tween is complete + (silently fails and returns FALSE if the tween has been killed) + + + Returns TRUE if this tween has been initialized + + + Returns TRUE if this tween is playing + + + Returns the total number of loops set for this tween + (returns -1 if the loops are infinite) + + + + Returns a point on a path based on the given path percentage. + Returns Vector3.zero if this is not a path tween, if the tween is invalid, or if the path is not yet initialized. + A path is initialized after its tween starts, or immediately if the tween was created with the Path Editor (DOTween Pro feature). + You can force a path to be initialized by calling myTween.ForceInit(). + + Percentage of the path (0 to 1) on which to get the point + + + + Returns an array of points that can be used to draw the path. + Note that this method generates allocations, because it creates a new array. + Returns NULL if this is not a path tween, if the tween is invalid, or if the path is not yet initialized. + A path is initialized after its tween starts, or immediately if the tween was created with the Path Editor (DOTween Pro feature). + You can force a path to be initialized by calling myTween.ForceInit(). + + How many points to create for each path segment (waypoint to waypoint). + Only used in case of non-Linear paths + + + + Returns the length of a path. + Returns -1 if this is not a path tween, if the tween is invalid, or if the path is not yet initialized. + A path is initialized after its tween starts, or immediately if the tween was created with the Path Editor (DOTween Pro feature). + You can force a path to be initialized by calling myTween.ForceInit(). + + + + + Types of loop + + + + Each loop cycle restarts from the beginning + + + The tween moves forward and backwards at alternate cycles + + + Continuously increments the tween at the end of each loop cycle (A to B, B to B+(A-B), and so on), thus always moving "onward". + In case of String tweens works only if the tween is set as relative + + + + Controls other tweens as a group + + + + + Methods that extend known Unity objects and allow to directly create and control tweens from their instances + + + + Tweens a Camera's aspect to the given value. + Also stores the camera as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Camera's backgroundColor to the given value. + Also stores the camera as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Camera's farClipPlane to the given value. + Also stores the camera as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Camera's fieldOfView to the given value. + Also stores the camera as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Camera's nearClipPlane to the given value. + Also stores the camera as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Camera's orthographicSize to the given value. + Also stores the camera as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Camera's pixelRect to the given value. + Also stores the camera as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Camera's rect to the given value. + Also stores the camera as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Shakes a Camera's localPosition along its relative X Y axes with the given values. + Also stores the camera as the tween's target so it can be used for filtered operations + The duration of the tween + The shake strength + Indicates how much will the shake vibrate + Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + Setting it to 0 will shake along a single direction. + If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + + + Shakes a Camera's localPosition along its relative X Y axes with the given values. + Also stores the camera as the tween's target so it can be used for filtered operations + The duration of the tween + The shake strength on each axis + Indicates how much will the shake vibrate + Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + Setting it to 0 will shake along a single direction. + If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + + + Shakes a Camera's localRotation. + Also stores the camera as the tween's target so it can be used for filtered operations + The duration of the tween + The shake strength + Indicates how much will the shake vibrate + Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + Setting it to 0 will shake along a single direction. + If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + + + Shakes a Camera's localRotation. + Also stores the camera as the tween's target so it can be used for filtered operations + The duration of the tween + The shake strength on each axis + Indicates how much will the shake vibrate + Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + Setting it to 0 will shake along a single direction. + If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + + + Tweens a Light's color to the given value. + Also stores the light as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Light's intensity to the given value. + Also stores the light as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Light's shadowStrength to the given value. + Also stores the light as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a LineRenderer's color to the given value. + Also stores the LineRenderer as the tween's target so it can be used for filtered operations. + Note that this method requires to also insert the start colors for the tween, + since LineRenderers have no way to get them. + The start value to tween from + The end value to reachThe duration of the tween + + + Tweens a Material's color to the given value. + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Material's named color property to the given value. + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reach + The name of the material property to tween (like _Tint or _SpecColor) + The duration of the tween + + + Tweens a Material's named color property with the given ID to the given value. + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reach + The ID of the material property to tween (also called nameID in Unity's manual) + The duration of the tween + + + Tweens a Material's alpha color to the given value + (will have no effect unless your material supports transparency). + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Material's alpha color to the given value + (will have no effect unless your material supports transparency). + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reach + The name of the material property to tween (like _Tint or _SpecColor) + The duration of the tween + + + Tweens a Material's alpha color with the given ID to the given value + (will have no effect unless your material supports transparency). + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reach + The ID of the material property to tween (also called nameID in Unity's manual) + The duration of the tween + + + Tweens a Material's named float property to the given value. + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reach + The name of the material property to tween + The duration of the tween + + + Tweens a Material's named float property with the given ID to the given value. + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reach + The ID of the material property to tween (also called nameID in Unity's manual) + The duration of the tween + + + Tweens a Material's texture offset to the given value. + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reach + The duration of the tween + + + Tweens a Material's named texture offset property to the given value. + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reach + The name of the material property to tween + The duration of the tween + + + Tweens a Material's texture scale to the given value. + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reach + The duration of the tween + + + Tweens a Material's named texture scale property to the given value. + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reach + The name of the material property to tween + The duration of the tween + + + Tweens a Material's named Vector property to the given value. + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reach + The name of the material property to tween + The duration of the tween + + + Tweens a Material's named Vector property with the given ID to the given value. + Also stores the material as the tween's target so it can be used for filtered operations + The end value to reach + The ID of the material property to tween (also called nameID in Unity's manual) + The duration of the tween + + + Tweens a TrailRenderer's startWidth/endWidth to the given value. + Also stores the TrailRenderer as the tween's target so it can be used for filtered operations + The end startWidth to reachThe end endWidth to reach + The duration of the tween + + + Tweens a TrailRenderer's time to the given value. + Also stores the TrailRenderer as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Transform's position to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + If TRUE the tween will smoothly snap all values to integers + + + Tweens a Transform's X position to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + If TRUE the tween will smoothly snap all values to integers + + + Tweens a Transform's Y position to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + If TRUE the tween will smoothly snap all values to integers + + + Tweens a Transform's Z position to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + If TRUE the tween will smoothly snap all values to integers + + + Tweens a Transform's localPosition to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + If TRUE the tween will smoothly snap all values to integers + + + Tweens a Transform's X localPosition to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + If TRUE the tween will smoothly snap all values to integers + + + Tweens a Transform's Y localPosition to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + If TRUE the tween will smoothly snap all values to integers + + + Tweens a Transform's Z localPosition to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + If TRUE the tween will smoothly snap all values to integers + + + Tweens a Transform's rotation to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + Rotation mode + + + Tweens a Transform's rotation to the given value using pure quaternion values. + Also stores the transform as the tween's target so it can be used for filtered operations. + PLEASE NOTE: DORotate, which takes Vector3 values, is the preferred rotation method. + This method was implemented for very special cases, and doesn't support LoopType.Incremental loops + (neither for itself nor if placed inside a LoopType.Incremental Sequence) + + The end value to reachThe duration of the tween + + + Tweens a Transform's localRotation to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + Rotation mode + + + Tweens a Transform's rotation to the given value using pure quaternion values. + Also stores the transform as the tween's target so it can be used for filtered operations. + PLEASE NOTE: DOLocalRotate, which takes Vector3 values, is the preferred rotation method. + This method was implemented for very special cases, and doesn't support LoopType.Incremental loops + (neither for itself nor if placed inside a LoopType.Incremental Sequence) + + The end value to reachThe duration of the tween + + + Tweens a Transform's localScale to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Transform's localScale uniformly to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Transform's X localScale to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Transform's Y localScale to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Transform's Z localScale to the given value. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Transform's rotation so that it will look towards the given world position. + Also stores the transform as the tween's target so it can be used for filtered operations + The position to look atThe duration of the tween + Eventual axis constraint for the rotation + The vector that defines in which direction up is (default: Vector3.up) + + + EXPERIMENTAL Tweens a Transform's rotation so that it will look towards the given world position, + while also updating the lookAt position every frame + (contrary to which calculates the lookAt rotation only once, when the tween starts). + Also stores the transform as the tween's target so it can be used for filtered operations + The position to look atThe duration of the tween + Eventual axis constraint for the rotation + The vector that defines in which direction up is (default: Vector3.up) + + + Punches a Transform's localPosition towards the given direction and then back to the starting one + as if it was connected to the starting position via an elastic. + The direction and strength of the punch (added to the Transform's current position) + The duration of the tween + Indicates how much will the punch vibrate + Represents how much (0 to 1) the vector will go beyond the starting position when bouncing backwards. + 1 creates a full oscillation between the punch direction and the opposite direction, + while 0 oscillates only between the punch and the start position + If TRUE the tween will smoothly snap all values to integers + + + Punches a Transform's localScale towards the given size and then back to the starting one + as if it was connected to the starting scale via an elastic. + The punch strength (added to the Transform's current scale) + The duration of the tween + Indicates how much will the punch vibrate + Represents how much (0 to 1) the vector will go beyond the starting size when bouncing backwards. + 1 creates a full oscillation between the punch scale and the opposite scale, + while 0 oscillates only between the punch scale and the start scale + + + Punches a Transform's localRotation towards the given size and then back to the starting one + as if it was connected to the starting rotation via an elastic. + The punch strength (added to the Transform's current rotation) + The duration of the tween + Indicates how much will the punch vibrate + Represents how much (0 to 1) the vector will go beyond the starting rotation when bouncing backwards. + 1 creates a full oscillation between the punch rotation and the opposite rotation, + while 0 oscillates only between the punch and the start rotation + + + Shakes a Transform's localPosition with the given values. + The duration of the tween + The shake strength + Indicates how much will the shake vibrate + Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + Setting it to 0 will shake along a single direction. + If TRUE the tween will smoothly snap all values to integers + If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + + + Shakes a Transform's localPosition with the given values. + The duration of the tween + The shake strength on each axis + Indicates how much will the shake vibrate + Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + Setting it to 0 will shake along a single direction. + If TRUE the tween will smoothly snap all values to integers + If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + + + Shakes a Transform's localRotation. + The duration of the tween + The shake strength + Indicates how much will the shake vibrate + Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + Setting it to 0 will shake along a single direction. + If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + + + Shakes a Transform's localRotation. + The duration of the tween + The shake strength on each axis + Indicates how much will the shake vibrate + Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + Setting it to 0 will shake along a single direction. + If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + + + Shakes a Transform's localScale. + The duration of the tween + The shake strength + Indicates how much will the shake vibrate + Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + Setting it to 0 will shake along a single direction. + If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + + + Shakes a Transform's localScale. + The duration of the tween + The shake strength on each axis + Indicates how much will the shake vibrate + Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + Setting it to 0 will shake along a single direction. + If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + + + Tweens a Transform's position to the given value, while also applying a jump effect along the Y axis. + Returns a Sequence instead of a Tweener. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reach + Power of the jump (the max height of the jump is represented by this plus the final Y offset) + Total number of jumps + The duration of the tween + If TRUE the tween will smoothly snap all values to integers + + + Tweens a Transform's localPosition to the given value, while also applying a jump effect along the Y axis. + Returns a Sequence instead of a Tweener. + Also stores the transform as the tween's target so it can be used for filtered operations + The end value to reach + Power of the jump (the max height of the jump is represented by this plus the final Y offset) + Total number of jumps + The duration of the tween + If TRUE the tween will smoothly snap all values to integers + + + Tweens a Transform's position through the given path waypoints, using the chosen path algorithm. + Also stores the transform as the tween's target so it can be used for filtered operations + The waypoints to go through + The duration of the tween + The type of path: Linear (straight path), CatmullRom (curved CatmullRom path) or CubicBezier (curved with control points) + The path mode: 3D, side-scroller 2D, top-down 2D + The resolution of the path (useless in case of Linear paths): higher resolutions make for more detailed curved paths but are more expensive. + Defaults to 10, but a value of 5 is usually enough if you don't have dramatic long curves between waypoints + The color of the path (shown when gizmos are active in the Play panel and the tween is running) + + + Tweens a Transform's localPosition through the given path waypoints, using the chosen path algorithm. + Also stores the transform as the tween's target so it can be used for filtered operations + The waypoint to go through + The duration of the tween + The type of path: Linear (straight path), CatmullRom (curved CatmullRom path) or CubicBezier (curved with control points) + The path mode: 3D, side-scroller 2D, top-down 2D + The resolution of the path: higher resolutions make for more detailed curved paths but are more expensive. + Defaults to 10, but a value of 5 is usually enough if you don't have dramatic long curves between waypoints + The color of the path (shown when gizmos are active in the Play panel and the tween is running) + + + IMPORTANT: Unless you really know what you're doing, you should use the overload that accepts a Vector3 array instead. + Tweens a Transform's position via the given path. + Also stores the transform as the tween's target so it can be used for filtered operations + The path to use + The duration of the tween + The path mode: 3D, side-scroller 2D, top-down 2D + + + IMPORTANT: Unless you really know what you're doing, you should use the overload that accepts a Vector3 array instead. + Tweens a Transform's localPosition via the given path. + Also stores the transform as the tween's target so it can be used for filtered operations + The path to use + The duration of the tween + The path mode: 3D, side-scroller 2D, top-down 2D + + + Tweens a Tween's timeScale to the given value. + Also stores the Tween as the tween's target so it can be used for filtered operations + The end value to reachThe duration of the tween + + + Tweens a Light's color to the given value, + in a way that allows other DOBlendableColor tweens to work together on the same target, + instead than fight each other as multiple DOColor would do. + Also stores the Light as the tween's target so it can be used for filtered operations + The value to tween toThe duration of the tween + + + Tweens a Material's color to the given value, + in a way that allows other DOBlendableColor tweens to work together on the same target, + instead than fight each other as multiple DOColor would do. + Also stores the Material as the tween's target so it can be used for filtered operations + The value to tween toThe duration of the tween + + + Tweens a Material's named color property to the given value, + in a way that allows other DOBlendableColor tweens to work together on the same target, + instead than fight each other as multiple DOColor would do. + Also stores the Material as the tween's target so it can be used for filtered operations + The value to tween to + The name of the material property to tween (like _Tint or _SpecColor) + The duration of the tween + + + Tweens a Material's named color property with the given ID to the given value, + in a way that allows other DOBlendableColor tweens to work together on the same target, + instead than fight each other as multiple DOColor would do. + Also stores the Material as the tween's target so it can be used for filtered operations + The value to tween to + The ID of the material property to tween (also called nameID in Unity's manual) + The duration of the tween + + + Tweens a Transform's position BY the given value (as if you chained a SetRelative), + in a way that allows other DOBlendableMove tweens to work together on the same target, + instead than fight each other as multiple DOMove would do. + Also stores the transform as the tween's target so it can be used for filtered operations + The value to tween byThe duration of the tween + If TRUE the tween will smoothly snap all values to integers + + + Tweens a Transform's localPosition BY the given value (as if you chained a SetRelative), + in a way that allows other DOBlendableMove tweens to work together on the same target, + instead than fight each other as multiple DOMove would do. + Also stores the transform as the tween's target so it can be used for filtered operations + The value to tween byThe duration of the tween + If TRUE the tween will smoothly snap all values to integers + + + EXPERIMENTAL METHOD - Tweens a Transform's rotation BY the given value (as if you chained a SetRelative), + in a way that allows other DOBlendableRotate tweens to work together on the same target, + instead than fight each other as multiple DORotate would do. + Also stores the transform as the tween's target so it can be used for filtered operations + The value to tween byThe duration of the tween + Rotation mode + + + EXPERIMENTAL METHOD - Tweens a Transform's lcoalRotation BY the given value (as if you chained a SetRelative), + in a way that allows other DOBlendableRotate tweens to work together on the same target, + instead than fight each other as multiple DORotate would do. + Also stores the transform as the tween's target so it can be used for filtered operations + The value to tween byThe duration of the tween + Rotation mode + + + Punches a Transform's localRotation BY the given value and then back to the starting one + as if it was connected to the starting rotation via an elastic. Does it in a way that allows other + DOBlendableRotate tweens to work together on the same target + The punch strength (added to the Transform's current rotation) + The duration of the tween + Indicates how much will the punch vibrate + Represents how much (0 to 1) the vector will go beyond the starting rotation when bouncing backwards. + 1 creates a full oscillation between the punch rotation and the opposite rotation, + while 0 oscillates only between the punch and the start rotation + + + Tweens a Transform's localScale BY the given value (as if you chained a SetRelative), + in a way that allows other DOBlendableScale tweens to work together on the same target, + instead than fight each other as multiple DOScale would do. + Also stores the transform as the tween's target so it can be used for filtered operations + The value to tween byThe duration of the tween + + + + Completes all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens completed + (meaning the tweens that don't have infinite loops and were not already complete) + + For Sequences only: if TRUE also internal Sequence callbacks will be fired, + otherwise they will be ignored + + + + Completes all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens completed + (meaning the tweens that don't have infinite loops and were not already complete) + + For Sequences only: if TRUE also internal Sequence callbacks will be fired, + otherwise they will be ignored + + + + Kills all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens killed. + + If TRUE completes the tween before killing it + + + + Kills all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens killed. + + If TRUE completes the tween before killing it + + + + Flips the direction (backwards if it was going forward or viceversa) of all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens flipped. + + + + + Flips the direction (backwards if it was going forward or viceversa) of all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens flipped. + + + + + Sends to the given position all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens involved. + + Time position to reach + (if higher than the whole tween duration the tween will simply reach its end) + If TRUE will play the tween after reaching the given position, otherwise it will pause it + + + + Sends to the given position all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens involved. + + Time position to reach + (if higher than the whole tween duration the tween will simply reach its end) + If TRUE will play the tween after reaching the given position, otherwise it will pause it + + + + Pauses all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens paused. + + + + + Pauses all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens paused. + + + + + Plays all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens played. + + + + + Plays all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens played. + + + + + Plays backwards all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens played. + + + + + Plays backwards all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens played. + + + + + Plays forward all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens played. + + + + + Plays forward all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens played. + + + + + Restarts all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens restarted. + + + + + Restarts all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens restarted. + + + + + Rewinds all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens rewinded. + + + + + Rewinds all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens rewinded. + + + + + Smoothly rewinds all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens rewinded. + + + + + Smoothly rewinds all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens rewinded. + + + + + Toggles the paused state (plays if it was paused, pauses if it was playing) of all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens involved. + + + + + Toggles the paused state (plays if it was paused, pauses if it was playing) of all tweens that have this target as a reference + (meaning tweens that were started from this target, or that had this target added as an Id) + and returns the total number of tweens involved. + + + + + This class serves only as a utility class to store tween settings to apply on multiple tweens. + It is in no way needed otherwise, since you can directly apply tween settings to a tween via chaining + + + + A variable you can eventually Clear and reuse when needed, + to avoid instantiating TweenParams objects + + + Creates a new TweenParams object, which you can use to store tween settings + to pass to multiple tweens via myTween.SetAs(myTweenParms) + + + Clears and resets this TweenParams instance using default values, + so it can be reused without instantiating another one + + + Sets the autoKill behaviour of the tween. + Has no effect if the tween has already started + If TRUE the tween will be automatically killed when complete + + + Sets an ID for the tween, which can then be used as a filter with DOTween's static methods. + The ID to assign to this tween. Can be an int, a string, an object or anything else. + + + Sets the target for the tween, which can then be used as a filter with DOTween's static methods. + IMPORTANT: use it with caution. If you just want to set an ID for the tween use SetId instead. + When using shorcuts the shortcut target is already assigned as the tween's target, + so using this method will overwrite it and prevent shortcut-operations like myTarget.DOPause from working correctly. + The target to assign to this tween. Can be an int, a string, an object or anything else. + + + Sets the looping options for the tween. + Has no effect if the tween has already started + Number of cycles to play (-1 for infinite - will be converted to 1 in case the tween is nested in a Sequence) + Loop behaviour type (default: LoopType.Restart) + + + Sets the ease of the tween. + If applied to Sequences eases the whole sequence animation + Eventual overshoot or amplitude to use with Back or Elastic easeType (default is 1.70158) + Eventual period to use with Elastic easeType (default is 0) + + + Sets the ease of the tween using an AnimationCurve. + If applied to Sequences eases the whole sequence animation + + + Sets the ease of the tween using a custom ease function. + If applied to Sequences eases the whole sequence animation + + + Sets the recycling behaviour for the tween. + If TRUE the tween will be recycled after being killed, otherwise it will be destroyed. + + + Sets the update type to the one defined in DOTween.defaultUpdateType (UpdateType.Normal unless changed) + and lets you choose if it should be independent from Unity's Time.timeScale + If TRUE the tween will ignore Unity's Time.timeScale + + + Sets the type of update (default or independent) for the tween + The type of update (default: UpdateType.Normal) + If TRUE the tween will ignore Unity's Time.timeScale + + + Sets the onStart callback for the tween. + Called the first time the tween is set in a playing state, after any eventual delay + + + Sets the onPlay callback for the tween. + Called when the tween is set in a playing state, after any eventual delay. + Also called each time the tween resumes playing from a paused state + + + Sets the onRewind callback for the tween. + Called when the tween is rewinded, + either by calling Rewind or by reaching the start position while playing backwards. + Rewinding a tween that is already rewinded will not fire this callback + + + Sets the onUpdate callback for the tween. + Called each time the tween updates + + + Sets the onStepComplete callback for the tween. + Called the moment the tween completes one loop cycle, even when going backwards + + + Sets the onComplete callback for the tween. + Called the moment the tween reaches its final forward position, loops included + + + Sets the onKill callback for the tween. + Called the moment the tween is killed + + + Sets the onWaypointChange callback for the tween. + Called when a path tween reaches a new waypoint + + + Sets a delayed startup for the tween. + Has no effect on Sequences or if the tween has already started + + + If isRelative is TRUE sets the tween as relative + (the endValue will be calculated as startValue + endValue instead than being used directly). + Has no effect on Sequences or if the tween has already started + + + If isSpeedBased is TRUE sets the tween as speed based + (the duration will represent the number of units the tween moves x second). + Has no effect on Sequences, nested tweens, or if the tween has already started + + + + Methods that extend Tween objects and allow to set their parameters + + + + Sets the autoKill behaviour of the tween to TRUE. + Has no effect if the tween has already started or if it's added to a Sequence + + + Sets the autoKill behaviour of the tween. + Has no effect if the tween has already started or if it's added to a Sequence + If TRUE the tween will be automatically killed when complete + + + Sets an ID for the tween (), which can then be used as a filter with DOTween's static methods. + The ID to assign to this tween. Can be an int, a string, an object or anything else. + + + Sets a string ID for the tween (), which can then be used as a filter with DOTween's static methods. + Filtering via string is 2X faster than using an object as an ID (using the alternate obejct overload) + The string ID to assign to this tween. + + + Sets an int ID for the tween (), which can then be used as a filter with DOTween's static methods. + Filtering via int is 4X faster than via object, 2X faster than via string (using the alternate object/string overloads) + The int ID to assign to this tween. + + + Allows to link this tween to a GameObject + so that it will be automatically killed when the GameObject is destroyed. + Has no effect if the tween is added to a Sequence + The link target (unrelated to the target set via SetTarget) + + + Allows to link this tween to a GameObject and assign a behaviour depending on it. + This will also automatically kill the tween when the GameObject is destroyed. + Has no effect if the tween is added to a Sequence + The link target (unrelated to the target set via SetTarget) + The behaviour to use ( is always evaluated even if you choose another one) + + + Sets the target for the tween, which can then be used as a filter with DOTween's static methods. + IMPORTANT: use it with caution. If you just want to set an ID for the tween use SetId instead. + When using shorcuts the shortcut target is already assigned as the tween's target, + so using this method will overwrite it and prevent shortcut-operations like myTarget.DOPause from working correctly. + The target to assign to this tween. Can be an int, a string, an object or anything else. + + + Sets the looping options for the tween. + Has no effect if the tween has already started + Number of cycles to play (-1 for infinite - will be converted to 1 in case the tween is nested in a Sequence) + + + Sets the looping options for the tween. + Has no effect if the tween has already started + Number of cycles to play (-1 for infinite - will be converted to 1 in case the tween is nested in a Sequence) + Loop behaviour type (default: LoopType.Restart) + + + Sets the ease of the tween. + If applied to Sequences eases the whole sequence animation + + + Sets the ease of the tween. + If applied to Sequences eases the whole sequence animation + + Eventual overshoot to use with Back or Flash ease (default is 1.70158 - 1 for Flash). + In case of Flash ease it must be an intenger and sets the total number of flashes that will happen. + Using an even number will complete the tween on the starting value, while an odd one will complete it on the end value. + + + + Sets the ease of the tween. + If applied to Sequences eases the whole sequence animation + Eventual amplitude to use with Elastic easeType or overshoot to use with Flash easeType (default is 1.70158 - 1 for Flash). + In case of Flash ease it must be an integer and sets the total number of flashes that will happen. + Using an even number will complete the tween on the starting value, while an odd one will complete it on the end value. + + Eventual period to use with Elastic or Flash easeType (default is 0). + In case of Flash ease it indicates the power in time of the ease, and must be between -1 and 1. + 0 is balanced, 1 weakens the ease with time, -1 starts the ease weakened and gives it power towards the end. + + + + Sets the ease of the tween using an AnimationCurve. + If applied to Sequences eases the whole sequence animation + + + Sets the ease of the tween using a custom ease function (which must return a value between 0 and 1). + If applied to Sequences eases the whole sequence animation + + + Allows the tween to be recycled after being killed. + + + Sets the recycling behaviour for the tween. + If TRUE the tween will be recycled after being killed, otherwise it will be destroyed. + + + Sets the update type to UpdateType.Normal and lets you choose if it should be independent from Unity's Time.timeScale + If TRUE the tween will ignore Unity's Time.timeScale + + + Sets the type of update for the tween + The type of update (defalt: UpdateType.Normal) + + + Sets the type of update for the tween and lets you choose if it should be independent from Unity's Time.timeScale + The type of update + If TRUE the tween will ignore Unity's Time.timeScale + + + EXPERIMENTAL: inverts this tween, so that it will play from the end to the beginning + (playing it backwards will actually play it from the beginning to the end). + Has no effect if the tween has already started or if it's added to a Sequence + + + EXPERIMENTAL: inverts this tween, so that it will play from the end to the beginning + (playing it backwards will actually play it from the beginning to the end). + Has no effect if the tween has already started or if it's added to a Sequence + If TRUE the tween will be inverted, otherwise it won't + + + Sets the onStart callback for the tween, clearing any previous onStart callback that was set. + Called the first time the tween is set in a playing state, after any eventual delay + + + Sets the onPlay callback for the tween, clearing any previous onPlay callback that was set. + Called when the tween is set in a playing state, after any eventual delay. + Also called each time the tween resumes playing from a paused state + + + Sets the onPause callback for the tween, clearing any previous onPause callback that was set. + Called when the tween state changes from playing to paused. + If the tween has autoKill set to FALSE, this is called also when the tween reaches completion. + + + Sets the onRewind callback for the tween, clearing any previous onRewind callback that was set. + Called when the tween is rewinded, + either by calling Rewind or by reaching the start position while playing backwards. + Rewinding a tween that is already rewinded will not fire this callback + + + Sets the onUpdate callback for the tween, clearing any previous onUpdate callback that was set. + Called each time the tween updates + + + Sets the onStepComplete callback for the tween, clearing any previous onStepComplete callback that was set. + Called the moment the tween completes one loop cycle, even when going backwards + + + Sets the onComplete callback for the tween, clearing any previous onComplete callback that was set. + Called the moment the tween reaches its final forward position, loops included + + + Sets the onKill callback for the tween, clearing any previous onKill callback that was set. + Called the moment the tween is killed + + + Sets the onWaypointChange callback for the tween, clearing any previous onWaypointChange callback that was set. + Called when a path tween's current waypoint changes + + + Sets the parameters of the tween (id, ease, loops, delay, timeScale, callbacks, etc) as the parameters of the given one. + Doesn't copy specific SetOptions settings: those will need to be applied manually each time. + Has no effect if the tween has already started. + NOTE: the tween's target will not be changed + Tween from which to copy the parameters + + + Sets the parameters of the tween (id, ease, loops, delay, timeScale, callbacks, etc) as the parameters of the given TweenParams. + Has no effect if the tween has already started. + TweenParams from which to copy the parameters + + + Adds the given tween to the end of the Sequence. + Has no effect if the Sequence has already started + The tween to append + + + Adds the given tween to the beginning of the Sequence, pushing forward the other nested content. + Has no effect if the Sequence has already started + The tween to prepend + + + Inserts the given tween at the same time position of the last tween, callback or intervale added to the Sequence. + Note that, in case of a Join after an interval, the insertion time will be the time where the interval starts, not where it finishes. + Has no effect if the Sequence has already started + + + Inserts the given tween at the given time position in the Sequence, + automatically adding an interval if needed. + Has no effect if the Sequence has already started + The time position where the tween will be placed + The tween to insert + + + Adds the given interval to the end of the Sequence. + Has no effect if the Sequence has already started + The interval duration + + + Adds the given interval to the beginning of the Sequence, pushing forward the other nested content. + Has no effect if the Sequence has already started + The interval duration + + + Adds the given callback to the end of the Sequence. + Has no effect if the Sequence has already started + The callback to append + + + Adds the given callback to the beginning of the Sequence, pushing forward the other nested content. + Has no effect if the Sequence has already started + The callback to prepend + + + Inserts the given callback at the given time position in the Sequence, + automatically adding an interval if needed. + Has no effect if the Sequence has already started + The time position where the callback will be placed + The callback to insert + + + Changes a TO tween into a FROM tween: sets the current target's position as the tween's endValue + then immediately sends the target to the previously set endValue. + + + Changes a TO tween into a FROM tween: sets the current target's position as the tween's endValue + then immediately sends the target to the previously set endValue. + If TRUE the FROM value will be calculated as relative to the current one + + + Changes a TO tween into a FROM tween: sets the current value of the target as the endValue, + and the previously passed endValue as the actual startValue. + If TRUE sets the target to from value immediately, otherwise waits for the tween to start + If TRUE the FROM value will be calculated as relative to the current one + + + Changes a TO tween into a FROM tween: sets the tween's starting value to the given one + and eventually sets the tween's target to that value immediately. + Value to start from + If TRUE sets the target to from value immediately, otherwise waits for the tween to start + If TRUE the FROM/TO values will be calculated as relative to the current ones + + + Changes a TO tween into a FROM tween: sets the tween's starting value to the given one + and eventually sets the tween's target to that value immediately. + Alpha value to start from (in case of Fade tweens) + If TRUE sets the target to from value immediately, otherwise waits for the tween to start + If TRUE the FROM/TO values will be calculated as relative to the current ones + + + Changes a TO tween into a FROM tween: sets the tween's starting value to the given one + and eventually sets the tween's target to that value immediately. + Value to start from (in case of Vector tweens that act on a single coordinate or scale tweens) + If TRUE sets the target to from value immediately, otherwise waits for the tween to start + If TRUE the FROM/TO values will be calculated as relative to the current ones + + + Changes a TO tween into a FROM tween: sets the tween's starting value to the given one + and eventually sets the tween's target to that value immediately. + Value to start from (in case of Vector tweens that act on a single coordinate or scale tweens) + If TRUE sets the target to from value immediately, otherwise waits for the tween to start + If TRUE the FROM/TO values will be calculated as relative to the current ones + + + Sets a delayed startup for the tween. + In case of Sequences behaves the same as , + which means the delay will repeat in case of loops (while with tweens it's ignored after the first loop cycle). + Has no effect if the tween has already started + + + EXPERIMENTAL: implemented in v1.2.340. + Sets a delayed startup for the tween with options to choose how the delay is applied in case of Sequences. + Has no effect if the tween has already started + Only used by types: If FALSE sets the delay as a one-time occurrence + (defaults to this for types), + otherwise as a Sequence interval which will repeat at the beginning of every loop cycle + + + Sets the tween as relative + (the endValue will be calculated as startValue + endValue instead than being used directly). + Has no effect on Sequences or if the tween has already started + + + If isRelative is TRUE sets the tween as relative + (the endValue will be calculated as startValue + endValue instead than being used directly). + Has no effect on Sequences or if the tween has already started + + + If isSpeedBased is TRUE sets the tween as speed based + (the duration will represent the number of units the tween moves x second). + Has no effect on Sequences, nested tweens, or if the tween has already started + + + If isSpeedBased is TRUE sets the tween as speed based + (the duration will represent the number of units the tween moves x second). + Has no effect on Sequences, nested tweens, or if the tween has already started + + + Options for float tweens + If TRUE the tween will smoothly snap all values to integers + + + Options for Vector2 tweens + If TRUE the tween will smoothly snap all values to integers + + + Options for Vector2 tweens + Selecting an axis will tween the vector only on that axis, leaving the others untouched + If TRUE the tween will smoothly snap all values to integers + + + Options for Vector3 tweens + If TRUE the tween will smoothly snap all values to integers + + + Options for Vector3 tweens + Selecting an axis will tween the vector only on that axis, leaving the others untouched + If TRUE the tween will smoothly snap all values to integers + + + Options for Vector4 tweens + If TRUE the tween will smoothly snap all values to integers + + + Options for Vector4 tweens + Selecting an axis will tween the vector only on that axis, leaving the others untouched + If TRUE the tween will smoothly snap all values to integers + + + Options for Quaternion tweens + If TRUE (default) the rotation will take the shortest route, and will not rotate more than 360°. + If FALSE the rotation will be fully accounted. Is always FALSE if the tween is set as relative + + + Options for Color tweens + If TRUE only the alpha value of the color will be tweened + + + Options for Vector4 tweens + If TRUE the tween will smoothly snap all values to integers + + + Options for Vector4 tweens + If TRUE, rich text will be interpreted correctly while animated, + otherwise all tags will be considered as normal text + The type of scramble to use, if any + A string containing the characters to use for scrambling. + Use as many characters as possible (minimum 10) because DOTween uses a fast scramble mode which gives better results with more characters. + Leave it to NULL to use default ones + + + Options for Vector3Array tweens + If TRUE the tween will smoothly snap all values to integers + + + Options for Vector3Array tweens + If TRUE the tween will smoothly snap all values to integers + + + Options for ShapeCircle tweens + If TRUE the center you set in the DOTween.To method will be considered as relative + to the starting position of the target + If TRUE the tween will smoothly snap all values to integers + + + Options for Path tweens (created via the DOPath shortcut) + The eventual movement axis to lock. You can input multiple axis if you separate them like this: + AxisConstrain.X | AxisConstraint.Y + The eventual rotation axis to lock. You can input multiple axis if you separate them like this: + AxisConstrain.X | AxisConstraint.Y + + + Options for Path tweens (created via the DOPath shortcut) + If TRUE the path will be automatically closed + The eventual movement axis to lock. You can input multiple axis if you separate them like this: + AxisConstrain.X | AxisConstraint.Y + The eventual rotation axis to lock. You can input multiple axis if you separate them like this: + AxisConstrain.X | AxisConstraint.Y + + + Additional LookAt options for Path tweens (created via the DOPath shortcut). + Orients the target towards the given position. + Must be chained directly to the tween creation method or to a SetOptions + The position to look at + The eventual direction to consider as "forward". + If left to NULL defaults to the regular forward side of the transform + The vector that defines in which direction up is (default: Vector3.up) + + + Additional LookAt options for Path tweens (created via the DOPath shortcut). + Orients the target towards the given position with options to keep the Z rotation stable. + Must be chained directly to the tween creation method or to a SetOptions + The position to look at + If TRUE doesn't rotate the target along the Z axis + + + Additional LookAt options for Path tweens (created via the DOPath shortcut). + Orients the target towards another transform. + Must be chained directly to the tween creation method or to a SetOptions + The transform to look at + The eventual direction to consider as "forward". + If left to NULL defaults to the regular forward side of the transform + The vector that defines in which direction up is (default: Vector3.up) + + + Additional LookAt options for Path tweens (created via the DOPath shortcut). + Orients the target towards another transform with options to keep the Z rotation stable. + Must be chained directly to the tween creation method or to a SetOptions + The transform to look at + If TRUE doesn't rotate the target along the Z axis + + + Additional LookAt options for Path tweens (created via the DOPath shortcut). + Orients the target to the path, with the given lookAhead. + Must be chained directly to the tween creation method or to a SetOptions + The percentage of lookAhead to use (0 to 1) + The eventual direction to consider as "forward". + If left to NULL defaults to the regular forward side of the transform + The vector that defines in which direction up is (default: Vector3.up) + + + Additional LookAt options for Path tweens (created via the DOPath shortcut). + Orients the path with options to keep the Z rotation stable. + Must be chained directly to the tween creation method or to a SetOptions + The percentage of lookAhead to use (0 to 1) + If TRUE doesn't rotate the target along the Z axis + + + + Types of log behaviours + + + + Log only warnings and errors + + + Log warnings, errors and additional infos + + + Log only errors + + + + Indicates either a Tweener or a Sequence + + + + TimeScale for the tween + + + If TRUE the tween will play backwards + + + If TRUE the tween is completely inverted but without playing it backwards + (play backwards will actually play the tween in the original direction) + + + Object ID (usable for filtering with DOTween static methods). Can be anything except a string or an int + (use or for those) + + + String ID (usable for filtering with DOTween static methods). 2X faster than using an object id + + + Int ID (usable for filtering with DOTween static methods). 4X faster than using an object id, 2X faster than using a string id. + Default is -999 so avoid using an ID like that or it will capture all unset intIds + + + Tween target (usable for filtering with DOTween static methods). Automatically set by tween creation shortcuts + + + Called when the tween is set in a playing state, after any eventual delay. + Also called each time the tween resumes playing from a paused state + + + Called when the tween state changes from playing to paused. + If the tween has autoKill set to FALSE, this is called also when the tween reaches completion. + + + Called when the tween is rewinded, + either by calling Rewind or by reaching the start position while playing backwards. + Rewinding a tween that is already rewinded will not fire this callback + + + Called each time the tween updates + + + Called the moment the tween completes one loop cycle + + + Called the moment the tween reaches completion (loops included) + + + Called the moment the tween is killed + + + Called when a path tween's current waypoint changes + + + Tweeners-only (ignored by Sequences), returns TRUE if the tween was set as relative + + + + Set by SetTarget if DOTween's Debug Mode is on (see DOTween Utility Panel -> "Store GameObject's ID" debug option + + + + FALSE when tween is (or should be) despawned - set only by TweenManager + + + Gets and sets the time position (loops included, delays excluded) of the tween + + + Returns TRUE if the tween is set to loop (either a set number of times or infinitely) + + + TRUE after the tween was set in a play state at least once, AFTER any delay is elapsed + + + Time position within a single loop cycle + + + + Animates a single value + + + + Changes the start value of a tween and rewinds it (without pausing it). + Has no effect with tweens that are inside Sequences + The new start value + If bigger than 0 applies it as the new tween duration + + + Changes the end value of a tween and rewinds it (without pausing it). + Has no effect with tweens that are inside Sequences + The new end value + If bigger than 0 applies it as the new tween duration + If TRUE the start value will become the current target's value, otherwise it will stay the same + + + Changes the end value of a tween and rewinds it (without pausing it). + Has no effect with tweens that are inside Sequences + The new end value + If TRUE the start value will become the current target's value, otherwise it will stay the same + + + Changes the start and end value of a tween and rewinds it (without pausing it). + Has no effect with tweens that are inside Sequences + The new start value + The new end value + If bigger than 0 applies it as the new tween duration + + + + Used internally + + + + + Update type + + + + Updates every frame during Update calls + + + Updates every frame during LateUpdate calls + + + Updates using FixedUpdate calls + + + Updates using manual update calls + + + diff --git a/Assets/Plugins/Demigiant/DOTween/DOTween.XML.meta b/Assets/Plugins/Demigiant/DOTween/DOTween.XML.meta new file mode 100644 index 0000000..7a866b5 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/DOTween.XML.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 34192c5e0d14aee43a0e86cc4823268a +TextScriptImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/DOTween.dll b/Assets/Plugins/Demigiant/DOTween/DOTween.dll new file mode 100644 index 0000000000000000000000000000000000000000..4c0bb10614d73a5b46e58df117be2e2e2729aae0 GIT binary patch literal 172032 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
n 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 ~)CFU>gFNmEmDDr()MofeLM*N!iq)bs8(sgG(U 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 CoM(&x literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DOTween/DOTween.dll.mdb.meta b/Assets/Plugins/Demigiant/DOTween/DOTween.dll.mdb.meta new file mode 100644 index 0000000..f64a22a --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/DOTween.dll.mdb.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 4f007001a22b3d24dae350342c4d19c8 +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/DOTween.dll.meta b/Assets/Plugins/Demigiant/DOTween/DOTween.dll.meta new file mode 100644 index 0000000..482dbb8 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/DOTween.dll.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: a811bde74b26b53498b4f6d872b09b6d +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Any: + enabled: 1 + settings: {} + Editor: + enabled: 0 + settings: + DefaultValueInitialized: true + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DOTween/Editor.meta b/Assets/Plugins/Demigiant/DOTween/Editor.meta new file mode 100644 index 0000000..532edfb --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Editor.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: b27f58ae5d5c33a4bb2d1f4f34bd036d +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.XML b/Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.XML new file mode 100644 index 0000000..8b82472 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.XML @@ -0,0 +1,110 @@ + + + + DOTweenEditor + + + + + Starts the update loop of tween in the editor. Has no effect during playMode. + + Eventual callback to call after every update + + + + Stops the update loop and clears the onPreviewUpdated callback. + + If TRUE also resets the tweened objects to their original state. + Note that this works by calling Rewind on all tweens, so it will work correctly + only if you have a single tween type per object and it wasn't killed + If TRUE also kills any cached tween + + + + Readies the tween for editor preview by setting its UpdateType to Manual plus eventual extra settings. + + The tween to ready + If TRUE (recommended) removes all callbacks (OnComplete/Rewind/etc) + If TRUE prevents the tween from being auto-killed at completion + If TRUE starts playing the tween immediately + + + Full major version + first minor version (ex: 2018.1f) + + + Major version + + + First minor version (ex: in 2018.1 it would be 1) + + + + Checks that the given editor texture use the correct import settings, + and applies them if they're incorrect. + + + + + Returns TRUE if setup is required + + + + + Returns TRUE if the file/directory at the given path exists. + + Path, relative to Unity's project folder + + + + + Converts the given project-relative path to a full path, + with backward (\) slashes). + + + + + Converts the given full path to a path usable with AssetDatabase methods + (relative to Unity's project folder, and with the correct Unity forward (/) slashes). + + + + + Connects to a asset. + If the asset already exists at the given path, loads it and returns it. + Otherwise, either returns NULL or automatically creates it before loading and returning it + (depending on the given parameters). + + Asset type + File path (relative to Unity's project folder) + If TRUE and the requested asset doesn't exist, forces its creation + + + + Full path for the given loaded assembly, assembly file included + + + + + Adds the given global define if it's not already present + + + + + Removes the given global define if it's present + + + + + Returns TRUE if the given global define is present in all the + or only in the given , depending on passed parameters. + + + to use. Leave NULL to check in all of them. + + + + Not used as menu item anymore, but as a utiity function + + + + diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.XML.meta b/Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.XML.meta new file mode 100644 index 0000000..7cec113 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.XML.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 2e2c6224d345d9249acfa6e8ef40bb2d +TextScriptImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.dll b/Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.dll new file mode 100644 index 0000000000000000000000000000000000000000..1599b4066a5a958b3446e67cddd5926fc2ed7688 GIT binary patch literal 66048 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 QuO7ac!T&$z|2hZ$7vfCwQUCw| literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.dll.mdb b/Assets/Plugins/Demigiant/DOTween/Editor/DOTweenEditor.dll.mdb new file mode 100644 index 0000000000000000000000000000000000000000..fa2e9032c8671017aaf1b6bc5c2175026edb576f GIT binary patch literal 11774 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 P00000NkvXXu0mjftl$Bl literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/DOTweenIcon.png.meta b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/DOTweenIcon.png.meta new file mode 100644 index 0000000..61c3cce --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/DOTweenIcon.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 8da095e39e9b4df488dfd436f81116d6 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 128 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/DOTweenMiniIcon.png b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/DOTweenMiniIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..7cd74c1a26df1a45564c7a0e21c62d0ef3af2fd1 GIT binary patch literal 319 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{!3Opi<85sBugD~Uq{1quc!H=FU zjv*3LlT#WP(iF^Cl2R3(u|Mi}s1fft&-^joZ3WZ(2Ug1Y!S$8-a*li}_21XqSnvJ# z@Y+`2=i8W`Zfg*cV81TuZmqUr`JI~8M}9x(m1v%HMLo`ySuokJ?%Vq7{C4$+ST-HH z5`RuO<@s#=8XoVy+lF)YEaxg?4vAr1(jlM1>Tx0PF<0}pFUf679a{7Ee==}5`qQz? zuIUa#(3byge21?t-^6oqTDwHc&iz0s`zDdQwtGKbESsPtIM1KwqFB4+nW=frYn!|7 zvs(U9y->(A=TFZ3t)>6Hv^;B{u+A(fd3smW;eIaTDS0KOITHVv7#gf%Y$mkMJ`MCd NgQu&X%Q~loCICTRfS>>X literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/DOTweenMiniIcon.png.meta b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/DOTweenMiniIcon.png.meta new file mode 100644 index 0000000..c343a61 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/DOTweenMiniIcon.png.meta @@ -0,0 +1,68 @@ +fileFormatVersion: 2 +guid: 61521df2e071645488ba3d05e49289ae +timeCreated: 1602317874 +licenseType: Store +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: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer.png b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer.png new file mode 100644 index 0000000000000000000000000000000000000000..e29d02fe18b777b1d316feb647b339803c5126de GIT binary patch literal 4409 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 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer.png.meta b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer.png.meta new file mode 100644 index 0000000..7ca1911 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 7051dba417b3d53409f2918f1ea4938d +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 256 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer_dark.png b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e48db5ef7a2b83eff50d6e3b5fe9ba3bcd4a5015 GIT binary patch literal 4429 zcmV-T5wh-yP)pV|4BqaRCt{2oC}ndRTam-d$}`=KmylMW&q7h$wvaYFsxjKXh5NY zB9jj^Mg|3ZgbTB@GBPO*luF(MISEQRg33b?5=J1f0`oy8p+q3e3=A`fs0_^9+wXtp zoV(6^e)rD6fVgV*T4$ZtKKnerz4zJsoO5r;JA!c2O*i!kg+dQapFaKEBT3i7h!G>c z7>~!_fPUy`&`$+7-+c2y=Jlm%)240kji+}k7Mnd|#*9u)?Zd3y3%=qp%=Ka4SY9OR z?UvE517q9S)G_=&L-<$^pc$Is(*TjC5!HwCP5<8^+lqJ|{k>w_78DeGj`|@a+YnY#x7Zm= zHvJAIoWK}<*U%aaA3nT0v<8u^%FN81`N$)W>}8H$C!dW*pKtLP)1{1K7k&NZP}aB^ zjy^PLN8n?Bo9IQD z@Zd}(%)AT1jW=b@o8jm{Q+EV0&yUf138qHliRms^8YUb@^g(WJ?p4y}ghCkiowBmB zepOXf&qkxs88Gd6($WVH9=sCVSEfvv@-__lYtk=c^9~ms1nO~UmCHYHJI>0=8c1Iq zq5pYk*HAQ-wi1jxN&nEGL4L+Bl#rcI^i#qTnDLjy)9K?L)r}lE@;R7(a{m5l2t(tESBvn6~B*tw(-_R!~FgNQJf zeMGPOiZdBoSGRz**y+cs0n&`G85#ji6$CNoTASe`t$@iAg20EpfT%OfummRbh*f+% z<>wa{7cZi0w#*O8UZE_X^ejWBC!sy{OASp$@M)|ow37@#o1TOM#~bqKz|TIv^5cL_`u-@ku<((E8V)2rJtzTuGl6=5}PN{ClhS655W zHeova%k>jFcI>zSbE|-U)?&v$O}ZDwHE8td7Kc6yVB{S7X-QgwaFH4J4;lBLshcm2 z%}#Iw@gHW*npKGa%z@T0LJ9q?qMiJgz+J|`9t26I-VzvIg0~j`V5w7INSFFVXlr(3Gc&P%U}j++JxUAt%~D#8BFkbvYTL##jZ^+Z4M*%lvZ|W>O=@3 zx`K8cp!*M7Z%(4VV)NPswr}6wmwwLy_n!#I3zj~NsgtMg6EwaEJIXvUy6pqUIEv5= z&YwM6~gGUg&b=S{Z^0 zrH)P8w{L#}LU5msml59E)8VJMS#A_G-z+yBntY-5X$6>LHyZuGvFe|lA&Z@4D`SxM zzPP~#&2UWNe^wCCkiCv&|GHf!%J`)F&Ckz25i{;&b1N>NX`Ak6{CFcrjy%n)yH&3T zy4hFE4s{B?PdiM?@|iPdmb*BZuI-LH?zmG(?gM|bi*MWeq3z>~+Gl2ZUkt@VS+THJ z)#m+H8@A+Mlr-mbD1p+bkuT`BlbKpxUakWRucD&jt>WV1ddkht1C#k}zv-zv7{*kQ zot?eY(g*_e`#&oP|F4jlnJH5+aj1YWB<^8gvTbA^z&x8`@%Z?91<)segf*8R1m|iU z1dzVW*T=oo-9d64;e6BAILd~2K65)d@43zyvDm|L&(kxUh!=``x?BIK%?HW026P7{ z^RC{5O?<#!@;wu@qES6#neW!qrw$`}gQNM3vgHz>($dn`PzJxn-y26@!{J0mQT z8n;TWLY>q5VvrU&9Dx3vx-&ppE7IYO7%?IbybXM;H`C#z0vzenaW?Z9|EXl(gI0Ax6(0$oK~GC`UjeNWH=V8x8uLun^#bsU8ru(apCDS|mN75gny1um21nmcZ=G~( ztefe3DVxk#b6MY?xVY4J3!n$5a{d5T7H;;e~ z)JM(k(9=)H;3rQe_0j>TbWbZ27ix4g1%|mnfl5tUAM8Q<1i=LzZKfKyePHGSG`snC zmms_#(Dvp$U<(Aazy*x|K^CGfW4}?ti`KoHd{@dZG7kei${$oXl==AkMzB6+^V8Rl znBznKaz8G8FCh#{H+3Q%%pzBT9m)ZHRKb*b-nM@xIf|9~~vg^#V zWIadLt*OkZz2t|(1TRo`A!%(f+A0T8_YwK=)QuA@^140lr8hg~xw54849fLD@7I+7 z%-_G9v8=4D8E6Atg2}9TUeB`q=lB8^NzWGa#Co+`E>ny?uCO~DsOf<@4C|H#Wrd9sIpa-|%8cKd}m=UF)JQ^`x2 zJm*7gV=i#-qJ9Fq-qVa}pV9n{f^<(TJuv~D^F0G#h8|2oaaO5 zPeB#*v(h|s&^UE*mat2~pU4>Z2t8nk5UZWj`cXz=rsa44}`gyOOHZ4nOgKrf?3nGF?Qn+wy8nX$@0Sfh(j z^E^fCIWWLVXk{)Gk8I4sF@8B?9AWF>3V$+Ckq7 z!zF%;fX35v11-7)A$iFIbN3>WFs#tAmb4R-T4ZidlXkEiGa_lv>(K&T2s-(YgQVA~ zLjs1{3K|ET_S&JIa^~?2V;kX{+pYL5wVIFm(9;jV-R3K4Gg%4d`(>gi0`VK=5r%cl z&##eOm`~exOk2(GkUxqu&N0mAyT0Pn4wF`Aogxv}v(II^`f<%Sh`>-{;^lg*X#5-b zLS?MQ8U&!bz9HX9>-MqByimOEsZA&zI@y-R;-Qj|PO3ujfu3{169lpzh!RJ%&aS1t zqU_Yk_gpUUZRYZAZf9Jh3knJ*r(F;qr2E0i=@5KZX_&YRThB7$os>->bRoDx^scY@ z-T;!)99rB7HbCPn%C@;klxs^C?GYBwJl9?&lPO@Fn+fOGJPiISA4ks}bV{I`+P3~S z+KmvdmzYl(^e0htrVqt^94CRU@ICk58Zf^EFsIF_>JAl{mwu$w)eT+)CpBqkC7#DK z_mYNiSwpK7D$Hq-+UOWl&pn=zDP#@^G~ZT1G-5Tidf6Mp7`xJz?aJ$4wllB)GR&oo z4UNJ4;!oh>+H}fyTeQ=Toyk14JM3wwpJcnBLcO8U_RivI3lwt}kzXV;0;&5t<;A`x z>7FTD&^9acsvk7^DCpN`(DFai)&k2e9PQv;%NWMlpJCSPI2M~j{ZK0;@*{K-VopN> zPpW7$mwxBVL`yNBBrpyMd5+Ji?wktWJP-d=f%(~}e(1E8b$PiVeEZy8=CCP}Y1l)* zF|li9>nIB}jVi7gAZ4-;H{rYvPc6RVForDws)S$i>_HCZrcMC&%1=qvNZ(z*1SF{+ zhBfL?Mqsu2xh&Rhlh$^mUwP>jrDYH?*@w~uI3g#*9Cro0*-s1D`z2`L{cLLwz*P6* z4D04|u{rWe{yT&;5My};ftZ+|pP!eJks%Xp8hMT3B|lxZY5npoFEcZ9jec$kz4d4` z39=s4$t0Q>FdY4sIw4fI+;YojG5vnv+u@Q>SXlTfbl+y|;|32Ne0Tfy?PV%mN|+La z|0#iN<9o?}kr^TFs-L7@>qlg6?x*FW9h^-z)MY}(CscVeA>G2Vsrd7Vx)Wu^wT zhd=Lu2jpKw)Ai$mc7!)!ic95fE07m~LZt6yl&yhZt_$qq}LVicQ?svt48^OOrr#gIe?RIyQ->cWKa-#k7p-dmH zTQnNgZ=c7LpJ{24-|Enn$yDLAOVSFWdz3)WAzIVlV+74zzQIpe)9(0hTO7P9gL}Oj zSdSd9?t-^iYn;u{1nE~k8M z3$NBaR^O%fVM-8xQ?&S&PX^3yj_SZk{MN+0{N3du$hoHe9y7l8189_+c1idzW*92o TqmFO~00000NkvXXu0mjf{EM6C literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer_dark.png.meta b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer_dark.png.meta new file mode 100644 index 0000000..f12a1a7 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Footer_dark.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 519694efe2bb2914788b151fbd8c01f4 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Header.jpg b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Header.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4d710d719075150879b1ee76680af87791c4d3b3 GIT binary patch literal 22787 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 QE#Li`lK-oJv9mh=KQ4fgsQ>@~ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Header.jpg.meta b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Header.jpg.meta new file mode 100644 index 0000000..26e4255 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Editor/Imgs/Header.jpg.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 78a59ca99f8987941adb61f9e14a06a7 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 512 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Modules.meta b/Assets/Plugins/Demigiant/DOTween/Modules.meta new file mode 100644 index 0000000..24cd2ac --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 143604b8bad857d47a6f7cc7a533e2dc +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleAudio.cs b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleAudio.cs new file mode 100644 index 0000000..c195b6c --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleAudio.cs @@ -0,0 +1,202 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2018/07/13 + +#if true // MODULE_MARKER +using System; +using DG.Tweening.Core; +using DG.Tweening.Plugins.Options; +using UnityEngine; +#if UNITY_5 || UNITY_2017_1_OR_NEWER +using UnityEngine.Audio; // Required for AudioMixer +#endif + +#pragma warning disable 1591 +namespace DG.Tweening +{ + public static class DOTweenModuleAudio + { + #region Shortcuts + + #region Audio + + /// Tweens an AudioSource's volume to the given value. + /// Also stores the AudioSource as the tween's target so it can be used for filtered operations + /// The end value to reach (0 to 1)The duration of the tween + public static TweenerCore DOFade(this AudioSource target, float endValue, float duration) + { + if (endValue < 0) endValue = 0; + else if (endValue > 1) endValue = 1; + TweenerCore t = DOTween.To(() => target.volume, x => target.volume = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens an AudioSource's pitch to the given value. + /// Also stores the AudioSource as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOPitch(this AudioSource target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.pitch, x => target.pitch = x, endValue, duration); + t.SetTarget(target); + return t; + } + + #endregion + +#if UNITY_5 || UNITY_2017_1_OR_NEWER + #region AudioMixer (Unity 5 or Newer) + + /// Tweens an AudioMixer's exposed float to the given value. + /// Also stores the AudioMixer as the tween's target so it can be used for filtered operations. + /// Note that you need to manually expose a float in an AudioMixerGroup in order to be able to tween it from an AudioMixer. + /// Name given to the exposed float to set + /// The end value to reachThe duration of the tween + public static TweenerCore DOSetFloat(this AudioMixer target, string floatName, float endValue, float duration) + { + TweenerCore t = DOTween.To(()=> { + float currVal; + target.GetFloat(floatName, out currVal); + return currVal; + }, x=> target.SetFloat(floatName, x), endValue, duration); + t.SetTarget(target); + return t; + } + + #region Operation Shortcuts + + /// + /// Completes all tweens that have this target as a reference + /// (meaning tweens that were started from this target, or that had this target added as an Id) + /// and returns the total number of tweens completed + /// (meaning the tweens that don't have infinite loops and were not already complete) + /// + /// For Sequences only: if TRUE also internal Sequence callbacks will be fired, + /// otherwise they will be ignored + public static int DOComplete(this AudioMixer target, bool withCallbacks = false) + { + return DOTween.Complete(target, withCallbacks); + } + + /// + /// Kills all tweens that have this target as a reference + /// (meaning tweens that were started from this target, or that had this target added as an Id) + /// and returns the total number of tweens killed. + /// + /// If TRUE completes the tween before killing it + public static int DOKill(this AudioMixer target, bool complete = false) + { + return DOTween.Kill(target, complete); + } + + /// + /// Flips the direction (backwards if it was going forward or viceversa) of all tweens that have this target as a reference + /// (meaning tweens that were started from this target, or that had this target added as an Id) + /// and returns the total number of tweens flipped. + /// + public static int DOFlip(this AudioMixer target) + { + return DOTween.Flip(target); + } + + /// + /// Sends to the given position all tweens that have this target as a reference + /// (meaning tweens that were started from this target, or that had this target added as an Id) + /// and returns the total number of tweens involved. + /// + /// Time position to reach + /// (if higher than the whole tween duration the tween will simply reach its end) + /// If TRUE will play the tween after reaching the given position, otherwise it will pause it + public static int DOGoto(this AudioMixer target, float to, bool andPlay = false) + { + return DOTween.Goto(target, to, andPlay); + } + + /// + /// Pauses all tweens that have this target as a reference + /// (meaning tweens that were started from this target, or that had this target added as an Id) + /// and returns the total number of tweens paused. + /// + public static int DOPause(this AudioMixer target) + { + return DOTween.Pause(target); + } + + /// + /// Plays all tweens that have this target as a reference + /// (meaning tweens that were started from this target, or that had this target added as an Id) + /// and returns the total number of tweens played. + /// + public static int DOPlay(this AudioMixer target) + { + return DOTween.Play(target); + } + + /// + /// Plays backwards all tweens that have this target as a reference + /// (meaning tweens that were started from this target, or that had this target added as an Id) + /// and returns the total number of tweens played. + /// + public static int DOPlayBackwards(this AudioMixer target) + { + return DOTween.PlayBackwards(target); + } + + /// + /// Plays forward all tweens that have this target as a reference + /// (meaning tweens that were started from this target, or that had this target added as an Id) + /// and returns the total number of tweens played. + /// + public static int DOPlayForward(this AudioMixer target) + { + return DOTween.PlayForward(target); + } + + /// + /// Restarts all tweens that have this target as a reference + /// (meaning tweens that were started from this target, or that had this target added as an Id) + /// and returns the total number of tweens restarted. + /// + public static int DORestart(this AudioMixer target) + { + return DOTween.Restart(target); + } + + /// + /// Rewinds all tweens that have this target as a reference + /// (meaning tweens that were started from this target, or that had this target added as an Id) + /// and returns the total number of tweens rewinded. + /// + public static int DORewind(this AudioMixer target) + { + return DOTween.Rewind(target); + } + + /// + /// Smoothly rewinds all tweens that have this target as a reference + /// (meaning tweens that were started from this target, or that had this target added as an Id) + /// and returns the total number of tweens rewinded. + /// + public static int DOSmoothRewind(this AudioMixer target) + { + return DOTween.SmoothRewind(target); + } + + /// + /// Toggles the paused state (plays if it was paused, pauses if it was playing) of all tweens that have this target as a reference + /// (meaning tweens that were started from this target, or that had this target added as an Id) + /// and returns the total number of tweens involved. + /// + public static int DOTogglePause(this AudioMixer target) + { + return DOTween.TogglePause(target); + } + + #endregion + + #endregion +#endif + + #endregion + } +} +#endif diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleAudio.cs.meta b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleAudio.cs.meta new file mode 100644 index 0000000..50aa010 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleAudio.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b766d08851589514b97afb23c6f30a70 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleEPOOutline.cs b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleEPOOutline.cs new file mode 100644 index 0000000..aff1235 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleEPOOutline.cs @@ -0,0 +1,142 @@ +using UnityEngine; + +#if false || EPO_DOTWEEN // MODULE_MARKER + +using EPOOutline; +using DG.Tweening.Plugins.Options; +using DG.Tweening; +using DG.Tweening.Core; + +namespace DG.Tweening +{ + public static class DOTweenModuleEPOOutline + { + public static int DOKill(this SerializedPass target, bool complete) + { + return DOTween.Kill(target, complete); + } + + public static TweenerCore DOFloat(this SerializedPass target, string propertyName, float endValue, float duration) + { + var tweener = DOTween.To(() => target.GetFloat(propertyName), x => target.SetFloat(propertyName, x), endValue, duration); + tweener.SetOptions(true).SetTarget(target); + return tweener; + } + + public static TweenerCore DOFade(this SerializedPass target, string propertyName, float endValue, float duration) + { + var tweener = DOTween.ToAlpha(() => target.GetColor(propertyName), x => target.SetColor(propertyName, x), endValue, duration); + tweener.SetOptions(true).SetTarget(target); + return tweener; + } + + public static TweenerCore DOColor(this SerializedPass target, string propertyName, Color endValue, float duration) + { + var tweener = DOTween.To(() => target.GetColor(propertyName), x => target.SetColor(propertyName, x), endValue, duration); + tweener.SetOptions(false).SetTarget(target); + return tweener; + } + + public static TweenerCore DOVector(this SerializedPass target, string propertyName, Vector4 endValue, float duration) + { + var tweener = DOTween.To(() => target.GetVector(propertyName), x => target.SetVector(propertyName, x), endValue, duration); + tweener.SetOptions(false).SetTarget(target); + return tweener; + } + + public static TweenerCore DOFloat(this SerializedPass target, int propertyId, float endValue, float duration) + { + var tweener = DOTween.To(() => target.GetFloat(propertyId), x => target.SetFloat(propertyId, x), endValue, duration); + tweener.SetOptions(true).SetTarget(target); + return tweener; + } + + public static TweenerCore DOFade(this SerializedPass target, int propertyId, float endValue, float duration) + { + var tweener = DOTween.ToAlpha(() => target.GetColor(propertyId), x => target.SetColor(propertyId, x), endValue, duration); + tweener.SetOptions(true).SetTarget(target); + return tweener; + } + + public static TweenerCore DOColor(this SerializedPass target, int propertyId, Color endValue, float duration) + { + var tweener = DOTween.To(() => target.GetColor(propertyId), x => target.SetColor(propertyId, x), endValue, duration); + tweener.SetOptions(false).SetTarget(target); + return tweener; + } + + public static TweenerCore DOVector(this SerializedPass target, int propertyId, Vector4 endValue, float duration) + { + var tweener = DOTween.To(() => target.GetVector(propertyId), x => target.SetVector(propertyId, x), endValue, duration); + tweener.SetOptions(false).SetTarget(target); + return tweener; + } + + public static int DOKill(this Outlinable.OutlineProperties target, bool complete = false) + { + return DOTween.Kill(target, complete); + } + + public static int DOKill(this Outliner target, bool complete = false) + { + return DOTween.Kill(target, complete); + } + + public static TweenerCore DOFade(this Outlinable.OutlineProperties target, float endValue, float duration) + { + var tweener = DOTween.ToAlpha(() => target.Color, x => target.Color = x, endValue, duration); + tweener.SetOptions(true).SetTarget(target); + return tweener; + } + + public static TweenerCore DOColor(this Outlinable.OutlineProperties target, Color endValue, float duration) + { + var tweener = DOTween.To(() => target.Color, x => target.Color = x, endValue, duration); + tweener.SetOptions(false).SetTarget(target); + return tweener; + } + + public static TweenerCore DODilateShift(this Outlinable.OutlineProperties target, float endValue, float duration, bool snapping = false) + { + var tweener = DOTween.To(() => target.DilateShift, x => target.DilateShift = x, endValue, duration); + tweener.SetOptions(snapping).SetTarget(target); + return tweener; + } + + public static TweenerCore DOBlurShift(this Outlinable.OutlineProperties target, float endValue, float duration, bool snapping = false) + { + var tweener = DOTween.To(() => target.BlurShift, x => target.BlurShift = x, endValue, duration); + tweener.SetOptions(snapping).SetTarget(target); + return tweener; + } + + public static TweenerCore DOBlurShift(this Outliner target, float endValue, float duration, bool snapping = false) + { + var tweener = DOTween.To(() => target.BlurShift, x => target.BlurShift = x, endValue, duration); + tweener.SetOptions(snapping).SetTarget(target); + return tweener; + } + + public static TweenerCore DODilateShift(this Outliner target, float endValue, float duration, bool snapping = false) + { + var tweener = DOTween.To(() => target.DilateShift, x => target.DilateShift = x, endValue, duration); + tweener.SetOptions(snapping).SetTarget(target); + return tweener; + } + + public static TweenerCore DOInfoRendererScale(this Outliner target, float endValue, float duration, bool snapping = false) + { + var tweener = DOTween.To(() => target.InfoRendererScale, x => target.InfoRendererScale = x, endValue, duration); + tweener.SetOptions(snapping).SetTarget(target); + return tweener; + } + + public static TweenerCore DOPrimaryRendererScale(this Outliner target, float endValue, float duration, bool snapping = false) + { + var tweener = DOTween.To(() => target.PrimaryRendererScale, x => target.PrimaryRendererScale = x, endValue, duration); + tweener.SetOptions(snapping).SetTarget(target); + return tweener; + } + } +} +#endif diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleEPOOutline.cs.meta b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleEPOOutline.cs.meta new file mode 100644 index 0000000..4b8991f --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleEPOOutline.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e944529dcaee98f4e9498d80e541d93e +timeCreated: 1602593330 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics.cs b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics.cs new file mode 100644 index 0000000..08b0700 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics.cs @@ -0,0 +1,216 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2018/07/13 + +#if true // MODULE_MARKER +using System; +using DG.Tweening.Core; +using DG.Tweening.Core.Enums; +using DG.Tweening.Plugins; +using DG.Tweening.Plugins.Core.PathCore; +using DG.Tweening.Plugins.Options; +using UnityEngine; + +#pragma warning disable 1591 +namespace DG.Tweening +{ + public static class DOTweenModulePhysics + { + #region Shortcuts + + #region Rigidbody + + /// Tweens a Rigidbody's position to the given value. + /// Also stores the rigidbody as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOMove(this Rigidbody target, Vector3 endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.position, target.MovePosition, endValue, duration); + t.SetOptions(snapping).SetTarget(target); + return t; + } + + /// Tweens a Rigidbody's X position to the given value. + /// Also stores the rigidbody as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOMoveX(this Rigidbody target, float endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.position, target.MovePosition, new Vector3(endValue, 0, 0), duration); + t.SetOptions(AxisConstraint.X, snapping).SetTarget(target); + return t; + } + + /// Tweens a Rigidbody's Y position to the given value. + /// Also stores the rigidbody as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOMoveY(this Rigidbody target, float endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.position, target.MovePosition, new Vector3(0, endValue, 0), duration); + t.SetOptions(AxisConstraint.Y, snapping).SetTarget(target); + return t; + } + + /// Tweens a Rigidbody's Z position to the given value. + /// Also stores the rigidbody as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOMoveZ(this Rigidbody target, float endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.position, target.MovePosition, new Vector3(0, 0, endValue), duration); + t.SetOptions(AxisConstraint.Z, snapping).SetTarget(target); + return t; + } + + /// Tweens a Rigidbody's rotation to the given value. + /// Also stores the rigidbody as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// Rotation mode + public static TweenerCore DORotate(this Rigidbody target, Vector3 endValue, float duration, RotateMode mode = RotateMode.Fast) + { + TweenerCore t = DOTween.To(() => target.rotation, target.MoveRotation, endValue, duration); + t.SetTarget(target); + t.plugOptions.rotateMode = mode; + return t; + } + + /// Tweens a Rigidbody's rotation so that it will look towards the given position. + /// Also stores the rigidbody as the tween's target so it can be used for filtered operations + /// The position to look atThe duration of the tween + /// Eventual axis constraint for the rotation + /// The vector that defines in which direction up is (default: Vector3.up) + public static TweenerCore DOLookAt(this Rigidbody target, Vector3 towards, float duration, AxisConstraint axisConstraint = AxisConstraint.None, Vector3? up = null) + { + TweenerCore t = DOTween.To(() => target.rotation, target.MoveRotation, towards, duration) + .SetTarget(target).SetSpecialStartupMode(SpecialStartupMode.SetLookAt); + t.plugOptions.axisConstraint = axisConstraint; + t.plugOptions.up = (up == null) ? Vector3.up : (Vector3)up; + return t; + } + + #region Special + + /// Tweens a Rigidbody's position to the given value, while also applying a jump effect along the Y axis. + /// Returns a Sequence instead of a Tweener. + /// Also stores the Rigidbody as the tween's target so it can be used for filtered operations + /// The end value to reach + /// Power of the jump (the max height of the jump is represented by this plus the final Y offset) + /// Total number of jumps + /// The duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static Sequence DOJump(this Rigidbody target, Vector3 endValue, float jumpPower, int numJumps, float duration, bool snapping = false) + { + if (numJumps < 1) numJumps = 1; + float startPosY = 0; + float offsetY = -1; + bool offsetYSet = false; + Sequence s = DOTween.Sequence(); + Tween yTween = DOTween.To(() => target.position, target.MovePosition, new Vector3(0, jumpPower, 0), duration / (numJumps * 2)) + .SetOptions(AxisConstraint.Y, snapping).SetEase(Ease.OutQuad).SetRelative() + .SetLoops(numJumps * 2, LoopType.Yoyo) + .OnStart(() => startPosY = target.position.y); + s.Append(DOTween.To(() => target.position, target.MovePosition, new Vector3(endValue.x, 0, 0), duration) + .SetOptions(AxisConstraint.X, snapping).SetEase(Ease.Linear) + ).Join(DOTween.To(() => target.position, target.MovePosition, new Vector3(0, 0, endValue.z), duration) + .SetOptions(AxisConstraint.Z, snapping).SetEase(Ease.Linear) + ).Join(yTween) + .SetTarget(target).SetEase(DOTween.defaultEaseType); + yTween.OnUpdate(() => { + if (!offsetYSet) { + offsetYSet = true; + offsetY = s.isRelative ? endValue.y : endValue.y - startPosY; + } + Vector3 pos = target.position; + pos.y += DOVirtual.EasedValue(0, offsetY, yTween.ElapsedPercentage(), Ease.OutQuad); + target.MovePosition(pos); + }); + return s; + } + + /// Tweens a Rigidbody's position through the given path waypoints, using the chosen path algorithm. + /// Also stores the Rigidbody as the tween's target so it can be used for filtered operations. + /// NOTE: to tween a rigidbody correctly it should be set to kinematic at least while being tweened. + /// BEWARE: doesn't work on Windows Phone store (waiting for Unity to fix their own bug). + /// If you plan to publish there you should use a regular transform.DOPath. + /// The waypoints to go through + /// The duration of the tween + /// The type of path: Linear (straight path), CatmullRom (curved CatmullRom path) or CubicBezier (curved with control points) + /// The path mode: 3D, side-scroller 2D, top-down 2D + /// The resolution of the path (useless in case of Linear paths): higher resolutions make for more detailed curved paths but are more expensive. + /// Defaults to 10, but a value of 5 is usually enough if you don't have dramatic long curves between waypoints + /// The color of the path (shown when gizmos are active in the Play panel and the tween is running) + public static TweenerCore DOPath( + this Rigidbody target, Vector3[] path, float duration, PathType pathType = PathType.Linear, + PathMode pathMode = PathMode.Full3D, int resolution = 10, Color? gizmoColor = null + ) + { + if (resolution < 1) resolution = 1; + TweenerCore t = DOTween.To(PathPlugin.Get(), () => target.position, target.MovePosition, new Path(pathType, path, resolution, gizmoColor), duration) + .SetTarget(target).SetUpdate(UpdateType.Fixed); + + t.plugOptions.isRigidbody = true; + t.plugOptions.mode = pathMode; + return t; + } + /// Tweens a Rigidbody's localPosition through the given path waypoints, using the chosen path algorithm. + /// Also stores the Rigidbody as the tween's target so it can be used for filtered operations + /// NOTE: to tween a rigidbody correctly it should be set to kinematic at least while being tweened. + /// BEWARE: doesn't work on Windows Phone store (waiting for Unity to fix their own bug). + /// If you plan to publish there you should use a regular transform.DOLocalPath. + /// The waypoint to go through + /// The duration of the tween + /// The type of path: Linear (straight path), CatmullRom (curved CatmullRom path) or CubicBezier (curved with control points) + /// The path mode: 3D, side-scroller 2D, top-down 2D + /// The resolution of the path: higher resolutions make for more detailed curved paths but are more expensive. + /// Defaults to 10, but a value of 5 is usually enough if you don't have dramatic long curves between waypoints + /// The color of the path (shown when gizmos are active in the Play panel and the tween is running) + public static TweenerCore DOLocalPath( + this Rigidbody target, Vector3[] path, float duration, PathType pathType = PathType.Linear, + PathMode pathMode = PathMode.Full3D, int resolution = 10, Color? gizmoColor = null + ) + { + if (resolution < 1) resolution = 1; + Transform trans = target.transform; + TweenerCore t = DOTween.To(PathPlugin.Get(), () => trans.localPosition, x => target.MovePosition(trans.parent == null ? x : trans.parent.TransformPoint(x)), new Path(pathType, path, resolution, gizmoColor), duration) + .SetTarget(target).SetUpdate(UpdateType.Fixed); + + t.plugOptions.isRigidbody = true; + t.plugOptions.mode = pathMode; + t.plugOptions.useLocalPosition = true; + return t; + } + // Used by path editor when creating the actual tween, so it can pass a pre-compiled path + internal static TweenerCore DOPath( + this Rigidbody target, Path path, float duration, PathMode pathMode = PathMode.Full3D + ) + { + TweenerCore t = DOTween.To(PathPlugin.Get(), () => target.position, target.MovePosition, path, duration) + .SetTarget(target); + + t.plugOptions.isRigidbody = true; + t.plugOptions.mode = pathMode; + return t; + } + internal static TweenerCore DOLocalPath( + this Rigidbody target, Path path, float duration, PathMode pathMode = PathMode.Full3D + ) + { + Transform trans = target.transform; + TweenerCore t = DOTween.To(PathPlugin.Get(), () => trans.localPosition, x => target.MovePosition(trans.parent == null ? x : trans.parent.TransformPoint(x)), path, duration) + .SetTarget(target); + + t.plugOptions.isRigidbody = true; + t.plugOptions.mode = pathMode; + t.plugOptions.useLocalPosition = true; + return t; + } + + #endregion + + #endregion + + #endregion + } +} +#endif diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics.cs.meta b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics.cs.meta new file mode 100644 index 0000000..0ce0d75 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dae9aa560b4242648a3affa2bfabc365 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics2D.cs b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics2D.cs new file mode 100644 index 0000000..d01f728 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics2D.cs @@ -0,0 +1,193 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2018/07/13 + +#if true && (UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_2017_1_OR_NEWER) // MODULE_MARKER +using System; +using DG.Tweening.Core; +using DG.Tweening.Plugins; +using DG.Tweening.Plugins.Core.PathCore; +using DG.Tweening.Plugins.Options; +using UnityEngine; + +#pragma warning disable 1591 +namespace DG.Tweening +{ + public static class DOTweenModulePhysics2D + { + #region Shortcuts + + #region Rigidbody2D Shortcuts + + /// Tweens a Rigidbody2D's position to the given value. + /// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOMove(this Rigidbody2D target, Vector2 endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.position, target.MovePosition, endValue, duration); + t.SetOptions(snapping).SetTarget(target); + return t; + } + + /// Tweens a Rigidbody2D's X position to the given value. + /// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOMoveX(this Rigidbody2D target, float endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.position, target.MovePosition, new Vector2(endValue, 0), duration); + t.SetOptions(AxisConstraint.X, snapping).SetTarget(target); + return t; + } + + /// Tweens a Rigidbody2D's Y position to the given value. + /// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOMoveY(this Rigidbody2D target, float endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.position, target.MovePosition, new Vector2(0, endValue), duration); + t.SetOptions(AxisConstraint.Y, snapping).SetTarget(target); + return t; + } + + /// Tweens a Rigidbody2D's rotation to the given value. + /// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DORotate(this Rigidbody2D target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.rotation, target.MoveRotation, endValue, duration); + t.SetTarget(target); + return t; + } + + #region Special + + /// Tweens a Rigidbody2D's position to the given value, while also applying a jump effect along the Y axis. + /// Returns a Sequence instead of a Tweener. + /// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations. + /// IMPORTANT: a rigidbody2D can't be animated in a jump arc using MovePosition, so the tween will directly set the position + /// The end value to reach + /// Power of the jump (the max height of the jump is represented by this plus the final Y offset) + /// Total number of jumps + /// The duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static Sequence DOJump(this Rigidbody2D target, Vector2 endValue, float jumpPower, int numJumps, float duration, bool snapping = false) + { + if (numJumps < 1) numJumps = 1; + float startPosY = 0; + float offsetY = -1; + bool offsetYSet = false; + Sequence s = DOTween.Sequence(); + Tween yTween = DOTween.To(() => target.position, x => target.position = x, new Vector2(0, jumpPower), duration / (numJumps * 2)) + .SetOptions(AxisConstraint.Y, snapping).SetEase(Ease.OutQuad).SetRelative() + .SetLoops(numJumps * 2, LoopType.Yoyo) + .OnStart(() => startPosY = target.position.y); + s.Append(DOTween.To(() => target.position, x => target.position = x, new Vector2(endValue.x, 0), duration) + .SetOptions(AxisConstraint.X, snapping).SetEase(Ease.Linear) + ).Join(yTween) + .SetTarget(target).SetEase(DOTween.defaultEaseType); + yTween.OnUpdate(() => { + if (!offsetYSet) { + offsetYSet = true; + offsetY = s.isRelative ? endValue.y : endValue.y - startPosY; + } + Vector3 pos = target.position; + pos.y += DOVirtual.EasedValue(0, offsetY, yTween.ElapsedPercentage(), Ease.OutQuad); + target.MovePosition(pos); + }); + return s; + } + + /// Tweens a Rigidbody2D's position through the given path waypoints, using the chosen path algorithm. + /// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations. + /// NOTE: to tween a Rigidbody2D correctly it should be set to kinematic at least while being tweened. + /// BEWARE: doesn't work on Windows Phone store (waiting for Unity to fix their own bug). + /// If you plan to publish there you should use a regular transform.DOPath. + /// The waypoints to go through + /// The duration of the tween + /// The type of path: Linear (straight path), CatmullRom (curved CatmullRom path) or CubicBezier (curved with control points) + /// The path mode: 3D, side-scroller 2D, top-down 2D + /// The resolution of the path (useless in case of Linear paths): higher resolutions make for more detailed curved paths but are more expensive. + /// Defaults to 10, but a value of 5 is usually enough if you don't have dramatic long curves between waypoints + /// The color of the path (shown when gizmos are active in the Play panel and the tween is running) + public static TweenerCore DOPath( + this Rigidbody2D target, Vector2[] path, float duration, PathType pathType = PathType.Linear, + PathMode pathMode = PathMode.Full3D, int resolution = 10, Color? gizmoColor = null + ) + { + if (resolution < 1) resolution = 1; + int len = path.Length; + Vector3[] path3D = new Vector3[len]; + for (int i = 0; i < len; ++i) path3D[i] = path[i]; + TweenerCore t = DOTween.To(PathPlugin.Get(), () => target.position, x => target.MovePosition(x), new Path(pathType, path3D, resolution, gizmoColor), duration) + .SetTarget(target).SetUpdate(UpdateType.Fixed); + + t.plugOptions.isRigidbody2D = true; + t.plugOptions.mode = pathMode; + return t; + } + /// Tweens a Rigidbody2D's localPosition through the given path waypoints, using the chosen path algorithm. + /// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations + /// NOTE: to tween a Rigidbody2D correctly it should be set to kinematic at least while being tweened. + /// BEWARE: doesn't work on Windows Phone store (waiting for Unity to fix their own bug). + /// If you plan to publish there you should use a regular transform.DOLocalPath. + /// The waypoint to go through + /// The duration of the tween + /// The type of path: Linear (straight path), CatmullRom (curved CatmullRom path) or CubicBezier (curved with control points) + /// The path mode: 3D, side-scroller 2D, top-down 2D + /// The resolution of the path: higher resolutions make for more detailed curved paths but are more expensive. + /// Defaults to 10, but a value of 5 is usually enough if you don't have dramatic long curves between waypoints + /// The color of the path (shown when gizmos are active in the Play panel and the tween is running) + public static TweenerCore DOLocalPath( + this Rigidbody2D target, Vector2[] path, float duration, PathType pathType = PathType.Linear, + PathMode pathMode = PathMode.Full3D, int resolution = 10, Color? gizmoColor = null + ) + { + if (resolution < 1) resolution = 1; + int len = path.Length; + Vector3[] path3D = new Vector3[len]; + for (int i = 0; i < len; ++i) path3D[i] = path[i]; + Transform trans = target.transform; + TweenerCore t = DOTween.To(PathPlugin.Get(), () => trans.localPosition, x => target.MovePosition(trans.parent == null ? x : trans.parent.TransformPoint(x)), new Path(pathType, path3D, resolution, gizmoColor), duration) + .SetTarget(target).SetUpdate(UpdateType.Fixed); + + t.plugOptions.isRigidbody2D = true; + t.plugOptions.mode = pathMode; + t.plugOptions.useLocalPosition = true; + return t; + } + // Used by path editor when creating the actual tween, so it can pass a pre-compiled path + internal static TweenerCore DOPath( + this Rigidbody2D target, Path path, float duration, PathMode pathMode = PathMode.Full3D + ) + { + TweenerCore t = DOTween.To(PathPlugin.Get(), () => target.position, x => target.MovePosition(x), path, duration) + .SetTarget(target); + + t.plugOptions.isRigidbody2D = true; + t.plugOptions.mode = pathMode; + return t; + } + internal static TweenerCore DOLocalPath( + this Rigidbody2D target, Path path, float duration, PathMode pathMode = PathMode.Full3D + ) + { + Transform trans = target.transform; + TweenerCore t = DOTween.To(PathPlugin.Get(), () => trans.localPosition, x => target.MovePosition(trans.parent == null ? x : trans.parent.TransformPoint(x)), path, duration) + .SetTarget(target); + + t.plugOptions.isRigidbody2D = true; + t.plugOptions.mode = pathMode; + t.plugOptions.useLocalPosition = true; + return t; + } + + #endregion + + #endregion + + #endregion + } +} +#endif diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics2D.cs.meta b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics2D.cs.meta new file mode 100644 index 0000000..ca9ed29 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModulePhysics2D.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 230fe34542e175245ba74b4659dae700 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleSprite.cs b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleSprite.cs new file mode 100644 index 0000000..549fff3 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleSprite.cs @@ -0,0 +1,93 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2018/07/13 + +#if true && (UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_2017_1_OR_NEWER) // MODULE_MARKER +using System; +using UnityEngine; +using DG.Tweening.Core; +using DG.Tweening.Plugins.Options; + +#pragma warning disable 1591 +namespace DG.Tweening +{ + public static class DOTweenModuleSprite + { + #region Shortcuts + + #region SpriteRenderer + + /// Tweens a SpriteRenderer's color to the given value. + /// Also stores the spriteRenderer as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOColor(this SpriteRenderer target, Color endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a Material's alpha color to the given value. + /// Also stores the spriteRenderer as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOFade(this SpriteRenderer target, float endValue, float duration) + { + TweenerCore t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a SpriteRenderer's color using the given gradient + /// (NOTE 1: only uses the colors of the gradient, not the alphas - NOTE 2: creates a Sequence, not a Tweener). + /// Also stores the image as the tween's target so it can be used for filtered operations + /// The gradient to useThe duration of the tween + public static Sequence DOGradientColor(this SpriteRenderer target, Gradient gradient, float duration) + { + Sequence s = DOTween.Sequence(); + GradientColorKey[] colors = gradient.colorKeys; + int len = colors.Length; + for (int i = 0; i < len; ++i) { + GradientColorKey c = colors[i]; + if (i == 0 && c.time <= 0) { + target.color = c.color; + continue; + } + float colorDuration = i == len - 1 + ? duration - s.Duration(false) // Verifies that total duration is correct + : duration * (i == 0 ? c.time : c.time - colors[i - 1].time); + s.Append(target.DOColor(c.color, colorDuration).SetEase(Ease.Linear)); + } + s.SetTarget(target); + return s; + } + + #endregion + + #region Blendables + + #region SpriteRenderer + + /// Tweens a SpriteRenderer's color to the given value, + /// in a way that allows other DOBlendableColor tweens to work together on the same target, + /// instead than fight each other as multiple DOColor would do. + /// Also stores the SpriteRenderer as the tween's target so it can be used for filtered operations + /// The value to tween toThe duration of the tween + public static Tweener DOBlendableColor(this SpriteRenderer target, Color endValue, float duration) + { + endValue = endValue - target.color; + Color to = new Color(0, 0, 0, 0); + return DOTween.To(() => to, x => { + Color diff = x - to; + to = x; + target.color += diff; + }, endValue, duration) + .Blendable().SetTarget(target); + } + + #endregion + + #endregion + + #endregion + } +} +#endif diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleSprite.cs.meta b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleSprite.cs.meta new file mode 100644 index 0000000..a0c67c4 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleSprite.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 188918ab119d93148aa0de59ccf5286b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUI.cs b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUI.cs new file mode 100644 index 0000000..dc24ebf --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUI.cs @@ -0,0 +1,660 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2018/07/13 + +#if true && (UNITY_4_6 || UNITY_5 || UNITY_2017_1_OR_NEWER) // MODULE_MARKER + +using System; +using System.Globalization; +using UnityEngine; +using UnityEngine.UI; +using DG.Tweening.Core; +using DG.Tweening.Core.Enums; +using DG.Tweening.Plugins; +using DG.Tweening.Plugins.Options; +using Outline = UnityEngine.UI.Outline; +using Text = UnityEngine.UI.Text; + +#pragma warning disable 1591 +namespace DG.Tweening +{ + public static class DOTweenModuleUI + { + #region Shortcuts + + #region CanvasGroup + + /// Tweens a CanvasGroup's alpha color to the given value. + /// Also stores the canvasGroup as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOFade(this CanvasGroup target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.alpha, x => target.alpha = x, endValue, duration); + t.SetTarget(target); + return t; + } + + #endregion + + #region Graphic + + /// Tweens an Graphic's color to the given value. + /// Also stores the image as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOColor(this Graphic target, Color endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens an Graphic's alpha color to the given value. + /// Also stores the image as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOFade(this Graphic target, float endValue, float duration) + { + TweenerCore t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + #endregion + + #region Image + + /// Tweens an Image's color to the given value. + /// Also stores the image as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOColor(this Image target, Color endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens an Image's alpha color to the given value. + /// Also stores the image as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOFade(this Image target, float endValue, float duration) + { + TweenerCore t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens an Image's fillAmount to the given value. + /// Also stores the image as the tween's target so it can be used for filtered operations + /// The end value to reach (0 to 1)The duration of the tween + public static TweenerCore DOFillAmount(this Image target, float endValue, float duration) + { + if (endValue > 1) endValue = 1; + else if (endValue < 0) endValue = 0; + TweenerCore t = DOTween.To(() => target.fillAmount, x => target.fillAmount = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens an Image's colors using the given gradient + /// (NOTE 1: only uses the colors of the gradient, not the alphas - NOTE 2: creates a Sequence, not a Tweener). + /// Also stores the image as the tween's target so it can be used for filtered operations + /// The gradient to useThe duration of the tween + public static Sequence DOGradientColor(this Image target, Gradient gradient, float duration) + { + Sequence s = DOTween.Sequence(); + GradientColorKey[] colors = gradient.colorKeys; + int len = colors.Length; + for (int i = 0; i < len; ++i) { + GradientColorKey c = colors[i]; + if (i == 0 && c.time <= 0) { + target.color = c.color; + continue; + } + float colorDuration = i == len - 1 + ? duration - s.Duration(false) // Verifies that total duration is correct + : duration * (i == 0 ? c.time : c.time - colors[i - 1].time); + s.Append(target.DOColor(c.color, colorDuration).SetEase(Ease.Linear)); + } + s.SetTarget(target); + return s; + } + + #endregion + + #region LayoutElement + + /// Tweens an LayoutElement's flexibleWidth/Height to the given value. + /// Also stores the LayoutElement as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOFlexibleSize(this LayoutElement target, Vector2 endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => new Vector2(target.flexibleWidth, target.flexibleHeight), x => { + target.flexibleWidth = x.x; + target.flexibleHeight = x.y; + }, endValue, duration); + t.SetOptions(snapping).SetTarget(target); + return t; + } + + /// Tweens an LayoutElement's minWidth/Height to the given value. + /// Also stores the LayoutElement as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOMinSize(this LayoutElement target, Vector2 endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => new Vector2(target.minWidth, target.minHeight), x => { + target.minWidth = x.x; + target.minHeight = x.y; + }, endValue, duration); + t.SetOptions(snapping).SetTarget(target); + return t; + } + + /// Tweens an LayoutElement's preferredWidth/Height to the given value. + /// Also stores the LayoutElement as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOPreferredSize(this LayoutElement target, Vector2 endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => new Vector2(target.preferredWidth, target.preferredHeight), x => { + target.preferredWidth = x.x; + target.preferredHeight = x.y; + }, endValue, duration); + t.SetOptions(snapping).SetTarget(target); + return t; + } + + #endregion + + #region Outline + + /// Tweens a Outline's effectColor to the given value. + /// Also stores the Outline as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOColor(this Outline target, Color endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.effectColor, x => target.effectColor = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a Outline's effectColor alpha to the given value. + /// Also stores the Outline as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOFade(this Outline target, float endValue, float duration) + { + TweenerCore t = DOTween.ToAlpha(() => target.effectColor, x => target.effectColor = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a Outline's effectDistance to the given value. + /// Also stores the Outline as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScale(this Outline target, Vector2 endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.effectDistance, x => target.effectDistance = x, endValue, duration); + t.SetTarget(target); + return t; + } + + #endregion + + #region RectTransform + + /// Tweens a RectTransform's anchoredPosition to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOAnchorPos(this RectTransform target, Vector2 endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.anchoredPosition, x => target.anchoredPosition = x, endValue, duration); + t.SetOptions(snapping).SetTarget(target); + return t; + } + /// Tweens a RectTransform's anchoredPosition X to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOAnchorPosX(this RectTransform target, float endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.anchoredPosition, x => target.anchoredPosition = x, new Vector2(endValue, 0), duration); + t.SetOptions(AxisConstraint.X, snapping).SetTarget(target); + return t; + } + /// Tweens a RectTransform's anchoredPosition Y to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOAnchorPosY(this RectTransform target, float endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.anchoredPosition, x => target.anchoredPosition = x, new Vector2(0, endValue), duration); + t.SetOptions(AxisConstraint.Y, snapping).SetTarget(target); + return t; + } + + /// Tweens a RectTransform's anchoredPosition3D to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOAnchorPos3D(this RectTransform target, Vector3 endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.anchoredPosition3D, x => target.anchoredPosition3D = x, endValue, duration); + t.SetOptions(snapping).SetTarget(target); + return t; + } + /// Tweens a RectTransform's anchoredPosition3D X to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOAnchorPos3DX(this RectTransform target, float endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.anchoredPosition3D, x => target.anchoredPosition3D = x, new Vector3(endValue, 0, 0), duration); + t.SetOptions(AxisConstraint.X, snapping).SetTarget(target); + return t; + } + /// Tweens a RectTransform's anchoredPosition3D Y to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOAnchorPos3DY(this RectTransform target, float endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.anchoredPosition3D, x => target.anchoredPosition3D = x, new Vector3(0, endValue, 0), duration); + t.SetOptions(AxisConstraint.Y, snapping).SetTarget(target); + return t; + } + /// Tweens a RectTransform's anchoredPosition3D Z to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOAnchorPos3DZ(this RectTransform target, float endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.anchoredPosition3D, x => target.anchoredPosition3D = x, new Vector3(0, 0, endValue), duration); + t.SetOptions(AxisConstraint.Z, snapping).SetTarget(target); + return t; + } + + /// Tweens a RectTransform's anchorMax to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOAnchorMax(this RectTransform target, Vector2 endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.anchorMax, x => target.anchorMax = x, endValue, duration); + t.SetOptions(snapping).SetTarget(target); + return t; + } + + /// Tweens a RectTransform's anchorMin to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOAnchorMin(this RectTransform target, Vector2 endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.anchorMin, x => target.anchorMin = x, endValue, duration); + t.SetOptions(snapping).SetTarget(target); + return t; + } + + /// Tweens a RectTransform's pivot to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOPivot(this RectTransform target, Vector2 endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.pivot, x => target.pivot = x, endValue, duration); + t.SetTarget(target); + return t; + } + /// Tweens a RectTransform's pivot X to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOPivotX(this RectTransform target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.pivot, x => target.pivot = x, new Vector2(endValue, 0), duration); + t.SetOptions(AxisConstraint.X).SetTarget(target); + return t; + } + /// Tweens a RectTransform's pivot Y to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOPivotY(this RectTransform target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.pivot, x => target.pivot = x, new Vector2(0, endValue), duration); + t.SetOptions(AxisConstraint.Y).SetTarget(target); + return t; + } + + /// Tweens a RectTransform's sizeDelta to the given value. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOSizeDelta(this RectTransform target, Vector2 endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.sizeDelta, x => target.sizeDelta = x, endValue, duration); + t.SetOptions(snapping).SetTarget(target); + return t; + } + + /// Punches a RectTransform's anchoredPosition towards the given direction and then back to the starting one + /// as if it was connected to the starting position via an elastic. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The direction and strength of the punch (added to the RectTransform's current position) + /// The duration of the tween + /// Indicates how much will the punch vibrate + /// Represents how much (0 to 1) the vector will go beyond the starting position when bouncing backwards. + /// 1 creates a full oscillation between the punch direction and the opposite direction, + /// while 0 oscillates only between the punch and the start position + /// If TRUE the tween will smoothly snap all values to integers + public static Tweener DOPunchAnchorPos(this RectTransform target, Vector2 punch, float duration, int vibrato = 10, float elasticity = 1, bool snapping = false) + { + return DOTween.Punch(() => target.anchoredPosition, x => target.anchoredPosition = x, punch, duration, vibrato, elasticity) + .SetTarget(target).SetOptions(snapping); + } + + /// Shakes a RectTransform's anchoredPosition with the given values. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The duration of the tween + /// The shake strength + /// Indicates how much will the shake vibrate + /// Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + /// Setting it to 0 will shake along a single direction. + /// If TRUE the tween will smoothly snap all values to integers + /// If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + public static Tweener DOShakeAnchorPos(this RectTransform target, float duration, float strength = 100, int vibrato = 10, float randomness = 90, bool snapping = false, bool fadeOut = true) + { + return DOTween.Shake(() => target.anchoredPosition, x => target.anchoredPosition = x, duration, strength, vibrato, randomness, true, fadeOut) + .SetTarget(target).SetSpecialStartupMode(SpecialStartupMode.SetShake).SetOptions(snapping); + } + /// Shakes a RectTransform's anchoredPosition with the given values. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The duration of the tween + /// The shake strength on each axis + /// Indicates how much will the shake vibrate + /// Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + /// Setting it to 0 will shake along a single direction. + /// If TRUE the tween will smoothly snap all values to integers + /// If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + public static Tweener DOShakeAnchorPos(this RectTransform target, float duration, Vector2 strength, int vibrato = 10, float randomness = 90, bool snapping = false, bool fadeOut = true) + { + return DOTween.Shake(() => target.anchoredPosition, x => target.anchoredPosition = x, duration, strength, vibrato, randomness, fadeOut) + .SetTarget(target).SetSpecialStartupMode(SpecialStartupMode.SetShake).SetOptions(snapping); + } + + #region Special + + /// Tweens a RectTransform's anchoredPosition to the given value, while also applying a jump effect along the Y axis. + /// Returns a Sequence instead of a Tweener. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations + /// The end value to reach + /// Power of the jump (the max height of the jump is represented by this plus the final Y offset) + /// Total number of jumps + /// The duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static Sequence DOJumpAnchorPos(this RectTransform target, Vector2 endValue, float jumpPower, int numJumps, float duration, bool snapping = false) + { + if (numJumps < 1) numJumps = 1; + float startPosY = 0; + float offsetY = -1; + bool offsetYSet = false; + + // Separate Y Tween so we can elaborate elapsedPercentage on that insted of on the Sequence + // (in case users add a delay or other elements to the Sequence) + Sequence s = DOTween.Sequence(); + Tween yTween = DOTween.To(() => target.anchoredPosition, x => target.anchoredPosition = x, new Vector2(0, jumpPower), duration / (numJumps * 2)) + .SetOptions(AxisConstraint.Y, snapping).SetEase(Ease.OutQuad).SetRelative() + .SetLoops(numJumps * 2, LoopType.Yoyo) + .OnStart(()=> startPosY = target.anchoredPosition.y); + s.Append(DOTween.To(() => target.anchoredPosition, x => target.anchoredPosition = x, new Vector2(endValue.x, 0), duration) + .SetOptions(AxisConstraint.X, snapping).SetEase(Ease.Linear) + ).Join(yTween) + .SetTarget(target).SetEase(DOTween.defaultEaseType); + s.OnUpdate(() => { + if (!offsetYSet) { + offsetYSet = true; + offsetY = s.isRelative ? endValue.y : endValue.y - startPosY; + } + Vector2 pos = target.anchoredPosition; + pos.y += DOVirtual.EasedValue(0, offsetY, s.ElapsedDirectionalPercentage(), Ease.OutQuad); + target.anchoredPosition = pos; + }); + return s; + } + + #endregion + + #endregion + + #region ScrollRect + + /// Tweens a ScrollRect's horizontal/verticalNormalizedPosition to the given value. + /// Also stores the ScrollRect as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static Tweener DONormalizedPos(this ScrollRect target, Vector2 endValue, float duration, bool snapping = false) + { + return DOTween.To(() => new Vector2(target.horizontalNormalizedPosition, target.verticalNormalizedPosition), + x => { + target.horizontalNormalizedPosition = x.x; + target.verticalNormalizedPosition = x.y; + }, endValue, duration) + .SetOptions(snapping).SetTarget(target); + } + /// Tweens a ScrollRect's horizontalNormalizedPosition to the given value. + /// Also stores the ScrollRect as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static Tweener DOHorizontalNormalizedPos(this ScrollRect target, float endValue, float duration, bool snapping = false) + { + return DOTween.To(() => target.horizontalNormalizedPosition, x => target.horizontalNormalizedPosition = x, endValue, duration) + .SetOptions(snapping).SetTarget(target); + } + /// Tweens a ScrollRect's verticalNormalizedPosition to the given value. + /// Also stores the ScrollRect as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static Tweener DOVerticalNormalizedPos(this ScrollRect target, float endValue, float duration, bool snapping = false) + { + return DOTween.To(() => target.verticalNormalizedPosition, x => target.verticalNormalizedPosition = x, endValue, duration) + .SetOptions(snapping).SetTarget(target); + } + + #endregion + + #region Slider + + /// Tweens a Slider's value to the given value. + /// Also stores the Slider as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOValue(this Slider target, float endValue, float duration, bool snapping = false) + { + TweenerCore t = DOTween.To(() => target.value, x => target.value = x, endValue, duration); + t.SetOptions(snapping).SetTarget(target); + return t; + } + + #endregion + + #region Text + + /// Tweens a Text's color to the given value. + /// Also stores the Text as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOColor(this Text target, Color endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// + /// Tweens a Text's text from one integer to another, with options for thousands separators + /// + /// The value to start from + /// The end value to reach + /// The duration of the tween + /// If TRUE (default) also adds thousands separators + /// The to use (InvariantCulture if NULL) + public static TweenerCore DOCounter( + this Text target, int fromValue, int endValue, float duration, bool addThousandsSeparator = true, CultureInfo culture = null + ){ + int v = fromValue; + CultureInfo cInfo = !addThousandsSeparator ? null : culture ?? CultureInfo.InvariantCulture; + TweenerCore t = DOTween.To(() => v, x => { + v = x; + target.text = addThousandsSeparator + ? v.ToString("N0", cInfo) + : v.ToString(); + }, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a Text's alpha color to the given value. + /// Also stores the Text as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOFade(this Text target, float endValue, float duration) + { + TweenerCore t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a Text's text to the given value. + /// Also stores the Text as the tween's target so it can be used for filtered operations + /// The end string to tween toThe duration of the tween + /// If TRUE (default), rich text will be interpreted correctly while animated, + /// otherwise all tags will be considered as normal text + /// The type of scramble mode to use, if any + /// A string containing the characters to use for scrambling. + /// Use as many characters as possible (minimum 10) because DOTween uses a fast scramble mode which gives better results with more characters. + /// Leave it to NULL (default) to use default ones + public static TweenerCore DOText(this Text target, string endValue, float duration, bool richTextEnabled = true, ScrambleMode scrambleMode = ScrambleMode.None, string scrambleChars = null) + { + if (endValue == null) { + if (Debugger.logPriority > 0) Debugger.LogWarning("You can't pass a NULL string to DOText: an empty string will be used instead to avoid errors"); + endValue = ""; + } + TweenerCore t = DOTween.To(() => target.text, x => target.text = x, endValue, duration); + t.SetOptions(richTextEnabled, scrambleMode, scrambleChars) + .SetTarget(target); + return t; + } + + #endregion + + #region Blendables + + #region Graphic + + /// Tweens a Graphic's color to the given value, + /// in a way that allows other DOBlendableColor tweens to work together on the same target, + /// instead than fight each other as multiple DOColor would do. + /// Also stores the Graphic as the tween's target so it can be used for filtered operations + /// The value to tween toThe duration of the tween + public static Tweener DOBlendableColor(this Graphic target, Color endValue, float duration) + { + endValue = endValue - target.color; + Color to = new Color(0, 0, 0, 0); + return DOTween.To(() => to, x => { + Color diff = x - to; + to = x; + target.color += diff; + }, endValue, duration) + .Blendable().SetTarget(target); + } + + #endregion + + #region Image + + /// Tweens a Image's color to the given value, + /// in a way that allows other DOBlendableColor tweens to work together on the same target, + /// instead than fight each other as multiple DOColor would do. + /// Also stores the Image as the tween's target so it can be used for filtered operations + /// The value to tween toThe duration of the tween + public static Tweener DOBlendableColor(this Image target, Color endValue, float duration) + { + endValue = endValue - target.color; + Color to = new Color(0, 0, 0, 0); + return DOTween.To(() => to, x => { + Color diff = x - to; + to = x; + target.color += diff; + }, endValue, duration) + .Blendable().SetTarget(target); + } + + #endregion + + #region Text + + /// Tweens a Text's color BY the given value, + /// in a way that allows other DOBlendableColor tweens to work together on the same target, + /// instead than fight each other as multiple DOColor would do. + /// Also stores the Text as the tween's target so it can be used for filtered operations + /// The value to tween toThe duration of the tween + public static Tweener DOBlendableColor(this Text target, Color endValue, float duration) + { + endValue = endValue - target.color; + Color to = new Color(0, 0, 0, 0); + return DOTween.To(() => to, x => { + Color diff = x - to; + to = x; + target.color += diff; + }, endValue, duration) + .Blendable().SetTarget(target); + } + + #endregion + + #endregion + + #region Shapes + + /// Tweens a RectTransform's anchoredPosition so that it draws a circle around the given center. + /// Also stores the RectTransform as the tween's target so it can be used for filtered operations. + /// IMPORTANT: SetFrom(value) requires a instead of a float, where the X property represents the "from degrees value" + /// Circle-center/pivot around which to rotate (in UI anchoredPosition coordinates) + /// The end value degrees to reach (to rotate counter-clockwise pass a negative value) + /// The duration of the tween + /// If TRUE the coordinates will be considered as relative to the target's current anchoredPosition + /// If TRUE the tween will smoothly snap all values to integers + public static TweenerCore DOShapeCircle( + this RectTransform target, Vector2 center, float endValueDegrees, float duration, bool relativeCenter = false, bool snapping = false + ) + { + TweenerCore t = DOTween.To( + CirclePlugin.Get(), () => target.anchoredPosition, x => target.anchoredPosition = x, center, duration + ); + t.SetOptions(endValueDegrees, relativeCenter, snapping).SetTarget(target); + return t; + } + + #endregion + + #endregion + + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + // ███ INTERNAL CLASSES ████████████████████████████████████████████████████████████████████████████████████████████████ + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + + public static class Utils + { + /// + /// Converts the anchoredPosition of the first RectTransform to the second RectTransform, + /// taking into consideration offset, anchors and pivot, and returns the new anchoredPosition + /// + public static Vector2 SwitchToRectTransform(RectTransform from, RectTransform to) + { + Vector2 localPoint; + Vector2 fromPivotDerivedOffset = new Vector2(from.rect.width * 0.5f + from.rect.xMin, from.rect.height * 0.5f + from.rect.yMin); + Vector2 screenP = RectTransformUtility.WorldToScreenPoint(null, from.position); + screenP += fromPivotDerivedOffset; + RectTransformUtility.ScreenPointToLocalPointInRectangle(to, screenP, null, out localPoint); + Vector2 pivotDerivedOffset = new Vector2(to.rect.width * 0.5f + to.rect.xMin, to.rect.height * 0.5f + to.rect.yMin); + return to.anchoredPosition + localPoint - pivotDerivedOffset; + } + } + } +} +#endif diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUI.cs.meta b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUI.cs.meta new file mode 100644 index 0000000..60d55ef --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUI.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a060394c03331a64392db53a10e7f2d1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUnityVersion.cs b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUnityVersion.cs new file mode 100644 index 0000000..fa1ac05 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUnityVersion.cs @@ -0,0 +1,403 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2018/07/13 + +using System; +using UnityEngine; +using DG.Tweening.Core; +using DG.Tweening.Plugins.Options; +//#if UNITY_2018_1_OR_NEWER && (NET_4_6 || NET_STANDARD_2_0) +//using Task = System.Threading.Tasks.Task; +//#endif + +#pragma warning disable 1591 +namespace DG.Tweening +{ + /// + /// Shortcuts/functions that are not strictly related to specific Modules + /// but are available only on some Unity versions + /// + public static class DOTweenModuleUnityVersion + { +#if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_2017_1_OR_NEWER + #region Unity 4.3 or Newer + + #region Material + + /// Tweens a Material's color using the given gradient + /// (NOTE 1: only uses the colors of the gradient, not the alphas - NOTE 2: creates a Sequence, not a Tweener). + /// Also stores the image as the tween's target so it can be used for filtered operations + /// The gradient to useThe duration of the tween + public static Sequence DOGradientColor(this Material target, Gradient gradient, float duration) + { + Sequence s = DOTween.Sequence(); + GradientColorKey[] colors = gradient.colorKeys; + int len = colors.Length; + for (int i = 0; i < len; ++i) { + GradientColorKey c = colors[i]; + if (i == 0 && c.time <= 0) { + target.color = c.color; + continue; + } + float colorDuration = i == len - 1 + ? duration - s.Duration(false) // Verifies that total duration is correct + : duration * (i == 0 ? c.time : c.time - colors[i - 1].time); + s.Append(target.DOColor(c.color, colorDuration).SetEase(Ease.Linear)); + } + s.SetTarget(target); + return s; + } + /// Tweens a Material's named color property using the given gradient + /// (NOTE 1: only uses the colors of the gradient, not the alphas - NOTE 2: creates a Sequence, not a Tweener). + /// Also stores the image as the tween's target so it can be used for filtered operations + /// The gradient to use + /// The name of the material property to tween (like _Tint or _SpecColor) + /// The duration of the tween + public static Sequence DOGradientColor(this Material target, Gradient gradient, string property, float duration) + { + Sequence s = DOTween.Sequence(); + GradientColorKey[] colors = gradient.colorKeys; + int len = colors.Length; + for (int i = 0; i < len; ++i) { + GradientColorKey c = colors[i]; + if (i == 0 && c.time <= 0) { + target.SetColor(property, c.color); + continue; + } + float colorDuration = i == len - 1 + ? duration - s.Duration(false) // Verifies that total duration is correct + : duration * (i == 0 ? c.time : c.time - colors[i - 1].time); + s.Append(target.DOColor(c.color, property, colorDuration).SetEase(Ease.Linear)); + } + s.SetTarget(target); + return s; + } + + #endregion + + #endregion +#endif + +#if UNITY_5_3_OR_NEWER || UNITY_2017_1_OR_NEWER + #region Unity 5.3 or Newer + + #region CustomYieldInstructions + + /// + /// Returns a that waits until the tween is killed or complete. + /// It can be used inside a coroutine as a yield. + /// Example usage:yield return myTween.WaitForCompletion(true); + /// + public static CustomYieldInstruction WaitForCompletion(this Tween t, bool returnCustomYieldInstruction) + { + if (!t.active) { + if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t); + return null; + } + return new DOTweenCYInstruction.WaitForCompletion(t); + } + + /// + /// Returns a that waits until the tween is killed or rewinded. + /// It can be used inside a coroutine as a yield. + /// Example usage:yield return myTween.WaitForRewind(); + /// + public static CustomYieldInstruction WaitForRewind(this Tween t, bool returnCustomYieldInstruction) + { + if (!t.active) { + if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t); + return null; + } + return new DOTweenCYInstruction.WaitForRewind(t); + } + + /// + /// Returns a that waits until the tween is killed. + /// It can be used inside a coroutine as a yield. + /// Example usage:yield return myTween.WaitForKill(); + /// + public static CustomYieldInstruction WaitForKill(this Tween t, bool returnCustomYieldInstruction) + { + if (!t.active) { + if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t); + return null; + } + return new DOTweenCYInstruction.WaitForKill(t); + } + + /// + /// Returns a that waits until the tween is killed or has gone through the given amount of loops. + /// It can be used inside a coroutine as a yield. + /// Example usage:yield return myTween.WaitForElapsedLoops(2); + /// + /// Elapsed loops to wait for + public static CustomYieldInstruction WaitForElapsedLoops(this Tween t, int elapsedLoops, bool returnCustomYieldInstruction) + { + if (!t.active) { + if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t); + return null; + } + return new DOTweenCYInstruction.WaitForElapsedLoops(t, elapsedLoops); + } + + /// + /// Returns a that waits until the tween is killed + /// or has reached the given time position (loops included, delays excluded). + /// It can be used inside a coroutine as a yield. + /// Example usage:yield return myTween.WaitForPosition(2.5f); + /// + /// Position (loops included, delays excluded) to wait for + public static CustomYieldInstruction WaitForPosition(this Tween t, float position, bool returnCustomYieldInstruction) + { + if (!t.active) { + if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t); + return null; + } + return new DOTweenCYInstruction.WaitForPosition(t, position); + } + + /// + /// Returns a that waits until the tween is killed or started + /// (meaning when the tween is set in a playing state the first time, after any eventual delay). + /// It can be used inside a coroutine as a yield. + /// Example usage:yield return myTween.WaitForStart(); + /// + public static CustomYieldInstruction WaitForStart(this Tween t, bool returnCustomYieldInstruction) + { + if (!t.active) { + if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t); + return null; + } + return new DOTweenCYInstruction.WaitForStart(t); + } + + #endregion + + #endregion +#endif + +#if UNITY_2018_1_OR_NEWER + #region Unity 2018.1 or Newer + + #region Material + + /// Tweens a Material's named texture offset property with the given ID to the given value. + /// Also stores the material as the tween's target so it can be used for filtered operations + /// The end value to reach + /// The ID of the material property to tween (also called nameID in Unity's manual) + /// The duration of the tween + public static TweenerCore DOOffset(this Material target, Vector2 endValue, int propertyID, float duration) + { + if (!target.HasProperty(propertyID)) { + if (Debugger.logPriority > 0) Debugger.LogMissingMaterialProperty(propertyID); + return null; + } + TweenerCore t = DOTween.To(() => target.GetTextureOffset(propertyID), x => target.SetTextureOffset(propertyID, x), endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a Material's named texture scale property with the given ID to the given value. + /// Also stores the material as the tween's target so it can be used for filtered operations + /// The end value to reach + /// The ID of the material property to tween (also called nameID in Unity's manual) + /// The duration of the tween + public static TweenerCore DOTiling(this Material target, Vector2 endValue, int propertyID, float duration) + { + if (!target.HasProperty(propertyID)) { + if (Debugger.logPriority > 0) Debugger.LogMissingMaterialProperty(propertyID); + return null; + } + TweenerCore t = DOTween.To(() => target.GetTextureScale(propertyID), x => target.SetTextureScale(propertyID, x), endValue, duration); + t.SetTarget(target); + return t; + } + + #endregion + + #region .NET 4.6 or Newer + +#if UNITY_2018_1_OR_NEWER && (NET_4_6 || NET_STANDARD_2_0) + + #region Async Instructions + + /// + /// Returns an async that waits until the tween is killed or complete. + /// It can be used inside an async operation. + /// Example usage:await myTween.WaitForCompletion(); + /// + public static async System.Threading.Tasks.Task AsyncWaitForCompletion(this Tween t) + { + if (!t.active) { + if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t); + return; + } + while (t.active && !t.IsComplete()) await System.Threading.Tasks.Task.Yield(); + } + + /// + /// Returns an async that waits until the tween is killed or rewinded. + /// It can be used inside an async operation. + /// Example usage:await myTween.AsyncWaitForRewind(); + /// + public static async System.Threading.Tasks.Task AsyncWaitForRewind(this Tween t) + { + if (!t.active) { + if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t); + return; + } + while (t.active && (!t.playedOnce || t.position * (t.CompletedLoops() + 1) > 0)) await System.Threading.Tasks.Task.Yield(); + } + + /// + /// Returns an async that waits until the tween is killed. + /// It can be used inside an async operation. + /// Example usage:await myTween.AsyncWaitForKill(); + /// + public static async System.Threading.Tasks.Task AsyncWaitForKill(this Tween t) + { + if (!t.active) { + if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t); + return; + } + while (t.active) await System.Threading.Tasks.Task.Yield(); + } + + /// + /// Returns an async that waits until the tween is killed or has gone through the given amount of loops. + /// It can be used inside an async operation. + /// Example usage:await myTween.AsyncWaitForElapsedLoops(); + /// + /// Elapsed loops to wait for + public static async System.Threading.Tasks.Task AsyncWaitForElapsedLoops(this Tween t, int elapsedLoops) + { + if (!t.active) { + if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t); + return; + } + while (t.active && t.CompletedLoops() < elapsedLoops) await System.Threading.Tasks.Task.Yield(); + } + + /// + /// Returns an async that waits until the tween is killed or started + /// (meaning when the tween is set in a playing state the first time, after any eventual delay). + /// It can be used inside an async operation. + /// Example usage:await myTween.AsyncWaitForPosition(); + /// + /// Position (loops included, delays excluded) to wait for + public static async System.Threading.Tasks.Task AsyncWaitForPosition(this Tween t, float position) + { + if (!t.active) { + if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t); + return; + } + while (t.active && t.position * (t.CompletedLoops() + 1) < position) await System.Threading.Tasks.Task.Yield(); + } + + /// + /// Returns an async that waits until the tween is killed. + /// It can be used inside an async operation. + /// Example usage:await myTween.AsyncWaitForKill(); + /// + public static async System.Threading.Tasks.Task AsyncWaitForStart(this Tween t) + { + if (!t.active) { + if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t); + return; + } + while (t.active && !t.playedOnce) await System.Threading.Tasks.Task.Yield(); + } + + #endregion +#endif + + #endregion + + #endregion +#endif + } + + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + // ███ CLASSES █████████████████████████████████████████████████████████████████████████████████████████████████████████ + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + +#if UNITY_5_3_OR_NEWER || UNITY_2017_1_OR_NEWER + public static class DOTweenCYInstruction + { + public class WaitForCompletion : CustomYieldInstruction + { + public override bool keepWaiting { get { + return t.active && !t.IsComplete(); + }} + readonly Tween t; + public WaitForCompletion(Tween tween) + { + t = tween; + } + } + + public class WaitForRewind : CustomYieldInstruction + { + public override bool keepWaiting { get { + return t.active && (!t.playedOnce || t.position * (t.CompletedLoops() + 1) > 0); + }} + readonly Tween t; + public WaitForRewind(Tween tween) + { + t = tween; + } + } + + public class WaitForKill : CustomYieldInstruction + { + public override bool keepWaiting { get { + return t.active; + }} + readonly Tween t; + public WaitForKill(Tween tween) + { + t = tween; + } + } + + public class WaitForElapsedLoops : CustomYieldInstruction + { + public override bool keepWaiting { get { + return t.active && t.CompletedLoops() < elapsedLoops; + }} + readonly Tween t; + readonly int elapsedLoops; + public WaitForElapsedLoops(Tween tween, int elapsedLoops) + { + t = tween; + this.elapsedLoops = elapsedLoops; + } + } + + public class WaitForPosition : CustomYieldInstruction + { + public override bool keepWaiting { get { + return t.active && t.position * (t.CompletedLoops() + 1) < position; + }} + readonly Tween t; + readonly float position; + public WaitForPosition(Tween tween, float position) + { + t = tween; + this.position = position; + } + } + + public class WaitForStart : CustomYieldInstruction + { + public override bool keepWaiting { get { + return t.active && !t.playedOnce; + }} + readonly Tween t; + public WaitForStart(Tween tween) + { + t = tween; + } + } + } +#endif +} diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUnityVersion.cs.meta b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUnityVersion.cs.meta new file mode 100644 index 0000000..290189f --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUnityVersion.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 63c02322328255542995bd02b47b0457 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUtils.cs b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUtils.cs new file mode 100644 index 0000000..12a365d --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUtils.cs @@ -0,0 +1,167 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2018/07/13 + +using System; +using System.Reflection; +using UnityEngine; +using DG.Tweening.Core; +using DG.Tweening.Plugins.Core.PathCore; +using DG.Tweening.Plugins.Options; + +#pragma warning disable 1591 +namespace DG.Tweening +{ + /// + /// Utility functions that deal with available Modules. + /// Modules defines: + /// - DOTAUDIO + /// - DOTPHYSICS + /// - DOTPHYSICS2D + /// - DOTSPRITE + /// - DOTUI + /// Extra defines set and used for implementation of external assets: + /// - DOTWEEN_TMP ► TextMesh Pro + /// - DOTWEEN_TK2D ► 2D Toolkit + /// + public static class DOTweenModuleUtils + { + static bool _initialized; + + #region Reflection + + /// + /// Called via Reflection by DOTweenComponent on Awake + /// +#if UNITY_2018_1_OR_NEWER + [UnityEngine.Scripting.Preserve] +#endif + public static void Init() + { + if (_initialized) return; + + _initialized = true; + DOTweenExternalCommand.SetOrientationOnPath += Physics.SetOrientationOnPath; + +#if UNITY_EDITOR +#if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_2017_1 + UnityEditor.EditorApplication.playmodeStateChanged += PlaymodeStateChanged; +#else + UnityEditor.EditorApplication.playModeStateChanged += PlaymodeStateChanged; +#endif +#endif + } + +#if UNITY_2018_1_OR_NEWER +#pragma warning disable + [UnityEngine.Scripting.Preserve] + // Just used to preserve methods when building, never called + static void Preserver() + { + Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); + MethodInfo mi = typeof(MonoBehaviour).GetMethod("Stub"); + } +#pragma warning restore +#endif + + #endregion + +#if UNITY_EDITOR + // Fires OnApplicationPause in DOTweenComponent even when Editor is paused (otherwise it's only fired at runtime) +#if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_2017_1 + static void PlaymodeStateChanged() + #else + static void PlaymodeStateChanged(UnityEditor.PlayModeStateChange state) +#endif + { + if (DOTween.instance == null) return; + DOTween.instance.OnApplicationPause(UnityEditor.EditorApplication.isPaused); + } +#endif + + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + // ███ INTERNAL CLASSES ████████████████████████████████████████████████████████████████████████████████████████████████ + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + + public static class Physics + { + // Called via DOTweenExternalCommand callback + public static void SetOrientationOnPath(PathOptions options, Tween t, Quaternion newRot, Transform trans) + { +#if true // PHYSICS_MARKER + if (options.isRigidbody) ((Rigidbody)t.target).rotation = newRot; + else trans.rotation = newRot; +#else + trans.rotation = newRot; +#endif + } + + // Returns FALSE if the DOTween's Physics2D Module is disabled, or if there's no Rigidbody2D attached + public static bool HasRigidbody2D(Component target) + { +#if true // PHYSICS2D_MARKER + return target.GetComponent() != null; +#else + return false; +#endif + } + + #region Called via Reflection + + + // Called via Reflection by DOTweenPathInspector + // Returns FALSE if the DOTween's Physics Module is disabled, or if there's no rigidbody attached +#if UNITY_2018_1_OR_NEWER + [UnityEngine.Scripting.Preserve] +#endif + public static bool HasRigidbody(Component target) + { +#if true // PHYSICS_MARKER + return target.GetComponent() != null; +#else + return false; +#endif + } + + // Called via Reflection by DOTweenPath +#if UNITY_2018_1_OR_NEWER + [UnityEngine.Scripting.Preserve] +#endif + public static TweenerCore CreateDOTweenPathTween( + MonoBehaviour target, bool tweenRigidbody, bool isLocal, Path path, float duration, PathMode pathMode + ){ + TweenerCore t = null; + bool rBodyFoundAndTweened = false; +#if true // PHYSICS_MARKER + if (tweenRigidbody) { + Rigidbody rBody = target.GetComponent(); + if (rBody != null) { + rBodyFoundAndTweened = true; + t = isLocal + ? rBody.DOLocalPath(path, duration, pathMode) + : rBody.DOPath(path, duration, pathMode); + } + } +#endif +#if true // PHYSICS2D_MARKER + if (!rBodyFoundAndTweened && tweenRigidbody) { + Rigidbody2D rBody2D = target.GetComponent(); + if (rBody2D != null) { + rBodyFoundAndTweened = true; + t = isLocal + ? rBody2D.DOLocalPath(path, duration, pathMode) + : rBody2D.DOPath(path, duration, pathMode); + } + } +#endif + if (!rBodyFoundAndTweened) { + t = isLocal + ? target.transform.DOLocalPath(path, duration, pathMode) + : target.transform.DOPath(path, duration, pathMode); + } + return t; + } + + #endregion + } + } +} diff --git a/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUtils.cs.meta b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUtils.cs.meta new file mode 100644 index 0000000..ab62186 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/Modules/DOTweenModuleUtils.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7bcaf917d9cf5b84090421a5a2abe42e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTween/readme.txt b/Assets/Plugins/Demigiant/DOTween/readme.txt new file mode 100644 index 0000000..37ff7ef --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/readme.txt @@ -0,0 +1,29 @@ +DOTween and DOTween Pro are copyright (c) 2014-2018 Daniele Giardini - Demigiant + +// IMPORTANT!!! ///////////////////////////////////////////// +// Upgrading DOTween from versions older than 1.2.000 /////// +// (or DOTween Pro older than 1.0.000) ////////////////////// +------------------------------------------------------------- +If you're upgrading your project from a version of DOTween older than 1.2.000 (or DOTween Pro older than 1.0.000) please follow these instructions carefully. +1) Import the new version in the same folder as the previous one, overwriting old files. A lot of errors will appear but don't worry +2) Close and reopen Unity (and your project). This is fundamental: skipping this step will cause a bloodbath +3) Open DOTween's Utility Panel (Tools > Demigiant > DOTween Utility Panel) if it doesn't open automatically, then press "Setup DOTween...": this will run the upgrade setup +4) From the Add/Remove Modules panel that opens, activate/deactivate Modules for Unity systems and for external assets (Pro version only) + +// GET STARTED ////////////////////////////////////////////// + +- After importing a new DOTween update, select DOTween's Utility Panel from the "Tools/Demigiant" menu (if it doesn't open automatically) and press the "Setup DOTween..." button to activate/deactivate Modules. You can also access a Preferences Tab from there to choose default settings for DOTween. +- In your code, add "using DG.Tweening" to each class where you want to use DOTween. +- You're ready to tween. Check out the links below for full documentation and license info. + + +// LINKS /////////////////////////////////////////////////////// + +DOTween website (documentation, examples, etc): http://dotween.demigiant.com +DOTween license: http://dotween.demigiant.com/license.php +DOTween repository (Google Code): https://code.google.com/p/dotween/ +Demigiant website (documentation, examples, etc): http://www.demigiant.com + +// NOTES ////////////////////////////////////////////////////// + +- DOTween's Utility Panel can be found under "Tools > Demigiant > DOTween Utility Panel" and also contains other useful options, plus a tab to set DOTween's preferences \ No newline at end of file diff --git a/Assets/Plugins/Demigiant/DOTween/readme.txt.meta b/Assets/Plugins/Demigiant/DOTween/readme.txt.meta new file mode 100644 index 0000000..3799165 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTween/readme.txt.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: fccfc62abf2eb0a4db614853430894fd +TextScriptImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples.meta b/Assets/Plugins/Demigiant/DOTweenPro Examples.meta new file mode 100644 index 0000000..12bbcd4 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples.meta @@ -0,0 +1,23 @@ +fileFormatVersion: 2 +guid: 0e606767f2f03204fb289d21d2696684 +labels: +- Tween +- Tweening +- Animation +- HOTween +- Paths +- VisualScripting +- VisualEditor +- iTween +- DFTween +- LeanTween +- Ease +- Easing +- Shake +- Punch +- 2DToolkit +- TextMeshPro +- Text +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Advanced.unity b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Advanced.unity new file mode 100644 index 0000000..7f3be75 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Advanced.unity @@ -0,0 +1,5311 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 1 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 512 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 6170f89af9323474fa8134461d605c9f, type: 2} +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &45542689 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 45542690} + - component: {fileID: 45542693} + - component: {fileID: 45542692} + - component: {fileID: 45542691} + m_Layer: 5 + m_Name: 'Button (ID: move)' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &45542690 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 45542689} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 191643491} + m_Father: {fileID: 1997177219} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -36} + m_SizeDelta: {x: 100, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &45542691 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 45542689} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 45542692} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DORestartById + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: move + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &45542692 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 45542689} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &45542693 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 45542689} + m_CullTransparentMesh: 1 +--- !u!1 &76224661 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 76224668} + - component: {fileID: 76224667} + - component: {fileID: 76224666} + - component: {fileID: 76224665} + - component: {fileID: 76224664} + - component: {fileID: 76224663} + m_Layer: 0 + m_Name: Cube C (w animation) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &76224663 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 76224661} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 1 + easeType: 6 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 0 + loops: 1 + id: rotate + isRelative: 0 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 0 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 76224668} + animationType: 3 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 180, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 1, b: 1, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!114 &76224664 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 76224661} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 1 + easeType: 6 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 0 + loops: 1 + id: move + isRelative: 1 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 0 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 76224668} + animationType: 1 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 1, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 1, b: 1, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!114 &76224665 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 76224661} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 1 + easeType: 6 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 0 + loops: 1 + id: toRed + isRelative: 0 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 0 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 76224666} + animationType: 6 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 0, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 0, b: 0, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!23 &76224666 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 76224661} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10302, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &76224667 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 76224661} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &76224668 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 76224661} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 2, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1760580329} + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &83016929 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 83016930} + - component: {fileID: 83016932} + - component: {fileID: 83016931} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &83016930 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 83016929} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1839080358} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &83016931 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 83016929} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ID: toRed' +--- !u!222 &83016932 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 83016929} + m_CullTransparentMesh: 1 +--- !u!1 &118309267 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 118309271} + - component: {fileID: 118309270} + - component: {fileID: 118309268} + - component: {fileID: 118309274} + - component: {fileID: 118309272} + - component: {fileID: 118309269} + m_Layer: 0 + m_Name: Cube A (w animation) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &118309268 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10302, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &118309269 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 1 + easeType: 6 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 0 + loops: 1 + id: rotate + isRelative: 0 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 0 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 118309271} + animationType: 3 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 180, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 1, b: 1, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!33 &118309270 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &118309271 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -2, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1192540964} + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &118309272 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 1 + easeType: 6 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 0 + loops: 1 + id: move + isRelative: 1 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 0 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 118309271} + animationType: 1 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 1, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 1, b: 1, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!114 &118309274 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 1 + easeType: 6 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 0 + loops: 1 + id: toRed + isRelative: 0 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 0 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 118309268} + animationType: 6 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 0, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 0, b: 0, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!1 &186391000 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 186391001} + m_Layer: 5 + m_Name: Buttons - PlayAllById + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &186391001 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 186391000} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 467194356} + - {fileID: 1492174307} + - {fileID: 323853745} + - {fileID: 1644045641} + m_Father: {fileID: 1260203941} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -34} + m_SizeDelta: {x: 0, y: -48.000015} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &191643490 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 191643491} + - component: {fileID: 191643493} + - component: {fileID: 191643492} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &191643491 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 191643490} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 45542690} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &191643492 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 191643490} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ID: move' +--- !u!222 &191643493 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 191643490} + m_CullTransparentMesh: 1 +--- !u!1 &215583160 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 215583161} + - component: {fileID: 215583163} + - component: {fileID: 215583162} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &215583161 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 215583160} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1619597526} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &215583162 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 215583160} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ID: move' +--- !u!222 &215583163 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 215583160} + m_CullTransparentMesh: 1 +--- !u!1 &286188793 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 286188794} + m_Layer: 5 + m_Name: Buttons - PlayById + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &286188794 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 286188793} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1158456312} + - {fileID: 1839080358} + - {fileID: 1095596651} + - {fileID: 566135255} + m_Father: {fileID: 1260203941} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 42} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &323853744 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 323853745} + - component: {fileID: 323853748} + - component: {fileID: 323853747} + - component: {fileID: 323853746} + m_Layer: 5 + m_Name: 'Button (ID: move)' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &323853745 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 323853744} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 645240663} + m_Father: {fileID: 186391001} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -36} + m_SizeDelta: {x: 100, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &323853746 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 323853744} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 323853747} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DOPlayAllById + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: move + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &323853747 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 323853744} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &323853748 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 323853744} + m_CullTransparentMesh: 1 +--- !u!1 &386943563 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 386943564} + - component: {fileID: 386943566} + - component: {fileID: 386943565} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &386943564 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 386943563} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 766204080} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &386943565 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 386943563} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ID: toRed' +--- !u!222 &386943566 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 386943563} + m_CullTransparentMesh: 1 +--- !u!1 &461995929 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 461995932} + - component: {fileID: 461995931} + - component: {fileID: 461995930} + m_Layer: 0 + m_Name: Name + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!102 &461995930 +TextMesh: + serializedVersion: 3 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 461995929} + m_Text: B + m_OffsetZ: 0 + m_CharacterSize: 20 + m_LineSpacing: 1 + m_Anchor: 4 + m_Alignment: 1 + m_TabSize: 4 + m_FontSize: 30 + m_FontStyle: 1 + m_RichText: 1 + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_Color: + serializedVersion: 2 + rgba: 4294967295 +--- !u!23 &461995931 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 461995929} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!4 &461995932 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 461995929} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.01, y: 0.01, z: 0.01} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1844382606} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &467194355 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 467194356} + - component: {fileID: 467194358} + - component: {fileID: 467194357} + m_Layer: 5 + m_Name: Description + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &467194356 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 467194355} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 186391001} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 550, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &467194357 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 467194355} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 1 + m_LineSpacing: 1 + m_Text: 'DOPlayAllById (Cube B as target) + + Will play the DOTweenAnimations + with the given ID, on ANY gameObject' +--- !u!222 &467194358 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 467194355} + m_CullTransparentMesh: 1 +--- !u!1 &502741617 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 502741618} + - component: {fileID: 502741621} + - component: {fileID: 502741620} + - component: {fileID: 502741619} + m_Layer: 5 + m_Name: 'Button (ID: rotate)' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &502741618 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 502741617} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 685170976} + m_Father: {fileID: 1997177219} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 100, y: -36} + m_SizeDelta: {x: 100, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &502741619 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 502741617} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 502741620} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DORestartById + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: rotate + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &502741620 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 502741617} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &502741621 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 502741617} + m_CullTransparentMesh: 1 +--- !u!1 &566135254 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 566135255} + - component: {fileID: 566135258} + - component: {fileID: 566135257} + - component: {fileID: 566135256} + m_Layer: 5 + m_Name: 'Button (ID: rotate)' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &566135255 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 566135254} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 740664255} + m_Father: {fileID: 286188794} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 100, y: -36} + m_SizeDelta: {x: 100, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &566135256 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 566135254} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 566135257} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DOPlayById + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: rotate + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &566135257 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 566135254} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &566135258 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 566135254} + m_CullTransparentMesh: 1 +--- !u!1 &608072282 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 608072283} + - component: {fileID: 608072285} + - component: {fileID: 608072284} + m_Layer: 5 + m_Name: Description + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &608072283 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 608072282} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1785989881} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 550, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &608072284 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 608072282} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 1 + m_LineSpacing: 1 + m_Text: 'DORestartAllById (Cube B as target) + + Will restart the DOTweenAnimations + with the given ID, on ANY gameObject' +--- !u!222 &608072285 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 608072282} + m_CullTransparentMesh: 1 +--- !u!1 &645240662 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 645240663} + - component: {fileID: 645240665} + - component: {fileID: 645240664} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &645240663 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 645240662} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 323853745} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &645240664 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 645240662} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ID: move' +--- !u!222 &645240665 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 645240662} + m_CullTransparentMesh: 1 +--- !u!1 &685170975 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 685170976} + - component: {fileID: 685170978} + - component: {fileID: 685170977} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &685170976 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 685170975} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 502741618} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &685170977 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 685170975} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ID: rotate' +--- !u!222 &685170978 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 685170975} + m_CullTransparentMesh: 1 +--- !u!1 &718047501 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 718047502} + - component: {fileID: 718047504} + - component: {fileID: 718047503} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &718047502 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 718047501} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1371900811} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &718047503 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 718047501} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ID: rotate' +--- !u!222 &718047504 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 718047501} + m_CullTransparentMesh: 1 +--- !u!1 &731424937 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 731424938} + - component: {fileID: 731424940} + - component: {fileID: 731424939} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &731424938 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 731424937} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 899835911} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &731424939 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 731424937} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ID: toRed' +--- !u!222 &731424940 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 731424937} + m_CullTransparentMesh: 1 +--- !u!1 &740664254 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 740664255} + - component: {fileID: 740664257} + - component: {fileID: 740664256} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &740664255 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 740664254} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 566135255} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &740664256 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 740664254} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ID: rotate' +--- !u!222 &740664257 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 740664254} + m_CullTransparentMesh: 1 +--- !u!1 &766204079 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 766204080} + - component: {fileID: 766204083} + - component: {fileID: 766204082} + - component: {fileID: 766204081} + m_Layer: 5 + m_Name: 'Button (ID: toRed)' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &766204080 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 766204079} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 386943564} + m_Father: {fileID: 1785989881} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -100, y: -36} + m_SizeDelta: {x: 100, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &766204081 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 766204079} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 766204082} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DORestartAllById + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: toRed + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &766204082 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 766204079} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &766204083 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 766204079} + m_CullTransparentMesh: 1 +--- !u!1 &848136767 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 848136772} + - component: {fileID: 848136771} + - component: {fileID: 848136769} + - component: {fileID: 848136768} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &848136768 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 848136767} + m_Enabled: 1 +--- !u!124 &848136769 +Behaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 848136767} + m_Enabled: 1 +--- !u!20 &848136771 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 848136767} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.16176468, g: 0.16176468, b: 0.16176468, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &848136772 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 848136767} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &899835910 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 899835911} + - component: {fileID: 899835914} + - component: {fileID: 899835913} + - component: {fileID: 899835912} + m_Layer: 5 + m_Name: 'Button (ID: toRed)' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &899835911 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 899835910} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 731424938} + m_Father: {fileID: 1997177219} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -100, y: -36} + m_SizeDelta: {x: 100, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &899835912 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 899835910} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 899835913} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DORestartById + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: toRed + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &899835913 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 899835910} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &899835914 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 899835910} + m_CullTransparentMesh: 1 +--- !u!1 &970591913 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 970591914} + - component: {fileID: 970591916} + - component: {fileID: 970591915} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &970591914 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970591913} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1356883401} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &970591915 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970591913} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: DOPlayNext +--- !u!222 &970591916 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970591913} + m_CullTransparentMesh: 1 +--- !u!1 &1025578319 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1025578320} + - component: {fileID: 1025578322} + - component: {fileID: 1025578321} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1025578320 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1025578319} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1095596651} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1025578321 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1025578319} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ID: move' +--- !u!222 &1025578322 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1025578319} + m_CullTransparentMesh: 1 +--- !u!1 &1053889438 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1053889442} + - component: {fileID: 1053889441} + - component: {fileID: 1053889440} + - component: {fileID: 1053889439} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1053889439 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1053889438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2d49b7c1bcd2e07499844da127be038d, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &1053889440 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1053889438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1053889441 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1053889438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1053889442 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1053889438} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1095596650 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1095596651} + - component: {fileID: 1095596654} + - component: {fileID: 1095596653} + - component: {fileID: 1095596652} + m_Layer: 5 + m_Name: 'Button (ID: move)' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1095596651 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1095596650} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1025578320} + m_Father: {fileID: 286188794} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -36} + m_SizeDelta: {x: 100, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1095596652 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1095596650} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1095596653} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DOPlayById + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: move + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1095596653 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1095596650} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1095596654 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1095596650} + m_CullTransparentMesh: 1 +--- !u!1 &1158456309 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1158456312} + - component: {fileID: 1158456311} + - component: {fileID: 1158456310} + m_Layer: 5 + m_Name: Description + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1158456310 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1158456309} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 1 + m_LineSpacing: 1 + m_Text: 'DOPlayById (Cube B as target) + + Will play only the DOTweenAnimations + with the given ID that are on Cube B' +--- !u!222 &1158456311 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1158456309} + m_CullTransparentMesh: 1 +--- !u!224 &1158456312 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1158456309} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 286188794} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 550, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1192540961 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1192540964} + - component: {fileID: 1192540963} + - component: {fileID: 1192540962} + m_Layer: 0 + m_Name: Name + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!102 &1192540962 +TextMesh: + serializedVersion: 3 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1192540961} + m_Text: A + m_OffsetZ: 0 + m_CharacterSize: 20 + m_LineSpacing: 1 + m_Anchor: 4 + m_Alignment: 1 + m_TabSize: 4 + m_FontSize: 30 + m_FontStyle: 1 + m_RichText: 1 + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_Color: + serializedVersion: 2 + rgba: 4294967295 +--- !u!23 &1192540963 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1192540961} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!4 &1192540964 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1192540961} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.01, y: 0.01, z: 0.01} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 118309271} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1242857378 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1242857380} + - component: {fileID: 1242857379} + m_Layer: 0 + m_Name: Directional light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1242857379 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1242857378} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1242857380 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1242857378} + m_LocalRotation: {x: 0.40821794, y: -0.23456973, z: 0.10938166, w: 0.8754261} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 0.99999994, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1260203940 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1260203941} + - component: {fileID: 1260203944} + - component: {fileID: 1260203943} + - component: {fileID: 1260203942} + m_Layer: 5 + m_Name: Canvas (w button controls) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1260203941 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1260203940} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1356883401} + - {fileID: 286188794} + - {fileID: 186391001} + - {fileID: 1997177219} + - {fileID: 1785989881} + m_Father: {fileID: 0} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &1260203942 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1260203940} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &1260203943 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1260203940} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!223 &1260203944 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1260203940} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 1 + m_Camera: {fileID: 848136771} + m_PlaneDistance: 100 + m_PixelPerfect: 1 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!1 &1305249262 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1305249263} + - component: {fileID: 1305249265} + - component: {fileID: 1305249264} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1305249263 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1305249262} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1492174307} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1305249264 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1305249262} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ID: toRed' +--- !u!222 &1305249265 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1305249262} + m_CullTransparentMesh: 1 +--- !u!1 &1356883400 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1356883401} + - component: {fileID: 1356883404} + - component: {fileID: 1356883403} + - component: {fileID: 1356883402} + m_Layer: 5 + m_Name: Button (DOPlayNext) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1356883401 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1356883400} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 970591914} + m_Father: {fileID: 1260203941} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 82} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1356883402 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1356883400} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1356883403} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 118309274} + m_TargetAssemblyTypeName: + m_MethodName: DOPlayNext + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DOPlayNext + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 76224665} + m_TargetAssemblyTypeName: + m_MethodName: DOPlayNext + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1356883403 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1356883400} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1356883404 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1356883400} + m_CullTransparentMesh: 1 +--- !u!1 &1371900810 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1371900811} + - component: {fileID: 1371900814} + - component: {fileID: 1371900813} + - component: {fileID: 1371900812} + m_Layer: 5 + m_Name: 'Button (ID: rotate)' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1371900811 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1371900810} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 718047502} + m_Father: {fileID: 1785989881} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 100, y: -36} + m_SizeDelta: {x: 100, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1371900812 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1371900810} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1371900813} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DORestartAllById + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: rotate + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1371900813 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1371900810} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1371900814 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1371900810} + m_CullTransparentMesh: 1 +--- !u!1 &1477055226 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1477055227} + - component: {fileID: 1477055229} + - component: {fileID: 1477055228} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1477055227 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1477055226} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1644045641} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1477055228 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1477055226} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'ID: rotate' +--- !u!222 &1477055229 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1477055226} + m_CullTransparentMesh: 1 +--- !u!1 &1492174306 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1492174307} + - component: {fileID: 1492174310} + - component: {fileID: 1492174309} + - component: {fileID: 1492174308} + m_Layer: 5 + m_Name: 'Button (ID: toRed)' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1492174307 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1492174306} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1305249263} + m_Father: {fileID: 186391001} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -100, y: -36} + m_SizeDelta: {x: 100, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1492174308 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1492174306} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1492174309} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DOPlayAllById + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: toRed + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1492174309 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1492174306} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1492174310 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1492174306} + m_CullTransparentMesh: 1 +--- !u!1 &1619597525 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1619597526} + - component: {fileID: 1619597529} + - component: {fileID: 1619597528} + - component: {fileID: 1619597527} + m_Layer: 5 + m_Name: 'Button (ID: move)' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1619597526 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619597525} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 215583161} + m_Father: {fileID: 1785989881} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -36} + m_SizeDelta: {x: 100, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1619597527 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619597525} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1619597528} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DORestartAllById + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: move + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1619597528 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619597525} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1619597529 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619597525} + m_CullTransparentMesh: 1 +--- !u!1 &1644045637 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1644045641} + - component: {fileID: 1644045640} + - component: {fileID: 1644045639} + - component: {fileID: 1644045638} + m_Layer: 5 + m_Name: 'Button (ID: rotate)' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1644045638 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1644045637} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1644045639} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DOPlayAllById + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: rotate + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1644045639 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1644045637} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1644045640 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1644045637} + m_CullTransparentMesh: 1 +--- !u!224 &1644045641 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1644045637} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1477055227} + m_Father: {fileID: 186391001} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 100, y: -36} + m_SizeDelta: {x: 100, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1760580328 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1760580329} + - component: {fileID: 1760580331} + - component: {fileID: 1760580330} + m_Layer: 0 + m_Name: Name + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1760580329 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1760580328} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.01, y: 0.01, z: 0.01} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 76224668} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!102 &1760580330 +TextMesh: + serializedVersion: 3 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1760580328} + m_Text: C + m_OffsetZ: 0 + m_CharacterSize: 20 + m_LineSpacing: 1 + m_Anchor: 4 + m_Alignment: 1 + m_TabSize: 4 + m_FontSize: 30 + m_FontStyle: 1 + m_RichText: 1 + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_Color: + serializedVersion: 2 + rgba: 4294967295 +--- !u!23 &1760580331 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1760580328} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &1785989880 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1785989881} + m_Layer: 5 + m_Name: Buttons - RestartAllById + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1785989881 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1785989880} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 608072283} + - {fileID: 766204080} + - {fileID: 1619597526} + - {fileID: 1371900811} + m_Father: {fileID: 1260203941} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -184} + m_SizeDelta: {x: 0, y: -48} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1812319720 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1812319721} + - component: {fileID: 1812319723} + - component: {fileID: 1812319722} + m_Layer: 5 + m_Name: Description + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1812319721 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1812319720} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1997177219} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 550, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1812319722 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1812319720} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 1 + m_LineSpacing: 1 + m_Text: 'DORestartById (Cube B as target) + + Will restart only the DOTweenAnimations + with the given ID that are on Cube B' +--- !u!222 &1812319723 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1812319720} + m_CullTransparentMesh: 1 +--- !u!1 &1839080357 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1839080358} + - component: {fileID: 1839080361} + - component: {fileID: 1839080360} + - component: {fileID: 1839080359} + m_Layer: 5 + m_Name: 'Button (ID: toRed)' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1839080358 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1839080357} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 83016930} + m_Father: {fileID: 286188794} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -100, y: -36} + m_SizeDelta: {x: 100, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1839080359 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1839080357} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1839080360} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1844382610} + m_TargetAssemblyTypeName: + m_MethodName: DOPlayById + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: toRed + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1839080360 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1839080357} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1839080361 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1839080357} + m_CullTransparentMesh: 1 +--- !u!1 &1844382605 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1844382606} + - component: {fileID: 1844382612} + - component: {fileID: 1844382611} + - component: {fileID: 1844382610} + - component: {fileID: 1844382609} + - component: {fileID: 1844382608} + m_Layer: 0 + m_Name: Cube B (w animation) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1844382606 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1844382605} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 461995932} + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1844382608 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1844382605} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 1 + easeType: 6 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 0 + loops: 1 + id: rotate + isRelative: 0 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 0 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 1844382606} + animationType: 3 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 180, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 1, b: 1, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!114 &1844382609 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1844382605} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 1 + easeType: 6 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 0 + loops: 1 + id: move + isRelative: 1 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 0 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 1844382606} + animationType: 1 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 1, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 1, b: 1, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!114 &1844382610 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1844382605} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 1 + easeType: 6 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 0 + loops: 1 + id: toRed + isRelative: 0 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 0 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 1844382611} + animationType: 6 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 0, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 0, b: 0, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!23 &1844382611 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1844382605} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10302, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1844382612 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1844382605} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1997177218 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1997177219} + m_Layer: 5 + m_Name: Buttons - RestartById + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1997177219 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1997177218} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1812319721} + - {fileID: 899835911} + - {fileID: 45542690} + - {fileID: 502741618} + m_Father: {fileID: 1260203941} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -109.99999} + m_SizeDelta: {x: 0, y: -200} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Advanced.unity.meta b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Advanced.unity.meta new file mode 100644 index 0000000..e46232a --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Advanced.unity.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: a5f7a56d339da84449899ecf95fbe33d +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_AdvancedSettings.lighting b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_AdvancedSettings.lighting new file mode 100644 index 0000000..3673603 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_AdvancedSettings.lighting @@ -0,0 +1,64 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!850595691 &4890085278179872738 +LightingSettings: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: DOTweenAnimation_AdvancedSettings + serializedVersion: 4 + m_GIWorkflowMode: 1 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_RealtimeEnvironmentLighting: 1 + m_BounceScale: 1 + m_AlbedoBoost: 1 + m_IndirectOutputScale: 1 + m_UsingShadowmask: 0 + m_BakeBackend: 0 + m_LightmapMaxSize: 1024 + m_BakeResolution: 50 + m_Padding: 2 + m_LightmapCompression: 0 + m_AO: 1 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAO: 0 + m_MixedBakeMode: 1 + m_LightmapsBakeMode: 1 + m_FilterMode: 1 + m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0} + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_RealtimeResolution: 1 + m_ForceWhiteAlbedo: 0 + m_ForceUpdates: 0 + m_FinalGather: 0 + m_FinalGatherRayCount: 256 + m_FinalGatherFiltering: 1 + m_PVRCulling: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVREnvironmentSampleCount: 512 + m_PVREnvironmentReferencePointCount: 2048 + m_LightProbeSampleCountMultiplier: 4 + m_PVRBounces: 2 + m_PVRMinBounces: 2 + m_PVREnvironmentMIS: 0 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_PVRTiledBaking: 0 diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_AdvancedSettings.lighting.meta b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_AdvancedSettings.lighting.meta new file mode 100644 index 0000000..a144290 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_AdvancedSettings.lighting.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6170f89af9323474fa8134461d605c9f +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 4890085278179872738 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Basics.unity b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Basics.unity new file mode 100644 index 0000000..ddf746f --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Basics.unity @@ -0,0 +1,1801 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 1 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 512 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 5df26e7fb5bd9154c88f9274aa38f6a9, type: 2} +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &118309267 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 118309271} + - component: {fileID: 118309270} + - component: {fileID: 118309268} + - component: {fileID: 118309273} + - component: {fileID: 118309272} + m_Layer: 0 + m_Name: Cube (w animation) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &118309268 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10302, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &118309270 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &118309271 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -4, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &118309272 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 2 + easeType: 6 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 1 + loops: -1 + id: + isRelative: 0 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 1 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 118309271} + animationType: 3 + targetType: 11 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 180, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 1, b: 1, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!114 &118309273 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 2 + easeType: 6 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 1 + loops: -1 + id: + isRelative: 1 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 1 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 118309271} + animationType: 1 + targetType: 11 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 4, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 1, b: 1, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!1 &848136767 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 848136772} + - component: {fileID: 848136771} + - component: {fileID: 848136769} + - component: {fileID: 848136768} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &848136768 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 848136767} + m_Enabled: 1 +--- !u!124 &848136769 +Behaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 848136767} + m_Enabled: 1 +--- !u!20 &848136771 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 848136767} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.16176468, g: 0.16176468, b: 0.16176468, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &848136772 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 848136767} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &970591913 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 970591914} + - component: {fileID: 970591916} + - component: {fileID: 970591915} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &970591914 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970591913} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1356883401} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &970591915 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970591913} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: PLAY +--- !u!222 &970591916 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970591913} + m_CullTransparentMesh: 1 +--- !u!1 &990238542 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 990238543} + - component: {fileID: 990238545} + - component: {fileID: 990238544} + - component: {fileID: 990238546} + m_Layer: 5 + m_Name: Text (w text animation) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &990238543 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 990238542} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1260203941} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 230} + m_SizeDelta: {x: 400, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &990238544 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 990238542} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 16 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 1 + m_LineSpacing: 1 + m_Text: 'Original text
that will be
+ tweened
+ +' +--- !u!222 &990238545 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 990238542} + m_CullTransparentMesh: 1 +--- !u!114 &990238546 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 990238542} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 3 + easeType: 1 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 1 + loops: 0 + id: + isRelative: 0 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 1 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 990238544} + animationType: 8 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 0, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 1, b: 1, a: 1} + endValueString: This is the new tweened
text + (scandalous)! + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 1 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!1 &1053889438 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1053889442} + - component: {fileID: 1053889441} + - component: {fileID: 1053889440} + - component: {fileID: 1053889439} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1053889439 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1053889438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2d49b7c1bcd2e07499844da127be038d, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &1053889440 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1053889438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1053889441 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1053889438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1053889442 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1053889438} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1127963255 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1127963256} + - component: {fileID: 1127963258} + - component: {fileID: 1127963257} + m_Layer: 5 + m_Name: Info + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1127963256 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1127963255} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1260203941} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -186} + m_SizeDelta: {x: 300, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1127963257 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1127963255} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 1 + m_LineSpacing: 1 + m_Text: The PLAY button starts the logo fade out. When the fade out is complete, + it will start all the other animations (thanks to the Events created in the logo + DOTweenAnimation Component) +--- !u!222 &1127963258 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1127963255} + m_CullTransparentMesh: 1 +--- !u!1 &1242857378 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1242857380} + - component: {fileID: 1242857379} + m_Layer: 0 + m_Name: Directional light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1242857379 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1242857378} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1242857380 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1242857378} + m_LocalRotation: {x: 0.40821794, y: -0.23456973, z: 0.10938166, w: 0.8754261} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 0.99999994, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1260203940 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1260203941} + - component: {fileID: 1260203944} + - component: {fileID: 1260203943} + - component: {fileID: 1260203942} + m_Layer: 5 + m_Name: Canvas (contains animated objects) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1260203941 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1260203940} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1636198022} + - {fileID: 990238543} + - {fileID: 1323952358} + - {fileID: 1356883401} + - {fileID: 1127963256} + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &1260203942 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1260203940} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &1260203943 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1260203940} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!223 &1260203944 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1260203940} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 1 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!1 &1323952357 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1323952358} + - component: {fileID: 1323952362} + - component: {fileID: 1323952361} + - component: {fileID: 1323952360} + - component: {fileID: 1323952359} + m_Layer: 5 + m_Name: Text (w color animation) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1323952358 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1323952357} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1260203941} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 254} + m_SizeDelta: {x: 400, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1323952359 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1323952357} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 3 + easeType: 1 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 1 + loops: -1 + id: + isRelative: 0 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 1 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 1323952361} + animationType: 6 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 0, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 0, b: 0.8068962, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!114 &1323952360 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1323952357} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 3 + easeType: 1 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 1 + loops: 0 + id: + isRelative: 1 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 1 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 1323952361} + animationType: 8 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 0, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 1, b: 1, a: 1} + endValueString: ' See? What did I tell you?' + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 1 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!114 &1323952361 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1323952357} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 16 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 1 + m_LineSpacing: 1 + m_Text: This text will change color... +--- !u!222 &1323952362 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1323952357} + m_CullTransparentMesh: 1 +--- !u!1 &1356883400 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1356883401} + - component: {fileID: 1356883404} + - component: {fileID: 1356883403} + - component: {fileID: 1356883402} + m_Layer: 5 + m_Name: Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1356883401 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1356883400} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 970591914} + m_Father: {fileID: 1260203941} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -147} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1356883402 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1356883400} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1356883403} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1636198019} + m_TargetAssemblyTypeName: + m_MethodName: DOPlay + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1356883403 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1356883400} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1356883404 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1356883400} + m_CullTransparentMesh: 1 +--- !u!1 &1636198018 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1636198022} + - component: {fileID: 1636198021} + - component: {fileID: 1636198020} + - component: {fileID: 1636198019} + m_Layer: 5 + m_Name: Logo (starts animations w events) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1636198019 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1636198018} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d0390bd8b8ffd640b34fe25065ff1df, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 1 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 990238546} + m_TargetAssemblyTypeName: + m_MethodName: DOPlay + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 118309273} + m_TargetAssemblyTypeName: + m_MethodName: DOPlay + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1323952360} + m_TargetAssemblyTypeName: + m_MethodName: DOPlay + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + targetIsSelf: 1 + targetGO: {fileID: 0} + tweenTargetIsTargetGO: 1 + delay: 0 + duration: 1 + easeType: 5 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loopType: 0 + loops: 1 + id: + isRelative: 0 + isFrom: 0 + isIndependentUpdate: 0 + autoKill: 1 + autoGenerate: 1 + isActive: 1 + isValid: 1 + target: {fileID: 1636198020} + animationType: 7 + targetType: 0 + forcedTargetType: 0 + autoPlay: 0 + useTargetAsV3: 0 + endValueFloat: 0 + endValueV3: {x: 0, y: 0, z: 0} + endValueV2: {x: 0, y: 0} + endValueColor: {r: 1, g: 1, b: 1, a: 1} + endValueString: + endValueRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + endValueTransform: {fileID: 0} + optionalBool0: 0 + optionalBool1: 0 + optionalFloat0: 0 + optionalInt0: 0 + optionalRotationMode: 0 + optionalScrambleMode: 0 + optionalString: +--- !u!114 &1636198020 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1636198018} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 44a054df1702e39458b7072b08d0f212, type: 3} + m_Type: 0 + m_PreserveAspect: 1 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1636198021 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1636198018} + m_CullTransparentMesh: 1 +--- !u!224 &1636198022 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1636198018} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1260203941} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 45} + m_SizeDelta: {x: 241, y: 320} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Basics.unity.meta b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Basics.unity.meta new file mode 100644 index 0000000..226d596 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_Basics.unity.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 6a2ad353325ffe64983c28d69a8738f5 +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_BasicsSettings.lighting b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_BasicsSettings.lighting new file mode 100644 index 0000000..2457909 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_BasicsSettings.lighting @@ -0,0 +1,64 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!850595691 &4890085278179872738 +LightingSettings: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: DOTweenAnimation_BasicsSettings + serializedVersion: 4 + m_GIWorkflowMode: 1 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_RealtimeEnvironmentLighting: 1 + m_BounceScale: 1 + m_AlbedoBoost: 1 + m_IndirectOutputScale: 1 + m_UsingShadowmask: 0 + m_BakeBackend: 0 + m_LightmapMaxSize: 1024 + m_BakeResolution: 50 + m_Padding: 2 + m_LightmapCompression: 0 + m_AO: 1 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAO: 0 + m_MixedBakeMode: 1 + m_LightmapsBakeMode: 1 + m_FilterMode: 1 + m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0} + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_RealtimeResolution: 1 + m_ForceWhiteAlbedo: 0 + m_ForceUpdates: 0 + m_FinalGather: 0 + m_FinalGatherRayCount: 256 + m_FinalGatherFiltering: 1 + m_PVRCulling: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVREnvironmentSampleCount: 512 + m_PVREnvironmentReferencePointCount: 2048 + m_LightProbeSampleCountMultiplier: 4 + m_PVRBounces: 2 + m_PVRMinBounces: 2 + m_PVREnvironmentMIS: 0 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_PVRTiledBaking: 0 diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_BasicsSettings.lighting.meta b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_BasicsSettings.lighting.meta new file mode 100644 index 0000000..f340f1f --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenAnimation_BasicsSettings.lighting.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5df26e7fb5bd9154c88f9274aa38f6a9 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 4890085278179872738 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPath.unity b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPath.unity new file mode 100644 index 0000000..f4f9c84 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPath.unity @@ -0,0 +1,1594 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 1 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 512 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 26ec36f0e3bda4c4b877368e751c1ef0, type: 2} +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &118309267 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 118309271} + - component: {fileID: 118309270} + - component: {fileID: 118309268} + - component: {fileID: 118309269} + m_Layer: 0 + m_Name: Cube A (w path) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &118309268 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10302, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &118309269 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -333801856, guid: aa0b1eebb5db27a419fa4564bbe5c9c5, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 1 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1087750405} + m_TargetAssemblyTypeName: + m_MethodName: DOPlay + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + delay: 0 + duration: 3 + easeType: 6 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loops: 1 + id: + loopType: 0 + orientType: 0 + lookAtTransform: {fileID: 0} + lookAtPosition: {x: 0, y: 0, z: 0} + lookAhead: 0.01 + autoPlay: 0 + autoKill: 1 + relative: 0 + isLocal: 0 + isClosedPath: 1 + pathResolution: 10 + pathMode: 1 + lockRotation: 0 + assignForwardAndUp: 0 + forwardDirection: {x: 0, y: 0, z: 1} + upDirection: {x: 0, y: 1, z: 0} + tweenRigidbody: 0 + wps: + - {x: 3.8321667, y: 6.9544535, z: 0} + - {x: -6.0542445, y: 9.465288, z: 0} + - {x: -12.069765, y: 6.1698112, z: 0} + - {x: -12.069786, y: -0.2641964, z: 0} + - {x: -6.368099, y: -4.187376, z: 0} + fullWps: [] + path: + wpLengths: + - 0 + - 9.359136 + - 10.405018 + - 7.102792 + - 6.6672983 + - 7.1915474 + - 11.289525 + wps: + - {x: 4.45, y: -1.83, z: 0} + - {x: 3.8321667, y: 6.9544535, z: 0} + - {x: -6.0542445, y: 9.465288, z: 0} + - {x: -12.069765, y: 6.1698112, z: 0} + - {x: -12.069786, y: -0.2641964, z: 0} + - {x: -6.368099, y: -4.187376, z: 0} + - {x: 4.45, y: -1.83, z: 0} + type: 1 + subdivisionsXSegment: 10 + subdivisions: 70 + controlPoints: + - a: {x: -6.368099, y: -4.187376, z: 0} + b: {x: 0, y: 0, z: 0} + - a: {x: 3.8321667, y: 6.9544535, z: 0} + b: {x: 0, y: 0, z: 0} + length: 52.02238 + isFinalized: 1 + timesTable: + - 0.014285714 + - 0.028571429 + - 0.042857144 + - 0.057142857 + - 0.071428575 + - 0.08571429 + - 0.1 + - 0.114285715 + - 0.12857144 + - 0.14285715 + - 0.15714286 + - 0.17142858 + - 0.18571429 + - 0.2 + - 0.21428572 + - 0.22857143 + - 0.24285714 + - 0.25714287 + - 0.27142859 + - 0.2857143 + - 0.3 + - 0.31428573 + - 0.32857144 + - 0.34285715 + - 0.35714287 + - 0.37142858 + - 0.3857143 + - 0.4 + - 0.41428572 + - 0.42857143 + - 0.44285715 + - 0.45714286 + - 0.47142857 + - 0.4857143 + - 0.5 + - 0.51428574 + - 0.5285714 + - 0.54285717 + - 0.55714285 + - 0.5714286 + - 0.5857143 + - 0.6 + - 0.6142857 + - 0.62857145 + - 0.64285713 + - 0.6571429 + - 0.67142856 + - 0.6857143 + - 0.7 + - 0.71428573 + - 0.7285714 + - 0.74285716 + - 0.75714284 + - 0.7714286 + - 0.78571427 + - 0.8 + - 0.8142857 + - 0.82857144 + - 0.8428571 + - 0.85714287 + - 0.87142855 + - 0.8857143 + - 0.9 + - 0.9142857 + - 0.92857146 + - 0.94285715 + - 0.9571429 + - 0.9714286 + - 0.9857143 + - 1 + lengthsTable: + - 0.66792893 + - 1.3899281 + - 2.16896 + - 2.9980419 + - 3.8644814 + - 4.752426 + - 5.6444182 + - 6.5224686 + - 7.368998 + - 8.167948 + - 8.906464 + - 9.58573 + - 10.313842 + - 11.125577 + - 12.012393 + - 12.959278 + - 13.947668 + - 14.956963 + - 15.965341 + - 16.950247 + - 17.888689 + - 18.75748 + - 19.533484 + - 20.220243 + - 20.891918 + - 21.555 + - 22.208927 + - 22.852415 + - 23.483595 + - 24.100157 + - 24.699495 + - 25.278862 + - 25.83552 + - 26.366951 + - 26.8711 + - 27.376375 + - 27.912098 + - 28.475262 + - 29.060778 + - 29.66227 + - 30.272577 + - 30.884148 + - 31.48931 + - 32.080574 + - 32.650936 + - 33.194313 + - 33.709743 + - 34.240025 + - 34.79521 + - 35.371506 + - 35.965523 + - 36.574467 + - 37.19625 + - 37.829685 + - 38.474625 + - 39.132145 + - 39.804657 + - 40.496033 + - 41.23852 + - 42.10978 + - 43.088493 + - 44.145332 + - 45.25077 + - 46.375446 + - 47.49042 + - 48.567577 + - 49.58027 + - 50.50447 + - 51.32128 + - 52.02238 + inspectorMode: 0 + pathType: 1 + handlesType: 0 + livePreview: 1 + handlesDrawMode: 0 + perspectiveHandleSize: 0.5 + showIndexes: 1 + showWpLength: 0 + pathColor: {r: 1, g: 1, b: 1, a: 0.5} + lastSrcPosition: {x: 4.45, y: -1.83, z: 0} + lastSrcRotation: {x: 0, y: 0, z: 0, w: 0} + wpsDropdown: 0 + dropToFloorOffset: 0 +--- !u!33 &118309270 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &118309271 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118309267} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 4.45, y: -1.83, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &848136767 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 848136772} + - component: {fileID: 848136771} + - component: {fileID: 848136769} + - component: {fileID: 848136768} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &848136768 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 848136767} + m_Enabled: 1 +--- !u!124 &848136769 +Behaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 848136767} + m_Enabled: 1 +--- !u!20 &848136771 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 848136767} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.16176468, g: 0.16176468, b: 0.16176468, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &848136772 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 848136767} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -30} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &970591913 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 970591914} + - component: {fileID: 970591916} + - component: {fileID: 970591915} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &970591914 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970591913} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1356883401} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &970591915 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970591913} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.196, g: 0.196, b: 0.196, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: PLAY +--- !u!222 &970591916 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 970591913} + m_CullTransparentMesh: 1 +--- !u!1 &1053889438 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1053889442} + - component: {fileID: 1053889441} + - component: {fileID: 1053889440} + - component: {fileID: 1053889439} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1053889439 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1053889438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2d49b7c1bcd2e07499844da127be038d, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ForceModuleActive: 0 +--- !u!114 &1053889440 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1053889438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1053889441 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1053889438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1053889442 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1053889438} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1087750404 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1087750408} + - component: {fileID: 1087750407} + - component: {fileID: 1087750406} + - component: {fileID: 1087750405} + m_Layer: 0 + m_Name: Cube B (animated after Cube A) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1087750405 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1087750404} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -333801856, guid: aa0b1eebb5db27a419fa4564bbe5c9c5, type: 3} + m_Name: + m_EditorClassIdentifier: + updateType: 0 + isSpeedBased: 0 + hasOnStart: 0 + hasOnPlay: 0 + hasOnUpdate: 0 + hasOnStepComplete: 0 + hasOnComplete: 0 + hasOnTweenCreated: 0 + hasOnRewind: 0 + onStart: + m_PersistentCalls: + m_Calls: [] + onPlay: + m_PersistentCalls: + m_Calls: [] + onUpdate: + m_PersistentCalls: + m_Calls: [] + onStepComplete: + m_PersistentCalls: + m_Calls: [] + onComplete: + m_PersistentCalls: + m_Calls: [] + onTweenCreated: + m_PersistentCalls: + m_Calls: [] + onRewind: + m_PersistentCalls: + m_Calls: [] + delay: 0 + duration: 3 + easeType: 1 + easeCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + loops: -1 + id: + loopType: 0 + orientType: 0 + lookAtTransform: {fileID: 0} + lookAtPosition: {x: 0, y: 0, z: 0} + lookAhead: 0.01 + autoPlay: 0 + autoKill: 1 + relative: 1 + isLocal: 0 + isClosedPath: 1 + pathResolution: 10 + pathMode: 1 + lockRotation: 0 + assignForwardAndUp: 0 + forwardDirection: {x: 0, y: 0, z: 1} + upDirection: {x: 0, y: 1, z: 0} + tweenRigidbody: 0 + wps: + - {x: 13.417454, y: 2.978077, z: 0} + - {x: 9.493597, y: 8.510473, z: 0} + - {x: -3.3649445, y: 5.5603714, z: 0} + - {x: -13.000723, y: 12.019701, z: 0} + - {x: -19.387083, y: 4.5597005, z: 0} + - {x: -15.279156, y: -3.646319, z: 0} + - {x: -4.1231623, y: -1.0233588, z: 0} + - {x: 3.7979867, y: -4.5040193, z: 0} + fullWps: [] + path: + wpLengths: + - 0 + - 5.8644567 + - 7.2802324 + - 13.301847 + - 11.81175 + - 10.301735 + - 9.680841 + - 11.593836 + - 8.754475 + - 7.309784 + wps: + - {x: 10.45, y: -1.83, z: 0} + - {x: 13.417454, y: 2.978077, z: 0} + - {x: 9.493597, y: 8.510473, z: 0} + - {x: -3.3649445, y: 5.5603714, z: 0} + - {x: -13.000723, y: 12.019701, z: 0} + - {x: -19.387083, y: 4.5597005, z: 0} + - {x: -15.279156, y: -3.646319, z: 0} + - {x: -4.1231623, y: -1.0233588, z: 0} + - {x: 3.7979867, y: -4.5040193, z: 0} + - {x: 10.45, y: -1.83, z: 0} + type: 1 + subdivisionsXSegment: 10 + subdivisions: 100 + controlPoints: + - a: {x: 3.7979867, y: -4.5040193, z: 0} + b: {x: 0, y: 0, z: 0} + - a: {x: 13.417454, y: 2.978077, z: 0} + b: {x: 0, y: 0, z: 0} + length: 85.91056 + isFinalized: 1 + timesTable: + - 0.01 + - 0.02 + - 0.03 + - 0.04 + - 0.049999997 + - 0.06 + - 0.07 + - 0.08 + - 0.089999996 + - 0.099999994 + - 0.11 + - 0.12 + - 0.13 + - 0.14 + - 0.14999999 + - 0.16 + - 0.17 + - 0.17999999 + - 0.19 + - 0.19999999 + - 0.21 + - 0.22 + - 0.22999999 + - 0.24 + - 0.25 + - 0.26 + - 0.26999998 + - 0.28 + - 0.29 + - 0.29999998 + - 0.31 + - 0.32 + - 0.32999998 + - 0.34 + - 0.35 + - 0.35999998 + - 0.37 + - 0.38 + - 0.39 + - 0.39999998 + - 0.41 + - 0.42 + - 0.42999998 + - 0.44 + - 0.45 + - 0.45999998 + - 0.47 + - 0.48 + - 0.48999998 + - 0.5 + - 0.51 + - 0.52 + - 0.53 + - 0.53999996 + - 0.55 + - 0.56 + - 0.57 + - 0.58 + - 0.59 + - 0.59999996 + - 0.61 + - 0.62 + - 0.63 + - 0.64 + - 0.65 + - 0.65999997 + - 0.66999996 + - 0.68 + - 0.69 + - 0.7 + - 0.71 + - 0.71999997 + - 0.72999996 + - 0.74 + - 0.75 + - 0.76 + - 0.77 + - 0.78 + - 0.78999996 + - 0.79999995 + - 0.81 + - 0.82 + - 0.83 + - 0.84 + - 0.84999996 + - 0.85999995 + - 0.87 + - 0.88 + - 0.89 + - 0.9 + - 0.90999997 + - 0.91999996 + - 0.93 + - 0.94 + - 0.95 + - 0.96 + - 0.96999997 + - 0.97999996 + - 0.98999995 + - 1 + lengthsTable: + - 0.5545968 + - 1.1175883 + - 1.6830537 + - 2.245447 + - 2.7997518 + - 3.3416884 + - 3.867998 + - 4.376838 + - 4.868309 + - 5.3450947 + - 5.813135 + - 6.311367 + - 6.877433 + - 7.495066 + - 8.148528 + - 8.823632 + - 9.508459 + - 10.194385 + - 10.877503 + - 11.560418 + - 12.254057 + - 12.978595 + - 13.783311 + - 14.741959 + - 15.848983 + - 17.077965 + - 18.394625 + - 19.761522 + - 21.140495 + - 22.494476 + - 23.78951 + - 24.997858 + - 26.103634 + - 27.136875 + - 28.20907 + - 29.343433 + - 30.531721 + - 31.750658 + - 32.96895 + - 34.151752 + - 35.26419 + - 36.275455 + - 37.165974 + - 37.94238 + - 38.672184 + - 39.461693 + - 40.331173 + - 41.275455 + - 42.278408 + - 43.318016 + - 44.36911 + - 45.404976 + - 46.39841 + - 47.322807 + - 48.15364 + - 48.891544 + - 49.678425 + - 50.534695 + - 51.444313 + - 52.38865 + - 53.348053 + - 54.30292 + - 55.23473 + - 56.12729 + - 56.968613 + - 57.754013 + - 58.495777 + - 59.294735 + - 60.205452 + - 61.226448 + - 62.33766 + - 63.510315 + - 64.71169 + - 65.907745 + - 67.06497 + - 68.15262 + - 69.14602 + - 70.03488 + - 70.87562 + - 71.70776 + - 72.54151 + - 73.377945 + - 74.21172 + - 75.033615 + - 75.83277 + - 76.59903 + - 77.325615 + - 78.01288 + - 78.67338 + - 79.33375 + - 80.00281 + - 80.68108 + - 81.366684 + - 82.05582 + - 82.74328 + - 83.422775 + - 84.087204 + - 84.728836 + - 85.33948 + - 85.91056 + inspectorMode: 0 + pathType: 1 + handlesType: 0 + livePreview: 1 + handlesDrawMode: 0 + perspectiveHandleSize: 0.5 + showIndexes: 1 + showWpLength: 0 + pathColor: {r: 1, g: 1, b: 1, a: 0.5} + lastSrcPosition: {x: 10.45, y: -1.83, z: 0} + lastSrcRotation: {x: 0, y: 0, z: 0, w: 0} + wpsDropdown: 0 + dropToFloorOffset: 0 +--- !u!23 &1087750406 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1087750404} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10302, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1087750407 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1087750404} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1087750408 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1087750404} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 10.45, y: -1.83, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1127963255 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1127963256} + - component: {fileID: 1127963258} + - component: {fileID: 1127963257} + m_Layer: 5 + m_Name: Info + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1127963256 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1127963255} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1260203941} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -186} + m_SizeDelta: {x: 300, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1127963257 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1127963255} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 1 + m_LineSpacing: 1 + m_Text: The PLAY button starts Cube A path animation. When that is complete, it + will start the other cube's animation (thanks to the Event created in Cube A's + DOTweenPath Component) +--- !u!222 &1127963258 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1127963255} + m_CullTransparentMesh: 1 +--- !u!1 &1242857378 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1242857380} + - component: {fileID: 1242857379} + m_Layer: 0 + m_Name: Directional light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1242857379 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1242857378} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1242857380 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1242857378} + m_LocalRotation: {x: 0.40821794, y: -0.23456973, z: 0.10938166, w: 0.8754261} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 0.99999994, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1260203940 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1260203941} + - component: {fileID: 1260203944} + - component: {fileID: 1260203943} + - component: {fileID: 1260203942} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1260203941 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1260203940} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1356883401} + - {fileID: 1127963256} + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &1260203942 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1260203940} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &1260203943 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1260203940} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!223 &1260203944 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1260203940} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 1 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!1 &1356883400 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1356883401} + - component: {fileID: 1356883404} + - component: {fileID: 1356883403} + - component: {fileID: 1356883402} + m_Layer: 5 + m_Name: Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1356883401 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1356883400} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 970591914} + m_Father: {fileID: 1260203941} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -147} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1356883402 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1356883400} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Highlighted + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1356883403} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 118309269} + m_TargetAssemblyTypeName: + m_MethodName: DOPlay + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1356883403 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1356883400} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1356883404 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1356883400} + m_CullTransparentMesh: 1 diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPath.unity.meta b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPath.unity.meta new file mode 100644 index 0000000..9051851 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPath.unity.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: a351b59ca54a0bc4083c35844da13a61 +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPathSettings.lighting b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPathSettings.lighting new file mode 100644 index 0000000..f278f45 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPathSettings.lighting @@ -0,0 +1,64 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!850595691 &4890085278179872738 +LightingSettings: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: DOTweenPathSettings + serializedVersion: 4 + m_GIWorkflowMode: 1 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_RealtimeEnvironmentLighting: 1 + m_BounceScale: 1 + m_AlbedoBoost: 1 + m_IndirectOutputScale: 1 + m_UsingShadowmask: 0 + m_BakeBackend: 0 + m_LightmapMaxSize: 1024 + m_BakeResolution: 50 + m_Padding: 2 + m_LightmapCompression: 0 + m_AO: 1 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAO: 0 + m_MixedBakeMode: 1 + m_LightmapsBakeMode: 1 + m_FilterMode: 1 + m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0} + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_RealtimeResolution: 1 + m_ForceWhiteAlbedo: 0 + m_ForceUpdates: 0 + m_FinalGather: 0 + m_FinalGatherRayCount: 256 + m_FinalGatherFiltering: 1 + m_PVRCulling: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVREnvironmentSampleCount: 512 + m_PVREnvironmentReferencePointCount: 2048 + m_LightProbeSampleCountMultiplier: 4 + m_PVRBounces: 2 + m_PVRMinBounces: 2 + m_PVREnvironmentMIS: 0 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_PVRTiledBaking: 0 diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPathSettings.lighting.meta b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPathSettings.lighting.meta new file mode 100644 index 0000000..a0cd52a --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/DOTweenPathSettings.lighting.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 26ec36f0e3bda4c4b877368e751c1ef0 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 4890085278179872738 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/Examples Assets.meta b/Assets/Plugins/Demigiant/DOTweenPro Examples/Examples Assets.meta new file mode 100644 index 0000000..27d6f9b --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro Examples/Examples Assets.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 2add6a5374e55e642a55ed3b43fd9db4 +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro Examples/Examples Assets/dotweenpro_logo.png b/Assets/Plugins/Demigiant/DOTweenPro Examples/Examples Assets/dotweenpro_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c6d84204d243ecbb2398c9130d5346cc91e86889 GIT binary patch literal 17098 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�v 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%0DY$h0<3+C#9u^kxY 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 + /// Attach this to a GameObject to create a tween + /// + [AddComponentMenu("DOTween/DOTween Animation")] + public class DOTweenAnimation : ABSAnimationComponent + { + public enum AnimationType + { + None, + Move, LocalMove, + Rotate, LocalRotate, + Scale, + Color, Fade, + Text, + PunchPosition, PunchRotation, PunchScale, + ShakePosition, ShakeRotation, ShakeScale, + CameraAspect, CameraBackgroundColor, CameraFieldOfView, CameraOrthoSize, CameraPixelRect, CameraRect, + UIWidthHeight + } + + public enum TargetType + { + Unset, + + Camera, + CanvasGroup, + Image, + Light, + RectTransform, + Renderer, SpriteRenderer, + Rigidbody, Rigidbody2D, + Text, + Transform, + + tk2dBaseSprite, + tk2dTextMesh, + + TextMeshPro, + TextMeshProUGUI + } + + #region EVENTS - EDITOR-ONLY + + /// Used internally by the editor + public static event Action OnReset; + static void Dispatch_OnReset(DOTweenAnimation anim) { if (OnReset != null) OnReset(anim); } + + #endregion + + public bool targetIsSelf = true; // If FALSE allows to set the target manually + public GameObject targetGO = null; // Used in case targetIsSelf is FALSE + // If FALSE always uses the GO containing this DOTweenAnimation (and not the one containing the target) as DOTween's SetTarget target + public bool tweenTargetIsTargetGO = true; + + public float delay; + public float duration = 1; + public Ease easeType = Ease.OutQuad; + public AnimationCurve easeCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(1, 1)); + public LoopType loopType = LoopType.Restart; + public int loops = 1; + public string id = ""; + public bool isRelative; + public bool isFrom; + public bool isIndependentUpdate = false; + public bool autoKill = true; + public bool autoGenerate = true; // If TRUE automatically creates the tween at startup + + public bool isActive = true; + public bool isValid; + public Component target; + public AnimationType animationType; + public TargetType targetType; + public TargetType forcedTargetType; // Used when choosing between multiple targets + public bool autoPlay = true; + public bool useTargetAsV3; + + public float endValueFloat; + public Vector3 endValueV3; + public Vector2 endValueV2; + public Color endValueColor = new Color(1, 1, 1, 1); + public string endValueString = ""; + public Rect endValueRect = new Rect(0, 0, 0, 0); + public Transform endValueTransform; + + public bool optionalBool0, optionalBool1; + public float optionalFloat0; + public int optionalInt0; + public RotateMode optionalRotationMode = RotateMode.Fast; + public ScrambleMode optionalScrambleMode = ScrambleMode.None; + public string optionalString; + + bool _tweenAutoGenerationCalled; // TRUE after the tweens have been autoGenerated + int _playCount = -1; // Used when calling DOPlayNext + + #region Unity Methods + + void Awake() + { + if (!isActive || !autoGenerate) return; + + if (animationType != AnimationType.Move || !useTargetAsV3) { + // Don't create tweens if we're using a RectTransform as a Move target, + // because that will work only inside Start + CreateTween(false, autoPlay); + _tweenAutoGenerationCalled = true; + } + } + + void Start() + { + if (_tweenAutoGenerationCalled || !isActive || !autoGenerate) return; + + CreateTween(false, autoPlay); + _tweenAutoGenerationCalled = true; + } + + void Reset() + { + Dispatch_OnReset(this); + } + + void OnDestroy() + { + if (tween != null && tween.active) tween.Kill(); + tween = null; + } + + /// + /// Creates/recreates the tween without playing it, but first rewinding and killing the existing one if present. + /// + public void RewindThenRecreateTween() + { + if (tween != null && tween.active) tween.Rewind(); + CreateTween(true, false); + } + /// + /// Creates/recreates the tween and plays it, first rewinding and killing the existing one if present. + /// + public void RewindThenRecreateTweenAndPlay() + { + if (tween != null && tween.active) tween.Rewind(); + CreateTween(true, true); + } + /// + /// Creates/recreates the tween from its target's current value without playing it, but first killing the existing one if present. + /// + public void RecreateTween() + { CreateTween(true, false); } + /// + /// Creates/recreates the tween from its target's current value and plays it, first killing the existing one if present. + /// + public void RecreateTweenAndPlay() + { CreateTween(true, true); } + // Used also by DOTweenAnimationInspector when applying runtime changes and restarting + /// + /// Creates the tween manually (called automatically if AutoGenerate is set in the Inspector) + /// from its target's current value. + /// + /// If TRUE and an existing tween was already created (and not killed), kills it and recreates it with the current + /// parameters. Otherwise, if a tween already exists, does nothing. + /// If TRUE also plays the tween, otherwise only creates it + public void CreateTween(bool regenerateIfExists = false, bool andPlay = true) + { + if (!isValid) { + if (regenerateIfExists) { // Called manually: warn users + Debug.LogWarning(string.Format("{0} :: This DOTweenAnimation isn't valid and its tween won't be created", this.gameObject.name), this.gameObject); + } + return; + } + if (tween != null) { + if (tween.active) { + if (regenerateIfExists) tween.Kill(); + else return; + } + tween = null; + } + +// if (target == null) { +// Debug.LogWarning(string.Format("{0} :: This DOTweenAnimation's target is NULL, because the animation was created with a DOTween Pro version older than 0.9.255. To fix this, exit Play mode then simply select this object, and it will update automatically", this.gameObject.name), this.gameObject); +// return; +// } + + GameObject tweenGO = GetTweenGO(); + if (target == null || tweenGO == null) { + if (targetIsSelf && target == null) { + // Old error caused during upgrade from DOTween Pro 0.9.255 + Debug.LogWarning(string.Format("{0} :: This DOTweenAnimation's target is NULL, because the animation was created with a DOTween Pro version older than 0.9.255. To fix this, exit Play mode then simply select this object, and it will update automatically", this.gameObject.name), this.gameObject); + } else { + // Missing non-self target + Debug.LogWarning(string.Format("{0} :: This DOTweenAnimation's target/GameObject is unset: the tween will not be created.", this.gameObject.name), this.gameObject); + } + return; + } + + if (forcedTargetType != TargetType.Unset) targetType = forcedTargetType; + if (targetType == TargetType.Unset) { + // Legacy DOTweenAnimation (made with a version older than 0.9.450) without stored targetType > assign it now + targetType = TypeToDOTargetType(target.GetType()); + } + + switch (animationType) { + case AnimationType.None: + break; + case AnimationType.Move: + if (useTargetAsV3) { + isRelative = false; + if (endValueTransform == null) { + Debug.LogWarning(string.Format("{0} :: This tween's TO target is NULL, a Vector3 of (0,0,0) will be used instead", this.gameObject.name), this.gameObject); + endValueV3 = Vector3.zero; + } else { +#if true // UI_MARKER + if (targetType == TargetType.RectTransform) { + RectTransform endValueT = endValueTransform as RectTransform; + if (endValueT == null) { + Debug.LogWarning(string.Format("{0} :: This tween's TO target should be a RectTransform, a Vector3 of (0,0,0) will be used instead", this.gameObject.name), this.gameObject); + endValueV3 = Vector3.zero; + } else { + RectTransform rTarget = target as RectTransform; + if (rTarget == null) { + Debug.LogWarning(string.Format("{0} :: This tween's target and TO target are not of the same type. Please reassign the values", this.gameObject.name), this.gameObject); + } else { + // Problem: doesn't work inside Awake (ararargh!) + endValueV3 = DOTweenModuleUI.Utils.SwitchToRectTransform(endValueT, rTarget); + } + } + } else +#endif + endValueV3 = endValueTransform.position; + } + } + switch (targetType) { + case TargetType.Transform: + tween = ((Transform)target).DOMove(endValueV3, duration, optionalBool0); + break; + case TargetType.RectTransform: +#if true // UI_MARKER + tween = ((RectTransform)target).DOAnchorPos3D(endValueV3, duration, optionalBool0); +#else + tween = ((Transform)target).DOMove(endValueV3, duration, optionalBool0); +#endif + break; + case TargetType.Rigidbody: +#if true // PHYSICS_MARKER + tween = ((Rigidbody)target).DOMove(endValueV3, duration, optionalBool0); +#else + tween = ((Transform)target).DOMove(endValueV3, duration, optionalBool0); +#endif + break; + case TargetType.Rigidbody2D: +#if true // PHYSICS2D_MARKER + tween = ((Rigidbody2D)target).DOMove(endValueV3, duration, optionalBool0); +#else + tween = ((Transform)target).DOMove(endValueV3, duration, optionalBool0); +#endif + break; + } + break; + case AnimationType.LocalMove: + tween = tweenGO.transform.DOLocalMove(endValueV3, duration, optionalBool0); + break; + case AnimationType.Rotate: + switch (targetType) { + case TargetType.Transform: + tween = ((Transform)target).DORotate(endValueV3, duration, optionalRotationMode); + break; + case TargetType.Rigidbody: +#if true // PHYSICS_MARKER + tween = ((Rigidbody)target).DORotate(endValueV3, duration, optionalRotationMode); +#else + tween = ((Transform)target).DORotate(endValueV3, duration, optionalRotationMode); +#endif + break; + case TargetType.Rigidbody2D: +#if true // PHYSICS2D_MARKER + tween = ((Rigidbody2D)target).DORotate(endValueFloat, duration); +#else + tween = ((Transform)target).DORotate(endValueV3, duration, optionalRotationMode); +#endif + break; + } + break; + case AnimationType.LocalRotate: + tween = tweenGO.transform.DOLocalRotate(endValueV3, duration, optionalRotationMode); + break; + case AnimationType.Scale: + switch (targetType) { +#if false // TK2D_MARKER + case TargetType.tk2dTextMesh: + tween = ((tk2dTextMesh)target).DOScale(optionalBool0 ? new Vector3(endValueFloat, endValueFloat, endValueFloat) : endValueV3, duration); + break; + case TargetType.tk2dBaseSprite: + tween = ((tk2dBaseSprite)target).DOScale(optionalBool0 ? new Vector3(endValueFloat, endValueFloat, endValueFloat) : endValueV3, duration); + break; +#endif + default: + tween = tweenGO.transform.DOScale(optionalBool0 ? new Vector3(endValueFloat, endValueFloat, endValueFloat) : endValueV3, duration); + break; + } + break; +#if true // UI_MARKER + case AnimationType.UIWidthHeight: + tween = ((RectTransform)target).DOSizeDelta(optionalBool0 ? new Vector2(endValueFloat, endValueFloat) : endValueV2, duration); + break; +#endif + case AnimationType.Color: + isRelative = false; + switch (targetType) { + case TargetType.Renderer: + tween = ((Renderer)target).material.DOColor(endValueColor, duration); + break; + case TargetType.Light: + tween = ((Light)target).DOColor(endValueColor, duration); + break; +#if true // SPRITE_MARKER + case TargetType.SpriteRenderer: + tween = ((SpriteRenderer)target).DOColor(endValueColor, duration); + break; +#endif +#if true // UI_MARKER + case TargetType.Image: + tween = ((Graphic)target).DOColor(endValueColor, duration); + break; + case TargetType.Text: + tween = ((Text)target).DOColor(endValueColor, duration); + break; +#endif +#if false // TK2D_MARKER + case TargetType.tk2dTextMesh: + tween = ((tk2dTextMesh)target).DOColor(endValueColor, duration); + break; + case TargetType.tk2dBaseSprite: + tween = ((tk2dBaseSprite)target).DOColor(endValueColor, duration); + break; +#endif +#if false // TEXTMESHPRO_MARKER + case TargetType.TextMeshProUGUI: + tween = ((TextMeshProUGUI)target).DOColor(endValueColor, duration); + break; + case TargetType.TextMeshPro: + tween = ((TextMeshPro)target).DOColor(endValueColor, duration); + break; +#endif + } + break; + case AnimationType.Fade: + isRelative = false; + switch (targetType) { + case TargetType.Renderer: + tween = ((Renderer)target).material.DOFade(endValueFloat, duration); + break; + case TargetType.Light: + tween = ((Light)target).DOIntensity(endValueFloat, duration); + break; +#if true // SPRITE_MARKER + case TargetType.SpriteRenderer: + tween = ((SpriteRenderer)target).DOFade(endValueFloat, duration); + break; +#endif +#if true // UI_MARKER + case TargetType.Image: + tween = ((Graphic)target).DOFade(endValueFloat, duration); + break; + case TargetType.Text: + tween = ((Text)target).DOFade(endValueFloat, duration); + break; + case TargetType.CanvasGroup: + tween = ((CanvasGroup)target).DOFade(endValueFloat, duration); + break; +#endif +#if false // TK2D_MARKER + case TargetType.tk2dTextMesh: + tween = ((tk2dTextMesh)target).DOFade(endValueFloat, duration); + break; + case TargetType.tk2dBaseSprite: + tween = ((tk2dBaseSprite)target).DOFade(endValueFloat, duration); + break; +#endif +#if false // TEXTMESHPRO_MARKER + case TargetType.TextMeshProUGUI: + tween = ((TextMeshProUGUI)target).DOFade(endValueFloat, duration); + break; + case TargetType.TextMeshPro: + tween = ((TextMeshPro)target).DOFade(endValueFloat, duration); + break; +#endif + } + break; + case AnimationType.Text: +#if true // UI_MARKER + switch (targetType) { + case TargetType.Text: + tween = ((Text)target).DOText(endValueString, duration, optionalBool0, optionalScrambleMode, optionalString); + break; + } +#endif +#if false // TK2D_MARKER + switch (targetType) { + case TargetType.tk2dTextMesh: + tween = ((tk2dTextMesh)target).DOText(endValueString, duration, optionalBool0, optionalScrambleMode, optionalString); + break; + } +#endif +#if false // TEXTMESHPRO_MARKER + switch (targetType) { + case TargetType.TextMeshProUGUI: + tween = ((TextMeshProUGUI)target).DOText(endValueString, duration, optionalBool0, optionalScrambleMode, optionalString); + break; + case TargetType.TextMeshPro: + tween = ((TextMeshPro)target).DOText(endValueString, duration, optionalBool0, optionalScrambleMode, optionalString); + break; + } +#endif + break; + case AnimationType.PunchPosition: + switch (targetType) { + case TargetType.Transform: + tween = ((Transform)target).DOPunchPosition(endValueV3, duration, optionalInt0, optionalFloat0, optionalBool0); + break; +#if true // UI_MARKER + case TargetType.RectTransform: + tween = ((RectTransform)target).DOPunchAnchorPos(endValueV3, duration, optionalInt0, optionalFloat0, optionalBool0); + break; +#endif + } + break; + case AnimationType.PunchScale: + tween = tweenGO.transform.DOPunchScale(endValueV3, duration, optionalInt0, optionalFloat0); + break; + case AnimationType.PunchRotation: + tween = tweenGO.transform.DOPunchRotation(endValueV3, duration, optionalInt0, optionalFloat0); + break; + case AnimationType.ShakePosition: + switch (targetType) { + case TargetType.Transform: + tween = ((Transform)target).DOShakePosition(duration, endValueV3, optionalInt0, optionalFloat0, optionalBool0, optionalBool1); + break; +#if true // UI_MARKER + case TargetType.RectTransform: + tween = ((RectTransform)target).DOShakeAnchorPos(duration, endValueV3, optionalInt0, optionalFloat0, optionalBool0, optionalBool1); + break; +#endif + } + break; + case AnimationType.ShakeScale: + tween = tweenGO.transform.DOShakeScale(duration, endValueV3, optionalInt0, optionalFloat0, optionalBool1); + break; + case AnimationType.ShakeRotation: + tween = tweenGO.transform.DOShakeRotation(duration, endValueV3, optionalInt0, optionalFloat0, optionalBool1); + break; + case AnimationType.CameraAspect: + tween = ((Camera)target).DOAspect(endValueFloat, duration); + break; + case AnimationType.CameraBackgroundColor: + tween = ((Camera)target).DOColor(endValueColor, duration); + break; + case AnimationType.CameraFieldOfView: + tween = ((Camera)target).DOFieldOfView(endValueFloat, duration); + break; + case AnimationType.CameraOrthoSize: + tween = ((Camera)target).DOOrthoSize(endValueFloat, duration); + break; + case AnimationType.CameraPixelRect: + tween = ((Camera)target).DOPixelRect(endValueRect, duration); + break; + case AnimationType.CameraRect: + tween = ((Camera)target).DORect(endValueRect, duration); + break; + } + + if (tween == null) return; + + // Created + + if (isFrom) { + ((Tweener)tween).From(isRelative); + } else { + tween.SetRelative(isRelative); + } + GameObject setTarget = GetTweenTarget(); + tween.SetTarget(setTarget).SetDelay(delay).SetLoops(loops, loopType).SetAutoKill(autoKill) + .OnKill(()=> tween = null); + if (isSpeedBased) tween.SetSpeedBased(); + if (easeType == Ease.INTERNAL_Custom) tween.SetEase(easeCurve); + else tween.SetEase(easeType); + if (!string.IsNullOrEmpty(id)) tween.SetId(id); + tween.SetUpdate(isIndependentUpdate); + + if (hasOnStart) { + if (onStart != null) tween.OnStart(onStart.Invoke); + } else onStart = null; + if (hasOnPlay) { + if (onPlay != null) tween.OnPlay(onPlay.Invoke); + } else onPlay = null; + if (hasOnUpdate) { + if (onUpdate != null) tween.OnUpdate(onUpdate.Invoke); + } else onUpdate = null; + if (hasOnStepComplete) { + if (onStepComplete != null) tween.OnStepComplete(onStepComplete.Invoke); + } else onStepComplete = null; + if (hasOnComplete) { + if (onComplete != null) tween.OnComplete(onComplete.Invoke); + } else onComplete = null; + if (hasOnRewind) { + if (onRewind != null) tween.OnRewind(onRewind.Invoke); + } else onRewind = null; + + if (andPlay) tween.Play(); + else tween.Pause(); + + if (hasOnTweenCreated && onTweenCreated != null) onTweenCreated.Invoke(); + } + + #endregion + + #region Public Methods + + #region Special + + /// + /// Returns the tweens (if generated and not killed) created by all DOTweenAnimations on this gameObject, + /// in the same order as they appear in the Inspector (top to bottom). + /// Note that a tween is generated inside the Awake call (except RectTransform tweens which are generated inside Start), + /// so this method won't return them before that + /// + public List GetTweens() + { + List result = new List(); + DOTweenAnimation[] anims = this.GetComponents(); + foreach (DOTweenAnimation anim in anims) { + if (anim.tween != null && anim.tween.active) result.Add(anim.tween); + } + return result; + } + + /// + /// Sets the animation target (which must be of the same type of the one set in the Inspector). + /// This is useful if you want to change it BEFORE this + /// creates a tween, while after that it won't have any effect. + /// Consider that a creates its tween inside its Awake (except for special tweens), + /// so you will need to sure your code runs before this object's Awake (via ScriptExecutionOrder or enabling/disabling methods) + /// + /// + /// New target for the animation (must be of the same type of the previous one) + /// If TRUE also uses tweenTarget's gameObject when settings the target-ID of the tween + /// (which is used with DOPlay/DORestart/etc to apply the same operation on all tweens that have the same target-id). + /// You should usually leave this to TRUE if you change the target. + /// + public void SetAnimationTarget(Component tweenTarget, bool useTweenTargetGameObjectForGroupOperations = true) + { + TargetType newTargetType = TypeToDOTargetType(target.GetType()); + if (newTargetType != targetType) { + Debug.LogError("DOTweenAnimation ► SetAnimationTarget: the new target is of a different type from the one set in the Inspector"); + return; + } + target = tweenTarget; + targetGO = target.gameObject; + tweenTargetIsTargetGO = useTweenTargetGameObjectForGroupOperations; + } + + #endregion + + /// + /// Plays all tweens whose target-id is the same as the one set by this animation + /// + public override void DOPlay() + { + DOTween.Play(GetTweenTarget()); + } + + /// + /// Plays backwards all tweens whose target-id is the same as the one set by this animation + /// + public override void DOPlayBackwards() + { + DOTween.PlayBackwards(GetTweenTarget()); + } + + /// + /// Plays foward all tweens whose target-id is the same as the one set by this animation + /// + public override void DOPlayForward() + { + DOTween.PlayForward(GetTweenTarget()); + } + + /// + /// Pauses all tweens whose target-id is the same as the one set by this animation + /// + public override void DOPause() + { + DOTween.Pause(GetTweenTarget()); + } + + /// + /// Pauses/unpauses (depending on the current state) all tweens whose target-id is the same as the one set by this animation + /// + public override void DOTogglePause() + { + DOTween.TogglePause(GetTweenTarget()); + } + + /// + /// Rewinds all tweens created by this animation in the correct order + /// + public override void DORewind() + { + _playCount = -1; + // Rewind using Components order (in case there are multiple animations on the same property) + DOTweenAnimation[] anims = this.gameObject.GetComponents(); + for (int i = anims.Length - 1; i > -1; --i) { + Tween t = anims[i].tween; + if (t != null && t.IsInitialized()) anims[i].tween.Rewind(); + } + // DOTween.Rewind(GetTweenTarget()); + } + + /// + /// Restarts all tweens whose target-id is the same as the one set by this animation + /// + public override void DORestart() + { DORestart(false); } + /// + /// Restarts all tweens whose target-id is the same as the one set by this animation + /// + /// If TRUE, re-evaluates the tween's start and end values from its current position. + /// Set it to TRUE when spawning the same DOTweenAnimation in different positions (like when using a pooling system) + public override void DORestart(bool fromHere) + { + _playCount = -1; + if (tween == null) { + if (Debugger.logPriority > 1) Debugger.LogNullTween(tween); return; + } + if (fromHere && isRelative) ReEvaluateRelativeTween(); + DOTween.Restart(GetTweenTarget()); + } + + /// + /// Completes all tweens whose target-id is the same as the one set by this animation + /// + public override void DOComplete() + { + DOTween.Complete(GetTweenTarget()); + } + + /// + /// Kills all tweens whose target-id is the same as the one set by this animation + /// + public override void DOKill() + { + DOTween.Kill(GetTweenTarget()); + tween = null; + } + + #region Specifics + + /// + /// Plays all tweens with the given ID and whose target-id is the same as the one set by this animation + /// + public void DOPlayById(string id) + { + DOTween.Play(GetTweenTarget(), id); + } + /// + /// Plays all tweens with the given ID (regardless of their target gameObject) + /// + public void DOPlayAllById(string id) + { + DOTween.Play(id); + } + + /// + /// Pauses all tweens that with the given ID (regardless of their target gameObject) + /// + public void DOPauseAllById(string id) + { + DOTween.Pause(id); + } + + /// + /// Plays backwards all tweens with the given ID and whose target-id is the same as the one set by this animation + /// + public void DOPlayBackwardsById(string id) + { + DOTween.PlayBackwards(GetTweenTarget(), id); + } + /// + /// Plays backwards all tweens with the given ID (regardless of their target gameObject) + /// + public void DOPlayBackwardsAllById(string id) + { + DOTween.PlayBackwards(id); + } + + /// + /// Plays forward all tweens with the given ID and whose target-id is the same as the one set by this animation + /// + public void DOPlayForwardById(string id) + { + DOTween.PlayForward(GetTweenTarget(), id); + } + /// + /// Plays forward all tweens with the given ID (regardless of their target gameObject) + /// + public void DOPlayForwardAllById(string id) + { + DOTween.PlayForward(id); + } + + /// + /// Plays the next animation on this animation's gameObject (if any) + /// + public void DOPlayNext() + { + DOTweenAnimation[] anims = this.GetComponents(); + while (_playCount < anims.Length - 1) { + _playCount++; + DOTweenAnimation anim = anims[_playCount]; + if (anim != null && anim.tween != null && anim.tween.active && !anim.tween.IsPlaying() && !anim.tween.IsComplete()) { + anim.tween.Play(); + break; + } + } + } + + /// + /// Rewinds all tweens with the given ID and whose target-id is the same as the one set by this animation, + /// then plays the next animation on this animation's gameObject (if any) + /// + public void DORewindAndPlayNext() + { + _playCount = -1; + DOTween.Rewind(GetTweenTarget()); + DOPlayNext(); + } + + /// + /// Rewinds all tweens with the given ID (regardless of their target gameObject) + /// + public void DORewindAllById(string id) + { + _playCount = -1; + DOTween.Rewind(id); + } + + /// + /// Restarts all tweens with the given ID and whose target-id is the same as the one set by this animation + /// + public void DORestartById(string id) + { + _playCount = -1; + DOTween.Restart(GetTweenTarget(), id); + } + /// + /// Restarts all tweens with the given ID (regardless of their target gameObject) + /// + public void DORestartAllById(string id) + { + _playCount = -1; + DOTween.Restart(id); + } + + /// + /// Kills all tweens with the given ID and whose target-id is the same as the one set by this animation + /// + public void DOKillById(string id) + { + DOTween.Kill(GetTweenTarget(), id); + } + /// + /// Kills all tweens with the given ID (regardless of their target gameObject) + /// + public void DOKillAllById(string id) + { + DOTween.Kill(id); + } + + #endregion + + #region Internal (also used by Inspector) + + public static TargetType TypeToDOTargetType(Type t) + { + string str = t.ToString(); + int dotIndex = str.LastIndexOf("."); + if (dotIndex != -1) str = str.Substring(dotIndex + 1); + if (str.IndexOf("Renderer") != -1 && (str != "SpriteRenderer")) str = "Renderer"; +//#if true // PHYSICS_MARKER +// if (str == "Rigidbody") str = "Transform"; +//#endif +//#if true // PHYSICS2D_MARKER +// if (str == "Rigidbody2D") str = "Transform"; +//#endif +#if true // UI_MARKER +// if (str == "RectTransform") str = "Transform"; + if (str == "RawImage" || str == "Graphic") str = "Image"; // RawImages/Graphics are managed like Images for DOTweenAnimation (color and fade use Graphic target anyway) +#endif + return (TargetType)Enum.Parse(typeof(TargetType), str); + } + + // Editor preview system + /// + /// Previews the tween in the editor. Only for DOTween internal usage: don't use otherwise. + /// + public Tween CreateEditorPreview() + { + if (Application.isPlaying) return null; + + // CHANGE: first param switched to TRUE otherwise changing an animation and replaying in editor would still play old one + CreateTween(true, autoPlay); + return tween; + } + + #endregion + + #endregion + + #region Private + + /// + /// Returns the gameObject whose target component should be animated + /// + /// + GameObject GetTweenGO() + { + return targetIsSelf ? this.gameObject : targetGO; + } + + /// + /// Returns the GameObject which should be used/retrieved for SetTarget + /// + GameObject GetTweenTarget() + { + return targetIsSelf || !tweenTargetIsTargetGO ? this.gameObject : targetGO; + } + + // Re-evaluate relative position of path + void ReEvaluateRelativeTween() + { + GameObject tweenGO = GetTweenGO(); + if (tweenGO == null) { + Debug.LogWarning(string.Format("{0} :: This DOTweenAnimation's target/GameObject is unset: the tween will not be created.", this.gameObject.name), this.gameObject); + return; + } + if (animationType == AnimationType.Move) { + ((Tweener)tween).ChangeEndValue(tweenGO.transform.position + endValueV3, true); + } else if (animationType == AnimationType.LocalMove) { + ((Tweener)tween).ChangeEndValue(tweenGO.transform.localPosition + endValueV3, true); + } + } + + #endregion + } + + public static class DOTweenAnimationExtensions + { +// // Doesn't work on Win 8.1 +// public static bool IsSameOrSubclassOf(this Type t, Type tBase) +// { +// return t.IsSubclassOf(tBase) || t == tBase; +// } + + public static bool IsSameOrSubclassOf(this Component t) + { + return t is T; + } + } +} diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenAnimation.cs.meta b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenAnimation.cs.meta new file mode 100644 index 0000000..a10ceea --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenAnimation.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4d0390bd8b8ffd640b34fe25065ff1df +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeAudio.cs b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeAudio.cs new file mode 100644 index 0000000..c9df396 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeAudio.cs @@ -0,0 +1,9 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2015/03/27 19:02 +// +// License Copyright (c) Daniele Giardini. +// This work is subject to the terms at http://dotween.demigiant.com/license.php + + +#if false // MODULE_MARKER +#endif diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeAudio.cs.meta b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeAudio.cs.meta new file mode 100644 index 0000000..32c1ec8 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeAudio.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1d1aa01bacf85c04ea18116651a7f0db +timeCreated: 1587116610 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeUnityExtended.cs b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeUnityExtended.cs new file mode 100644 index 0000000..c9df396 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeUnityExtended.cs @@ -0,0 +1,9 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2015/03/27 19:02 +// +// License Copyright (c) Daniele Giardini. +// This work is subject to the terms at http://dotween.demigiant.com/license.php + + +#if false // MODULE_MARKER +#endif diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeUnityExtended.cs.meta b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeUnityExtended.cs.meta new file mode 100644 index 0000000..9cba4ea --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenDeUnityExtended.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0a0cc3e90c4a6ea41bb14d7f35c577c3 +timeCreated: 1587116610 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.XML b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.XML new file mode 100644 index 0000000..301a65a --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.XML @@ -0,0 +1,67 @@ + + + + DOTweenPro + + + + + Restarts the tween + + + + + Restarts the tween + + If TRUE, re-evaluates the tween's start and end values from its current position. + Set it to TRUE when spawning the same DOTweenPath in different positions (like when using a pooling system) + + + + Attach this to a GameObject to create and assign a path to it + + + + Used internally by the editor + + + + Restarts the tween + + + + + Restarts the tween + + If TRUE, re-evaluates the tween's start and end values from its current position. + Set it to TRUE when spawning the same DOTweenPath in different positions (like when using a pooling system) + + + + Kills all tweens (path/animations/etc.) with the given ID (regardless of their target gameObject) + + + + + Returns a list of points that are used to draw the path inside the editor. + + + + + Tweens a Vector3 along a spiral. + EndValue represents the direction of the spiral + + + + + Spiral tween mode + + + + The spiral motion will expand outwards for the whole the tween + + + The spiral motion will expand outwards for half the tween and then will spiral back to the starting position + + + diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.XML.meta b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.XML.meta new file mode 100644 index 0000000..ddc78e5 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.XML.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: db7d7ef84c388bc4fbc3835d31a15306 +TextScriptImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.dll b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.dll new file mode 100644 index 0000000000000000000000000000000000000000..e3f93244084fd71a6aeb2783fbd4d820db999307 GIT binary patch literal 15872 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 X{R>v~{}`R3|0&!={{~pmzX|p~F?pAq literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.dll.mdb.meta b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.dll.mdb.meta new file mode 100644 index 0000000..6979090 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.dll.mdb.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: d719ed2e2c87eae4e8dd520e2df659c1 +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.dll.meta b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.dll.meta new file mode 100644 index 0000000..9ecbfd3 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenPro.dll.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: aa0b1eebb5db27a419fa4564bbe5c9c5 +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Any: + enabled: 1 + settings: {} + Editor: + enabled: 0 + settings: + DefaultValueInitialized: true + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenProShortcuts.cs b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenProShortcuts.cs new file mode 100644 index 0000000..12ee7ef --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenProShortcuts.cs @@ -0,0 +1,90 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2018/07/13 + +using System; +using DG.Tweening.Core; +using DG.Tweening.Plugins; +using UnityEngine; + +#pragma warning disable 1591 +namespace DG.Tweening +{ + public static class DOTweenProShortcuts + { + static DOTweenProShortcuts() + { + // Create stub instances of custom plugins, in order to allow IL2CPP to understand they must be included in the build +#pragma warning disable 219 + SpiralPlugin stub = new SpiralPlugin(); +#pragma warning restore 219 + } + + #region Shortcuts + + #region Transform + + /// Tweens a Transform's localPosition in a spiral shape. + /// Also stores the transform as the tween's target so it can be used for filtered operations + /// The duration of the tween + /// The axis around which the spiral will rotate + /// The type of spiral movement + /// Speed of the rotations + /// Frequency of the rotation. Lower values lead to wider spirals + /// Indicates how much the tween should move along the spiral's axis + /// If TRUE the tween will smoothly snap all values to integers + public static Tweener DOSpiral( + this Transform target, float duration, Vector3? axis = null, SpiralMode mode = SpiralMode.Expand, + float speed = 1, float frequency = 10, float depth = 0, bool snapping = false + ) { + if (Mathf.Approximately(speed, 0)) speed = 1; + if (axis == null || axis == Vector3.zero) axis = Vector3.forward; + + TweenerCore t = DOTween.To(SpiralPlugin.Get(), () => target.localPosition, x => target.localPosition = x, (Vector3)axis, duration) + .SetTarget(target); + + t.plugOptions.mode = mode; + t.plugOptions.speed = speed; + t.plugOptions.frequency = frequency; + t.plugOptions.depth = depth; + t.plugOptions.snapping = snapping; + return t; + } + + #endregion + +#if true // PHYSICS_MARKER + #region Rigidbody + + /// Tweens a Rigidbody's position in a spiral shape. + /// Also stores the transform as the tween's target so it can be used for filtered operations + /// The duration of the tween + /// The axis around which the spiral will rotate + /// The type of spiral movement + /// Speed of the rotations + /// Frequency of the rotation. Lower values lead to wider spirals + /// Indicates how much the tween should move along the spiral's axis + /// If TRUE the tween will smoothly snap all values to integers + public static Tweener DOSpiral( + this Rigidbody target, float duration, Vector3? axis = null, SpiralMode mode = SpiralMode.Expand, + float speed = 1, float frequency = 10, float depth = 0, bool snapping = false + ) { + if (Mathf.Approximately(speed, 0)) speed = 1; + if (axis == null || axis == Vector3.zero) axis = Vector3.forward; + + TweenerCore t = DOTween.To(SpiralPlugin.Get(), () => target.position, target.MovePosition, (Vector3)axis, duration) + .SetTarget(target); + + t.plugOptions.mode = mode; + t.plugOptions.speed = speed; + t.plugOptions.frequency = frequency; + t.plugOptions.depth = depth; + t.plugOptions.snapping = snapping; + return t; + } + + #endregion +#endif + + #endregion + } +} diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenProShortcuts.cs.meta b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenProShortcuts.cs.meta new file mode 100644 index 0000000..bc6e863 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenProShortcuts.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1c3190a1a1c53f449926f6d5542b4ce5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenTextMeshPro.cs b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenTextMeshPro.cs new file mode 100644 index 0000000..935bbee --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenTextMeshPro.cs @@ -0,0 +1,1037 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2015/03/27 19:02 +// +// License Copyright (c) Daniele Giardini. +// This work is subject to the terms at http://dotween.demigiant.com/license.php + + +#if false // MODULE_MARKER +using System; +using System.Globalization; +using System.Collections.Generic; +using DG.Tweening.Core; +using DG.Tweening.Plugins.Options; +using UnityEngine; +using TMPro; +using Object = UnityEngine.Object; + +namespace DG.Tweening +{ + public enum TMPSkewSpanMode + { + /// Applies the skew as-is (like normal skew works): the longer the text-span the higher the last character will be + Default, + /// Applies the skew scaled by the size of the text-span: the max skew/displacement will be the given skew factor + AsMaxSkewFactor + } + + /// + /// Methods that extend TMP_Text objects and allow to directly create and control tweens from their instances. + /// + public static class ShortcutExtensionsTMPText + { + #region Colors + + /// Tweens a TextMeshPro's color to the given value. + /// Also stores the TextMeshPro as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOColor(this TMP_Text target, Color endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a TextMeshPro's faceColor to the given value. + /// Also stores the TextMeshPro as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOFaceColor(this TMP_Text target, Color32 endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.faceColor, x => target.faceColor = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a TextMeshPro's outlineColor to the given value. + /// Also stores the TextMeshPro as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOOutlineColor(this TMP_Text target, Color32 endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.outlineColor, x => target.outlineColor = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a TextMeshPro's glow color to the given value. + /// Also stores the TextMeshPro as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + /// If TRUE will use the fontSharedMaterial instead than the fontMaterial + public static TweenerCore DOGlowColor(this TMP_Text target, Color endValue, float duration, bool useSharedMaterial = false) + { + TweenerCore t = useSharedMaterial + ? target.fontSharedMaterial.DOColor(endValue, "_GlowColor", duration) + : target.fontMaterial.DOColor(endValue, "_GlowColor", duration); + t.SetTarget(target); + return t; + } + + /// Tweens a TextMeshPro's alpha color to the given value. + /// Also stores the TextMeshPro as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOFade(this TMP_Text target, float endValue, float duration) + { + TweenerCore t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a TextMeshPro faceColor's alpha to the given value. + /// Also stores the TextMeshPro as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOFaceFade(this TMP_Text target, float endValue, float duration) + { + TweenerCore t = DOTween.ToAlpha(() => target.faceColor, x => target.faceColor = x, endValue, duration); + t.SetTarget(target); + return t; + } + + #endregion + + #region Other + + /// Tweens a TextMeshPro's scale to the given value (using correct uniform scale as TMP requires). + /// Also stores the TextMeshPro as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScale(this TMP_Text target, float endValue, float duration) + { + Transform trans = target.transform; + Vector3 endValueV3 = new Vector3(endValue, endValue, endValue); + TweenerCore t = DOTween.To(() => trans.localScale, x => trans.localScale = x, endValueV3, duration); + t.SetTarget(target); + return t; + } + + /// + /// Tweens a TextMeshPro's text from one integer to another, with options for thousands separators + /// + /// The value to start from + /// The end value to reach + /// The duration of the tween + /// If TRUE (default) also adds thousands separators + /// The to use (InvariantCulture if NULL) + public static TweenerCore DOCounter( + this TMP_Text target, int fromValue, int endValue, float duration, bool addThousandsSeparator = true, CultureInfo culture = null + ){ + int v = fromValue; + CultureInfo cInfo = !addThousandsSeparator ? null : culture ?? CultureInfo.InvariantCulture; + TweenerCore t = DOTween.To(() => v, x => { + v = x; + target.text = addThousandsSeparator + ? v.ToString("N0", cInfo) + : v.ToString(); + }, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a TextMeshPro's fontSize to the given value. + /// Also stores the TextMeshPro as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOFontSize(this TMP_Text target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.fontSize, x => target.fontSize = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a TextMeshPro's maxVisibleCharacters to the given value. + /// Also stores the TextMeshPro as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOMaxVisibleCharacters(this TMP_Text target, int endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.maxVisibleCharacters, x => target.maxVisibleCharacters = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a TextMeshPro's text to the given value. + /// Also stores the TextMeshPro as the tween's target so it can be used for filtered operations + /// The end string to tween toThe duration of the tween + /// If TRUE (default), rich text will be interpreted correctly while animated, + /// otherwise all tags will be considered as normal text + /// The type of scramble mode to use, if any + /// A string containing the characters to use for scrambling. + /// Use as many characters as possible (minimum 10) because DOTween uses a fast scramble mode which gives better results with more characters. + /// Leave it to NULL (default) to use default ones + public static TweenerCore DOText(this TMP_Text target, string endValue, float duration, bool richTextEnabled = true, ScrambleMode scrambleMode = ScrambleMode.None, string scrambleChars = null) + { + TweenerCore t = DOTween.To(() => target.text, x => target.text = x, endValue, duration); + t.SetOptions(richTextEnabled, scrambleMode, scrambleChars) + .SetTarget(target); + return t; + } + + #endregion + } + + #region DOTweenTMPAnimator + + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + // ███ CLASS ███████████████████████████████████████████████████████████████████████████████████████████████████████████ + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + + /// + /// Wrapper for objects that enables per-character tweening + /// (you don't need this if instead you want to animate the whole text object). + /// It also contains various handy methods to simply deform text without animating it ;) + /// EXAMPLE: + /// DOTweenTMPAnimator animator = new DOTweenTMPAnimator(myTextMeshProTextField); + /// Tween tween = animator.DOCharScale(characterIndex, scaleValue, duration); + /// + /// + public class DOTweenTMPAnimator : IDisposable + { + static readonly Dictionary _targetToAnimator = new Dictionary(); + + /// that this animator is linked to + public TMP_Text target { get; private set; } + public TMP_TextInfo textInfo { get; private set; } + readonly List _charTransforms = new List(); + TMP_MeshInfo[] _cachedMeshInfos; + bool _ignoreTextChangedEvent; + + /// + /// Creates a new instance of the , which is necessary to animate by single characters. + /// If a already exists for the same object it will be disposed + /// (but not its tweens, those you will have to kill manually). + /// If you want to animate the whole text object you don't need this, and you can use direct DO shortcuts instead. + /// IMPORTANT: the target must have been enabled/activated at least once before you can use it with this + /// + /// The that will be linked to this animator + public DOTweenTMPAnimator(TMP_Text target) + { + if (target == null) { + Debugger.LogError("DOTweenTMPAnimator target can't be null"); + return; + } + if (!target.gameObject.activeInHierarchy) { + Debugger.LogError("You can't create a DOTweenTMPAnimator if its target is disabled"); + return; + } + // Verify that there's no other animators for the same target, and in case dispose them + if (_targetToAnimator.ContainsKey(target)) { + if (Debugger.logPriority >= 2) { + Debugger.Log(string.Format( + "A DOTweenTMPAnimator for \"{0}\" already exists: disposing it because you can't have more than one DOTweenTMPAnimator" + + " for the same TextMesh Pro object. If you have tweens running on the disposed DOTweenTMPAnimator you should kill them manually", + target + )); + } + _targetToAnimator[target].Dispose(); + _targetToAnimator.Remove(target); + } + // + this.target = target; + _targetToAnimator.Add(target, this); + Refresh(); + // Listeners + TMPro_EventManager.TEXT_CHANGED_EVENT.Add(OnTextChanged); + } + + /// + /// If a instance exists for the given target disposes it + /// + public static void DisposeInstanceFor(TMP_Text target) + { + if (!_targetToAnimator.ContainsKey(target)) return; + _targetToAnimator[target].Dispose(); + _targetToAnimator.Remove(target); + } + + /// + /// Clears and disposes of this object + /// + public void Dispose() + { + target = null; + _charTransforms.Clear(); + textInfo = null; + _cachedMeshInfos = null; + TMPro_EventManager.TEXT_CHANGED_EVENT.Remove(OnTextChanged); + } + + /// + /// Refreshes the animator text data and resets all transformation data. Call this after you change the target + /// + public void Refresh() + { + _ignoreTextChangedEvent = true; + target.ForceMeshUpdate(true); + textInfo = target.textInfo; + _cachedMeshInfos = textInfo.CopyMeshInfoVertexData(); + int totChars = textInfo.characterCount; + int totCurrent = _charTransforms.Count; + if (totCurrent > totChars) { + _charTransforms.RemoveRange(totChars, totCurrent - totChars); + totCurrent = totChars; + } + for (int i = 0; i < totCurrent; ++i) { + CharTransform c = _charTransforms[i]; + c.ResetTransformationData(); + c.Refresh(textInfo, _cachedMeshInfos); + _charTransforms[i] = c; + } + for (int i = totCurrent; i < totChars; ++i) _charTransforms.Add(new CharTransform(i, textInfo, _cachedMeshInfos)); + _ignoreTextChangedEvent = false; + } + + /// + /// Resets all deformations + /// + public void Reset() + { + int totCurrent = _charTransforms.Count; + for (int i = 0; i < totCurrent; ++i) _charTransforms[i].ResetAll(target, textInfo.meshInfo, _cachedMeshInfos); + } + + void OnTextChanged(Object obj) + { + if (_ignoreTextChangedEvent || target == null || obj != target) return; + Refresh(); + } + + bool ValidateChar(int charIndex, bool isTween = true) + { + if (textInfo.characterCount <= charIndex) { + Debugger.LogError(string.Format("CharIndex {0} doesn't exist", charIndex)); + return false; + } + if (!textInfo.characterInfo[charIndex].isVisible) { + if (Debugger.logPriority > 1) { + if (isTween) { + Debugger.Log(string.Format( + "CharIndex {0} isn't visible, ignoring it and returning an empty tween (TextMesh Pro will behave weirdly if invisible chars are included in the animation)", + charIndex + )); + } else { + Debugger.Log(string.Format("CharIndex {0} isn't visible, ignoring it", charIndex)); + } + } + return false; + } + return true; + } + + bool ValidateSpan(int fromCharIndex, int toCharIndex, out int firstVisibleCharIndex, out int lastVisibleCharIndex) + { + firstVisibleCharIndex = -1; // First visible/existing charIndex from given index + lastVisibleCharIndex = -1; // Last visible/existing charIndex backwards from given index + int charCount = textInfo.characterCount; + if (fromCharIndex >= charCount) return false; + if (toCharIndex >= charCount) toCharIndex = charCount - 1; + for (int i = fromCharIndex; i < toCharIndex + 1; ++i) { + if (!_charTransforms[i].isVisible) continue; + firstVisibleCharIndex = i; + break; + } + if (firstVisibleCharIndex == -1) return false; + for (int i = toCharIndex; i > firstVisibleCharIndex - 1; --i) { + if (!_charTransforms[i].isVisible) continue; + lastVisibleCharIndex = i; + break; + } + if (lastVisibleCharIndex == -1) return false; + return true; + } + + #region Word Setters + + /// + /// Skews a span of characters uniformly (like normal skew works in graphic applications) + /// + /// First char index of the span to skew + /// Last char index of the span to skew + /// Skew factor + /// If TRUE skews the top side of the span, otherwise the bottom one + public void SkewSpanX(int fromCharIndex, int toCharIndex, float skewFactor, bool skewTop = true) + { + int firstVisibleCharIndex, lastVisibleCharIndex; + if (!ValidateSpan(fromCharIndex, toCharIndex, out firstVisibleCharIndex, out lastVisibleCharIndex)) return; + for (int i = firstVisibleCharIndex; i < lastVisibleCharIndex + 1; ++i) { + if (!_charTransforms[i].isVisible) continue; + CharVertices v = _charTransforms[i].GetVertices(); + float skew = SkewCharX(i, skewFactor, skewTop); + } + } + + /// + /// Skews a span of characters uniformly (like normal skew works in graphic applications) + /// + /// First char index of the span to skew + /// Last char index of the span to skew + /// Skew factor + /// Skew mode + /// If TRUE skews the right side of the span, otherwise the left one + public void SkewSpanY( + int fromCharIndex, int toCharIndex, float skewFactor, + TMPSkewSpanMode mode = TMPSkewSpanMode.Default, bool skewRight = true + ){ + int firstVisibleCharIndex, lastVisibleCharIndex; + if (!ValidateSpan(fromCharIndex, toCharIndex, out firstVisibleCharIndex, out lastVisibleCharIndex)) return; + if (mode == TMPSkewSpanMode.AsMaxSkewFactor) { + CharVertices firstVisibleCharVertices = _charTransforms[firstVisibleCharIndex].GetVertices(); + CharVertices lastVisibleCharVertices = _charTransforms[lastVisibleCharIndex].GetVertices(); + float spanW = Mathf.Abs(lastVisibleCharVertices.bottomRight.x - firstVisibleCharVertices.bottomLeft.x); + float spanH = Mathf.Abs(lastVisibleCharVertices.topRight.y - lastVisibleCharVertices.bottomRight.y); + float ratio = spanH / spanW; + skewFactor *= ratio; + } + float offsetY = 0; + CharVertices prevCharVertices = new CharVertices(); + float prevCharSkew = 0; + if (skewRight) { + for (int i = firstVisibleCharIndex; i < lastVisibleCharIndex + 1; ++i) { + if (!_charTransforms[i].isVisible) continue; + CharVertices v = _charTransforms[i].GetVertices(); + float skew = SkewCharY(i, skewFactor, skewRight); + if (i > firstVisibleCharIndex) { + float prevCharW = Mathf.Abs(prevCharVertices.bottomLeft.x - prevCharVertices.bottomRight.x); + float charsDist = Mathf.Abs(v.bottomLeft.x - prevCharVertices.bottomRight.x); + offsetY += prevCharSkew + (prevCharSkew * charsDist) / prevCharW; + SetCharOffset(i, new Vector3(0, _charTransforms[i].offset.y + offsetY, 0)); + } + prevCharVertices = v; + prevCharSkew = skew; + } + } else { + for (int i = lastVisibleCharIndex; i > firstVisibleCharIndex - 1; --i) { + if (!_charTransforms[i].isVisible) continue; + CharVertices v = _charTransforms[i].GetVertices(); + float skew = SkewCharY(i, skewFactor, skewRight); + if (i < lastVisibleCharIndex) { + float prevCharW = Mathf.Abs(prevCharVertices.bottomLeft.x - prevCharVertices.bottomRight.x); + float charsDist = Mathf.Abs(v.bottomRight.x - prevCharVertices.bottomLeft.x); + offsetY += prevCharSkew + (prevCharSkew * charsDist) / prevCharW; + SetCharOffset(i, new Vector3(0, _charTransforms[i].offset.y + offsetY, 0)); + } + prevCharVertices = v; + prevCharSkew = skew; + } + } + } + + #endregion + + #region Char Getters + + /// + /// Returns the current color of the given character, if it exists and is visible. + /// + /// Character index + public Color GetCharColor(int charIndex) + { + if (!ValidateChar(charIndex)) return Color.white; + return _charTransforms[charIndex].GetColor(textInfo.meshInfo); + } + + /// + /// Returns the current offset of the given character, if it exists and is visible. + /// + /// Character index + public Vector3 GetCharOffset(int charIndex) + { + if (!ValidateChar(charIndex)) return Vector3.zero; + return _charTransforms[charIndex].offset; + } + + /// + /// Returns the current rotation of the given character, if it exists and is visible. + /// + /// Character index + public Vector3 GetCharRotation(int charIndex) + { + if (!ValidateChar(charIndex)) return Vector3.zero; + return _charTransforms[charIndex].rotation.eulerAngles; + } + + /// + /// Returns the current scale of the given character, if it exists and is visible. + /// + /// Character index + public Vector3 GetCharScale(int charIndex) + { + if (!ValidateChar(charIndex)) return Vector3.zero; + return _charTransforms[charIndex].scale; + } + + #endregion + + #region Char Setters + + /// + /// Immediately sets the color of the given character. + /// Will do nothing if the is invalid or the character isn't visible + /// + /// Character index + /// Color to set + public void SetCharColor(int charIndex, Color32 color) + { + if (!ValidateChar(charIndex)) return; + CharTransform c = _charTransforms[charIndex]; + c.UpdateColor(target, color, textInfo.meshInfo); + _charTransforms[charIndex] = c; + } + + /// + /// Immediately sets the offset of the given character. + /// Will do nothing if the is invalid or the character isn't visible + /// + /// Character index + /// Offset to set + public void SetCharOffset(int charIndex, Vector3 offset) + { + if (!ValidateChar(charIndex)) return; + CharTransform c = _charTransforms[charIndex]; + c.UpdateGeometry(target, offset, c.rotation, c.scale, _cachedMeshInfos); + _charTransforms[charIndex] = c; + } + + /// + /// Immediately sets the rotation of the given character. + /// Will do nothing if the is invalid or the character isn't visible + /// + /// Character index + /// Rotation to set + public void SetCharRotation(int charIndex, Vector3 rotation) + { + if (!ValidateChar(charIndex)) return; + CharTransform c = _charTransforms[charIndex]; + c.UpdateGeometry(target, c.offset, Quaternion.Euler(rotation), c.scale, _cachedMeshInfos); + _charTransforms[charIndex] = c; + } + + /// + /// Immediately sets the scale of the given character. + /// Will do nothing if the is invalid or the character isn't visible + /// + /// Character index + /// Scale to set + public void SetCharScale(int charIndex, Vector3 scale) + { + if (!ValidateChar(charIndex)) return; + CharTransform c = _charTransforms[charIndex]; + c.UpdateGeometry(target, c.offset, c.rotation, scale, _cachedMeshInfos); + _charTransforms[charIndex] = c; + } + + /// + /// Immediately shifts the vertices of the given character by the given factor. + /// Will do nothing if the is invalid or the character isn't visible + /// + /// Character index + /// Top left offset + /// Top right offset + /// Bottom left offset + /// Bottom right offset + public void ShiftCharVertices(int charIndex, Vector3 topLeftShift, Vector3 topRightShift, Vector3 bottomLeftShift, Vector3 bottomRightShift) + { + if (!ValidateChar(charIndex)) return; + CharTransform c = _charTransforms[charIndex]; + c.ShiftVertices(target, topLeftShift, topRightShift, bottomLeftShift, bottomRightShift); + _charTransforms[charIndex] = c; + } + + /// + /// Skews the given character horizontally along the X axis and returns the skew amount applied (based on the character's size) + /// + /// Character index + /// skew amount + /// If TRUE skews the top side of the character, otherwise the bottom one + public float SkewCharX(int charIndex, float skewFactor, bool skewTop = true) + { + if (!ValidateChar(charIndex)) return 0; + Vector3 skewV = new Vector3(skewFactor, 0, 0); + CharTransform c = _charTransforms[charIndex]; + if (skewTop) c.ShiftVertices(target, skewV, skewV, Vector3.zero, Vector3.zero); + else c.ShiftVertices(target, Vector3.zero, Vector3.zero, skewV, skewV); + _charTransforms[charIndex] = c; + return skewFactor; + } + + /// + /// Skews the given character vertically along the Y axis and returns the skew amount applied (based on the character's size) + /// + /// Character index + /// skew amount + /// If TRUE skews the right side of the character, otherwise the left one + /// If TRUE applies exactly the given , + /// otherwise modifies it based on the aspectRation of the character + public float SkewCharY(int charIndex, float skewFactor, bool skewRight = true, bool fixedSkew = false) + { + if (!ValidateChar(charIndex)) return 0; + float skew = fixedSkew ? skewFactor : skewFactor * textInfo.characterInfo[charIndex].aspectRatio; + Vector3 skewV = new Vector3(0, skew, 0); + CharTransform c = _charTransforms[charIndex]; + if (skewRight) c.ShiftVertices(target, Vector3.zero, skewV, Vector3.zero, skewV); + else c.ShiftVertices(target, skewV, Vector3.zero, skewV, Vector3.zero); + _charTransforms[charIndex] = c; + return skew; + } + + /// + /// Resets the eventual vertices shift applied to the given character via . + /// Will do nothing if the is invalid or the character isn't visible + /// + /// Character index + public void ResetVerticesShift(int charIndex) + { + if (!ValidateChar(charIndex)) return; + CharTransform c = _charTransforms[charIndex]; + c.ResetVerticesShift(target); + _charTransforms[charIndex] = c; + } + + #endregion + + #region Char Tweens + + /// Tweens a character's alpha to the given value and returns the . + /// Will return NULL if the is invalid or the character isn't visible. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The end value to reachThe duration of the tween + public TweenerCore DOFadeChar(int charIndex, float endValue, float duration) + { + if (!ValidateChar(charIndex)) return null; + TweenerCore t = DOTween.ToAlpha(() => _charTransforms[charIndex].GetColor(textInfo.meshInfo), x => { + _charTransforms[charIndex].UpdateAlpha(target, x, textInfo.meshInfo); + }, endValue, duration); + return t; + } + + /// Tweens a character's color to the given value and returns the . + /// Will return NULL if the is invalid or the character isn't visible. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The end value to reachThe duration of the tween + public TweenerCore DOColorChar(int charIndex, Color endValue, float duration) + { + if (!ValidateChar(charIndex)) return null; + TweenerCore t = DOTween.To(() => _charTransforms[charIndex].GetColor(textInfo.meshInfo), x => { + _charTransforms[charIndex].UpdateColor(target, x, textInfo.meshInfo); + }, endValue, duration); + return t; + } + + /// Tweens a character's offset to the given value and returns the . + /// Will return NULL if the is invalid or the character isn't visible. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The end value to reachThe duration of the tween + public TweenerCore DOOffsetChar(int charIndex, Vector3 endValue, float duration) + { + if (!ValidateChar(charIndex)) return null; + TweenerCore t = DOTween.To(() => _charTransforms[charIndex].offset, x => { + CharTransform charT = _charTransforms[charIndex]; + charT.UpdateGeometry(target, x, charT.rotation, charT.scale, _cachedMeshInfos); + _charTransforms[charIndex] = charT; + }, endValue, duration); + return t; + } + + /// Tweens a character's rotation to the given value and returns the . + /// Will return NULL if the is invalid or the character isn't visible. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The end value to reachThe duration of the tween + /// Rotation mode + public TweenerCore DORotateChar(int charIndex, Vector3 endValue, float duration, RotateMode mode = RotateMode.Fast) + { + if (!ValidateChar(charIndex)) return null; + TweenerCore t = DOTween.To(() => _charTransforms[charIndex].rotation, x => { + CharTransform charT = _charTransforms[charIndex]; + charT.UpdateGeometry(target, charT.offset, x, charT.scale, _cachedMeshInfos); + _charTransforms[charIndex] = charT; + }, endValue, duration); + t.plugOptions.rotateMode = mode; + return t; + } + + /// Tweens a character's scale to the given value and returns the . + /// Will return NULL if the is invalid or the character isn't visible. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The end value to reachThe duration of the tween + public TweenerCore DOScaleChar(int charIndex, float endValue, float duration) + { + return DOScaleChar(charIndex, new Vector3(endValue, endValue, endValue), duration); + } + /// Tweens a character's color to the given value and returns the . + /// Will return NULL if the is invalid or the character isn't visible. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The end value to reachThe duration of the tween + public TweenerCore DOScaleChar(int charIndex, Vector3 endValue, float duration) + { + if (!ValidateChar(charIndex)) return null; + TweenerCore t = DOTween.To(() => _charTransforms[charIndex].scale, x => { + CharTransform charT = _charTransforms[charIndex]; + charT.UpdateGeometry(target, charT.offset, charT.rotation, x, _cachedMeshInfos); + _charTransforms[charIndex] = charT; + }, endValue, duration); + return t; + } + + /// Punches a character's offset towards the given direction and then back to the starting one + /// as if it was connected to the starting position via an elastic. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The punch strength + /// The duration of the tween + /// Indicates how much will the punch vibrate per second + /// Represents how much (0 to 1) the vector will go beyond the starting size when bouncing backwards. + /// 1 creates a full oscillation between the punch offset and the opposite offset, + /// while 0 oscillates only between the punch offset and the start offset + public Tweener DOPunchCharOffset(int charIndex, Vector3 punch, float duration, int vibrato = 10, float elasticity = 1) + { + if (!ValidateChar(charIndex)) return null; + if (duration <= 0) { + if (Debugger.logPriority > 0) Debug.LogWarning("Duration can't be 0, returning NULL without creating a tween"); + return null; + } + return DOTween.Punch(() => _charTransforms[charIndex].offset, x => { + CharTransform charT = _charTransforms[charIndex]; + charT.UpdateGeometry(target, x, charT.rotation, charT.scale, _cachedMeshInfos); + _charTransforms[charIndex] = charT; + }, punch, duration, vibrato, elasticity); + } + + /// Punches a character's rotation towards the given direction and then back to the starting one + /// as if it was connected to the starting position via an elastic. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The punch strength + /// The duration of the tween + /// Indicates how much will the punch vibrate per second + /// Represents how much (0 to 1) the vector will go beyond the starting size when bouncing backwards. + /// 1 creates a full oscillation between the punch rotation and the opposite rotation, + /// while 0 oscillates only between the punch rotation and the start rotation + public Tweener DOPunchCharRotation(int charIndex, Vector3 punch, float duration, int vibrato = 10, float elasticity = 1) + { + if (!ValidateChar(charIndex)) return null; + if (duration <= 0) { + if (Debugger.logPriority > 0) Debug.LogWarning("Duration can't be 0, returning NULL without creating a tween"); + return null; + } + return DOTween.Punch(() => _charTransforms[charIndex].rotation.eulerAngles, x => { + CharTransform charT = _charTransforms[charIndex]; + charT.UpdateGeometry(target, charT.offset, Quaternion.Euler(x), charT.scale, _cachedMeshInfos); + _charTransforms[charIndex] = charT; + }, punch, duration, vibrato, elasticity); + } + + /// Punches a character's scale towards the given direction and then back to the starting one + /// as if it was connected to the starting position via an elastic. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The punch strength (added to the character's current scale) + /// The duration of the tween + /// Indicates how much will the punch vibrate per second + /// Represents how much (0 to 1) the vector will go beyond the starting size when bouncing backwards. + /// 1 creates a full oscillation between the punch scale and the opposite scale, + /// while 0 oscillates only between the punch scale and the start scale + public Tweener DOPunchCharScale(int charIndex, float punch, float duration, int vibrato = 10, float elasticity = 1) + { + return DOPunchCharScale(charIndex, new Vector3(punch, punch, punch), duration, vibrato, elasticity); + } + /// Punches a character's scale towards the given direction and then back to the starting one + /// as if it was connected to the starting position via an elastic. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The punch strength (added to the character's current scale) + /// The duration of the tween + /// Indicates how much will the punch vibrate per second + /// Represents how much (0 to 1) the vector will go beyond the starting size when bouncing backwards. + /// 1 creates a full oscillation between the punch scale and the opposite scale, + /// while 0 oscillates only between the punch scale and the start scale + public Tweener DOPunchCharScale(int charIndex, Vector3 punch, float duration, int vibrato = 10, float elasticity = 1) + { + if (!ValidateChar(charIndex)) return null; + if (duration <= 0) { + if (Debugger.logPriority > 0) Debug.LogWarning("Duration can't be 0, returning NULL without creating a tween"); + return null; + } + return DOTween.Punch(() => _charTransforms[charIndex].scale, x => { + CharTransform charT = _charTransforms[charIndex]; + charT.UpdateGeometry(target, charT.offset, charT.rotation, x, _cachedMeshInfos); + _charTransforms[charIndex] = charT; + }, punch, duration, vibrato, elasticity); + } + + /// Shakes a character's offset with the given values. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The duration of the tween + /// The shake strength + /// Indicates how much will the shake vibrate + /// Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + /// Setting it to 0 will shake along a single direction. + /// If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + public Tweener DOShakeCharOffset(int charIndex, float duration, float strength, int vibrato = 10, float randomness = 90, bool fadeOut = true) + { + return DOShakeCharOffset(charIndex, duration, new Vector3(strength, strength, strength), vibrato, randomness, fadeOut); + } + /// Shakes a character's offset with the given values. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The duration of the tween + /// The shake strength + /// Indicates how much will the shake vibrate + /// Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + /// Setting it to 0 will shake along a single direction. + /// If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + public Tweener DOShakeCharOffset(int charIndex, float duration, Vector3 strength, int vibrato = 10, float randomness = 90, bool fadeOut = true) + { + if (!ValidateChar(charIndex)) return null; + if (duration <= 0) { + if (Debugger.logPriority > 0) Debug.LogWarning("Duration can't be 0, returning NULL without creating a tween"); + return null; + } + return DOTween.Shake(() => _charTransforms[charIndex].offset, x => { + CharTransform charT = _charTransforms[charIndex]; + charT.UpdateGeometry(target, x, charT.rotation, charT.scale, _cachedMeshInfos); + _charTransforms[charIndex] = charT; + }, duration, strength, vibrato, randomness, fadeOut); + } + + /// Shakes a character's rotation with the given values. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The duration of the tween + /// The shake strength + /// Indicates how much will the shake vibrate + /// Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + /// Setting it to 0 will shake along a single direction. + /// If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + public Tweener DOShakeCharRotation(int charIndex, float duration, Vector3 strength, int vibrato = 10, float randomness = 90, bool fadeOut = true) + { + if (!ValidateChar(charIndex)) return null; + if (duration <= 0) { + if (Debugger.logPriority > 0) Debug.LogWarning("Duration can't be 0, returning NULL without creating a tween"); + return null; + } + return DOTween.Shake(() => _charTransforms[charIndex].rotation.eulerAngles, x => { + CharTransform charT = _charTransforms[charIndex]; + charT.UpdateGeometry(target, charT.offset, Quaternion.Euler(x), charT.scale, _cachedMeshInfos); + _charTransforms[charIndex] = charT; + }, duration, strength, vibrato, randomness, fadeOut); + } + + /// Shakes a character's scale with the given values. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The duration of the tween + /// The shake strength + /// Indicates how much will the shake vibrate + /// Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + /// Setting it to 0 will shake along a single direction. + /// If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + public Tweener DOShakeCharScale(int charIndex, float duration, float strength, int vibrato = 10, float randomness = 90, bool fadeOut = true) + { + return DOShakeCharScale(charIndex, duration, new Vector3(strength, strength, strength), vibrato, randomness, fadeOut); + } + /// Shakes a character's scale with the given values. + /// The index of the character to tween (will throw an error if it doesn't exist) + /// The duration of the tween + /// The shake strength + /// Indicates how much will the shake vibrate + /// Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware). + /// Setting it to 0 will shake along a single direction. + /// If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not + public Tweener DOShakeCharScale(int charIndex, float duration, Vector3 strength, int vibrato = 10, float randomness = 90, bool fadeOut = true) + { + if (!ValidateChar(charIndex)) return null; + if (duration <= 0) { + if (Debugger.logPriority > 0) Debug.LogWarning("Duration can't be 0, returning NULL without creating a tween"); + return null; + } + return DOTween.Shake(() => _charTransforms[charIndex].scale, x => { + CharTransform charT = _charTransforms[charIndex]; + charT.UpdateGeometry(target, charT.offset, charT.rotation, x, _cachedMeshInfos); + _charTransforms[charIndex] = charT; + }, duration, strength, vibrato, randomness, fadeOut); + } + + #endregion + + // ███ INTERNAL CLASSES ████████████████████████████████████████████████████████████████████████████████████████████████ + + struct CharVertices + { + public Vector3 bottomLeft, topLeft, topRight, bottomRight; + + public CharVertices(Vector3 bottomLeft, Vector3 topLeft, Vector3 topRight, Vector3 bottomRight) + { + this.bottomLeft = bottomLeft; + this.topLeft = topLeft; + this.topRight = topRight; + this.bottomRight = bottomRight; + } + } + + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + + // Vertices of each character are: + // 0 : bottom left, 1 : top left, 2 : top right, 3 : bottom right + struct CharTransform + { + public int charIndex; + public bool isVisible { get; private set; } // FALSE both if it's invisible or if it's a space + public Vector3 offset; + public Quaternion rotation; + public Vector3 scale; + Vector3 _topLeftShift, _topRightShift, _bottomLeftShift, _bottomRightShift; + Vector3 _charMidBaselineOffset; + int _matIndex, _firstVertexIndex; + TMP_MeshInfo _meshInfo; + + public CharTransform(int charIndex, TMP_TextInfo textInfo, TMP_MeshInfo[] cachedMeshInfos) : this() + { + this.charIndex = charIndex; + offset = Vector3.zero; + rotation = Quaternion.identity; + scale = Vector3.one; + Refresh(textInfo, cachedMeshInfos); + } + + public void Refresh(TMP_TextInfo textInfo, TMP_MeshInfo[] cachedMeshInfos) + { + TMP_CharacterInfo charInfo = textInfo.characterInfo[charIndex]; + bool isSpaceChar = charInfo.character == ' '; + isVisible = charInfo.isVisible && !isSpaceChar; + _matIndex = charInfo.materialReferenceIndex; + _firstVertexIndex = charInfo.vertexIndex; + _meshInfo = textInfo.meshInfo[_matIndex]; + Vector3[] cachedVertices = cachedMeshInfos[_matIndex].vertices; + _charMidBaselineOffset = isSpaceChar + ? Vector3.zero + : (cachedVertices[_firstVertexIndex] + cachedVertices[_firstVertexIndex + 2]) * 0.5f; + } + + public void ResetAll(TMP_Text target, TMP_MeshInfo[] meshInfos, TMP_MeshInfo[] cachedMeshInfos) + { + ResetGeometry(target, cachedMeshInfos); + ResetColors(target, meshInfos); + } + + public void ResetTransformationData() + { + offset = Vector3.zero; + rotation = Quaternion.identity; + scale = Vector3.one; + _topLeftShift = _topRightShift = _bottomLeftShift = _bottomRightShift = Vector3.zero; + } + + public void ResetGeometry(TMP_Text target, TMP_MeshInfo[] cachedMeshInfos) + { + ResetTransformationData(); + Vector3[] destinationVertices = _meshInfo.vertices; + Vector3[] cachedVertices = cachedMeshInfos[_matIndex].vertices; + destinationVertices[_firstVertexIndex + 0] = cachedVertices[_firstVertexIndex + 0]; + destinationVertices[_firstVertexIndex + 1] = cachedVertices[_firstVertexIndex + 1]; + destinationVertices[_firstVertexIndex + 2] = cachedVertices[_firstVertexIndex + 2]; + destinationVertices[_firstVertexIndex + 3] = cachedVertices[_firstVertexIndex + 3]; + _meshInfo.mesh.vertices = _meshInfo.vertices; + target.UpdateGeometry(_meshInfo.mesh, _matIndex); + } + + public void ResetColors(TMP_Text target, TMP_MeshInfo[] meshInfos) + { + Color color = target.color; + Color32[] vertexCols = meshInfos[_matIndex].colors32; + vertexCols[_firstVertexIndex] = color; + vertexCols[_firstVertexIndex + 1] = color; + vertexCols[_firstVertexIndex + 2] = color; + vertexCols[_firstVertexIndex + 3] = color; + target.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32); + } + + public Color32 GetColor(TMP_MeshInfo[] meshInfos) + { + return meshInfos[_matIndex].colors32[_firstVertexIndex]; + } + + public CharVertices GetVertices() + { + return new CharVertices( + _meshInfo.vertices[_firstVertexIndex], _meshInfo.vertices[_firstVertexIndex + 1], + _meshInfo.vertices[_firstVertexIndex + 2], _meshInfo.vertices[_firstVertexIndex + 3] + ); + } + + public void UpdateAlpha(TMP_Text target, Color alphaColor, TMP_MeshInfo[] meshInfos, bool apply = true) + { + byte alphaByte = (byte)(alphaColor.a * 255); + Color32[] vertexCols = meshInfos[_matIndex].colors32; + vertexCols[_firstVertexIndex].a = alphaByte; + vertexCols[_firstVertexIndex + 1].a = alphaByte; + vertexCols[_firstVertexIndex + 2].a = alphaByte; + vertexCols[_firstVertexIndex + 3].a = alphaByte; + if (apply) target.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32); + } + + public void UpdateColor(TMP_Text target, Color32 color, TMP_MeshInfo[] meshInfos, bool apply = true) + { + Color32[] vertexCols = meshInfos[_matIndex].colors32; + vertexCols[_firstVertexIndex] = color; + vertexCols[_firstVertexIndex + 1] = color; + vertexCols[_firstVertexIndex + 2] = color; + vertexCols[_firstVertexIndex + 3] = color; + if (apply) target.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32); + } + + public void UpdateGeometry(TMP_Text target, Vector3 offset, Quaternion rotation, Vector3 scale, TMP_MeshInfo[] cachedMeshInfos, bool apply = true) + { + this.offset = offset; + this.rotation = rotation; + this.scale = scale; + + if (!apply) return; + + Vector3[] destinationVertices = _meshInfo.vertices; + Vector3[] cachedVertices = cachedMeshInfos[_matIndex].vertices; + destinationVertices[_firstVertexIndex] = cachedVertices[_firstVertexIndex + 0] - _charMidBaselineOffset; + destinationVertices[_firstVertexIndex + 1] = cachedVertices[_firstVertexIndex + 1] - _charMidBaselineOffset; + destinationVertices[_firstVertexIndex + 2] = cachedVertices[_firstVertexIndex + 2] - _charMidBaselineOffset; + destinationVertices[_firstVertexIndex + 3] = cachedVertices[_firstVertexIndex + 3] - _charMidBaselineOffset; + Matrix4x4 matrix = Matrix4x4.TRS(this.offset, this.rotation, this.scale); + destinationVertices[_firstVertexIndex] + = matrix.MultiplyPoint3x4(destinationVertices[_firstVertexIndex + 0]) + _charMidBaselineOffset + _bottomLeftShift; + destinationVertices[_firstVertexIndex + 1] + = matrix.MultiplyPoint3x4(destinationVertices[_firstVertexIndex + 1]) + _charMidBaselineOffset + _topLeftShift; + destinationVertices[_firstVertexIndex + 2] + = matrix.MultiplyPoint3x4(destinationVertices[_firstVertexIndex + 2]) + _charMidBaselineOffset + _topRightShift; + destinationVertices[_firstVertexIndex + 3] + = matrix.MultiplyPoint3x4(destinationVertices[_firstVertexIndex + 3]) + _charMidBaselineOffset + _bottomRightShift; + _meshInfo.mesh.vertices = _meshInfo.vertices; + target.UpdateGeometry(_meshInfo.mesh, _matIndex); + } + + public void ShiftVertices(TMP_Text target, Vector3 topLeftShift, Vector3 topRightShift, Vector3 bottomLeftShift, Vector3 bottomRightShift) + { + _topLeftShift += topLeftShift; + _topRightShift += topRightShift; + _bottomLeftShift += bottomLeftShift; + _bottomRightShift += bottomRightShift; + Vector3[] destinationVertices = _meshInfo.vertices; + destinationVertices[_firstVertexIndex] = destinationVertices[_firstVertexIndex] + _bottomLeftShift; + destinationVertices[_firstVertexIndex + 1] = destinationVertices[_firstVertexIndex + 1] + _topLeftShift; + destinationVertices[_firstVertexIndex + 2] = destinationVertices[_firstVertexIndex + 2] + _topRightShift; + destinationVertices[_firstVertexIndex + 3] = destinationVertices[_firstVertexIndex + 3] + _bottomRightShift; + _meshInfo.mesh.vertices = _meshInfo.vertices; + target.UpdateGeometry(_meshInfo.mesh, _matIndex); + } + + public void ResetVerticesShift(TMP_Text target) + { + Vector3[] destinationVertices = _meshInfo.vertices; + destinationVertices[_firstVertexIndex] = destinationVertices[_firstVertexIndex] - _bottomLeftShift; + destinationVertices[_firstVertexIndex + 1] = destinationVertices[_firstVertexIndex + 1] - _topLeftShift; + destinationVertices[_firstVertexIndex + 2] = destinationVertices[_firstVertexIndex + 2] - _topRightShift; + destinationVertices[_firstVertexIndex + 3] = destinationVertices[_firstVertexIndex + 3] - _bottomRightShift; + _meshInfo.mesh.vertices = _meshInfo.vertices; + target.UpdateGeometry(_meshInfo.mesh, _matIndex); + _topLeftShift = _topRightShift = _bottomLeftShift = _bottomRightShift = Vector3.zero; + } + } + } + + #endregion +} +#endif diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenTextMeshPro.cs.meta b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenTextMeshPro.cs.meta new file mode 100644 index 0000000..613cdbc --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenTextMeshPro.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8fb0d65aa5b048649a3a785b82b8f8db +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenTk2d.cs b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenTk2d.cs new file mode 100644 index 0000000..0c57bfe --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenTk2d.cs @@ -0,0 +1,247 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2014/10/27 15:59 +// +// License Copyright (c) Daniele Giardini. +// This work is subject to the terms at http://dotween.demigiant.com/license.php + +#if false // MODULE_MARKER +using DG.Tweening.Core; +using DG.Tweening.Plugins.Options; +using UnityEngine; + +namespace DG.Tweening +{ + /// + /// Methods that extend 2D Toolkit objects and allow to directly create and control tweens from their instances. + /// + public static class ShortcutExtensionsTk2d + { + #region Sprite + + /// Tweens a 2D Toolkit Sprite's dimensions to the given value. + /// Also stores the Sprite as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScale(this tk2dBaseSprite target, Vector3 endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.scale, x => target.scale = x, endValue, duration); + t.SetTarget(target); + return t; + } + /// Tweens a Sprite's dimensions to the given value. + /// Also stores the Sprite as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScaleX(this tk2dBaseSprite target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.scale, x => target.scale = x, new Vector3(endValue, 0, 0), duration); + t.SetOptions(AxisConstraint.X) + .SetTarget(target); + return t; + } + /// Tweens a Sprite's dimensions to the given value. + /// Also stores the Sprite as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScaleY(this tk2dBaseSprite target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.scale, x => target.scale = x, new Vector3(0, endValue, 0), duration); + t.SetOptions(AxisConstraint.Y) + .SetTarget(target); + return t; + } + /// Tweens a Sprite's dimensions to the given value. + /// Also stores the Sprite as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScaleZ(this tk2dBaseSprite target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.scale, x => target.scale = x, new Vector3(0, 0, endValue), duration); + t.SetOptions(AxisConstraint.Z) + .SetTarget(target); + return t; + } + + /// Tweens a 2D Toolkit Sprite's color to the given value. + /// Also stores the Sprite as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOColor(this tk2dBaseSprite target, Color endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a 2D Toolkit Sprite's alpha color to the given value. + /// Also stores the Sprite as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOFade(this tk2dBaseSprite target, float endValue, float duration) + { + TweenerCore t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a 2D Toolkit Sprite's color using the given gradient + /// (NOTE 1: only uses the colors of the gradient, not the alphas - NOTE 2: creates a Sequence, not a Tweener). + /// Also stores the image as the tween's target so it can be used for filtered operations + /// The gradient to useThe duration of the tween + public static Sequence DOGradientColor(this tk2dBaseSprite target, Gradient gradient, float duration) + { + Sequence s = DOTween.Sequence(); + GradientColorKey[] colors = gradient.colorKeys; + int len = colors.Length; + for (int i = 0; i < len; ++i) { + GradientColorKey c = colors[i]; + if (i == 0 && c.time <= 0) { + target.color = c.color; + continue; + } + float colorDuration = i == len - 1 + ? duration - s.Duration(false) // Verifies that total duration is correct + : duration * (i == 0 ? c.time : c.time - colors[i - 1].time); + s.Append(target.DOColor(c.color, colorDuration).SetEase(Ease.Linear)); + } + s.SetTarget(target); + return s; + } + + #endregion + + #region tk2dSlicedSprite + + /// Tweens a 2D Toolkit SlicedSprite's dimensions to the given value. + /// Also stores the SlicedSprite as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScaleDimensions(this tk2dSlicedSprite target, Vector2 endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.dimensions, x => target.dimensions = x, endValue, duration); + t.SetTarget(target); + return t; + } + /// Tweens a SlicedSprite's dimensions to the given value. + /// Also stores the SlicedSprite as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScaleDimensionsX(this tk2dSlicedSprite target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.dimensions, x => target.dimensions = x, new Vector2(endValue, 0), duration); + t.SetOptions(AxisConstraint.X) + .SetTarget(target); + return t; + } + /// Tweens a SlicedSprite's dimensions to the given value. + /// Also stores the SlicedSprite as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScaleDimensionsY(this tk2dSlicedSprite target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.dimensions, x => target.dimensions = x, new Vector2(0, endValue), duration); + t.SetOptions(AxisConstraint.Y) + .SetTarget(target); + return t; + } + + #endregion + + #region TextMesh + + /// Tweens a 2D Toolkit TextMesh's dimensions to the given value. + /// Also stores the TextMesh as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScale(this tk2dTextMesh target, Vector3 endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.scale, x => target.scale = x, endValue, duration); + t.SetTarget(target); + return t; + } + /// Tweens a 2D Toolkit TextMesh's dimensions to the given value. + /// Also stores the TextMesh as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScaleX(this tk2dTextMesh target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.scale, x => target.scale = x, new Vector3(endValue, 0, 0), duration); + t.SetOptions(AxisConstraint.X) + .SetTarget(target); + return t; + } + /// Tweens a 2D Toolkit TextMesh's dimensions to the given value. + /// Also stores the TextMesh as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScaleY(this tk2dTextMesh target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.scale, x => target.scale = x, new Vector3(0, endValue, 0), duration); + t.SetOptions(AxisConstraint.Y) + .SetTarget(target); + return t; + } + /// Tweens a 2D Toolkit TextMesh's dimensions to the given value. + /// Also stores the TextMesh as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOScaleZ(this tk2dTextMesh target, float endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.scale, x => target.scale = x, new Vector3(0, 0, endValue), duration); + t.SetOptions(AxisConstraint.Z) + .SetTarget(target); + return t; + } + + /// Tweens a 2D Toolkit TextMesh's color to the given value. + /// Also stores the TextMesh as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOColor(this tk2dTextMesh target, Color endValue, float duration) + { + TweenerCore t = DOTween.To(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a 2D Toolkit TextMesh's alpha color to the given value. + /// Also stores the TextMesh as the tween's target so it can be used for filtered operations + /// The end value to reachThe duration of the tween + public static TweenerCore DOFade(this tk2dTextMesh target, float endValue, float duration) + { + TweenerCore t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration); + t.SetTarget(target); + return t; + } + + /// Tweens a 2D Toolkit TextMesh's color using the given gradient + /// (NOTE 1: only uses the colors of the gradient, not the alphas - NOTE 2: creates a Sequence, not a Tweener). + /// Also stores the image as the tween's target so it can be used for filtered operations + /// The gradient to useThe duration of the tween + public static Sequence DOGradientColor(this tk2dTextMesh target, Gradient gradient, float duration) + { + Sequence s = DOTween.Sequence(); + GradientColorKey[] colors = gradient.colorKeys; + int len = colors.Length; + for (int i = 0; i < len; ++i) { + GradientColorKey c = colors[i]; + if (i == 0 && c.time <= 0) { + target.color = c.color; + continue; + } + float colorDuration = i == len - 1 + ? duration - s.Duration(false) // Verifies that total duration is correct + : duration * (i == 0 ? c.time : c.time - colors[i - 1].time); + s.Append(target.DOColor(c.color, colorDuration).SetEase(Ease.Linear)); + } + s.SetTarget(target); + return s; + } + + /// Tweens a tk2dTextMesh's text to the given value. + /// Also stores the tk2dTextMesh as the tween's target so it can be used for filtered operations + /// The end string to tween toThe duration of the tween + /// If TRUE (default), rich text will be interpreted correctly while animated, + /// otherwise all tags will be considered as normal text + /// The type of scramble mode to use, if any + /// A string containing the characters to use for scrambling. + /// Use as many characters as possible (minimum 10) because DOTween uses a fast scramble mode which gives better results with more characters. + /// Leave it to NULL (default) to use default ones + public static TweenerCore DOText(this tk2dTextMesh target, string endValue, float duration, bool richTextEnabled = true, ScrambleMode scrambleMode = ScrambleMode.None, string scrambleChars = null) + { + TweenerCore t = DOTween.To(() => target.text, x => target.text = x, endValue, duration); + t.SetOptions(richTextEnabled, scrambleMode, scrambleChars) + .SetTarget(target); + return t; + } + + #endregion + } +} +#endif diff --git a/Assets/Plugins/Demigiant/DOTweenPro/DOTweenTk2d.cs.meta b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenTk2d.cs.meta new file mode 100644 index 0000000..c909f96 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/DOTweenTk2d.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b590cd7c24ffa5d4faa5b6fa993cccad +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/Editor.meta b/Assets/Plugins/Demigiant/DOTweenPro/Editor.meta new file mode 100644 index 0000000..e9164f7 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/Editor.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 34ca5bde92f87fa4dbeb9593d201fde2 +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenAnimationInspector.cs b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenAnimationInspector.cs new file mode 100644 index 0000000..0b38964 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenAnimationInspector.cs @@ -0,0 +1,750 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2015/03/12 16:03 + +using System; +using System.Collections.Generic; +using System.IO; +using DG.DemiEditor; +using DG.DOTweenEditor.Core; +using DG.DOTweenEditor.UI; +using DG.Tweening; +using DG.Tweening.Core; +using UnityEditor; +using UnityEngine; +using DOTweenSettings = DG.Tweening.Core.DOTweenSettings; +#if true // UI_MARKER +using UnityEngine.UI; +#endif +#if false // TEXTMESHPRO_MARKER + using TMPro; +#endif + +namespace DG.DOTweenEditor +{ + [CustomEditor(typeof(DOTweenAnimation))] + public class DOTweenAnimationInspector : ABSAnimationInspector + { + enum FadeTargetType + { + CanvasGroup, + Image + } + + enum ChooseTargetMode + { + None, + BetweenCanvasGroupAndImage + } + + static readonly Dictionary _AnimationTypeToComponent = new Dictionary() { + { DOTweenAnimation.AnimationType.Move, new[] { +#if true // PHYSICS_MARKER + typeof(Rigidbody), +#endif +#if true // PHYSICS2D_MARKER + typeof(Rigidbody2D), +#endif +#if true // UI_MARKER + typeof(RectTransform), +#endif + typeof(Transform) + }}, + { DOTweenAnimation.AnimationType.Rotate, new[] { +#if true // PHYSICS_MARKER + typeof(Rigidbody), +#endif +#if true // PHYSICS2D_MARKER + typeof(Rigidbody2D), +#endif + typeof(Transform) + }}, + { DOTweenAnimation.AnimationType.LocalMove, new[] { typeof(Transform) } }, + { DOTweenAnimation.AnimationType.LocalRotate, new[] { typeof(Transform) } }, + { DOTweenAnimation.AnimationType.Scale, new[] { typeof(Transform) } }, + { DOTweenAnimation.AnimationType.Color, new[] { + typeof(Light), +#if true // SPRITE_MARKER + typeof(SpriteRenderer), +#endif +#if true // UI_MARKER + typeof(Image), typeof(Text), typeof(RawImage), typeof(Graphic), +#endif + typeof(Renderer), + }}, + { DOTweenAnimation.AnimationType.Fade, new[] { + typeof(Light), +#if true // SPRITE_MARKER + typeof(SpriteRenderer), +#endif +#if true // UI_MARKER + typeof(Image), typeof(Text), typeof(CanvasGroup), typeof(RawImage), typeof(Graphic), +#endif + typeof(Renderer), + }}, +#if true // UI_MARKER + { DOTweenAnimation.AnimationType.Text, new[] { typeof(Text) } }, +#endif + { DOTweenAnimation.AnimationType.PunchPosition, new[] { +#if true // UI_MARKER + typeof(RectTransform), +#endif + typeof(Transform) + }}, + { DOTweenAnimation.AnimationType.PunchRotation, new[] { typeof(Transform) } }, + { DOTweenAnimation.AnimationType.PunchScale, new[] { typeof(Transform) } }, + { DOTweenAnimation.AnimationType.ShakePosition, new[] { +#if true // UI_MARKER + typeof(RectTransform), +#endif + typeof(Transform) + }}, + { DOTweenAnimation.AnimationType.ShakeRotation, new[] { typeof(Transform) } }, + { DOTweenAnimation.AnimationType.ShakeScale, new[] { typeof(Transform) } }, + { DOTweenAnimation.AnimationType.CameraAspect, new[] { typeof(Camera) } }, + { DOTweenAnimation.AnimationType.CameraBackgroundColor, new[] { typeof(Camera) } }, + { DOTweenAnimation.AnimationType.CameraFieldOfView, new[] { typeof(Camera) } }, + { DOTweenAnimation.AnimationType.CameraOrthoSize, new[] { typeof(Camera) } }, + { DOTweenAnimation.AnimationType.CameraPixelRect, new[] { typeof(Camera) } }, + { DOTweenAnimation.AnimationType.CameraRect, new[] { typeof(Camera) } }, +#if true // UI_MARKER + { DOTweenAnimation.AnimationType.UIWidthHeight, new[] { typeof(RectTransform) } }, +#endif + }; + +#if false // TK2D_MARKER + static readonly Dictionary _Tk2dAnimationTypeToComponent = new Dictionary() { + { DOTweenAnimation.AnimationType.Scale, new[] { typeof(tk2dBaseSprite), typeof(tk2dTextMesh) } }, + { DOTweenAnimation.AnimationType.Color, new[] { typeof(tk2dBaseSprite), typeof(tk2dTextMesh) } }, + { DOTweenAnimation.AnimationType.Fade, new[] { typeof(tk2dBaseSprite), typeof(tk2dTextMesh) } }, + { DOTweenAnimation.AnimationType.Text, new[] { typeof(tk2dTextMesh) } } + }; +#endif +#if false // TEXTMESHPRO_MARKER + static readonly Dictionary _TMPAnimationTypeToComponent = new Dictionary() { + { DOTweenAnimation.AnimationType.Color, new[] { typeof(TextMeshPro), typeof(TextMeshProUGUI) } }, + { DOTweenAnimation.AnimationType.Fade, new[] { typeof(TextMeshPro), typeof(TextMeshProUGUI) } }, + { DOTweenAnimation.AnimationType.Text, new[] { typeof(TextMeshPro), typeof(TextMeshProUGUI) } } + }; +#endif + + static readonly string[] _AnimationType = new[] { + "None", + "Move", "LocalMove", + "Rotate", "LocalRotate", + "Scale", + "Color", "Fade", +#if true // UI_MARKER + "Text", +#endif +#if false // TK2D_MARKER + "Text", +#endif +#if false // TEXTMESHPRO_MARKER + "Text", +#endif +#if true // UI_MARKER + "UIWidthHeight", +#endif + "Punch/Position", "Punch/Rotation", "Punch/Scale", + "Shake/Position", "Shake/Rotation", "Shake/Scale", + "Camera/Aspect", "Camera/BackgroundColor", "Camera/FieldOfView", "Camera/OrthoSize", "Camera/PixelRect", "Camera/Rect" + }; + static string[] _animationTypeNoSlashes; // _AnimationType list without slashes in values + static string[] _datString; // String representation of DOTweenAnimation enum (here for caching reasons) + + DOTweenAnimation _src; + DOTweenSettings _settings; + bool _runtimeEditMode; // If TRUE allows to change and save stuff at runtime + bool _refreshRequired; // If TRUE refreshes components data + int _totComponentsOnSrc; // Used to determine if a Component is added or removed from the source + bool _isLightSrc; // Used to determine if we're tweening a Light, to set the max Fade value to more than 1 +#pragma warning disable 414 + ChooseTargetMode _chooseTargetMode = ChooseTargetMode.None; +#pragma warning restore 414 + + static readonly GUIContent _GuiC_selfTarget_true = new GUIContent( + "SELF", "Will animate components on this gameObject" + ); + static readonly GUIContent _GuiC_selfTarget_false = new GUIContent( + "OTHER", "Will animate components on the given gameObject instead than on this one" + ); + static readonly GUIContent _GuiC_tweenTargetIsTargetGO_true = new GUIContent( + "Use As Tween Target", "Will set the tween target (via SetTarget, used to control a tween directly from a target) to the \"OTHER\" gameObject" + ); + static readonly GUIContent _GuiC_tweenTargetIsTargetGO_false = new GUIContent( + "Use As Tween Target", "Will set the tween target (via SetTarget, used to control a tween directly from a target) to the gameObject containing this animation, not the \"OTHER\" one" + ); + + #region MonoBehaviour Methods + + void OnEnable() + { + _src = target as DOTweenAnimation; + _settings = DOTweenUtilityWindow.GetDOTweenSettings(); + + onStartProperty = base.serializedObject.FindProperty("onStart"); + onPlayProperty = base.serializedObject.FindProperty("onPlay"); + onUpdateProperty = base.serializedObject.FindProperty("onUpdate"); + onStepCompleteProperty = base.serializedObject.FindProperty("onStepComplete"); + onCompleteProperty = base.serializedObject.FindProperty("onComplete"); + onRewindProperty = base.serializedObject.FindProperty("onRewind"); + onTweenCreatedProperty = base.serializedObject.FindProperty("onTweenCreated"); + + // Convert _AnimationType to _animationTypeNoSlashes + int len = _AnimationType.Length; + _animationTypeNoSlashes = new string[len]; + for (int i = 0; i < len; ++i) { + string a = _AnimationType[i]; + a = a.Replace("/", ""); + _animationTypeNoSlashes[i] = a; + } + } + + void OnDisable() + { + DOTweenPreviewManager.StopAllPreviews(); + } + + override public void OnInspectorGUI() + { + base.OnInspectorGUI(); + + GUILayout.Space(3); + EditorGUIUtils.SetGUIStyles(); + + bool playMode = Application.isPlaying; + _runtimeEditMode = _runtimeEditMode && playMode; + + GUILayout.BeginHorizontal(); + EditorGUIUtils.InspectorLogo(); + GUILayout.Label(_src.animationType.ToString() + (string.IsNullOrEmpty(_src.id) ? "" : " [" + _src.id + "]"), EditorGUIUtils.sideLogoIconBoldLabelStyle); + // Up-down buttons + GUILayout.FlexibleSpace(); + if (GUILayout.Button("▲", DeGUI.styles.button.toolIco)) UnityEditorInternal.ComponentUtility.MoveComponentUp(_src); + if (GUILayout.Button("▼", DeGUI.styles.button.toolIco)) UnityEditorInternal.ComponentUtility.MoveComponentDown(_src); + GUILayout.EndHorizontal(); + + if (playMode) { + if (_runtimeEditMode) { + + } else { + GUILayout.Space(8); + GUILayout.Label("Animation Editor disabled while in play mode", EditorGUIUtils.wordWrapLabelStyle); + if (!_src.isActive) { + GUILayout.Label("This animation has been toggled as inactive and won't be generated", EditorGUIUtils.wordWrapLabelStyle); + GUI.enabled = false; + } + if (GUILayout.Button(new GUIContent("Activate Edit Mode", "Switches to Runtime Edit Mode, where you can change animations values and restart them"))) { + _runtimeEditMode = true; + } + GUILayout.Label("NOTE: when using DOPlayNext, the sequence is determined by the DOTweenAnimation Components order in the target GameObject's Inspector", EditorGUIUtils.wordWrapLabelStyle); + GUILayout.Space(10); + if (!_runtimeEditMode) return; + } + } + + Undo.RecordObject(_src, "DOTween Animation"); + Undo.RecordObject(_settings, "DOTween Animation"); + +// _src.isValid = Validate(); // Moved down + + EditorGUIUtility.labelWidth = 110; + + if (playMode) { + GUILayout.Space(4); + DeGUILayout.Toolbar("Edit Mode Commands"); + DeGUILayout.BeginVBox(DeGUI.styles.box.stickyTop); + GUILayout.BeginHorizontal(); + if (GUILayout.Button("TogglePause")) _src.tween.TogglePause(); + if (GUILayout.Button("Rewind")) _src.tween.Rewind(); + if (GUILayout.Button("Restart")) _src.tween.Restart(); + GUILayout.EndHorizontal(); + if (GUILayout.Button("Commit changes and restart")) { + _src.tween.Rewind(); + _src.tween.Kill(); + if (_src.isValid) { + _src.CreateTween(); + _src.tween.Play(); + } + } + GUILayout.Label("To apply your changes when exiting Play mode, use the Component's upper right menu and choose \"Copy Component\", then \"Paste Component Values\" after exiting Play mode", DeGUI.styles.label.wordwrap); + DeGUILayout.EndVBox(); + } else { + GUILayout.BeginHorizontal(); + bool hasManager = _src.GetComponent() != null; + EditorGUI.BeginChangeCheck(); + _settings.showPreviewPanel = hasManager + ? DeGUILayout.ToggleButton(_settings.showPreviewPanel, "Preview Controls", styles.custom.inlineToggle) + : DeGUILayout.ToggleButton(_settings.showPreviewPanel, "Preview Controls", styles.custom.inlineToggle, GUILayout.Width(120)); + if (EditorGUI.EndChangeCheck()) { + EditorUtility.SetDirty(_settings); + DOTweenPreviewManager.StopAllPreviews(); + } + if (!hasManager) { + if (GUILayout.Button(new GUIContent("Add Manager", "Adds a manager component which allows you to choose additional options for this gameObject"))) { + _src.gameObject.AddComponent(); + } + } + GUILayout.EndHorizontal(); + } + + // Preview in editor + bool isPreviewing = _settings.showPreviewPanel ? DOTweenPreviewManager.PreviewGUI(_src) : false; + + EditorGUI.BeginDisabledGroup(isPreviewing); + // Choose target + GUILayout.BeginHorizontal(); + _src.isActive = EditorGUILayout.Toggle(new GUIContent("", "If unchecked, this animation will not be created"), _src.isActive, GUILayout.Width(14)); + EditorGUI.BeginChangeCheck(); + EditorGUI.BeginChangeCheck(); + _src.targetIsSelf = DeGUILayout.ToggleButton( + _src.targetIsSelf, _src.targetIsSelf ? _GuiC_selfTarget_true : _GuiC_selfTarget_false, + new Color(1f, 0.78f, 0f), DeGUI.colors.bg.toggleOn, new Color(0.33f, 0.14f, 0.02f), DeGUI.colors.content.toggleOn, + null, GUILayout.Width(47) + ); + bool innerChanged = EditorGUI.EndChangeCheck(); + if (innerChanged) { + _src.targetGO = null; + GUI.changed = true; + } + if (_src.targetIsSelf) GUILayout.Label(_GuiC_selfTarget_true.tooltip); + else { + using (new DeGUI.ColorScope(null, null, _src.targetGO == null ? Color.red : Color.white)) { + _src.targetGO = (GameObject)EditorGUILayout.ObjectField(_src.targetGO, typeof(GameObject), true); + } + _src.tweenTargetIsTargetGO = DeGUILayout.ToggleButton( + _src.tweenTargetIsTargetGO, _src.tweenTargetIsTargetGO ? _GuiC_tweenTargetIsTargetGO_true : _GuiC_tweenTargetIsTargetGO_false, + GUILayout.Width(131) + ); + } + bool check = EditorGUI.EndChangeCheck(); + if (check) _refreshRequired = true; + GUILayout.EndHorizontal(); + + GameObject targetGO = _src.targetIsSelf ? _src.gameObject : _src.targetGO; + + if (targetGO == null) { + // Uses external target gameObject but it's not set + if (_src.targetGO != null || _src.target != null) { + _src.targetGO = null; + _src.target = null; + GUI.changed = true; + } + } else { + GUILayout.BeginHorizontal(); + DOTweenAnimation.AnimationType prevAnimType = _src.animationType; +// _src.animationType = (DOTweenAnimation.AnimationType)EditorGUILayout.EnumPopup(_src.animationType, EditorGUIUtils.popupButton); + GUI.enabled = GUI.enabled && _src.isActive; + _src.animationType = AnimationToDOTweenAnimationType(_AnimationType[EditorGUILayout.Popup(DOTweenAnimationTypeToPopupId(_src.animationType), _AnimationType)]); + _src.autoGenerate = DeGUILayout.ToggleButton(_src.autoGenerate, new GUIContent("AutoGenerate", "If selected, the tween will be generated at startup (during Start for RectTransform position tween, Awake for all the others)")); + if (_src.autoGenerate) { + _src.autoPlay = DeGUILayout.ToggleButton(_src.autoPlay, new GUIContent("AutoPlay", "If selected, the tween will play automatically")); + } + _src.autoKill = DeGUILayout.ToggleButton(_src.autoKill, new GUIContent("AutoKill", "If selected, the tween will be killed when it completes, and won't be reusable")); + GUILayout.EndHorizontal(); + if (prevAnimType != _src.animationType) { + // Set default optional values based on animation type + _src.endValueTransform = null; + _src.useTargetAsV3 = false; + switch (_src.animationType) { + case DOTweenAnimation.AnimationType.Move: + case DOTweenAnimation.AnimationType.LocalMove: + case DOTweenAnimation.AnimationType.Rotate: + case DOTweenAnimation.AnimationType.LocalRotate: + case DOTweenAnimation.AnimationType.Scale: + _src.endValueV3 = Vector3.zero; + _src.endValueFloat = 0; + _src.optionalBool0 = _src.animationType == DOTweenAnimation.AnimationType.Scale; + break; + case DOTweenAnimation.AnimationType.UIWidthHeight: + _src.endValueV3 = Vector3.zero; + _src.endValueFloat = 0; + _src.optionalBool0 = _src.animationType == DOTweenAnimation.AnimationType.UIWidthHeight; + break; + case DOTweenAnimation.AnimationType.Color: + case DOTweenAnimation.AnimationType.Fade: + _isLightSrc = targetGO.GetComponent() != null; + _src.endValueFloat = 0; + break; + case DOTweenAnimation.AnimationType.Text: + _src.optionalBool0 = true; + break; + case DOTweenAnimation.AnimationType.PunchPosition: + case DOTweenAnimation.AnimationType.PunchRotation: + case DOTweenAnimation.AnimationType.PunchScale: + _src.endValueV3 = _src.animationType == DOTweenAnimation.AnimationType.PunchRotation ? new Vector3(0, 180, 0) : Vector3.one; + _src.optionalFloat0 = 1; + _src.optionalInt0 = 10; + _src.optionalBool0 = false; + break; + case DOTweenAnimation.AnimationType.ShakePosition: + case DOTweenAnimation.AnimationType.ShakeRotation: + case DOTweenAnimation.AnimationType.ShakeScale: + _src.endValueV3 = _src.animationType == DOTweenAnimation.AnimationType.ShakeRotation ? new Vector3(90, 90, 90) : Vector3.one; + _src.optionalInt0 = 10; + _src.optionalFloat0 = 90; + _src.optionalBool0 = false; + _src.optionalBool1 = true; + break; + case DOTweenAnimation.AnimationType.CameraAspect: + case DOTweenAnimation.AnimationType.CameraFieldOfView: + case DOTweenAnimation.AnimationType.CameraOrthoSize: + _src.endValueFloat = 0; + break; + case DOTweenAnimation.AnimationType.CameraPixelRect: + case DOTweenAnimation.AnimationType.CameraRect: + _src.endValueRect = new Rect(0, 0, 0, 0); + break; + } + } + if (_src.animationType == DOTweenAnimation.AnimationType.None) { + _src.isValid = false; + if (GUI.changed) EditorUtility.SetDirty(_src); + return; + } + + if (_refreshRequired || prevAnimType != _src.animationType || ComponentsChanged()) { + _refreshRequired = false; + _src.isValid = Validate(targetGO); + // See if we need to choose between multiple targets +#if true // UI_MARKER + if (_src.animationType == DOTweenAnimation.AnimationType.Fade && targetGO.GetComponent() != null && targetGO.GetComponent() != null) { + _chooseTargetMode = ChooseTargetMode.BetweenCanvasGroupAndImage; + // Reassign target and forcedTargetType if lost + if (_src.forcedTargetType == DOTweenAnimation.TargetType.Unset) _src.forcedTargetType = _src.targetType; + switch (_src.forcedTargetType) { + case DOTweenAnimation.TargetType.CanvasGroup: + _src.target = targetGO.GetComponent(); + break; + case DOTweenAnimation.TargetType.Image: + _src.target = targetGO.GetComponent(); + break; + } + } else { +#endif + _chooseTargetMode = ChooseTargetMode.None; + _src.forcedTargetType = DOTweenAnimation.TargetType.Unset; +#if true // UI_MARKER + } +#endif + } + + if (!_src.isValid) { + GUI.color = Color.red; + GUILayout.BeginVertical(GUI.skin.box); + GUILayout.Label("No valid Component was found for the selected animation", EditorGUIUtils.wordWrapLabelStyle); + GUILayout.EndVertical(); + GUI.color = Color.white; + if (GUI.changed) EditorUtility.SetDirty(_src); + return; + } + +#if true // UI_MARKER + // Special cases in which multiple target types could be used (set after validation) + if (_chooseTargetMode == ChooseTargetMode.BetweenCanvasGroupAndImage && _src.forcedTargetType != DOTweenAnimation.TargetType.Unset) { + FadeTargetType fadeTargetType = (FadeTargetType)Enum.Parse(typeof(FadeTargetType), _src.forcedTargetType.ToString()); + DOTweenAnimation.TargetType prevTargetType = _src.forcedTargetType; + _src.forcedTargetType = (DOTweenAnimation.TargetType)Enum.Parse(typeof(DOTweenAnimation.TargetType), EditorGUILayout.EnumPopup(_src.animationType + " Target", fadeTargetType).ToString()); + if (_src.forcedTargetType != prevTargetType) { + // Target type change > assign correct target + switch (_src.forcedTargetType) { + case DOTweenAnimation.TargetType.CanvasGroup: + _src.target = targetGO.GetComponent(); + break; + case DOTweenAnimation.TargetType.Image: + _src.target = targetGO.GetComponent(); + break; + } + } + } +#endif + + GUILayout.BeginHorizontal(); + _src.duration = EditorGUILayout.FloatField("Duration", _src.duration); + if (_src.duration < 0) _src.duration = 0; + _src.isSpeedBased = DeGUILayout.ToggleButton(_src.isSpeedBased, new GUIContent("SpeedBased", "If selected, the duration will count as units/degree x second"), DeGUI.styles.button.tool, GUILayout.Width(75)); + GUILayout.EndHorizontal(); + _src.delay = EditorGUILayout.FloatField("Delay", _src.delay); + if (_src.delay < 0) _src.delay = 0; + _src.isIndependentUpdate = EditorGUILayout.Toggle("Ignore TimeScale", _src.isIndependentUpdate); + _src.easeType = EditorGUIUtils.FilteredEasePopup("Ease", _src.easeType); + if (_src.easeType == Ease.INTERNAL_Custom) { + _src.easeCurve = EditorGUILayout.CurveField(" Ease Curve", _src.easeCurve); + } + _src.loops = EditorGUILayout.IntField(new GUIContent("Loops", "Set to -1 for infinite loops"), _src.loops); + if (_src.loops < -1) _src.loops = -1; + if (_src.loops > 1 || _src.loops == -1) + _src.loopType = (LoopType)EditorGUILayout.EnumPopup(" Loop Type", _src.loopType); + _src.id = EditorGUILayout.TextField("ID", _src.id); + + bool canBeRelative = true; + // End value and eventual specific options + switch (_src.animationType) { + case DOTweenAnimation.AnimationType.Move: + case DOTweenAnimation.AnimationType.LocalMove: + GUIEndValueV3(targetGO, _src.animationType == DOTweenAnimation.AnimationType.Move); + _src.optionalBool0 = EditorGUILayout.Toggle(" Snapping", _src.optionalBool0); + canBeRelative = !_src.useTargetAsV3; + break; + case DOTweenAnimation.AnimationType.Rotate: + case DOTweenAnimation.AnimationType.LocalRotate: + bool isRigidbody2D = DOTweenModuleUtils.Physics.HasRigidbody2D(_src); + if (isRigidbody2D) GUIEndValueFloat(); + else { + GUIEndValueV3(targetGO); + _src.optionalRotationMode = (RotateMode)EditorGUILayout.EnumPopup(" Rotation Mode", _src.optionalRotationMode); + } + break; + case DOTweenAnimation.AnimationType.Scale: + if (_src.optionalBool0) GUIEndValueFloat(); + else GUIEndValueV3(targetGO); + _src.optionalBool0 = EditorGUILayout.Toggle("Uniform Scale", _src.optionalBool0); + break; + case DOTweenAnimation.AnimationType.UIWidthHeight: + if (_src.optionalBool0) GUIEndValueFloat(); + else GUIEndValueV2(); + _src.optionalBool0 = EditorGUILayout.Toggle("Uniform Scale", _src.optionalBool0); + break; + case DOTweenAnimation.AnimationType.Color: + GUIEndValueColor(); + canBeRelative = false; + break; + case DOTweenAnimation.AnimationType.Fade: + GUIEndValueFloat(); + if (_src.endValueFloat < 0) _src.endValueFloat = 0; + if (!_isLightSrc && _src.endValueFloat > 1) _src.endValueFloat = 1; + canBeRelative = false; + break; + case DOTweenAnimation.AnimationType.Text: + GUIEndValueString(); + _src.optionalBool0 = EditorGUILayout.Toggle("Rich Text Enabled", _src.optionalBool0); + _src.optionalScrambleMode = (ScrambleMode)EditorGUILayout.EnumPopup("Scramble Mode", _src.optionalScrambleMode); + _src.optionalString = EditorGUILayout.TextField(new GUIContent("Custom Scramble", "Custom characters to use in case of ScrambleMode.Custom"), _src.optionalString); + break; + case DOTweenAnimation.AnimationType.PunchPosition: + case DOTweenAnimation.AnimationType.PunchRotation: + case DOTweenAnimation.AnimationType.PunchScale: + GUIEndValueV3(targetGO); + canBeRelative = false; + _src.optionalInt0 = EditorGUILayout.IntSlider(new GUIContent(" Vibrato", "How much will the punch vibrate"), _src.optionalInt0, 1, 50); + _src.optionalFloat0 = EditorGUILayout.Slider(new GUIContent(" Elasticity", "How much the vector will go beyond the starting position when bouncing backwards"), _src.optionalFloat0, 0, 1); + if (_src.animationType == DOTweenAnimation.AnimationType.PunchPosition) _src.optionalBool0 = EditorGUILayout.Toggle(" Snapping", _src.optionalBool0); + break; + case DOTweenAnimation.AnimationType.ShakePosition: + case DOTweenAnimation.AnimationType.ShakeRotation: + case DOTweenAnimation.AnimationType.ShakeScale: + GUIEndValueV3(targetGO); + canBeRelative = false; + _src.optionalInt0 = EditorGUILayout.IntSlider(new GUIContent(" Vibrato", "How much will the shake vibrate"), _src.optionalInt0, 1, 50); + _src.optionalFloat0 = EditorGUILayout.Slider(new GUIContent(" Randomness", "The shake randomness"), _src.optionalFloat0, 0, 90); + _src.optionalBool1 = EditorGUILayout.Toggle(new GUIContent(" FadeOut", "If selected the shake will fade out, otherwise it will constantly play with full force"), _src.optionalBool1); + if (_src.animationType == DOTweenAnimation.AnimationType.ShakePosition) _src.optionalBool0 = EditorGUILayout.Toggle(" Snapping", _src.optionalBool0); + break; + case DOTweenAnimation.AnimationType.CameraAspect: + case DOTweenAnimation.AnimationType.CameraFieldOfView: + case DOTweenAnimation.AnimationType.CameraOrthoSize: + GUIEndValueFloat(); + canBeRelative = false; + break; + case DOTweenAnimation.AnimationType.CameraBackgroundColor: + GUIEndValueColor(); + canBeRelative = false; + break; + case DOTweenAnimation.AnimationType.CameraPixelRect: + case DOTweenAnimation.AnimationType.CameraRect: + GUIEndValueRect(); + canBeRelative = false; + break; + } + + // Final settings + if (canBeRelative) _src.isRelative = EditorGUILayout.Toggle(" Relative", _src.isRelative); + + // Events + AnimationInspectorGUI.AnimationEvents(this, _src); + } + EditorGUI.EndDisabledGroup(); + + if (GUI.changed) EditorUtility.SetDirty(_src); + } + + #endregion + + #region Methods + + // Returns TRUE if the Component layout on the src gameObject changed (a Component was added or removed) + bool ComponentsChanged() + { + int prevTotComponentsOnSrc = _totComponentsOnSrc; + _totComponentsOnSrc = _src.gameObject.GetComponents().Length; + return prevTotComponentsOnSrc != _totComponentsOnSrc; + } + + // Checks if a Component that can be animated with the given animationType is attached to the src + bool Validate(GameObject targetGO) + { + if (_src.animationType == DOTweenAnimation.AnimationType.None) return false; + + Component srcTarget; + // First check for external plugins +#if false // TK2D_MARKER + if (_Tk2dAnimationTypeToComponent.ContainsKey(_src.animationType)) { + foreach (Type t in _Tk2dAnimationTypeToComponent[_src.animationType]) { + srcTarget = targetGO.GetComponent(t); + if (srcTarget != null) { + _src.target = srcTarget; + _src.targetType = DOTweenAnimation.TypeToDOTargetType(t); + return true; + } + } + } +#endif +#if false // TEXTMESHPRO_MARKER + if (_TMPAnimationTypeToComponent.ContainsKey(_src.animationType)) { + foreach (Type t in _TMPAnimationTypeToComponent[_src.animationType]) { + srcTarget = targetGO.GetComponent(t); + if (srcTarget != null) { + _src.target = srcTarget; + _src.targetType = DOTweenAnimation.TypeToDOTargetType(t); + return true; + } + } + } +#endif + // Then check for regular stuff + if (_AnimationTypeToComponent.ContainsKey(_src.animationType)) { + foreach (Type t in _AnimationTypeToComponent[_src.animationType]) { + srcTarget = targetGO.GetComponent(t); + if (srcTarget != null) { + _src.target = srcTarget; + _src.targetType = DOTweenAnimation.TypeToDOTargetType(t); + return true; + } + } + } + return false; + } + + DOTweenAnimation.AnimationType AnimationToDOTweenAnimationType(string animation) + { + if (_datString == null) _datString = Enum.GetNames(typeof(DOTweenAnimation.AnimationType)); + animation = animation.Replace("/", ""); + return (DOTweenAnimation.AnimationType)(Array.IndexOf(_datString, animation)); + } + int DOTweenAnimationTypeToPopupId(DOTweenAnimation.AnimationType animation) + { + return Array.IndexOf(_animationTypeNoSlashes, animation.ToString()); + } + + #endregion + + #region GUI Draw Methods + + void GUIEndValueFloat() + { + GUILayout.BeginHorizontal(); + GUIToFromButton(); + _src.endValueFloat = EditorGUILayout.FloatField(_src.endValueFloat); + GUILayout.EndHorizontal(); + } + + void GUIEndValueColor() + { + GUILayout.BeginHorizontal(); + GUIToFromButton(); + _src.endValueColor = EditorGUILayout.ColorField(_src.endValueColor); + GUILayout.EndHorizontal(); + } + + void GUIEndValueV3(GameObject targetGO, bool optionalTransform = false) + { + GUILayout.BeginHorizontal(); + GUIToFromButton(); + if (_src.useTargetAsV3) { + Transform prevT = _src.endValueTransform; + _src.endValueTransform = EditorGUILayout.ObjectField(_src.endValueTransform, typeof(Transform), true) as Transform; + if (_src.endValueTransform != prevT && _src.endValueTransform != null) { +#if true // UI_MARKER + // Check that it's a Transform for a Transform or a RectTransform for a RectTransform + if (targetGO.GetComponent() != null) { + if (_src.endValueTransform.GetComponent() == null) { + EditorUtility.DisplayDialog("DOTween Pro", "For Unity UI elements, the target must also be a UI element", "Ok"); + _src.endValueTransform = null; + } + } else if (_src.endValueTransform.GetComponent() != null) { + EditorUtility.DisplayDialog("DOTween Pro", "You can't use a UI target for a non UI object", "Ok"); + _src.endValueTransform = null; + } +#endif + } + } else { + _src.endValueV3 = EditorGUILayout.Vector3Field("", _src.endValueV3, GUILayout.Height(16)); + } + if (optionalTransform) { + if (GUILayout.Button(_src.useTargetAsV3 ? "target" : "value", EditorGUIUtils.sideBtStyle, GUILayout.Width(44))) _src.useTargetAsV3 = !_src.useTargetAsV3; + } + GUILayout.EndHorizontal(); +#if true // UI_MARKER + if (_src.useTargetAsV3 && _src.endValueTransform != null && _src.target is RectTransform) { + EditorGUILayout.HelpBox("NOTE: when using a UI target, the tween will be created during Start instead of Awake", MessageType.Info); + } +#endif + } + + void GUIEndValueV2() + { + GUILayout.BeginHorizontal(); + GUIToFromButton(); + _src.endValueV2 = EditorGUILayout.Vector2Field("", _src.endValueV2, GUILayout.Height(16)); + GUILayout.EndHorizontal(); + } + + void GUIEndValueString() + { + GUILayout.BeginHorizontal(); + GUIToFromButton(); + _src.endValueString = EditorGUILayout.TextArea(_src.endValueString, EditorGUIUtils.wordWrapTextArea); + GUILayout.EndHorizontal(); + } + + void GUIEndValueRect() + { + GUILayout.BeginHorizontal(); + GUIToFromButton(); + _src.endValueRect = EditorGUILayout.RectField(_src.endValueRect); + GUILayout.EndHorizontal(); + } + + void GUIToFromButton() + { + if (GUILayout.Button(_src.isFrom ? "FROM" : "TO", EditorGUIUtils.sideBtStyle, GUILayout.Width(90))) _src.isFrom = !_src.isFrom; + GUILayout.Space(16); + } + + #endregion + } + + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + // ███ INTERNAL CLASSES ████████████████████████████████████████████████████████████████████████████████████████████████ + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + + [InitializeOnLoad] + static class Initializer + { + static Initializer() + { + DOTweenAnimation.OnReset += OnReset; + } + + static void OnReset(DOTweenAnimation src) + { + DOTweenSettings settings = DOTweenUtilityWindow.GetDOTweenSettings(); + if (settings == null) return; + + Undo.RecordObject(src, "DOTweenAnimation"); + src.autoPlay = settings.defaultAutoPlay == AutoPlay.All || settings.defaultAutoPlay == AutoPlay.AutoPlayTweeners; + src.autoKill = settings.defaultAutoKill; + EditorUtility.SetDirty(src); + } + } +} diff --git a/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenAnimationInspector.cs.meta b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenAnimationInspector.cs.meta new file mode 100644 index 0000000..d2d7eee --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenAnimationInspector.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e0203fd81362bab4d842d87ad09ee76e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenPreviewManager.cs b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenPreviewManager.cs new file mode 100644 index 0000000..e607979 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenPreviewManager.cs @@ -0,0 +1,263 @@ +// Author: Daniele Giardini - http://www.demigiant.com +// Created: 2015/03/12 16:03 + +using System; +using System.Collections.Generic; +using DG.DemiEditor; +using DG.DemiLib; +using DG.Tweening; +using DG.Tweening.Core; +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace DG.DOTweenEditor +{ + public static class DOTweenPreviewManager + { + static bool _previewOnlyIfSetToAutoPlay = true; + static readonly Dictionary _AnimationToTween = new Dictionary(); + static readonly List _TmpKeys = new List(); + + #region Public Methods & GUI + + /// + /// Returns TRUE if its actually previewing animations + /// + public static bool PreviewGUI(DOTweenAnimation src) + { + if (EditorApplication.isPlaying) return false; + + Styles.Init(); + + bool isPreviewing = _AnimationToTween.Count > 0; + bool isPreviewingThis = isPreviewing && _AnimationToTween.ContainsKey(src); + + // Preview in editor + GUI.backgroundColor = isPreviewing + ? new DeSkinColor(new Color(0.49f, 0.8f, 0.86f), new Color(0.15f, 0.26f, 0.35f)) + : new DeSkinColor(Color.white, new Color(0.13f, 0.13f, 0.13f)); + GUILayout.BeginVertical(Styles.previewBox); + DeGUI.ResetGUIColors(); + GUILayout.BeginHorizontal(); + GUILayout.Label("Preview Mode - Experimental", Styles.previewLabel); + _previewOnlyIfSetToAutoPlay = DeGUILayout.ToggleButton( + _previewOnlyIfSetToAutoPlay, + new GUIContent("AutoPlay only", "If toggled only previews animations that have AutoPlay turned ON"), + Styles.btOption + ); + GUILayout.EndHorizontal(); + GUILayout.Space(1); + // Preview - Play + GUILayout.BeginHorizontal(); + EditorGUI.BeginDisabledGroup( + isPreviewingThis || src.animationType == DOTweenAnimation.AnimationType.None + || !src.isActive || _previewOnlyIfSetToAutoPlay && !src.autoPlay + ); + if (GUILayout.Button("► Play", Styles.btPreview)) { + if (!isPreviewing) StartupGlobalPreview(); + AddAnimationToGlobalPreview(src); + } + EditorGUI.EndDisabledGroup(); + EditorGUI.BeginDisabledGroup(isPreviewing); + if (GUILayout.Button("► Play All on GameObject", Styles.btPreview)) { + if (!isPreviewing) StartupGlobalPreview(); + DOTweenAnimation[] anims = src.gameObject.GetComponents(); + foreach (DOTweenAnimation anim in anims) AddAnimationToGlobalPreview(anim); + } + if (GUILayout.Button("► Play All in Scene", Styles.btPreview)) { + if (!isPreviewing) StartupGlobalPreview(); + DOTweenAnimation[] anims = Object.FindObjectsOfType(); + foreach (DOTweenAnimation anim in anims) AddAnimationToGlobalPreview(anim); + } + EditorGUI.EndDisabledGroup(); + GUILayout.EndHorizontal(); + // Preview - Stop + GUILayout.BeginHorizontal(); + EditorGUI.BeginDisabledGroup(!isPreviewingThis); + if (GUILayout.Button("■ Stop", Styles.btPreview)) { + if (_AnimationToTween.ContainsKey(src)) StopPreview(_AnimationToTween[src].tween); + } + EditorGUI.EndDisabledGroup(); + EditorGUI.BeginDisabledGroup(!isPreviewing); + if (GUILayout.Button("■ Stop All on GameObject", Styles.btPreview)) { + StopPreview(src.gameObject); + } + if (GUILayout.Button("■ Stop All in Scene", Styles.btPreview)) { + StopAllPreviews(); + } + EditorGUI.EndDisabledGroup(); + GUILayout.EndHorizontal(); + if (isPreviewing) { + int playingTweens = 0; + int completedTweens = 0; + int pausedTweens = 0; + foreach (KeyValuePair kvp in _AnimationToTween) { + Tween t = kvp.Value.tween; + if (t.IsPlaying()) playingTweens++; + else if (t.IsComplete()) completedTweens++; + else pausedTweens++; + } + GUILayout.Label("Playing Tweens: " + playingTweens, Styles.previewStatusLabel); + GUILayout.Label("Completed Tweens: " + completedTweens, Styles.previewStatusLabel); +// GUILayout.Label("Paused Tweens: " + playingTweens); + } + GUILayout.EndVertical(); + + return isPreviewing; + } + +#if !(UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5) + public static void StopAllPreviews(PlayModeStateChange state) + { + StopAllPreviews(); + } +#endif + + public static void StopAllPreviews() + { + _TmpKeys.Clear(); + foreach (KeyValuePair kvp in _AnimationToTween) { + _TmpKeys.Add(kvp.Key); + } + StopPreview(_TmpKeys); + _TmpKeys.Clear(); + _AnimationToTween.Clear(); + + DOTweenEditorPreview.Stop(); +#if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5 + UnityEditor.EditorApplication.playmodeStateChanged -= StopAllPreviews; +#else + UnityEditor.EditorApplication.playModeStateChanged -= StopAllPreviews; +#endif +// EditorApplication.playmodeStateChanged -= StopAllPreviews; + + InternalEditorUtility.RepaintAllViews(); + } + +#endregion + +#region Methods + + static void StartupGlobalPreview() + { + DOTweenEditorPreview.Start(); +#if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5 + UnityEditor.EditorApplication.playmodeStateChanged += StopAllPreviews; +#else + UnityEditor.EditorApplication.playModeStateChanged += StopAllPreviews; +#endif +// EditorApplication.playmodeStateChanged += StopAllPreviews; + } + + static void AddAnimationToGlobalPreview(DOTweenAnimation src) + { + if (!src.isActive) return; // Ignore sources whose tweens have been set to inactive + if (_previewOnlyIfSetToAutoPlay && !src.autoPlay) return; + + Tween t = src.CreateEditorPreview(); + _AnimationToTween.Add(src, new TweenInfo(src, t, src.isFrom)); + // Tween setup + DOTweenEditorPreview.PrepareTweenForPreview(t); + } + + static void StopPreview(GameObject go) + { + _TmpKeys.Clear(); + foreach (KeyValuePair kvp in _AnimationToTween) { + if (kvp.Key.gameObject != go) continue; + _TmpKeys.Add(kvp.Key); + } + StopPreview(_TmpKeys); + _TmpKeys.Clear(); + + if (_AnimationToTween.Count == 0) StopAllPreviews(); + else InternalEditorUtility.RepaintAllViews(); + } + + static void StopPreview(Tween t) + { + TweenInfo tInfo = null; + foreach (KeyValuePair kvp in _AnimationToTween) { + if (kvp.Value.tween != t) continue; + tInfo = kvp.Value; + _AnimationToTween.Remove(kvp.Key); + break; + } + if (tInfo == null) { + Debug.LogWarning("DOTween Preview ► Couldn't find tween to stop"); + return; + } + if (tInfo.isFrom) { + int totLoops = tInfo.tween.Loops(); + if (totLoops < 0 || totLoops > 1) { + tInfo.tween.Goto(tInfo.tween.Duration(false)); + } else tInfo.tween.Complete(); + } else tInfo.tween.Rewind(); + tInfo.tween.Kill(); + EditorUtility.SetDirty(tInfo.animation); // Refresh views + + if (_AnimationToTween.Count == 0) StopAllPreviews(); + else InternalEditorUtility.RepaintAllViews(); + } + + // Stops while iterating inversely, which deals better with tweens that overwrite each other + static void StopPreview(List keys) + { + for (int i = keys.Count - 1; i > -1; --i) { + DOTweenAnimation anim = keys[i]; + TweenInfo tInfo = _AnimationToTween[anim]; + if (tInfo.isFrom) { + int totLoops = tInfo.tween.Loops(); + if (totLoops < 0 || totLoops > 1) { + tInfo.tween.Goto(tInfo.tween.Duration(false)); + } else tInfo.tween.Complete(); + } else tInfo.tween.Rewind(); + tInfo.tween.Kill(); + EditorUtility.SetDirty(anim); // Refresh views + _AnimationToTween.Remove(anim); + } + } + +#endregion + + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + // ███ INTERNAL CLASSES ████████████████████████████████████████████████████████████████████████████████████████████████ + // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ + + class TweenInfo + { + public DOTweenAnimation animation; + public Tween tween; + public bool isFrom; + public TweenInfo(DOTweenAnimation animation, Tween tween, bool isFrom) + { + this.animation = animation; + this.tween = tween; + this.isFrom = isFrom; + } + } + + static class Styles + { + static bool _initialized; + + public static GUIStyle previewBox, previewLabel, btOption, btPreview, previewStatusLabel; + + public static void Init() + { + if (_initialized) return; + + _initialized = true; + + previewBox = new GUIStyle(GUI.skin.box).Clone().Padding(1, 1, 0, 3) + .Background(DeStylePalette.squareBorderCurved_darkBorders).Border(7, 7, 7, 7); + previewLabel = new GUIStyle(GUI.skin.label).Clone(10, FontStyle.Bold).Padding(1, 0, 3, 0).Margin(3, 6, 0, 0).StretchWidth(false); + btOption = DeGUI.styles.button.bBlankBorderCompact.MarginBottom(2).MarginRight(4); + btPreview = EditorStyles.miniButton.Clone(Format.RichText); + previewStatusLabel = EditorStyles.miniLabel.Clone().Padding(4, 0, 0, 0).Margin(0); + } + } + } +} diff --git a/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenPreviewManager.cs.meta b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenPreviewManager.cs.meta new file mode 100644 index 0000000..53780cc --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenPreviewManager.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 22292a5f27a9a644ba9e6ad1bf863531 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.XML b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.XML new file mode 100644 index 0000000..ad80aef --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.XML @@ -0,0 +1,18 @@ + + + + DOTweenProEditor + + + + + Custom colors + + + + + Needs to be overridden in order to initialize new styles added from inherited classes + + + + diff --git a/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.XML.meta b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.XML.meta new file mode 100644 index 0000000..f37a133 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.XML.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 753a4f4ed73b17143923101226957756 +TextScriptImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll new file mode 100644 index 0000000000000000000000000000000000000000..7bce843264af090a03369c21fc946417c9108421 GIT binary patch literal 35840 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 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll.mdb b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll.mdb new file mode 100644 index 0000000000000000000000000000000000000000..407847604c2f6107bb5ca74f2154b5220d19654d GIT binary patch literal 5678 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 QZ|?-Hq)$ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll.mdb.meta b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll.mdb.meta new file mode 100644 index 0000000..f7149bc --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll.mdb.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: ee3a420017f129443896310d9fab256b +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll.meta b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll.meta new file mode 100644 index 0000000..62ab8c0 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/Editor/DOTweenProEditor.dll.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: a6402d4311c862b4eb1325590d6466af +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Any: + enabled: 0 + settings: {} + Editor: + enabled: 1 + settings: + DefaultValueInitialized: true + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DOTweenPro/readme.txt b/Assets/Plugins/Demigiant/DOTweenPro/readme.txt new file mode 100644 index 0000000..9837c95 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/readme.txt @@ -0,0 +1,35 @@ +DOTween and DOTween Pro are copyright (c) 2014-2018 Daniele Giardini - Demigiant + +// IMPORTANT!!! ///////////////////////////////////////////// +// Upgrading DOTween from versions older than 1.2.000 /////// +// (or DOTween Pro older than 1.0.000) ////////////////////// +------------------------------------------------------------- +If you're upgrading your project from a version of DOTween older than 1.2.000 (or DOTween Pro older than 1.0.000) please follow these instructions carefully. +1) Import the new version in the same folder as the previous one, overwriting old files. A lot of errors will appear but don't worry +2) Close and reopen Unity (and your project). This is fundamental: skipping this step will cause a bloodbath +3) Open DOTween's Utility Panel (Tools > Demigiant > DOTween Utility Panel) if it doesn't open automatically, then press "Setup DOTween...": this will run the upgrade setup +4) From the Add/Remove Modules panel that opens, activate/deactivate Modules for Unity systems and for external assets (like TextMesh Pro) + +// GET STARTED ////////////////////////////////////////////// + +- After importing a new DOTween update, select DOTween's Utility Panel from the "Tools/Demigiant" menu (if it doesn't open automatically) and press the "Setup DOTween..." button to activate/deactivate Modules. You can also access a Preferences Tab from there to choose default settings for DOTween. + +// VISUAL SCRIPTING (PRO ONLY) +- To animate a gameObject, select it and choose "Add Component > DOTween > DOTween Animation" +- To animate a gameObject along a path, select it and choose "Add Component > DOTween > DOTween Path" + +// SCRIPTING +- In your code, add "using DG.Tweening" to each class where you want to use DOTween. +- You're ready to tween. Check out the links below for full documentation and license info. + + +// LINKS /////////////////////////////////////////////////////// + +DOTween website (documentation, examples, etc): http://dotween.demigiant.com +DOTween license: http://dotween.demigiant.com/license.php +DOTween repository (Google Code): https://code.google.com/p/dotween/ +Demigiant website (documentation, examples, etc): http://www.demigiant.com + +// NOTES ////////////////////////////////////////////////////// + +- DOTween's Utility Panel can be found under "Tools > Demigiant > DOTween Utility Panel" and also contains other useful options, plus a tab to set DOTween's preferences \ No newline at end of file diff --git a/Assets/Plugins/Demigiant/DOTweenPro/readme.txt.meta b/Assets/Plugins/Demigiant/DOTweenPro/readme.txt.meta new file mode 100644 index 0000000..6a87c35 --- /dev/null +++ b/Assets/Plugins/Demigiant/DOTweenPro/readme.txt.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: aa8f07903bf128e44a7d0b91a63dedab +TextScriptImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib.meta b/Assets/Plugins/Demigiant/DemiLib.meta new file mode 100644 index 0000000..edcf2cc --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib.meta @@ -0,0 +1,21 @@ +fileFormatVersion: 2 +guid: 5a499e4809836274eb38cd99b370a2c1 +labels: +- Tween +- Tweening +- Animation +- HOTween +- Paths +- iTween +- DFTween +- LeanTween +- Ease +- Easing +- Shake +- Punch +- 2DToolkit +- TextMeshPro +- Text +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core.meta b/Assets/Plugins/Demigiant/DemiLib/Core.meta new file mode 100644 index 0000000..86e5075 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 03513cf143bb144409fbb3a51ec77b1b +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.dll b/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.dll new file mode 100644 index 0000000000000000000000000000000000000000..61b68998bf5599ab724de8d06fa9686f326ccd08 GIT binary patch literal 13312 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 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.dll.mdb.meta b/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.dll.mdb.meta new file mode 100644 index 0000000..de5f720 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.dll.mdb.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 995cf2d9b4a41f840b3a41712e9b3bc0 +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.dll.meta b/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.dll.meta new file mode 100644 index 0000000..1ed9199 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.dll.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: 54be29b67d0d29a478da2c6e5c62f091 +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Any: + enabled: 1 + settings: {} + Editor: + enabled: 0 + settings: + DefaultValueInitialized: true + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.xml b/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.xml new file mode 100644 index 0000000..3b65c54 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.xml @@ -0,0 +1,205 @@ + + + + DemiLib + + + + + Class attribute + Sets the script execution order index + + + + + Sets the script execution order for this class + + Script execution order index + + + + Set when calling DeGUI.BeginGUI + + + + + Stores a color palette, which can be passed to default DeGUI layouts when calling DeGUI.BeginGUI, + and changed at any time by calling DeGUI.ChangePalette. + You can inherit from this class to create custom color palettes with more hColor options. + + + + + Converts a HEX color to a Unity Color and returns it + + The HEX color, either with or without the initial # (accepts both regular and short format) + + + + Global colors + + + + + Background colors + + + + Editor background color + + + + Content colors + + + + + Toggle button specific colors + + + + + Various Input utils + + + + + Returns a number key int if a number key was pressed in this frame, or -1 otherwise + + + + + + Extend this to replicate Unity's Scope system with any Unity version. + Thanks to Dmitriy Yukhanov for pointing this out and creating an initial version. + Expand this class to create scopes. + Example: + public class VBoxScope : DeScope + { + public VBoxScope(GUIStyle style) + { + BeginVBox(style); + } + + protected override void CloseScope() + { + EndVBox(); + } + } + Usage: + using (new VBoxScope(myStyle) { + // Do something + } + + + + + Contains both free and pro skins color variations, + and automatically returns the correct one when converted to Color + + + + + Used by DeHierarchy + + + + + Returns a list of all items whose gameObject is NULL, or NULL if there's no missing gameObjects. + + + + + If the item exists sets it, otherwise first creates it and then sets it + + + + + If the item exists sets it, otherwise first creates it and then sets it + + + + + If the item exists sets it, otherwise first creates it and then sets it + + + + + Returns TRUE if the item existed and was removed. + + + + + Returns TRUE if the item existed and was changed. + + + + + Returns the customizedItem for the given gameObject, or NULL if none was found + + + + + Returns the color corresponding to the given + + + + Must be univocal + + + Node position in editor GUI + + + Ids of all forward connected nodes. Length indicates how many forward connections are allowed. + Min length represents available connections from node. + + + + A serializable struct including a min and a max int value + + + + Min value + + + Max value + + + + Creates a new Range + + + + + Returns a random value within this range (min/max included) + + + + + + + + A serializable struct including a min and a max float value + + + + Min value + + + Max value + + + + Creates a new Range + + + + + Returns a random value within this range (min/max included) + + + + + + + diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.xml.meta b/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.xml.meta new file mode 100644 index 0000000..473a9b5 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/DemiLib.xml.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 9bf2564c9817bb34988453ae948954d2 +TextScriptImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor.meta new file mode 100644 index 0000000..11f8e33 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 77fbbad1c51d68f4c844d26743104b07 +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll new file mode 100644 index 0000000000000000000000000000000000000000..0c792c10cadfddb47da208beedc67101295ba7bb GIT binary patch literal 187392 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 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll.mdb b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll.mdb new file mode 100644 index 0000000000000000000000000000000000000000..110b4a96d18cead4e56e7d0348d4ee4feed620b0 GIT binary patch literal 63264 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 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll.mdb.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll.mdb.meta new file mode 100644 index 0000000..b640c3e --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll.mdb.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 2c20a7b4db3cd0a4a99bcf6218f92860 +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll.meta new file mode 100644 index 0000000..aa20ddf --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.dll.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: 202f9ddaf2c1a8a429504f7f3cd7b84f +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Any: + enabled: 0 + settings: {} + Editor: + enabled: 1 + settings: + DefaultValueInitialized: true + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.xml b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.xml new file mode 100644 index 0000000..0aee725 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.xml @@ -0,0 +1,2290 @@ + + + + DemiEditor + + + + + Utils to use the correct method based on Unity's version + + + + + Encodes to PNG using reflection to use correct method depending if editor is version 2017 or earlier + + + + + Returns the prefab parent by using different code on Unity 2018 or later + + + + + + + Starts an editor coroutine. You can't use normal yield new WaitFor methods because + those are Unity runtime, but you can instead use . + Other than that, you can use normal yield null/etc. + Returns an which you can use with to cancel the coroutine. + + + + + Stops the given coroutine generated by + + + + + To be used inside a coroutine as a yield instruction: waits for the given seconds + (replaces Unity's yield new WaitForSeconds because it's not available in-editor). + Example usage: + yield return DeEditorCoroutines.WaitForSeconds(1); + + + + + File utils + + + + Path slash for AssetDatabase format + + + Path slash to replace for AssetDatabase format + + + Current OS path slash + + + Path slash to replace on current OS + + + + Full path to project directory, without final slash. + + + + + Full path to project's Assets directory, without final slash. + + + + + Returns TRUE if the given path is an absolute path + + + + + Returns TRUE if the given path is an AssetDatabase path + + + + + Returns TRUE if the given GUID refers to a valid and existing project folder + + + + + Converts the given project-relative path to a full path + + + + + Converts the given full path to a project-relative path + + + + + Returns TRUE if the file/directory at the given path exists. + + Path, relative to Unity's project folder + + + + Validates the string as a valid fileName + (uses commonly accepted characters an all systems instead of system-specific ones). + BEWARE: doesn't check for reserved words + + string to replace + Minimum length for considering the string valid + + + + Returns TRUE if the given filepath is within this Unity project Assets folder + + Full file path + + + + Returns the given string stripped of any invalid filename characters. + BEWARE: doesn't check for reserved words + + string to replace + Character to use as replacement for invalid ones + + + + Returns the given path with all slashes converted to the correct ones used by the system + + + + + Returns the asset path of the given GUID (relative to Unity project's folder), + or an empty string if either the GUID is invalid or the related path doesn't exist. + + + + + Checks if the given directory (full path) is empty or not + + + + + Deletes all files and subdirectories from the given directory + + + + Returns the adb path to the given ScriptableObject + + + Returns the adb path to the given MonoBehaviour + + + Returns the adb directory that contains the given ScriptableObject without final slash + + + Returns the adb directory that contains the given MonoBehaviour without final slash + + + + Returns the adb paths to the selected folders in the Project panel, or NULL if there is none. + Contrary to Selection.activeObject, which only returns folders selected in the right side of the panel, + this method also works with folders selected in the left side. + + + + + Sets the script execution order of the given MonoBehaviour + + + + + Gets the script execution order of the given MonoBehaviour + + + + + Precisely returns the last controlId assigned to a GUI element + + + + + Framework used to fix missing monoScript reference in GameObjects when a script's meta guid changes + + + + + Retrieves the GUID in the given meta file and returns it, or NULL if it's not found + + Full filePath to the meta file + + + + Fixes all wrong Component GUIDs in scenes and prefabs + + objects to use for the operation + + + + Fixes all wrong Component GUIDs in the active scene and returns the total number of Components fixed + + objects to use for the operation + + + + Finds all MonoBehaviour/Behaviour/Component in the given scene/prefab file string + that contain the given + and replaces their GUID with the one passed (if different). + Returns the total number of Component GUIDs that were fixed + + + + + Utils to manage UnityPackages import/export and file mirroring + + + + + Stores all file paths (excluding metas) found in the given AssetDatabase directory and subdirectory + into the given AssetDatabase file (which will be created if missing), + writing them as relative to the given directory. + EXAMPLE: + adbReadFromDirPath = "Plugins/DOTween" + file "Assets/Plugins/DOTween/aScript.cs" stored as "aScript.cs" + file "Assets/Plugins/DOTween/Subdir/aScript.cs" stored as "Subdir/aScript.cs" + + + AssetDatabase path ("Assets/...") where the list should be written + AssetDatabase path ("Assets/...") from which the list of files should be retrieved, without final slash + If TRUE ignores ASMDEF files + + + + Parses a file list created via and removes any files not present in the list from the given directory + + Label to use when logging the result + AssetDatabase path ("Assets/...") to the file containing the list + AssetDatabase path ("Assets/...") to the directory to parse for extra files to remove + If TRUE ignores ASMDEF files + If TRUE only returns a report log and doesn't actually delete the files + + + + Utilities for Editor Panels. + + + + + Connects to a asset. + If the asset already exists at the given path, loads it and returns it. + Otherwise, depending on the given parameters, either returns NULL or automatically creates it before loading and returning it. + + Asset type + File path (relative to Unity's project folder) + If TRUE and the requested asset doesn't exist, forces its creation + If TRUE also creates the path folders if they don't exist + + + + Check if the at the given path exists and eventually if it's available + + File path (relative to Unity's project folder) + If TRUE also check if the file is available + (file can be unavailable if it was deleted outside Unity, or if Unity is just starting) + + + + + Returns TRUE if the given is dockable, FALSE if instead it's a utility window + + + + + + + Sets the icon and title of an editor window. Works with older versions of Unity, where the titleContent property wasn't available. + + Reference to the editor panel whose icon to set + Icon to apply + Title. If NULL doesn't change it + + + + Repaints the currently focues editor + + + + + Prefab utilities + + + + + Behaves as the Inspector's Apply button, applying any modification of this instance to the prefab parent + + + + + + Returns TRUe if a prefab instance has unapplied modifications, ignoring any modifications applied to the transform. + NOTE: this a somehow costly operation (since it generates GC) + + + + + Completely removes any prefab connection from the given prefab instances, by desotroing the original object and recreating it. + Returns a list with all the new elements created. + + Based on RodGreen's method (http://forum.unity3d.com/threads/82883-Breaking-connection-from-gameObject-to-prefab-for-good.?p=726602&viewfull=1#post726602) + + + + + + Completely removes any prefab connection from the given prefab instance, by desotroing the original object and recreating it. + + Based on RodGreen's method (http://forum.unity3d.com/threads/82883-Breaking-connection-from-gameObject-to-prefab-for-good.?p=726602&viewfull=1#post726602) + + + + + Calls the given action after the given delay + + + + Return the size of the editor game view, eventual extra bars excluded (meaning the true size of the game area) + + + + + Returns a value from 1 to N (2 for 200% scaling) indicating the UI Scaling of Unity's editor. + The first time this is called it will store the scaling and keep it without refreshing, + since you need to restart Unity in order to apply a scaling change + + + + + Clears all logs from Unity's console + + + + + Adds the given global define (if it's not already present) to all the + or only to the given , depending on passed parameters, + and returns TRUE if it was added, FALSE otherwise. + NOTE: when adding to all of them some legacy warnings might appear, which you can ignore. + + + to use. Leave NULL to add to all of them. + + + + Removes the given global define (if present) from all the + or only from the given , depending on passed parameters, + and returns TRUE if it was removed, FALSE otherwise. + NOTE: when removing from all of them some legacy warnings might appear, which you can ignore. + + + to use. Leave NULL to remove from all of them. + + + + Returns TRUE if the given global define is present in all the + or only in the given , depending on passed parameters. + + + to use. Leave NULL to check in all of them. + + + + Sets the gizmos icon visibility in the Scene and Game view for the given class names + + Visibility + Class names (no namespace), as many as you want separated by a comma + + + + Sets the gizmos icon visibility in the Scene and Game view for all custom icons + (for example icons created with HOTools) + + Visibility + + + + Returns all components of type T in the currently open scene, or NULL if none could be found. + If you're on Unity 5 or later, and have DeEditorTools, use DeEditorToolsUtils.FindAllComponentsOfType + instead, which is more efficient. + + + + + Shifts an item from an index to another, without modifying the list except than by moving elements around + + + + + Expands the given array and adds the given element as the last one + + + + + Removes the element at index from the given array, shifts everything after by -1 position and resizes the array + + + + Nothing is being dragged + + + Dragging + + + Dragging concluced and accepted + + + Dragging concluced but item position didn't change + + + Dragging canceled + + + Dragging concluced but not accepted because too short + + + Automatically determines if dragged elements are horizontal, vertical, or both + + + Forces vertical drag + + + Forces horizontal drag (useful to avoid initial wrong drag indicators + if the users starts dragging an horizontal system vertically) + + + + Manages the dragging of GUI elements + + + + + True if a GUI element is currently being dragged + + + + + Return the current item being dragged, or NULL if there is none + + + + + Type of current item being dragged, or NULL if there is none + + + + + Starting index of current item being dragged, or NULL if there is none + + + + + Retrieves the eventual optional data stored via the StartDrag method + + + + + Starts a drag operation on a GUI element. + + Reference to the current editor drawing the GUI (used when a Repaint is needed) + List containing the dragged item and all other relative draggable items + DraggableList index of the item being dragged + Optional data that can be retrieved via the static property + + + + Starts a drag operation on a GUI element. + + ID for this drag operation (must be the same for both StartDrag and Drag + Reference to the current editor drawing the GUI (used when a Repaint is needed) + List containing the dragged item and all other relative draggable items + DraggableList index of the item being dragged + Optional data that can be retrieved via the static property + + + + Starts a drag operation on a GUI element. + + Reference to the current editor drawing the GUI (used when a Repaint is needed) + List containing the dragged item and all other relative draggable items + DraggableList index of the item being dragged + Optional data that can be retrieved via the static property + + + + Starts a drag operation on a GUI element. + + ID for this drag operation (must be the same for both StartDrag and Drag + Reference to the current editor drawing the GUI (used when a Repaint is needed) + List containing the dragged item and all other relative draggable items + DraggableList index of the item being dragged + Optional data that can be retrieved via the static property + + + + Call this after each draggable GUI block, to calculate and draw the current drag state + (or complete it if the mouse was released). + + ID for this drag operation (must be the same for both StartDrag and Drag + List containing the draggable item and all other relative draggable items + Current index of the draggable item being drawn + If NULL will calculate this automatically using . + Pass this if you're creating a drag between elements that don't use GUILayout + Drag direction. You can leave it to + unless you want to skip eventual layout calculations + + + + Call this after each draggable GUI block, to calculate and draw the current drag state + (or complete it if the mouse was released). + + List containing the draggable item and all other relative draggable items + Current index of the draggable item being drawn + If NULL will calculate this automatically using . + Pass this if you're creating a drag between elements that don't use GUILayout + Drag direction. You can leave it to + unless you want to skip eventual layout calculations + + + + Call this after each draggable GUI block, to calculate and draw the current drag state + (or complete it if the mouse was released). + + ID for this drag operation (must be the same for both StartDrag and Drag + List containing the draggable item and all other relative draggable items + Current index of the draggable item being drawn + Color to use for drag divider and selection + If NULL will calculate this automatically using . + Pass this if you're creating a drag between elements that don't use GUILayout + Drag direction. You can leave it to + unless you want to skip eventual layout calculations + + + + Call this after each draggable GUI block, to calculate and draw the current drag state + (or complete it if the mouse was released). + + List containing the draggable item and all other relative draggable items + Current index of the draggable item being drawn + Color to use for drag divider and selection + If NULL will calculate this automatically using . + Pass this if you're creating a drag between elements that don't use GUILayout + Drag direction. You can leave it to + unless you want to skip eventual layout calculations + + + + Ends the drag operations, and eventually applies the drag outcome. + Returns TRUE if the position of the dragged item actually changed. + Called automatically by Drag method. Use it only if you want to force the end of a drag operation. + + If TRUE applies the drag results, otherwise simply cancels the drag + + + + Abstract dynamic class used for every node of the same type + (meaning there is only a single recycled instance for all same-type nodes) + + + + Used to fill + + + Called when the node needs to be drawn + + + + The connectedNodesIds list will be automatically increased/decreased when adding/removing connections + (otherwise connectedNodesIds will have to be increased via custom code) + + + + + Requires only two connectedNodesIds (no more, no less), + uses regular CTRL+Drag to connect connection 0, CTRL+SPACE+Drag to connect connection 1 + + + + + Like , but with an extra connection as a last extra index, which is set when pressing CTRL+SPACE+Drag. + Must always have at least one element in connectedNodesIds + + + + Layout, Repaint, LayoutAndRepaint + + + + Stores cloned nodes for pasting + + + + + Returns a list of pasteable nodes, with their GUID recreated and their connections adapted + + + + + + Returns a deep clone of the given node but doesn't clone UnityEngine references. + A new ID will be automatically generated. + + + + + Always connects a node from BottomOrRight side to TopOrLeft side + + + + + Always connects from BottomOrRight side to TopOrLeft side. + If ALT is pressed shows the delete connection button. + Called during Repaint or MouseDown/Up. + Returns TRUE if the connection was deleted using the delete connection button. + + + + + Always connects a node from BottomOrRight side to TopOrLeft side + + + + + Always connects from BottomOrRight side to TopOrLeft side. + If ALT is pressed shows the delete connection button. + Called during Repaint or MouseDown/Up. + Returns TRUE if the connection was deleted using the delete connection button. + + + + + You can attach to this + + + + + Use this to add a content group to the Help Panel + + + + Regular note + + + Editable note (activated by setting to TRUE + (but you will have to save the result somewhere yourself) + + + If TRUE shows the textArea + + + + Add definition. Supports rich-text but also these special tags: + - [b][/b] + + + + + Add key, automatically formatting these special keys: + / + + + → + + If TRUE and there's other keys/targets, adds the new key on a new line preceded by a comma + + + + Recalculates all rects based on the given Y shift + + + + + One per . + Partially independent, mainly controlled by process. + + + + TRUE when read-to or dragging nodes + + + + Resets the interaction state + + + + Returns TRUE if the given node is currently being dragged + + + + Returns TRUE if a repaint is required + + + + + + Main class for DeGUI Node system. + Create it, then enclose your GUI node calls inside a . + CODING ORDER: + - Create a to use for your node system (create it once, obviously) + - Inside OnGUI, write all your nodes GUI code inside a + - To draw the nodes, loop through the list and call for each node + + + + Distance at which nodes will be placed when snapping next to each other + + + Full area without zeroed coordinates + + + Position with zeroed coordinates (used by all node GUI since it's inside a GUILayout(area)) + + + Contains the nodes passed to NodeProcessScope ordered by depth. + You should loop through this list when drawing nodes + + + + Creates a new NodeProcess. + + EditorWindow for this process + Callback called when one or more nodes are going to be deleted. + Return FALSE if you want the deletion to be canceled. + Can be NULL, in which case it will be ignored + Callback called when a node is cloned. + Return FALSE if you want the cloning to be canceled. + Can be NULL, in which case it will be ignored + + + + Needs to be called when loading a complete new series of nodes + + + + + Call this when the layout/size of one or more nodes changed because of external intervention + (if a whole new range of nodes has been loaded, just call instead) + + + + + Forces the refresh of the area calculations. Useful if you need them before the first GUI call has run + + + + + Shifts the visible are to the given coordinates and repaints on end + + + + + Shifts the visible are to the given coordinates and repaints on end + + + + + Tells the process to repaint once the process has ended. + Calling this + + + + + Draws the given node using the given T editor GUINode type. + Returns the full area of the node + + + + + Opens the Help Panel + + + + + Closes the Help Panel + + + + + Opens or closes the Help panel based on its current state + + + + + Returns TRUE if the given area is visible (even if partially) inside the current nodeProcess area + + + + + Captures a screenshot of the node editor area and returns it when calling the onComplete method. + Sadly this requires a callback because if called immediately the capture will fail + with a "[d3d11] attempting to ReadPixels outside of RenderTexture bounds!" error in most cases + + Screenshot mode + A callback that accepts the generated Texture2D object + Screenshot scale factor (only used if screenshotMode is set to ) + If TRUE (default) displays a progress bar during the operation. + You'll want to set this to FALSE when you're already using a custom progressBar + and the screenshot is only part of a larger queue of operations + + + + Removes the node with the given ID from the list and removes all connections to it from other nodes. + Doesn't mark things dirty nor prepares them for undo + + + + + Use this to encapsulate node GUI operations. + Automatically manages various operations (press F1 to see them). + Sets GUI.changed to TRUE if the area is panned, a node is dragged, controlNodes change sorting or are deleted. + Wraps all content inside a GUILayout Area (nodeArea). + + The to use + Area within which the nodes will be drawn + Area shift (caused by dragging) + This list will be sorted based on current node draw order, + and changed in case one of its nodes is deleted. + IMPORTANT: this list should be part of your serialized class (MonoBehaviour or ScriptableObject), + so it will be stored as a reference and modifying one will modify the other. + Usually you want to pass all nodes to this except the eventual start node (or nodes that can't be sorted nor deleted). + + + + Set automatically when a selection ends up selecting a single node, + reset when deselecting all nodes, selecting multiple nodes, or resetting the + + + + + Returns TRUE if something was actually deselected, FALSE if there were no selected nodes + + + + + + Returns key modifiers currently pressed. + Requires to be updated at the beginning of every GUI call. + + + + + Call this method to update data required by softCtrl calculations. + Automatically called from within a . + Returns a object with the keys that were just pressed and just released + + Required to have the correct for the given target call + + + + Returns the given as an int, or -1 if it's not a number + + + + + Used code from Celtc on StackOverflow: https://stackoverflow.com/a/54044197/10151925 + + + + + Gets all fields from an object and its hierarchy inheritance + + + + + Perform a deep copy of the class + + + + + Does the copy + + + + + Returns by . + Contains properties and methods to manage non-layout scrollview better. + Remember to use or to increase or set the full content height + + + + Area used by ScrollView and its content + + + Full content area regardless if visible or not. Its height should be set manually based on the contents' height + + + Content area currently visible (scroll bars excluded) + + + Current scrollPosition + + + + Returns the current open, or an empty one if none is open. + + + + + Sets the width + + + + + Sets the height + + + + + Increase the height by the given amount + + + + + + Returns a Rect for a single line at the current scrollView yMax + + If less than 0 uses default line height, otherwise the value passed + if TRUE (default) automatically increases the height of the accordingly + + + + + Returns a Rect for a single line at the current scrollView yMax, as wide as the max visible rect width + + If less than 0 uses default line height, otherwise the value passed + if TRUE (default) automatically increases the height of the accordingly + + + + + Returns TRUE if the given rect is at least partially visible in the displayed scroll area + + + + + Contains both free and pro skins GUIStyle variations, + and automatically returns the correct one when converted to GUIStyle + + + + + Plays the given clip in the Editor + + + + + Stops playing the given clip. + + + + + Stops all clips playing. + + + + + A stopwatch whose time can be changed manually via + + + + + Start or resume playing + + + + + Stop the watch and reset the time + + + + + Restart measuring from zero + + + + + Pause the watch + + + + + Send the watch to the given time + + + + + Util to determine Unity editor version and store them as comparable numbers + + + + Full major version + first minor version (ex: 2018.1f) + + + Major version + + + First minor version (ex: in 2018.1 it would be 1) + + + + Assembly extensions + + + + + Full path to the assembly directory, without final slash + + + + + AssetDatabase path to the assembly directory, without final slash + + + + + GUI extension methods + + + + + Clones the style and adds the given formats to it. You can pass any of these types of values: + + Format:Rich-text, wordwrap + FontStyle:Font style + TextAnchor:Content anchor + int:Font size + Color/DeSkinColor:Font color + + + + + + Adds the given formats to the style. You can pass any of these types of values: + + Format:RichText, WordWrap + FontStyle:Font style + TextAnchor:Content anchor + int:Font size + Color/DeSkinColor:Font color + + + + + + Sets the border of the style + + + + + Sets the border of the style + + + + + Sets the border of the style + + + + + Sets the background of the style + + + + + Sets the background of the style + + + + + Sets the contentOffset of the style + + + + + Sets the contentOffset of the style + + + + + Sets the X contentOffset of the style + + + + + Sets the Y contentOffset of the style + + + + + Sets the margin of the style + + + + + Sets the margin of the style + + + + + Sets the margin of the style + + + + + Sets the left margin of the style + + + + + Sets the right margin of the style + + + + + Sets the top margin of the style + + + + + Sets the bottom margin of the style + + + + + Sets the overflow of the style + + + + + Sets the overflow of the style + + + + + Sets the overflow of the style + + + + + Sets the left overflow of the style + + + + + Sets the right overflow of the style + + + + + Sets the top overflow of the style + + + + + Sets the bottom overflow of the style + + + + + Sets the padding of the style + + + + + Sets the padding of the style + + + + + Sets the padding of the style + + + + + Sets the left padding of the style + + + + + Sets the right padding of the style + + + + + Sets the top padding of the style + + + + + Sets the bottom padding of the style + + + + + Sets the Y fixedWidth of the style + + + + + Sets the fixedHeight of the style + + + + + Sets the stretchHeight property of the style + + + + + Sets the stretchWidth property of the style + + + + + Stores a GUIStyle palette, which can be passed to default DeGUI layouts when calling DeGUI.BeginGUI, + and changed at any time by calling DeGUI.ChangePalette. + You can inherit from this class to create custom GUIStyle palettes with more options. + Each of the sub-options require a public Init method to initialize the styles, which will be called via Reflection. + + + + + Called automatically by DeGUI.BeginGUI. + Override when adding new style subclasses. + Returns TRUE if the styles were initialized or re-initialized + + + + + Extend any custom subpalettes from this, so they will be initialized correctly + + + + + GUILayout methods + + + + + A button that triggers an immediate repaint when hovered/pressed/unhovered + (which otherwise doesn't happen if you set a background to the button's GUIStyle). + Requires to be activated. + + + + + A button that triggers an immediate repaint when hovered/pressed/unhovered + (which otherwise doesn't happen if you set a background to the button's GUIStyle) + and also assigns different GUI colors based on the button's state and the given one. + Requires to be activated. + + Content + Default color + Style + GUILayout options + + + + A button that triggers an immediate repaint when hovered/pressed/unhovered + (which otherwise doesn't happen if you set a background to the button's GUIStyle) + and also assigns different GUI colors based on the button's state with options to eventually auto-generate them. + Requires to be activated. + + Content + Default color + Hover color (if NULL auto-generates it from the given one by making it brighter + Pressed color (if NULL auto-generates it from the given one by making it even brighter + Style + GUILayout options + + + Shaded button + + + Shaded button + + + Shaded button + + + Shaded button + + + Colored button + + + Colored button + + + Colored button + + + Colored button + + + + Draws a button that returns TRUE the first time it's pressed, instead than when its released. + + + + + Draws a button that returns TRUE the first time it's pressed, instead than when its released. + + + + + Draws a button that returns TRUE the first time the mouse moves over it while the mouse button is pressed, + even if it was pressed outside of the button first + + + + + Draws a button that returns TRUE the first time the mouse moves over it while the mouse button is pressed, + even if it was pressed outside of the button first + + + + Toolbar foldout button + + + Toolbar foldout button + + + Toolbar foldout button + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Begins an horizontal toolbar layout + + + Begins an horizontal toolbar layout + + + Begins an horizontal toolbar layout + + + Begins an horizontal toolbar layout + + + Ends an horizontal toolbar layout + + + A toolbar with a label + + + A toolbar with a label + + + A toolbar with a label + + + A toolbar with a label + + + A toolbar with a label + + + A toolbar with a label + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values. Auto-determines object type from the field's type + + + Returns TRUE if there's mixed values. Forces field to accept only objects of the given type + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Vertical box layout with style and color options + + + Vertical box layout with style and color options + + + End vertical box layout + + + Horizontal Divider + + + + A text field that becomes editable only on double-click + + EditorWindow reference + A unique ID to use in order to determine if the text is selected or not + Text + Style for default (non-editing mode) appearance + Style for editing mode + + + + A text field that becomes editable only on double-click + + Editor reference + A unique ID to use in order to determine if the text is selected or not + Text + Style for default (non-editing mode) appearance + Style for editing mode + + + + A text field that becomes editable only on double-click and can also be dragged + + EditorWindow reference + A unique ID to use in order to determine if the text is selected or not + Text + List containing the dragged item and all other relative draggable items + DraggableList index of the item being dragged + Style for default (non-editing mode) appearance + Style for editing mode + + + + + A text field that becomes editable only on double-click and can also be dragged + + Editor reference + A unique ID to use in order to determine if the text is selected or not + Text + List containing the dragged item and all other relative draggable items + DraggableList index of the item being dragged + Style for default (non-editing mode) appearance + Style for editing mode + + + + + Creates a Gradient field by using Unity 4.x hidden default one and Reflection. + + + + Scene field + + + + Global Demigiant GUI manager. Call to initialize it inside GUI calls. + + + + + Default color palette + + + + + Default style palette + + + + TRUE if we're using the PRO skin + + + + Call this at the beginning of GUI methods. + Returns TRUE if the styles were initialized or re-initialized + + Eventual to use + Eventual to use + + + + Better implementation of GUI.BeginScrollView. + Returns the modified scrollView struct. + Must be closed by a DeGUI.. +
EXAMPLE
+            Rect scrollViewArea = ...;
+            Rect drawArea = scrollViewArea;
+            // Decrease the full drawing area to exclude scrollbars if necessary
+            if (_scrollView.fullContentArea.height > scrollViewArea.height) drawArea = drawArea.Shift(0, 0, -11, 0);
+            // Begin scrollView
+            _scrollView = DeGUI.BeginScrollView(scrollViewArea, _scrollView);
+            // Increase scrollView area correctly (or directly set it with SetFullContentHeight
+            _scrollView.IncreaseContentHeightBy(...)
+            // End
+            DeGUI.EndScrollView();
+            
+
+ Visible area used by the scrollView + target. You'll need to set its size to the correct full content height + (either within the Begin/ENd ScrollView calls or before them) + If TRUE (default) resets .height to 0 + after beginning the ScrollView +
+ + + Closes a DeGUI. correctly + + + + + Exits the current event correctly, also taking care of eventual drag operations + + + + + Removes focus from any GUI button/text/element that has focus + + + + + Changes the active palettes to the given ones + (or resets them to the default ones if NULL). + Returns TRUE if the styles were initialized or re-initialized + + + + + Resets the GUI colors to the default ones (only available if BeginGUI was called first) + + + + + Sets the GUI colors to the given ones + + + + + Opens a panel that previews the given texture (if not NULL) + + + + + Gets either black or white, depending on the color that would be most visible on the given one + + + + + Gets either black or white, depending on the color that would be most visible on the given one + + + + + Sets the GUI cursor color to the given ones + + + + + Sets the GUI matrix to the given ones + + + + + Wrapper to set serialized fields with multiple sources selected: automatically sets GUI to show mixed values when necessary + and contains a fieldInfo which is set within the wrapper. + Note that you must set the property within the wrapper so that it's assigned correctly when closing the scope. + + + + Multi property scope + Name of the field so it can be found and set/get via Reflection + List of the sources containing the given field + If TRUE validates EditorGUI.EndChangeCheck before calling it + (fixes an issue which happens with advanced Undo usage in DOTween Timeline and ColorFields) + + + + A button that triggers an immediate repaint when hovered/pressed/unhovered + (which otherwise doesn't happen if you apply a background to the button's GUIStyle). + Requires to be activated. + + + + + A button that triggers an immediate repaint when hovered/pressed/unhovered + (which otherwise doesn't happen if you apply a background to the button's GUIStyle) + and also assigns different GUI colors based on the button's state and the given one. + Requires to be activated. + + Rect + Content + Default color + Style + + + + A button that triggers an immediate repaint when hovered/pressed/unhovered + (which otherwise doesn't happen if you apply a background to the button's GUIStyle) + and also assigns different GUI colors based on the button's state with options to eventually auto-generate them. + Requires to be activated. + + Rect + Content + Default color + Hover color (if NULL auto-generates it from the given one by making it brighter + Pressed color (if NULL auto-generates it from the given one by making it even brighter + Style + + + Shaded button + + + Shaded button + + + Shaded button + + + Shaded button + + + Colored button + + + Colored button + + + Colored button + + + Colored button + + + Toolbar foldout button which allows clicking even on its label + + + Foldout button + label (not intended to be used in toolbar) which allows click-to-foldout/foldin + + + + Draws a button that returns TRUE the first time it's pressed, instead than when its released. + + + + + Draws a button that returns TRUE the first time it's pressed, instead than when its released. + + + + + Draws a button that returns TRUE the first time the mouse moves over it while the mouse button is pressed, + even if it was pressed outside of the button first + + + + + Draws a button that returns TRUE the first time the mouse moves over it while the mouse button is pressed, + even if it was pressed outside of the button first + + + + Toolbar foldout button + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Button that can be toggled on and off + + + Scene field + + + + Draws a background grid using the given grid texture + + Area rect + Offset from 0, 0 position (used when area has been dragged) + Texture to use for the grid + Eventual scale to apply to the grid + + + + Draws a background grid using default grid textures + + Area rect + Offset from 0, 0 position (used when area has been dragged) + If TRUE forces a dark skin, otherwise uses a skin that fits with the current Unity's one + Eventual scale to apply to the grid + + + Box with style and color options + + + + Can be used instead of EditorGUI.PropertyField, to draw a serializedProperty without its attributes + (very useful in case you want to use this from within a PropertyDrawer for that same property, + since otherwise bad infinite loops might happen) + + + + Draws a colored square + + + Draws the given texture tiled within the given rect + Rect + Texture + Eventual scale to apply + If not NULL, colorizes the texture with this color + + + + A text field that becomes editable only on double-click + + Area + EditorWindow reference + A unique ID to use in order to determine if the text is selected or not + Text + Style for default (non-editing mode) appearance + Style for editing mode + + + + A text field that becomes editable only on double-click + + Area + Editor reference + A unique ID to use in order to determine if the text is selected or not + Text + Style for default (non-editing mode) appearance + Style for editing mode + + + + A text field that becomes editable only on double-click and can also be dragged + + Area + EditorWindow reference + A unique ID to use in order to determine if the text is selected or not + Text + List containing the dragged item and all other relative draggable items + DraggableList index of the item being dragged + Style for default (non-editing mode) appearance + Style for editing mode + + + + A text field that becomes editable only on double-click and can also be dragged + + Area + Editor reference + A unique ID to use in order to determine if the text is selected or not + Text + List containing the dragged item and all other relative draggable items + DraggableList index of the item being dragged + Style for default (non-editing mode) appearance + Style for editing mode + + + + A textArea that becomes editable only on double-click + + Area + EditorWindow reference + A unique ID to use in order to determine if the text is selected or not + Text + Style for default (non-editing mode) appearance + Style for editing mode + + + + A textArea that becomes editable only on double-click + + Area + Editor reference + A unique ID to use in order to determine if the text is selected or not + Text + Style for default (non-editing mode) appearance + Style for editing mode + + + Divider + + + Draws a Vector3Field that can have single axes disabled + + + Draws a Vector3Field that can have single axes disabled + + + Draws a Vector3Field that can have single axes disabled + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values. Supports using an int as an enum + + + Returns TRUE if there's mixed values. Supports using an int as an enum + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values. Supports also uint fields + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values. Auto-determines object type from the field's type + + + Returns TRUE if there's mixed values. Forces field to accept only objects of the given type + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values. Supports passing int values as bool (1 = true, 0 = false) + + + Returns TRUE if there's mixed values. Supports passing int values as bool (1 = true, 0 = false) + + + Returns TRUE if there's mixed values. Supports passing int values as bool (1 = true, 0 = false) + + + Returns TRUE if there's mixed values. Requires a SerializedProperty representation of each UnityEven field + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + Returns TRUE if there's mixed values + + + + Returns a new color equal to the given one with changed brightness + + Color to evaluate + Brightness factor (multiplied by current brightness) + If set applies this alpha value + + + + Returns a new color equal to the given one with changed saturation + + Color to evaluate + Saturation factor (multiplied by current brightness) + If set applies this alpha value + + + + Changes the alpha of this color and returns it + + + + + Returns a new color equal to the given one with changed alpha + + + + + Returns a HEX version of the given Unity Color, without the initial # + + If TRUE, also converts the alpha value and returns a hex of 8 characters, + otherwise doesn't and returns a hex of 6 characters + + + + Returns a HEX version of the given Unity Color, without the initial # + + If TRUE, also converts the alpha value and returns a hex of 8 characters, + otherwise doesn't and returns a hex of 6 characters + + + + Replicates parts of DeExtensions.ListExtensions for internal usage + + + + + Shifts an item from an index to another, without modifying the list except than by moving elements around + + + + + Shuffles the list + + + + + Replicates DeExtensions.RectExtensions for internal usage + + + + + Adds one rect into another, and returns the resulting a + + + + + Returns a copy or the Rect expanded around its center by the given amount + + Indicates how much to expand the rect on each size + + + + Returns a copy or the Rect expanded around its center by the given amount + + Indicates how much to expand the rect on each horizontal side + Indicates how much to expand the rect on each vertical side + + + + Returns a copy or the Rect contracted around its center by the given amount + + Indicates how much to contract the rect on each size + + + + Returns a copy or the Rect contracted around its center by the given amount + + Indicates how much to contract the rect on each horizontal side + Indicates how much to contract the rect on each vertical side + + + + Returns a copy of the Rect resized so it fits proportionally within the given size limits + + Width to fit + Height to fit + If TRUE (default) only shrinks the rect if needed, if FALSE also enlarges it to fit + + + + + Returns TRUE if the first rect includes the second one + + If TRUE, returns TRUE only if the second rect is fully included, + otherwise just if some part of it is included + + + + Returns TRUE if this rect intersects the given one, and also outputs the intersection area + + Intersection area + + + + Returns a copy of the Rect with its X/Y coordinates set to 0 + + + + + Sets this rect to the left of the given x position, with options for margin and width resize + + Distance between this rect and the given x position + If greater than zero resizes this rect to the given size + + + + Sets this rect to the right of the given x position and resizes it so that its xMax remains the same. + + Distance between this rect and the given x position + Extra offset to add to the resulting width + + + + Returns a copy of the Rect with its values shifted according the the given parameters + + + + + Returns a copy of the Rect with its X value shifted by the given value + + + + + Returns a copy of the Rect with its Y value shifted by the given value + + + + + Returns a copy of the Rect with its x shifted by the given value and its width shrinked/expanded accordingly + (so that the xMax value will stay the same as before) + + + + + Returns a copy of the Rect with its y shifted by the given value and its height shrinked/expanded accordingly + (so that the yMax value will stay the same as before) + + + + + Returns a copy of the Rect with its X property set to the given value + + + + + Returns a copy of the Rect with its Y property set to the given value + + + + + Returns a copy of the Rect with its height property set to the given value + + + + + Returns a copy of the Rect with its width property set to the given value + + + + + Returns a copy of the Rect with its X,Y properties set so the rect center corresponds to the given values + + + + + Returns a copy of the Rect with its X property set so the rect X center corresponds to the given value + + + + + Returns a copy of the Rect with its Y property set so the rect Y center corresponds to the given value + + + + + Returns the value of the given property (works like a cast to type). + Improved from HiddenMonk's functions (http://answers.unity3d.com/questions/627090/convert-serializedproperty-to-custom-class.html) + + + + + Returns TRUE if this property is inside an array + + + + + Returns -1 if the property is not inside an array, otherwise returns its index inside the array + + + + + Returns the height of a UnityEvent serializedProperty + + + + + Uses code from FlaShG's GitMerge: https://github.com/FlaShG/GitMerge-for-Unity/blob/master/Editor/SerializedPropertyExtensions.cs + + + + + Uses code from FlaShG's GitMerge: https://github.com/FlaShG/GitMerge-for-Unity/blob/master/Editor/SerializedPropertyExtensions.cs + + + + + String extensions + + + + + Returns TRUE if the string is null or empty + + If TRUE (default) and the string contains only spaces, considers it empty + + + + Compares a version string (in format #.#.###) with another of the same format, + and return TRUE if this one is minor. Boths trings must have the same number of dot separators. + + + + + Converts a HEX color to a Unity Color and returns it + + The HEX color, either with or without the initial # (accepts both regular and short format) + + + + Nicifies a string, replacing underscores with spaces, and adding a space before Uppercase letters (except the first character) + + + + + If the given string is a directory path, returns its parent + with or without final slash depending on the original directory format + + + + + If the string is a directory, returns the directory name, + if instead it's a file returns its name without extension. + Works better than Path.GetDirectoryName, which kind of sucks imho + + + + + Evaluates the string as a property or field and returns its value. + + If NULL considers the string as a static property, otherwise uses obj as the starting instance + + + + Texture extensions + + + + + Returns the full Rect of this texture, with options for position and scale + + + + + Checks that the texture uses the correct import settings, and applies them if they're incorrect. + + + + + Returns a clone of the event + + + + + Utility class. You can either use it as is via its constructor, which automatically retrieves all serializedProperties in the instance, + or you can extend it so you can add as many public SerializedProperties as the SerializedProperties you want to access + (their name must be the same as the serialized field they refer to) + + + + + Draws all property fields + + +
+
diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.xml.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.xml.meta new file mode 100644 index 0000000..d199425 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/DemiEditor.xml.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: d4a42b2e4e6f64d4ba01d35c5a3dafed +TextScriptImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs.meta new file mode 100644 index 0000000..24b1340 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 1efb03f507a60b949a70ed828ac18eb8 +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquare.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquare.png new file mode 100644 index 0000000000000000000000000000000000000000..6fbcc5130cedc76f7566a958195e3703ada2eab4 GIT binary patch literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMkesKB zV~9m>a!NwNkMjanMkesKB zV~9m>a!NwNgp>sg28IC~ZoCqv30E2pCNeNHGpw>anMkesKB zV~9m>a!Nu%K=J|x1H%9gH(m+TgewgP6B(G98SdR+aC^Gv{4tanMkesKB zV~9m>a!Nu%LBawC1H%9gH(m+TgewgP6B(G989d|}5-xj9E&?iL@O1TaS?83{1OVO4 B8T|kN literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha25.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha25.png.meta new file mode 100644 index 0000000..2d94303 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha25.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: f7ff421f40d548444864a01cd7f47112 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha50.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha50.png new file mode 100644 index 0000000000000000000000000000000000000000..700b9debeaead0d7b26b31ed60c7e84dbf788ae6 GIT binary patch literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMkesKB zV~9m>a!NwNiu45x28IC~ZoCqv30E2pCNeNHGq@`;%)dF?xDTk5!PC{xWt~$(69Dad B8jt`0 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha50.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha50.png.meta new file mode 100644 index 0000000..e3040e1 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha50.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: aa1d42dc6ff3e894da2208c6929d2165 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha80.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blackSquareAlpha80.png new file mode 100644 index 0000000000000000000000000000000000000000..f4a47c3701daa735d11da1c8e1e3c6f752d222c9 GIT binary patch literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMkesKB zV~9m>a!Nvi#bF1=gro%mJyHf)2UajPA7)@anMprDMW zi(`n!#N-r@>Vpnk2}ufqJy{Z04MI!|3>X;nS1{&fnF;m*)iHRw`njxgN@xNAT}&7% literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blueSquare.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blueSquare.png.meta new file mode 100644 index 0000000..490a921 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/blueSquare.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 05cfe010378336646ad6c721f66543d1 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle.png new file mode 100644 index 0000000000000000000000000000000000000000..3ed059a404fad33f34ed81321288c886dab0c6de GIT binary patch literal 455 zcmV;&0XY7NP)pGc}YY;R9J<@m%&QIKomt^ii;xRPP(g9TCLFFH;B-M`aR;lD{<2g zaNAFCQxLzQ1aTvR-H6szv2H3p?@gkK1x;I%c?T{t5IXl}I!xa4WKL9d4Z{(10PR7W z&_?`t1U*0l=nA^@JnvQV0LI(U1vJt5nZ&=T{l~Zrok3Gwo@u;Bc~SEQG|>FuTD5u2 zeQ2cl!!`XZ^Ljz%=@47Lne#snw0P+8eI`n&3>~N?#nXztLc)6hiRu_`p%rn%JG6tl z;{Iy~PQ;x#q1P!V9^QT(<0G^xZh3<$+<`-JZ%*iW%m8h%qs;)m*x@rkRqUwp5USYm zQ4(Vq;92Z=VSu67F=T*1>_&^{M@cpt!bMS9|8sBDvMf)9U}KVJh0L`YvIrWTiF37R&1Ql$b@}GBnYI2R x?Ky8uw&(kjwC9!h@slL&`L#st`8a!3kxvBIUpIp~UK{`b002ovPDHLkV1h6R(RTm< literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle.png.meta new file mode 100644 index 0000000..bc2ac36 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: af28470bd0e2e9543a6dfa9a1a4b348d +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle_dashedBorderEmpty.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle_dashedBorderEmpty.png new file mode 100644 index 0000000000000000000000000000000000000000..f8294610e43490599de063ef2cf1c11e2d17279c GIT binary patch literal 673 zcmV;S0$%-zP)pHQ%OWYR9J<@mraO`VHC&DohD7vZSoa0U0Gn^Yi6M)BV~b@WMOP< zgtBF0DaMouF|!fP#$6Ci$;LuaiX=*;Ff}zOMNN`4rknEko$mkEd#}d*d>{Y%%`?x} zIp=-mdCz;s>QM+`CtQYS@CAOssOILuN!SPTEe&CKCX{Oy&T4LJV%*nVftAfT>wt^! z3A#153l71C%BQ5?rn$RNP$1rRHR5~~OeCJByUzW~VFd0&wqEDGFfHd#Js4|JIytws zzS_do@Kw(9ezB|t!p;fV^asoRYvG_4j#&$(`*BOQ-}wESYvBUe;~T8S3dPs-xq=w3 zoXkR>r7Zo4f56Ski5rS+v!yJ5ealXmPN&{iPb!@jLCP_GrOp98{cVdRe4Uoh0Y8d< zjYkUreN?-{1Mv6qH$1X|MqVI6oD{9tjkAC5tXpTIp0_FFs+sD0qau@I)< zj71QBmL*bu)?y2%r<4P(dcQ3(;U{q%7N;A6OwB($g$t4k_MCKW_J z1^eeqk6w7g!SH!)wZd?Hy^?MGE z!jc98cr52{VU0B+HeQnvKap`bSQ$(xmRMeJ9)U5~r18Bl6q@;GRVQ#=0hBbEaQrI# ztqZl<&(smfBAVT>9p3Tz9@d4L0MBUe;UzqTJIw#AZq@7$@4LV9X(+GG00000NkvXX Hu0mjfCz(G_ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle_dashedBorderEmpty.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle_dashedBorderEmpty.png.meta new file mode 100644 index 0000000..0055f30 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/circle_dashedBorderEmpty.png.meta @@ -0,0 +1,68 @@ +fileFormatVersion: 2 +guid: 522b0133a9838674ca9a12e0c6e5a59c +timeCreated: 1625322295 +licenseType: Store +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: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/greenSquare.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/greenSquare.png new file mode 100644 index 0000000000000000000000000000000000000000..63ef49a76b220d4de80807510b94f406c525e5cb GIT binary patch literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9F5he4R}c>anMprDMW zi(`n!#N;V^PaSgLN=Q-=?8%b2Y7k;#V8Fnje2P&lc>$vzP#uG(tDnm{r-UW|fY%uC literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/greenSquare.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/greenSquare.png.meta new file mode 100644 index 0000000..774d702 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/greenSquare.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 789ef07ba2573f6448fa8b5dc5224c44 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/grid_bright.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/grid_bright.png new file mode 100644 index 0000000000000000000000000000000000000000..5c2feae19dcc914919ab80fb84485e00a07e4699 GIT binary patch literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH$&H|6fVg?4j!ywFfJby(BP;i2$ zi(^Pe~gvJ1Rc= z?Ot!qiO>2DOF9@gq%oXjn8j$qoWXX1X90@9arT z#W5tK@$F4Rt^*1J3(_vMzVA+9hCAwRC4IicbTxXen@yoZH)$TLp zrW-e;F`Q+X#c0Bu!FGXXfusY9z&d`5^RH({?s9+MdcCA?-!-jS@BSaK$Ep;j_wA>K a4t9SLo(F6Gt~w8N6@#a%pUXO@geCx~6HWdA literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/grid_dark.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/grid_dark.png.meta new file mode 100644 index 0000000..9baf726 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/grid_dark.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: d542f997a51000946873268e3546b6ba +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alert.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alert.png new file mode 100644 index 0000000000000000000000000000000000000000..9242a22984b08edaeef4a97ca09251719599f746 GIT binary patch literal 540 zcmV+%0^|LOP)pG&PhZ;R5*>TmA^{@VHn4s_q;MC!-&SVNGQ<|XQe4zN*5>Bi0B8_ z(B#-6L6L|M{Rb{Vi#3V6gP0CRo1=x1WNCN4J&&ne`ihtMh3DS)?w;?*_nzm@7ewNm zNBRGBF5)l&co~PsW->XW`d^7=YV2ZK$Vt}(`*N5OAf<+A_H;Q-!fjD$0z5v=(< zNJ~q12;bJ;lls6LIQZ+Qr@Fvx59U!mYOCWHBylcbJT}v5{$er>gjS;ah<3I)od2#FpCA|3k6_{i&xm(Fx7bluOHSUk)dF{B0q6Z`^053cwF=zqZp!gO@D;0000anMprEOz zi(`mIZ*qzP(;s%G5<@oyhKoKtB29tJD-syEdm8mueQ3PsAj8w}ant&b^`}8BSioJ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignB.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignB.png.meta new file mode 100644 index 0000000..dff6533 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignB.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 8b6b31f71cd528243b053cfc488e73f5 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignBC.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignBC.png new file mode 100644 index 0000000000000000000000000000000000000000..3118ab10593c1b69d6e1d48975d2ada785dd2902 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC>Y@B z;uvDloBZYD$DijNTn`*^NIk%moO5$i>qMdE1iPiXxZQbWObf0!Br$N?c}}jZitt`! z>^Z&Q*>6FKwhHez;*R|ry1ds+KAfpAHTJ{-1_rYXzK^{pYK?$qGkCiCxvXqMdE1iPiXxZQbWObf0!Br%-sUf`b4<~c#m vYh|(8OQFchYLzxcJqMdE1iPiXxZQbWObf0!Br$OBl=6M{a^aL9 seF?e7mlI{$mQ1^|!N8e4q)d^SnPH0pZ@U)rX^^c9p00i_>zopr0Qs6O7ytkO literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignBR.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignBR.png.meta new file mode 100644 index 0000000..c3dd648 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignBR.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: eeac3acbf7d1cd54fabfb1c4a12f9fc8 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCC.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCC.png new file mode 100644 index 0000000000000000000000000000000000000000..c5f85ccf8c0fca414c90e664cda7f5db110bf004 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmDCp(s z;uvDloBZYD$DijNTn`*^NIk%moO5$i>qMdE1iPiXxZM{t>ikggefBcZHz<9Q-ou^) w7d<3f*dFz!)@FVdQ&MBb@035_LApigX literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCC.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCC.png.meta new file mode 100644 index 0000000..75090ea --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCC.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 8f0cb66458819764b94b93250bae94b6 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCL.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCL.png new file mode 100644 index 0000000000000000000000000000000000000000..39e15460bcb8572d222b8c9f81b7ea7042045945 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC>Y@B z;uvDloBZYD$DijNTn`*^NIk%moO5$i>qMdE1iPiXxZM{t>gYGgHA<>ER%x7k?sG|X zlTxNh5Zl5=9ii7x4)AzwmgDJh<9eE~Vfqao9tO^d0!J#qMdE1iPiXxZM{t>O9FZnYp}u(w#U18>Y*P xCmM0^s#s4uuM+EYa@FF<{;Grx({J$bFz|=+F9@hFv;-Q<;OXk;vd$@?2>|{=G4B8X literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCR.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCR.png.meta new file mode 100644 index 0000000..6223c1c --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignCR.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 6f504a3fa8848264bb4fb9bb7d582dd5 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignHC.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignHC.png new file mode 100644 index 0000000000000000000000000000000000000000..dc638a7f4794363ae5117c54dbd4656672539c99 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMprEU# zi(`mIZ*qzP(;s%G5<@oyhKoKtB2A6v4XnowJom3j5U6;#Y5m9gm`O)Y1ioRaPanMprDnf zi(`mIZ}N^e*?;6)Bu}vT@Q5&pl{Ef$XwW;x!LoyA!41~K2N-%Bj)*7RV5nUrC@;}_ ftg+vXjg8^anMprEs- zi(`mIZ*q!)aLhN;fBcJPN@%d?{80JN%(zQJSwP{lX4ydl1BQHsMeGu04m-IwxQf~t oNcGNWXq~a*5W7YRBQrCD=nbx>q?xC$0*zzvboFyt=akR{0RQPILI3~& literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignR.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignR.png.meta new file mode 100644 index 0000000..884fe5f --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignR.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 727ba41e4cc95fe4a98b07301e3ebfc8 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignT.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignT.png new file mode 100644 index 0000000000000000000000000000000000000000..b4397c60a97aaf24c2506005053933d6469f947d GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMprEm* zi(`mIZ}Ofu*?;CYG95T#@Ptvh=c7D_fl6b;1ev3W20T0ojfM%0PFfPYM;gr=8W|a! Xt+|SMR787$+8I1u{an^LB{Ts533wwe literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignT.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignT.png.meta new file mode 100644 index 0000000..30bc025 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignT.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: b4785ec6d937dab4fa59da70b69afc9d +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTC.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTC.png new file mode 100644 index 0000000000000000000000000000000000000000..de6a933ded8177badee0cc96a9aa1a2fbbf3f089 GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC>ZAH z;uvDloBZYD$DijLnD=m0wS>kb&6Uy9V!Z literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTC.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTC.png.meta new file mode 100644 index 0000000..0d20edc --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTC.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 0f79253104349f44cb73978f6c8e93de +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTL.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTL.png new file mode 100644 index 0000000000000000000000000000000000000000..627b907d345cf01adac7228639ef5ec9126558dc GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmDCq6! z;uvDln`|<3`S?L|7swrOvz3R3LGvN^CyAfE+CXC&JYD@<);T3K0RSeKFSq~z literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTL.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTL.png.meta new file mode 100644 index 0000000..cf3e9ab --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTL.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 6efe1c8569d975640ba0c9f2ac4a9d61 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTR.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignTR.png new file mode 100644 index 0000000000000000000000000000000000000000..6a0d89d4ab8ee1f7bb014545e12b133563639a3e GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmDCq0y z;uvDloBZYD$DijN*eV3SaICfvW}eE(-LoanMprECv zi(`mIZ}I_lz28#**%NEBW=LqT^t@pD-^j3@O~K(=@SCQ@1co?=`57uAxh)4WOoSLp dI^5XU7;GfO7!~URp8*YF@O1TaS?83{1OU0VB-Q`` literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignVC.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignVC.png.meta new file mode 100644 index 0000000..52134bf --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_alignVC.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: d1d45eadab0e41c4a82cdffb6396b1d7 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_camera.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_camera.png new file mode 100644 index 0000000000000000000000000000000000000000..f1465163efb49c68c56e9ba1105e270d1f95f79b GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^+(695!3HFgJ}hYlQk(@Ik;M!Qe1}1p@p%4<6rf;( zr;B5V#MER5_W%F?e`kFp9`L4HFOq-iiuO__%H znoN1md1U*78^W=L?2}%eU{JZn7^=*0q}!oq{{KSe33KdEyj9>+?nqD&GBBLL;Luh7 za3cH3ql_Qf4ftPlabCFKz^<^7Gr&{`XyJVZhG}PS7ZpG4M{{nR2Y?okUwsNPz=U-&>$pGlQm0E&;jvafB_CrG0+>(T%ot< z-i>x(?}B=UDB`~qiM=aBNQ4AMQD5yyVL+(;27Z3_XUm3g6H!X<6h--L+x8x~2R@`} z`gJL4n&w)Tbudk{!Ps$}A`HVbh#_s;&c{h$I%ZkM%Cck_!(`TV9YZ1Uef9GA5d>ju zmSuSt1i?>T*Bla7*1>) zsplTR{8j8PRaJE%`fj*?cSQN#q5%X~1DT<1wGmEJc=Z4P002ovPDHLkV1jVXlTZKv literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_camera_border.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_camera_border.png.meta new file mode 100644 index 0000000..234280c --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_camera_border.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 358cddede8023574191e0aae610a4645 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_cog.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_cog.png new file mode 100644 index 0000000000000000000000000000000000000000..b7f481e9d866280ded3971b2fa8d5c7ffad6c8ec GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4aTa()7BevL9R^{>eBfcF0TApGDoI2^R2Y?GW`Kg2n3z^kQPFj>va*-t<>ggXR8&q|Sy}O4zI=Hv zNS+C%@csMuamB^O{My>un?Sg*u#g`p77deU3=R&?`19va4$vfxNs}fqzj^ZpEFmHy z!jPAj_xJJR$2VA5Sf((zxVU^+w{G2kpyL0vwYAsH&CL&jFo+Ej1IdBZFflSRX71d% z^Ec2M1|a?JC*4wvlPiF)MOUI{ApQ02L6r?6hn1I_eFyQ6o z^=QkME&tQg)Bk|*wr$(~dwY97hFc9|0IgZt-`}74`}glC5dY4dJIf>_B$hyA85jUh Wy^gC3zEAG}0000anMpkR`x zi(`ny)MSRn|NsB*{?p!YJmb%DA0B}Owx#?FKk^?Cv2c3%SfXZup^w8K$*d)EQ~nDc zOK;%%*Un|6_|b9J42Q5Aj=k1LPn`I{-&xOegk5t(3)h?WODk$7Twma}E8&x*1jEX* Wyo)>cM1}xuWAJqKb6Mw<&;$SlB|xwM literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_comment.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_comment.png.meta new file mode 100644 index 0000000..1e64e47 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_comment.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 622fdb780ae13e840938631c5ed708f2 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_comment_border.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_comment_border.png new file mode 100644 index 0000000000000000000000000000000000000000..d61a35d12f89898b1bb6a87f416d2a361fc9df45 GIT binary patch literal 426 zcmV;b0agBqP)pGTuDShR2Y>lkilxgKoEvE8+S1qdrBSz(Z+Tuo@I4L}>6}4;Jg8U@aoq#-#rS2Zo*5{bv7}5y;M})vAjl4Nt-E zf*@E@N*}^7WXS(0hbomyW)Ify_j9#cjRG?B`TR|*)k-&;O$EqH1S*PhUMiJ-dF;Aw z$QZLXn~hd3mr1wV{ls;T?v$?@jYe!Xn-N)-zvA)uK1@j_lf*Pl5em-{h+Yg`*N+^> zA(AA$ilV5a9WF`c^Lb`88aW({;o+oMEXtiuhb2%7r+wD6TpQ@^Q zipIZrwQbwX^Sqw#`xm@F%d$Qo`?gc1m#7Zb>or-eRvvy>0zNDh3Z&g``(U0T5Uv}B zksFW4B#}rAG0Yh@5bbv|nWRu;@mSC_jgK!0f*?cY777Q*@8Nu1KZC*Gm=Hq#0Ta-T U6;Ga>XaE2J07*qoM6N<$f-3^I)&Kwi literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_comment_border.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_comment_border.png.meta new file mode 100644 index 0000000..2f10151 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_comment_border.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: d98b8847646169c4fb5af28dd84c4179 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_delete.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_delete.png new file mode 100644 index 0000000000000000000000000000000000000000..85bb2483c4ab2d98a3c48823b1d38c1d34308331 GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqoCO|{#S9F5he4R}c>anMprEs- zi(`ny)Z`!k|L^AzkY`BBWz%5TxG+hHCxDG(Pn%bU^G$_<21efpwjzg36{I;QH)yhW o8yN~Pv8+`%HnC#Q&v+Jwhi|t0e|4ql7|=KdPgg&ebxsLQ041|4GXMYp literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_delete.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_delete.png.meta new file mode 100644 index 0000000..31ad788 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_delete.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 6b1f9e1e1c2cf004b8e3bdd3033a8e75 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_demigiant.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_demigiant.png new file mode 100644 index 0000000000000000000000000000000000000000..3445065c4b6b03dfa8849bcbb2bcfa2d4b2e2c70 GIT binary patch literal 605 zcmV-j0;2tiP)pH4@pEpR5*>5Q_pJ?K@|RGH*N#jG^J~^0YM@X2)zi>o?1O92%fwY zPoj8`sE7Oo9zFGB6>L?g=s`Sq@gPMHD(Xo+`lA(;Dyb$d{#wU0-R@?5Z_*9BjTL;b z%=_NV_syHP?+I+OLZL7$gs6~vNGY|0V}zGzc|iC|y~kz`%wevX&1Rsod(n%aFjA?&3S3+)E7L)Tc8XI)`XLee}Vj{OV9vd1->_wQkH7?#9 z1Jm;ohvIl?wVv3kHNQmeeZ%+t8Sb#$(anMpkRWh zi(`mIZ}Ofu*?;CYG95VLz{^m?YBpU!*>5Aa#D8YSE(U>yjHIKQWd{um8d#^ZXk17L zT)O+GjanMpkTSD zi(`mIZ}N^e*?;6)Bo{oePZT)Vz#=ixw7KEjGGm?}2PVJMYU6J&Klsy!X9|emq_GlszP2N)P?_LrFKH{mS>I)TB{)z4*}Q$iB}C&NWd literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_distributeVAlignL.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_distributeVAlignL.png.meta new file mode 100644 index 0000000..50dfd23 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_distributeVAlignL.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 32eaa0efb2b38774ea9705b40fdcc00a +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_end.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_end.png new file mode 100644 index 0000000000000000000000000000000000000000..b71eefe4f8ca86bf8b5f34072ab4d52fa6be39da GIT binary patch literal 475 zcmV<10VMv3P)pGjY&j7R5*>TmCtIzKoG`fV--CJ^&m!XMGzlA=vh377bTbWF+}VIz)j$g_qya>y zop}kHp=;!G064)3@C^E9OaOch77Ct$IF4ZbmQ5x@=4$06Tv|4m;WJ;1!nK;)#0GOV zQ|b_g2v@6sjVzXJ_U-5$&d8VMa0qm_FI~T=ef_V&+Q&>wCjV@(KK}&}eF3^_XtWu^ R>+Apk002ovPDHLkV1l}g)4%`# literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_end.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_end.png.meta new file mode 100644 index 0000000..3580f68 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_end.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: a248c8288afb9184f953d9aa07a696b0 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_flipV.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_flipV.png new file mode 100644 index 0000000000000000000000000000000000000000..f4525da66a574728188a6a2a06bc798a8bfa3803 GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^AT|#N8<337)>#0gI14-?iy0XB4ude`@%$AjK*2~) z7sn8ZsmTqE|Ns9#-ekaR#}KlB@kso_2n)x|NsB@I-K$EJNDOM4`avM4=a<8EEDXk=IHn>At`CUXmzsE1BMA}xi{YQ z^HBCX;N&2;Jh(8EMUy4d;)sKeg0&T!c0vLJ!+BG+jF~?Te*w*A@O1TaS?83{1ONcS BGUfmP literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_foldout_closed.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_foldout_closed.png.meta new file mode 100644 index 0000000..fab01a6 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_foldout_closed.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 301c130dbb4bbba4e87072804939c861 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 32 + textureSettings: + filterMode: 0 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 100 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_foldout_open.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_foldout_open.png new file mode 100644 index 0000000000000000000000000000000000000000..50a913a971a434d3144fd70243f25abeee47e062 GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVxZVz5N14{zaj-F7~|>U z7@{#TS%R@aaOUU#|NmDhJZ*4(%jo8I%uS-5)3=C8p#I3Bm&zf1jH}%ibSkj^jWGG< z{8XagCdZ{30S{RRAu9$^WuAt*r|ge-1J0ax;9|(yz@FG9$SonkaDh*WN!Xr08fXuL Mr>mdKI;Vst05vx;wEzGB literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_foldout_open.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_foldout_open.png.meta new file mode 100644 index 0000000..cc34f91 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_foldout_open.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 18a5a7cde794cc04b9b446f0feedb3a0 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 32 + textureSettings: + filterMode: 0 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 100 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_heart.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_heart.png new file mode 100644 index 0000000000000000000000000000000000000000..7ea0c06f4746fde06696146f5fc58c0bd2a4705c GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4aTa()7BevL9R^{>ytLPfU_N>xK}dN*#rXpV6b>{n zCna{u>aU14wYq1NoD~D zm^$_=Ycg%r-C)I{A;@#2exZfL`qhnGMGg|7QyLi=n7I$IoRxdH4Co#PPgg&ebxsLQ E0P#aag#Z8m literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_heart.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_heart.png.meta new file mode 100644 index 0000000..072d281 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_heart.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: d173388c1d9c32a418b5b777dd89d71a +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_heart_border.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_heart_border.png new file mode 100644 index 0000000000000000000000000000000000000000..a53308482c1c4eba9d0d1029a8ca2efecf1d5546 GIT binary patch literal 307 zcmV-30nGl1P)pFMl_cq?D9T1v)q7DC+rIA~x~?DU zx>nen+P2*h%d+-C5YVpcC=`Zai-AW5h7O9ivMecARaL`qf!Vfw6$z6p%Y;kQG%^+# z>k9(&Q5?tQpWZAY>@hRfbuW3I(_bM2LuWX}_FQLdk&vvS@a=_E)L!3HEN&baUbDb50q$YKTtzQZ8Qcszea3Q(}X z)5S4FVrnu&CR${#usG2zMNh8rRs{)bs+ lOi=mRxP!%unUR^9Vf*65*esbtbAfgpF)=5M`R2Y?GWB>vK0|Qq=H|Zl=FOYpbLYcKQg#~|NehVOUv6#K(>mq zvN8iQkd>8X0GcAg^!M-IeS7xo`GYLEWXY1BEG#U08ML*vh3xI^U!6L23Tz~Z2J&A3 z9Vq}-sjshZ7!nfl2P7FB9Q+697(EnwfDZc&l5})*{0$RhfiXUR{`}w6)RcjlnHg?B q6O6&m&VH1QjqN9p-VYIBU;qGV6Kn1Qa9Ml+0000_o}_+Lvyv%WI`uW@8dYxngml%7+dnComzjliO;w-JtD?B; zu{7`9V>>@xzdqA4{ol;}x4%BR6vcj_S@%w^>F)!RQ+SPc91xgwpL5)(?L0_geb8ifvwV9VGnOl3`K%X*ry85}Sb4q9e05qY0+W-In literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_lock.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_lock.png.meta new file mode 100644 index 0000000..b7bc6d4 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_lock.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: e3d0592dad579e141924133869455c53 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_lock_open.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_lock_open.png new file mode 100644 index 0000000000000000000000000000000000000000..be8544366616d44dfba55c5524d3f756ad308cbe GIT binary patch literal 293 zcmeAS@N?(olHy`uVBq!ia0vp@K+MO%1|+}KPrC%9I14-?i-BT?L74G){)!Z!;B`+I z#}JK)$qsD)|Nl>Ceq^MukMD?m;}0=`>kUUFH!v<>;TFhee01L74)>8xhdVq+2ZPkyRh;F7Hb7t z;SN^Lj0fzGq8;Y&ZL0cL|K@=x-^ZT{&o?fZ`HR2fu7srI(S|L?0{FVdQ&MBb@03Tp9dH?_b literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_nodeArrow.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_nodeArrow.png.meta new file mode 100644 index 0000000..aabc040 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_nodeArrow.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 4aa34055b1d36ef479af3d7b5701b28a +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ok.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ok.png new file mode 100644 index 0000000000000000000000000000000000000000..b4d864a5b768bfbf4595d3b76ff9ff5d676a2b38 GIT binary patch literal 715 zcmV;+0yO=JP)pHeMv+?R5*>5mCsKTQ4q&xmn{jc7L8b-{%C16#;aP3L5PXoBs4{g zMB{-NjUGIZ22B3~V+rvOFvb&HM4C4EBS?allu&An9y}OB<%briURu~SX4|ea>vq$w zyQNMtncbQ9{p7v3@69rxW0E9s82soybPsx~Qd&n(qDRof48!ELT1E#(ppiL##yypr zfCV828F5{%*-Wj_Ztj9^Yaeu4E-Ybc2%%wJAc9y7_gBQ!@KE|DEbuX?X6=?P7_mPB zhshPf*C2w6THu4^ulVr5stn#7?L%mkRX)JO!1o*f1>4K*lOt(JOAKPszV*%vv#z8NuNijIdDDrT9<)R9Ww#~!1=e=jeCM@vRuoIn zPrpAvQ=JVO7&FB9*Kp@sKNO^b?#xc(-lM%IVAyBv|7So6x?S9YAGpW2*7`t{L@+Xc z<5dbz8RcMqzO;N!_bfJXHiU1Z3x+T{8PA+=Quug`Ra(&C=z+)bHPYJ8e5NXlG^8a4 zvE;8zcM$Jlh%UMwv>J>wq$LLB%8yNuy2f+YqTHHxG8#i;NkiIF-l)NjzU8OeUgRdL xHQ2A13K%w64Yd3h;6-m%N}K2jF#H7o`~gtZ6gst;c2NKT002ovPDHLkV1lxxN7euU literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ok.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ok.png.meta new file mode 100644 index 0000000..029aabf --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ok.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 34f39b5a760ddbb4d8b8749852868335 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_optionsDropdown.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_optionsDropdown.png new file mode 100644 index 0000000000000000000000000000000000000000..1d89e2aff67e6b03ae1ebb542f654799b30f9ba8 GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~o!3HGD9`RZNDb50q$YKTtzQZ8Qcszea3Q*9} z)5S4FV`B0G5rapQ|NQ^|-*(R|Ny(`RT%R4gCKlM8)N9CMdf4eOS$)zICKG25rYoGy ffexGr2@DK}AFAEl?xoNRG=#y^)z4*}Q$iB}Ky4`= literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_optionsDropdown.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_optionsDropdown.png.meta new file mode 100644 index 0000000..560af25 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_optionsDropdown.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 62a48d93e78c63b4ea9b46537c7c0091 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_play.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_play.png new file mode 100644 index 0000000000000000000000000000000000000000..0608dcb7ab4d0a1a5d2e56b3e7affa340ee4d695 GIT binary patch literal 256 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k&H|6fVg?4j!ywFfJby(BP;ir{ zi(`n!#Hm4!T+IdoF+Tj2&H5kaJ@PIRX3^it@z=+0!u<{pTkc<7_iR*NM~Q@a-?B1j zJYz8XjoJogLDi3rIi2f!-!AifprEK~XV`buyYgvWxf936fd6)#(`Ky>4Si_hyD?xd zo7Fmvr3UAVw_JNFW<$T%X&MBcEjH{|{-0xuic+ORkMZ}fy zn8bun1{WVLez{4fQ0Dl0-+1ZQPur8v{{3jmAeR59;KbVEH5EYDGkCiCxvXpGG)Y83R49>^k}+$8Kp2L<>f+`ggtSveOC}W@9EARWZf*^NOP7M; z?{IW04ia$@obne0hoTM{>X5;yTc~5j>gCRwgS11*3y0qOKHul@oi{LRwOVn4AUxyO zC%o=w`yH?Ncs#x~P4h*JsX&sXJBDF)x~|Kc%?3nKoanl)VY}TzmSyEQj*nGUeN3Gd zMJa@_iq5T}OSw z5SGD570+irYZwLy!w?L^fIQD9Z)QXW{t<3|v1fjUQD2xW%Ytc|kR%Ccnnou^9;6_Q zqKLxl^%~+h2HUoQ<2dTiOnCKJ*|u%Jm&@g@D2fOC+1tfp0X)w`-}kWJ@4@ptNYiw> gIGlf8`D*~20Kj|d@@JyvGXMYp07*qoM6N<$f*&fV3jhEB literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_play_border.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_play_border.png.meta new file mode 100644 index 0000000..e57aa67 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_play_border.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 45e128e1cf00555479ee7934ab11cadf +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_skull.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_skull.png new file mode 100644 index 0000000000000000000000000000000000000000..7e5397545d7a45641ad23338850e6cb0b88f03dc GIT binary patch literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4aTa()7BevL9R^{>pF{z*hZR2Y?Yk-ch#Koo?JKZT7=Dr<|Ru+S*cI!};iN$D#HVr47% z0zx1*7Pq-w2&A%zsAaIwG=d62H#-tT;F5ubVdmSzSymt}!!WKCMR^oO@j=tH8)RMA zy>Hw0v@Ax^2p$zK-1YJrzYkS(eeduKR&Uh7OF(FTb^IdmDx!sj5nnB%z=f4aTa()7BevL9R^{>$+Q-p%fJeONQYMtD+`qRv0zM#G2+ELR(T@C*1i yf7-ktN#oik#*bPGVQxafZCx7;4Gatz7;bn?UAF3X!Zn~n7(8A5T-G@yGywo>oJJ1- literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_star.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_star.png.meta new file mode 100644 index 0000000..59f2768 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_star.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 645aafe2260b2884a9df05b4bc01b1ec +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_star_border.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_star_border.png new file mode 100644 index 0000000000000000000000000000000000000000..4615829ffcca351f0e09b4b4287cdc14d2044f1c GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4aTa()7BevL9R^{>)M{{R2qJVSfp(U}u0Sy@^6Vq#)0-MMq;l7iVL z8RZMJ0@Bjbj=#UZ|FuokmlHeIt?TRV?Ce~)Z{NSwd-nXX^z%EXUH|{z-SZP>&%T|L zo&CH1`nuTv^7eIqf4aTa()7BevL9R^{>QNTh{iU<7c&ovDsNyG-pFXZWAl?kyu6|u-FzmI#H8}* z^_TBTj@Dn`_Sx{kQ}dxkU*eUhjk&ikyeTw$;QHP+GCMMeqjAeM=gr3@Hz!Q87o8fk zV;%S2@;T2rHJ`qJv}>J!(*cQQ3FSG(_a}dOwlDwI_qkEo^4&$}LcAoaK0Q1j9IKVF Uz+qRVG|+Jjp00i_>zopr0G3Bs*8l(j literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ui.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ui.png.meta new file mode 100644 index 0000000..0d3bf2e --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ui.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: cb46e1d925af22d43a6f8bf0e1d459e6 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ui_border.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ui_border.png new file mode 100644 index 0000000000000000000000000000000000000000..6613a3d325a527ada017fedeaa3447d3728e9eba GIT binary patch literal 259 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k&H|6fVg?4j!ywFfJby(BP;jfK zi(`n!#J!Ug`C1GFT>tAy=rt%l~V#R=!D_zopr E0AM_3LI3~& literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ui_border.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ui_border.png.meta new file mode 100644 index 0000000..2ee6aab --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_ui_border.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: c0c40ceac3c6df146a0fcd4e6b226540 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_visibility.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_visibility.png new file mode 100644 index 0000000000000000000000000000000000000000..56a1324846d22c617d1340eebbd88925cced18a0 GIT binary patch literal 298 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~e!3HF=pW8M9Db50q$YKTtzQZ8Qcszea3Q+Kl zr;B5V#>8X?_W%F?e`k5*>QKYpvES*V?1~xc%z6w{uCP41{GXF~f|TzJJGT{S+6r5R zJMJ@mEK<0~e&l>Z1mmiAi~`<_8-)ejnKl{->^3$sl4H&kV|=vRVGi#RodD*$jX#tp ztyS1&9n#0TN^FTci^>JAQpPjdOc}E#@;-D9N@qTD*2m#n_=aGC11udsH?RnMoZ)#_ z?siPs;gz+pSgQ?>3d01(niFvhP0S8|IJ=`J+>n%Df5NJ8l#~0&?pGAxT6*R49>klD$d;K@^2&C2VORq!1K*fna4~2mvceC2Xs&;2TK5 z!Xn8_SOwohEKRVq5{*AtstJfTJATL9)n%Q%@a@msnR9369;fi$$8Z5(un#LRhB>^! z4V=NAaxN4kYVZyz>_Q!8{(nrNQC!@H4QRp#yhy-u+Rdg_AHf4Gppz|Dr8`LMUm~CI z3e~_)D{ut2KSg*9f7Sjbo!EAt%FfJq7f$ujFPU&|B3G^?$Q?^P4JD%}I^;EhZHbkM zNMN;igk0>vBOK^hh3Z|c&0nG}rV`j@)h<*Q+qAL7*3`2}9c#@!46J4AIT00kwidUn z N002ovPDHLkV1mOvm^uIe literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_visibility_off.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_visibility_off.png.meta new file mode 100644 index 0000000..a0db454 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/ico_visibility_off.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 0c0132429106c8a4d89d9d0a6b723ec3 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/orangeSquare.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/orangeSquare.png new file mode 100644 index 0000000000000000000000000000000000000000..c272180edf95f9229ae13d1eb1c0362d92759ab5 GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9F5he4R}c>anMprDke xi(`n!#N(E8hH(Gnn1k=)1;xK#l381?e NJYD@<);T3K0RYm0RxJPk literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_atlas.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_atlas.png.meta new file mode 100644 index 0000000..eddd2e8 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_atlas.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: e2279677842a8064fbae0bc889fb85ab +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_audio.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_audio.png new file mode 100644 index 0000000000000000000000000000000000000000..90c521249c6777aaef0ba7a53c81f9744892bc82 GIT binary patch literal 338 zcmV-Y0j>UtP)pG1W80eR49>SpcP=lCBcYGLS0>bnzOUB$=$nmpa1>)_YX*H&z?Q4 zKW_m;x3Y8lPUfcI`8W5fKq_?B&aspZ@*($BwK3mqu|_RaG7k zW7e!$CO}Of+ZY4|1^408XbHr2KwEx-I4f4Hc<}l2=igAdZCI^QP*9k#dGqFnPoF;h zdhz1Lw;+FMX=%*^O4$Ih3=Y>ZIPKfF?igP)pGyh%hsR5*=e7;wOdM@|`tO@R0(5O0Ul7=Rgzm=O@i@i>Hc%ZiId zO7L;|{Qv*o@B8=f-+ZI7zKTe>(l-zB+JC`?;nHEy`u~g=hrhZy}bMJ z<;$11U%!668K|xan+uE-6cjS~S^g`CzPiTqmz9Izhp-&OcVR__*II52KPA*SxPO1; z{Qu@L*RNl{E&in(*|TS{f`WoCj_uigll{hF7O8tjco`U(7`_QeGyMMX{qt94 zGY*Yc=M-MNc<~gd{t&v~YyLyQ&!0d4u3x|Yfr*L9F#!RAqk<9T?-*v>{mNy75FpRP!^4u5mBsLbjaBeH$hkkiF#P@d_cxIF8K#zrfds(v z<1+)ug+S(CY%X{Y1V4dcz>chmk&%&w_3JwZg#%L%#14U#J4L~u4HCn zV&d1*(h^{2XJ@{5@80JfJ9e<}eS5{t_Ui7>w{KqG28u2D_wU~_p!$!vT&gA}Cf3!~ z)^=&ts#W)tm6ab#OG{q@8r;eNNu4MFUs9F>VowG{Qhv!W2mu2F08Rp}xKNEjp#T5? M07*qoM6N<$g8J0>{r~^~ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_bundle.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_bundle.png.meta new file mode 100644 index 0000000..66ef715 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_bundle.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 58676a985ae875646b7be748cf4499fd +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_cog.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_cog.png new file mode 100644 index 0000000000000000000000000000000000000000..fd589a0f316096bff8afdd0b9fbe51b3138d5466 GIT binary patch literal 406 zcmV;H0crk;P)pGNJ&INR49>S7%;$$Ma)P_N~-w(|NnNse*L<~!^2Y|A|m4T`Sa&D zK)L6H46J$i^5wVFr%%7Csj0aDqCtF+I6h5sK%5a47Pjy2-@pHn0f-M02g+vxu>yup zet!Pet5>hS`}60|Kahrt7cah@K7INP5Dnsk#IIeu_8z1TriTU200NLAW@cu_%a<>| zGd4D!2-L6*DC~9a+_`*RU0tDnKmbyQ&Do-bg@tE82F#v4`zDZY4iz^C@j>D_IXS0+ zd_fGIz))>Dd-m*WkfKYMF1-a>PzMw?0ns2nNc_r`D{qB`g*!2v&Bw>bAuTP<4Rjd; z$caFM@{b)m7G-5+B?{t$0*w&}fL{57&DlmkToVxyaR5(fXD~ow1t%ano*A*Z0GPs} zK7IQ1Hok0944~0%+A3JOBUy07*qoM6N<$f=el@ A5C8xG literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_cog.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_cog.png.meta new file mode 100644 index 0000000..fa51749 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_cog.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: fb605a2688b31194887f2e7a6769235b +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_cross.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_cross.png new file mode 100644 index 0000000000000000000000000000000000000000..a34a3e8a0f23b3390c7b578fa3b0db5b4157e266 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^{2anMpkRxq zi(`n!#AFE*hqn3i_w%|4YxV^sBqVHj@bmNY`=?HwI>-34Euhd@KwgD!((x>Y6Dbp# z{yTj5{{H^|0A?RYlMa3+g~}D&2Dxrw9E+~6jsDIsliyTe`DNaTybX*hy=^=!4Nsq) zoh`4F&GympQH#l>T;rd0%Ph8>>`R})_+*(u6%!j9gI(_3o%sQ3VLpGHc3Q5R2Y?GWPkz*2?=i?RSLvLP@!``-2LLki>)9IGl&ou7jI@_ zVwxes&!o_m$;a+x!NGp&`fr8rzZjypxw%=se*L>OK3}WmXZ3a#~{He%CPhKL53fHe|}*B34XG$Wca433081#!+HkYAG{3B#t@4XxMdh7 z-kit41oGW~7G}5||5;cV*qPbkd{!n_a0oC1ef5t0<;zG0U_f!*yv4xz-~q$SA8#1m z{Cv;w_}g=a#Shjp{P^=Tj}a+&Y8bG9fB*iqynOkx7HlUdoPZ{S0$2)&g@O1N5TE$} i|9>7((F_I#1_l6)Drz~&RO5yK0000anMprD7R zi(`n!#N-r)Cg0g+f71^z{`vFAK}6ZiQjLv^LD??)BjbYZBM~1oKYaaqRQ+$4QTl&& urcEYBMnPf;i)VSVEHL>!-)1cj55t^we1F}Q<{1OcWbkzLb6Mw<&;$TUXf4VB literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_folder.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_folder.png.meta new file mode 100644 index 0000000..e0a5072 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_folder.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 4f2c4b43188596b47866d41e1dc13c8a +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_fonts.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_fonts.png new file mode 100644 index 0000000000000000000000000000000000000000..9ce1a4de4485e5d4ab57c8f94b8523f6b9c46436 GIT binary patch literal 465 zcmV;?0WSWDP)pGgGod|R49>S7&L&92sOfvj*io%q@*MsKYslD(4j-AK(S8*H32a{ z5C^QX-eF^7v(?hll3u=i`MJ4s=U({(1i)Ak z1j)U6_3FE*s3`l37caho_&_h304W8SUgRi_Yiw+sz{SPI0Wtt+C~JItJgb0!0F$h& zZ2$A;&tK{3>8W14crh8|MP+5>Y@nVcAdM_YhHP(cZdTIP*0%fb;luN9-@d&ADzpG07*naR49>S7%;$$#@AL2C2ox#U20gKydEdxi=gf9E~6v#0QCkDPZGFn|91TgZHnJV+geW=BWIHUH7T=g*&iqlDm zAoD@;Aa&UMY_M$Evb+EBfTc^9-T|q@rWs^Y%b7E0USZP+5(mjM-~r5%l9GKur+q@! z2;zgp88D+31BmMC>dt%f=FNAIMi33+gTxt#1PV@0PV3&id-ub|#bqOi&p;wj5*8Nj g0MQJC3@|VN0AR)IPx# literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_heart.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_heart.png.meta new file mode 100644 index 0000000..ead0de6 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_heart.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 20794834c0a413f408b80110d0fc73b8 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_materials.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_materials.png new file mode 100644 index 0000000000000000000000000000000000000000..5a4b7eb1bf282c87f82b1f2ce362cb37312ff6ff GIT binary patch literal 355 zcmV-p0i6DcP)pG6-h)vR49>Spc`OB<1+)Xr?9Ya0xvJG&Mv~hz(7<`P!KG5{rdISYuBz_@#V{xLYPKoBuze+mX_6~rlz8*s;Ugi z%E}Dl;^GWKLPFd?pmg!##p^&dw?GP6U^;+KikFd*0ox!cDaoLzsR=g?$QBh76N?8r zbu)<11d{+dO$MLmfwsZr;WmB${{0Ei-RAG#zh`*<{5f1Phz%0^^y$+R3{7v}zFi2E zw0rdEktm4&=FJGjL`r9002ovPDHLkV1i2c BpN;?k literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_materials.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_materials.png.meta new file mode 100644 index 0000000..8e57f77 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_materials.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: e02713e10d7aced44a7a651231f0adef +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_models.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_models.png new file mode 100644 index 0000000000000000000000000000000000000000..42f1f236a8149ffa2b1cc8a076f7e4449356632e GIT binary patch literal 380 zcmV-?0fYXDP)pGE=fc|R49>S7*HU^#KcsmqocD0L<9K}=n5E-IqdB0ozBkA?)LWf zssaK6T<_n%|9a@qp*wr`?%nzG=g)GOI%XJylaq5|WMrg2P?H9b%?1@?Q&(3P2O1#p z?AbHbZ{NOcN7f{zsi|23l$1Gm@Zjw~fBt+E6cpsTc=6)nU%!4m&d<-6`u+Pi&++5O zw*b|CW`Sz@2qO4_Ku=Fk_xtzn-xe)ebaLCaZ6*>D5{e)>ph5qE)H@KH30p`2oyBEr zY%B=Wz=cg7rs*rty`TR90bBwIU~FI@{C)oX`DY;W2TDKyL+b3EJ9qxGu&@XMUCGDH z%>35D!9j5D+_|@-qN0``J9exEsO&XJEh84&jetQPAucYi|MlzFb8p|iT@4gF$1nhZ afdK$^w{jgtX~#DJ0000pGpGibPR49>S7%;$0KwcDxzX7of5QhV?8W2AM;-BaWH8?mp8hChk znt^O1Cnu+!jg5^LfnpshDk?jkKY#x9=FOY$#l*zAFsx8eP?-4U&71G<-@pHo0^)gdwF?@ZQHi( z-S6MO|LN-LUVr=c?XP3Uj`d*kpHX07;Lga%$YVfuO;J(Nnb)shf8V-w>mz1n=8f6e z*{4Cy#}`0>7cX9X1JZc!-n~ySr&d>2UjWeu4<39DRO13u%!H;{{lbL{?;k&Y{A1Im zO;11qmoHy_w`|$6i(9sAc{FR*touNrYgjc01O#{hLs^2CmzM=-+Xe{A8CT{P{P)z1q>tt jCm=2cVgrUj02mkmkjv85ZQi$C00000NkvXXu0mjfR!rc{ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_particles.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_particles.png.meta new file mode 100644 index 0000000..560f0dd --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_particles.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 8003873ab749935489bb11f23f830856 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_play.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_play.png new file mode 100644 index 0000000000000000000000000000000000000000..c441add0cc7487b51a19627c59917815d371bcb9 GIT binary patch literal 217 zcmeAS@N?(olHy`uVBq!ia0vp^JRmj)8<3o<+3y6TI14-?iy0XB4ude`@%$AjK*4TL z7sn8diOCD(A3S`RIc@6Hx9motA6F)~8H$LAIO)agnDFoQb^Y6qkN4ZNbKPZrRButb zYUN7bzx=G}=jK%A=H=~^&{*R=g-zhc&(F{AcM7Y=F?&t;ucLK6VN2Uk!4 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_play.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_play.png.meta new file mode 100644 index 0000000..2bef6e5 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_play.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: d8306b1e159c72c4ebc9a4fc31debe60 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_prefab.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_prefab.png new file mode 100644 index 0000000000000000000000000000000000000000..abc435323589096e2a85aec7d8960643efc53863 GIT binary patch literal 343 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=DjSL74G){)!X^21ZU# z7sn8diOCWH3P%qe3VQzb?Os+F=AS|pp`Sm0F28o=N=(JCFE6kEclhw*<70gVI}e%F zY=wm%JG;g8_kDhTet!M`i3}b46Am`rcKGROu=R|A`qJgg!&z8ZPWa5X`}+-~%+uSu zIQPzuk00B3rRAzCD?R`I`r7>*Xk2tdmi=LqVsTN?xvew*{rUNMeO_K3yQ7JZj=uhT zo&Z^P4?|(I`PCvKSA87ZhSFd(4En4n3w<^}rF_9@CPI}n{!S1(iNl8h94r};L{@%I0 lJwKfJ=s80khJ*wLhVlgy_8;k}Y5;~5gQu&X%Q~loCIH(^ly?9C literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_prefab.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_prefab.png.meta new file mode 100644 index 0000000..47f7775 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_prefab.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: ed3789262161efa4fa33c85ca534590e +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_scripts.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_scripts.png new file mode 100644 index 0000000000000000000000000000000000000000..c79b66833bb38b3cfcaf1efcc4ec2e967c4e7067 GIT binary patch literal 208 zcmeAS@N?(olHy`uVBq!ia0vp^f*>{r8<6y`Y?T61oCO|{#S9F5he4R}c>anMpkR}y zi(`n!#AJyt2RuSUOQpEEy=^;~7dh5Uu-M3ULQ+CPr{d?Qr`vOHZ?jEHPR?e!s9@(I zqvF4X@qc5&$45uY8iW`Q}D}Sb9lNz@<`{|2@AZZ>+NOL+*A7c8oPqMkguJP z3g0C5mCP%b&-8X^cw}(UpySSsM#iqoCmk5r*ci56nAf>4>xd7~H4L7velF{r5}E)W C9Y0fhdEP)pGElET{R49>Spc!C9;~Q!V80V|{QCX$%LAuB|9CqGD1H|t z$%3R%ug+-7G9TkijW2>s44(uT7+$h{u+6TJ{Q2k4j|LRQObjdm7OtskkAxT)X74FJ z%Pb_w${@hS0#tYmrUtI~AH$zd_hf(k`6J24Ce7+AwR2JJxu+M7Oae;nf~jFfa>n~t zY#*(7y`3cfnW^$=#rUdm@-rDfJaF_lQ0@h~V)B;3EGl1gf7-$R_ Z7y#{EYeavV3rhe1002ovPDHLkV1h5QtNj1~ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_shaders.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_shaders.png.meta new file mode 100644 index 0000000..1d860ee --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_shaders.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: f252c69cd0163714eba038403f61b09e +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_skull.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_skull.png new file mode 100644 index 0000000000000000000000000000000000000000..22930f4dff4fb6b1a715519097b639c0214e6677 GIT binary patch literal 368 zcmV-$0gwKPP)pGB1uF+R49?nQay@;Ko}i^41#Q%Gz!~Ut&Ng9q{#qHiKe5>XW8pyLLIjyimz zo~Lmf|29p-ilVr9c3GATI_mI=!W7eVT{rCe{_i{t4*fW7N*=)UeSg6Rv^frN0}lP# zI1q&2_%nBDnr=aGgG0YIiZ+b!&6=yKI@B~x;l1v=u3Pg>`y?*{LjD0_ZSpkwGZC%; O0000anMpx|Xs z7sn8diOCXk8rs{Jx9arj=;)NP^UKxnE%MxEqN@7zNxcHYMFl&Kr4ssH!qr+B1sN5AfsnHN}ldU`@`+_*90 z-{0TI3!a^sd0j#32z#gSl{G6@t}J?WWo7ugckf>N`1($EFzHyoaN)uu4jdmof8Nfd knQxMqzv9ON1|A-Ulj|3ped&L9JJ5R!p00i_>zopr0A1^Qv;Y7A literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_star.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_star.png.meta new file mode 100644 index 0000000..f872413 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_star.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 21820ec6fc9dd0b4fbf42a3b93fdad4e +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_terrains.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_terrains.png new file mode 100644 index 0000000000000000000000000000000000000000..750996d613ae7009e2760d9c4d8789612e9702dc GIT binary patch literal 309 zcmeAS@N?(olHy`uVBq!ia0vp^0w6XA8<1SE`<)7q;w2AI7y-w-3hMR0zr8&_RXhA%S7+zf zrW^kkDyXSF;|SoCxBEM7wt0RX$K?sLW>pp4-BtQM@efd7AN#7#150O~K72U&@%{bv ziLd_KSATo+x?5a--(PnoPft(vhAh^Nk^)Rc-|Cqje0zIaej?M%M%H5t$F?4AV&#@& zn8`1}!2ncu@OZy`^Ua=&A{(9-Mh$`ah5_sb1`G_E#Y+NQ;_7vQUS{xg^>bP0l+XkK Dah`nL literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_terrains.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_terrains.png.meta new file mode 100644 index 0000000..946cabd --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_terrains.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 4a091a7609ef2d34bbdfaa1a886deb18 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_textures.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_textures.png new file mode 100644 index 0000000000000000000000000000000000000000..6aae96483f84bee1755eeed1b1ccb872539b13bb GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=DjSL74G){)!Z!;0aF` z#}JK)$qMWSi#}FfxDh|$N4$ZFq_nhtK}pG#){p1sSblzgYiqVofo%M~n1A2iMl*Gs zWfFb7VcWKAFWhD|01=Nzy8^W$Uv z!-o&^6NTQqd9z*M!7V>PNjU{YK6;Q{02{q_GJ)CB|uRqf8WsAOSp zZ~y<`!^7?Nli%8O{rU3v_4W1Pa`tsR{pM+D&-O1}x|Bch&tmufIL4LC8&7%(rZBLv ZG3=K0P3}1Foe1<3gQu&X%Q~loCIG7cdr<%Y literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_textures.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_textures.png.meta new file mode 100644 index 0000000..c18d4ea --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/project/ico_textures.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 3e6b96a975eba1c43b2bad66fb7f8b4a +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/purpleSquare.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/purpleSquare.png new file mode 100644 index 0000000000000000000000000000000000000000..dd219ac3778c1e3f6361c363ad6d5f6856c76813 GIT binary patch literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9F5he4R}c>anMprDMW zi(`n!#N?Q@#q%3Q4jge%lDKNHDse?dLIMLro;2e%hOPfU0o5^hy85}Sb4q9e0KFI- A82|tP literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/purpleSquare.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/purpleSquare.png.meta new file mode 100644 index 0000000..96df50f --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/purpleSquare.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: dc0ca9b32ae9fd049911671cf1a480bf +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/redSquare.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/redSquare.png new file mode 100644 index 0000000000000000000000000000000000000000..798457f49eef9b7e8c27d20db55a3570fd2c4074 GIT binary patch literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9F5he4R}c>anMprDMW zi(`n!#N?X8Cr>(XB_t^b_GC$1H3%^=FkoP?Wnq;2uXyMdP#uG(tDnm{r-UW|hN&5< literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/redSquare.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/redSquare.png.meta new file mode 100644 index 0000000..299f17b --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/redSquare.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: fbdd7ecf39c13bf48a5bd02a1159c90b +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorder.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorder.png new file mode 100644 index 0000000000000000000000000000000000000000..51afe67326b5bbb4358d880a8eec9d5a10cc769d GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMprDSY zi(`mIZ}K0079J4>F@eHwZz4CDNJ~o_8yE&~xbaGuCR}0QSYTjnY{0;anMprD$k zi(`mIZ}K0079J4>F^#o;%l^&w;Sp&HWOn0~FlAuUICGANhk=EGQanMpkSG& zi(`mI@7u|STnz?149RRC*_Zz8viO-(Dzrc71^*i7zopr0L67hu>b%7 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved.png.meta new file mode 100644 index 0000000..32d19bd --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 4896b5aa9d63dec498136c21ffce735b +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 32 + textureSettings: + filterMode: 0 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 100 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved02.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved02.png new file mode 100644 index 0000000000000000000000000000000000000000..a1ed49d445d61396bf5e07beee7ae57f73a6d825 GIT binary patch literal 281 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMpx|jw z7sn8b-nWwv@-{1ow8>X|RN!mid$4hKMA*vW8=3qE*yFR!<+w>I3vJGOX8UH&y4Nbu zoABe*hsE!II~Vwego>)TecE;KWO^b?^}&YL2T5y}-gvMwLGi@2)K0M<(&>}x&ctuv zj0-we9pIBc&3R@8%;d`;VQPAAyZRt1X8*cN}bWtEMVj*aM977LTh&(*zsT&!pJ bDn&8Aja;eBwVt^Y=q(0MS3j3^P6;G|$ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved02.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved02.png.meta new file mode 100644 index 0000000..180331a --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved02.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: ff88be84254fb1f4b9a81a27ae0b2e81 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved02_darkBorders.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved02_darkBorders.png new file mode 100644 index 0000000000000000000000000000000000000000..2b313e46258bbd042a3eb1048f101f8cc698c393 GIT binary patch literal 336 zcmV-W0k8gvP)pG0!c(cR5*?8lQD{eKoo}GM9?N1(8?32rR|;~30^_%LpmEfI}_Me zkD!DcL>$3lJ%RR{LTx7R5jRx=%C`H%@Md(rZ$|JjnBuzbmN9n3VdL@xUgt*$!EwZC znqHqzJLZ^JM)RaJdzng*(>f+R^VLHg9Xt|3VhXxsLL_3PQr*j;-p ihdJ$x^^EWZ0N@Uw6N6qYJeYg{0000anMpkTSD zi(`mI@7u{6xeh4sxCrmw^5{vJ#*hE=pFVk}vMu=Xl8_e}1z#U1G~StAanMpkSJ( zi(`mIZ}N}-|M!asyk~nf|9>aD{lcmxGbAJ=#27zjDm+V95o)-?^f7Wn+yc$}jWe1X zT^KGg7jbrcoZslfaOw0B2So|fgewd)80}B^o^p64exhNqLyUWuV!&2jhng9O-u#K@ aVpvkPqanMpkTMB zi(`mIZ!$yU|NsAu84Ilh=CePV|G%(#et@aMR-Y5IrZawIR_J3%a%7WXP+<@K%&@Ax zlQHX-vw~Qnf>6U1r>{$l9p;K0b5LS<)yeRZ)o>s4Mg~bXj)pHy68|Mnu>60h=*cKy z%8+z`zi6@G67iG+yb5K?hl|WN#AO8S^Y;u|reo}=dg9DE9v%k48O%2poxC~+=qv_L LS3j3^P6anMpx|sz z7sn8b-nYSyT!$3|?(lMcv2?VVHs{xiOExOYFQuy}Hon#ASvfsO^*Ucq*SVgqbrxrI z8p;c{-Jh|N_vD@C)mIPO?q%anMpkSA$ zi(`mIZ?cb<*QBJx#K<52|JPf)xw)CKDKP}R)n9PSx&GguPWD%+kxyQ}eEH__#{cyM_8UjPhKR+;*eEaTkEK|kyY}5V^>;=vqM~3(gJ}VDT6GA zGY#?ww)k#xn;;jkj7hSfgTe~DWM4fq-Ic^ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved_darkBorders.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved_darkBorders.png.meta new file mode 100644 index 0000000..db7c113 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved_darkBorders.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 25da15ac84743244ab4c860cf8798ec8 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 32 + textureSettings: + filterMode: 0 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 100 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved_darkBordersAlpha.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved_darkBordersAlpha.png new file mode 100644 index 0000000000000000000000000000000000000000..4ddd37ad4450952bb5dd03637b99f6e8afcc5281 GIT binary patch literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMpkS4! zi(`mI@7u{6IS(iZxSm%IJ1LTB<8~)FIO3=*tJ&TQkWnE^Zu!b#Q u<*Gj&xY4SW`DFF~9+z8&8?7tP3D~RGm`MM&30nws1%s!npUXO@geCyThex9T literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved_darkBordersAlpha.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved_darkBordersAlpha.png.meta new file mode 100644 index 0000000..a248e7c --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderCurved_darkBordersAlpha.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: f536c51d3da3f2e4ca93ac8773ec2ad8 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty.png new file mode 100644 index 0000000000000000000000000000000000000000..188ed94dc5c375d5925ddcd7fd22b51cb1dbc595 GIT binary patch literal 114 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMprDGU zi(`mIZ}K007M>{#UOWshQanMprDGU zi(`mIZ}K007M>{#UOWshQanMprE#= zi(`mIZ}K0079J4>H8w6r?w*4jEK4$4cFsu>?~yXdI`F_CVL`DnGc&_Jb{%V(} P+88`t{an^LB{Ts5H+UYQ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty02.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty02.png.meta new file mode 100644 index 0000000..b2dcd93 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty02.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 29b0e8156f6fb774faf129c83bc9ee33 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 32 + textureSettings: + filterMode: 0 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 100 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty03.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty03.png new file mode 100644 index 0000000000000000000000000000000000000000..ca376a89c1bc8fe52bea75c4d9312d7d03e7d85d GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMprDSY zi(`mIZ}K0079J4>H8w8Bqih=#iX|EwBz#ZYldI70kuuQXk@z&TvyqYEi~^4&*Vda$ Qf%+IcUHx3vIVCg!08kDdzW@LL literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty03.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty03.png.meta new file mode 100644 index 0000000..e9f14fb --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderEmpty03.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: c0a56b88a1b449045b3fe5f561aa12fa +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 32 + textureSettings: + filterMode: 0 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 100 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickEmpty.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickEmpty.png new file mode 100644 index 0000000000000000000000000000000000000000..ec9ead73db0edfdbe31bc68ee6b8b2f164137618 GIT binary patch literal 121 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMprE#= zi(`mIZ}K0079J4>H8w6r?w*4jEK4$4cFsu>?~yXdI`F_CVL`DnGc&_Jb{%V(} P+88`t{an^LB{Ts5H+UYQ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickEmpty.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickEmpty.png.meta new file mode 100644 index 0000000..89331d1 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickEmpty.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: c456d5ac01d2aa843a63985497b04931 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickerEmpty.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickerEmpty.png new file mode 100644 index 0000000000000000000000000000000000000000..ca376a89c1bc8fe52bea75c4d9312d7d03e7d85d GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMprDSY zi(`mIZ}K0079J4>H8w8Bqih=#iX|EwBz#ZYldI70kuuQXk@z&TvyqYEi~^4&*Vda$ Qf%+IcUHx3vIVCg!08kDdzW@LL literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickerEmpty.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickerEmpty.png.meta new file mode 100644 index 0000000..7365c26 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareBorderThickerEmpty.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 7acc6bd588627b046bc1c9b3cd78a6c7 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareCorners03.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareCorners03.png new file mode 100644 index 0000000000000000000000000000000000000000..38dc1bb8015f9a79cc3209cb6d4f0dc26efc98d9 GIT binary patch literal 133 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMprE;@ zi(`mIZ}K0079I-*Wr2o_nyeWT8Z08x4Ubr7Oy*=vv1NYG+QlnTVIakwk=USU$zmkT a%*anMprEOz zi(`mIZ}K0079I-*Wr2o_nyeWT8Y~6k2Xd6f4txoG)0CKS;6U@mj3sGt2edqY-#KxB Zfk8H0fpdrTc0r&444$rjF6*2UngB35CO-fG literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareCornersEmpty02.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareCornersEmpty02.png.meta new file mode 100644 index 0000000..7f51fb8 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/squareCornersEmpty02.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: ca2f91cc405eb144dad970eb23db2f72 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_empty.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_empty.png new file mode 100644 index 0000000000000000000000000000000000000000..8e17561d53740055d922d1c24df9d17e43f6853d GIT binary patch literal 236 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4j!ywFfJby(BP;j27 zi(^Pc>)UINTn!2$EEg=dZs|~naaq2Nho$>Va=f(C-B&-@1V!}h!%~jfT^e* zN!VYsf_J}mLhFYJ;r(I;OA~eF#1}kR=#X7=s`aA8^iRtk&p)gyY%c5nL|xI|`G!OD zYJWbcz6*~wPq4o$8FH-K-Z6^-W|B ZusuG#)AVYPb|TQF44$rjF6*2UngBkaQPThb literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_empty.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_empty.png.meta new file mode 100644 index 0000000..890be39 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_empty.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: d1278357b25e10442b6ca6c24edc9781 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_slanted.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_slanted.png new file mode 100644 index 0000000000000000000000000000000000000000..c8cfc7fff7801ff59d70a57f7721f9e2828ae25b GIT binary patch literal 285 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4j!ywFfJby(BQ1HB` zi(^Pc>(OZ^IS(5MFqmg5w*S`GKekfwVgk>x9~a^-9cZ#U-DBspJ>Kz6PpaDSe+A__ zyPu}YU271qWcPNMA+v>XVbKMameUK(6kPdC88eG^aCuBU9OgTe~DWM4f@ZM@O literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_slanted.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_slanted.png.meta new file mode 100644 index 0000000..7edd20d --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_slanted.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: c99a391f381fe534c80a193fe9f307a0 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_slanted_alpha.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/tileBars_slanted_alpha.png new file mode 100644 index 0000000000000000000000000000000000000000..776309196aee7c5b4c5d5fdc8b19fd8e71cb8f62 GIT binary patch literal 266 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4j!ywFfJby(BP;if@ zi(^Pc>(ObJT!$Ta7^ZGf{Qv%w=i{o)!4f?mH?A&rSm1VMO4ZhDb&JwpZkBqtKmYK? z$a~Kh^A=3poWXSGiGlP3t@fD=<(55cEhiFH6nyyn85b7q;O3ZqIMks_<{ZanMprEj) pi(`mIZ?XjI;slW%CWC|o1_l-Z2F7h=jf_BP22WQ%mvv4FO#qDR6tn;U literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/transparentSquare.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/transparentSquare.png.meta new file mode 100644 index 0000000..cdc61f9 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/transparentSquare.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 4d338c631fa36f345b72a36f1c91ff9a +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 32 + textureSettings: + filterMode: 0 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 100 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot.png new file mode 100644 index 0000000000000000000000000000000000000000..768a2da31056ae9e904f3987d24054a50562d5d4 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqoCO|{#S9F5he4R}c>anMprD(l zi(`ny)MSRn|NsB5X8vfU@Q>xF!Zs_PAl{Dq|BtgM7>cs3$cjmjRi5yJ$E2g3(fY@s sBMuA=B5#f<@1H$E`6@@nY`kL{fF?3{y85}Sb4q9e0HxC}A^-pY literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot.png.meta new file mode 100644 index 0000000..afcc984 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: ed7cb8f9a27664e48896c904189f0e2c +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_darkBorder.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_darkBorder.png new file mode 100644 index 0000000000000000000000000000000000000000..705c72b68d0556f94b5f925f92a5b1705dd36d7e GIT binary patch literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqoCO|{#S9F5he4R}c>anMpkS}3 zi(`ny)Z`QfCRCSvfE$zna!EegGc4~5eJ3_kvI3YUi>`1jZP@GR48iDiCse|`M^{{BOjJ(Vxj81DZrT*FzgM+xXK N22WQ%mvv4FO#pS3SUCUy literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_darkBorder.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_darkBorder.png.meta new file mode 100644 index 0000000..2758634 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_darkBorder.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 27df4ca974a8eaf40803907859421506 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_whiteBorderAlpha.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_whiteBorderAlpha.png new file mode 100644 index 0000000000000000000000000000000000000000..2a081f6b2ab16c16b320321417083ca3aee328c4 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqoCO|{#S9F5he4R}c>anMpkR`x zi(`ny)MSRn|NsB5X8vfU@Q>xF!Zs_9KF$*X%$M35en<$cb~5a!<Hq)$ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_whiteBorderAlpha.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_whiteBorderAlpha.png.meta new file mode 100644 index 0000000..8bfeba8 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteDot_whiteBorderAlpha.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 039dc89c76661c344b7776f8a47cc5a4 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquare.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquare.png new file mode 100644 index 0000000000000000000000000000000000000000..afc2459caaa4d1c9fdb4366d6e09313f89bb081c GIT binary patch literal 103 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9F5he4R}c>anMprE9u wi(^Q|oa8_M|JyTbHgu|7T`c8h%A?845Sq&@Ya68K3{=G6>FVdQ&MBb@08(HWlK=n! literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquare.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquare.png.meta new file mode 100644 index 0000000..2a4aa36 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquare.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: dfe6e0ac3e5f24740a17e14b65e08406 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 32 + textureSettings: + filterMode: 0 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 100 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha10.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha10.png new file mode 100644 index 0000000000000000000000000000000000000000..6480ee22a955b1ab75ba087e81c747a94a62cdfc GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMprEX$ zi(^Q|oa8_M|J&;`vo>@Jon6eCIS^Qc)I$ztaD0e0stQU B9U}k$ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha10.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha10.png.meta new file mode 100644 index 0000000..1134262 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha10.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 93b68213089b05943a651574eb7e2fb5 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 32 + textureSettings: + filterMode: 0 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 100 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha15.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha15.png new file mode 100644 index 0000000000000000000000000000000000000000..e6f3c427d4cf110df50530e7da40f311824d3a74 GIT binary patch literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMkesKB zV~9m>@}K|z_e(LeHgq;R8Dt$;!MK=>hmTo8g5hrxv-7Tm-Nrzr44$rjF6*2UngB%K B9GCzA literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha15.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha15.png.meta new file mode 100644 index 0000000..8dfc149 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha15.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 5510cdd48a6aaaa439c95ef5b2fe9e28 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha25.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareAlpha25.png new file mode 100644 index 0000000000000000000000000000000000000000..5219f2a0fcdb4ad7dfefa5b057bc22afdc753bcd GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMprEX$ zi(^Q|oa8_M|JSQ9vo>@Jon6eanMprEX$ zi(^Q|oa8_M|JU0xvo>@Jon6eanMprC@M zi(`mIZ}Ol2|Nl#}aWM!pwanMprDhd zi(`mI@7tb(f(!~AhgT`@kg+z{y}_wfa7sUa(e-~q6QQk&T=WnM6{yLex}w&TewplJ-Au6{1-oD!M<#m_AD literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareCurved.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareCurved.png.meta new file mode 100644 index 0000000..8a6304e --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareCurved.png.meta @@ -0,0 +1,68 @@ +fileFormatVersion: 2 +guid: 070edb62059c27b408e16f28cb87f941 +timeCreated: 1604057757 +licenseType: Store +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: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareCurved02.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquareCurved02.png new file mode 100644 index 0000000000000000000000000000000000000000..c7ed49b005c6aff08c0586d66c4bb87d4f88a749 GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMpkRTg zi(`mI@7u{6c@HS?u*hn$ot)PZ8_}vdsl)fdV}6lLCDk2gJ^MBOsGEy19msAanMprEOz zi(`mIZ}Ol2|Lx70SsPe8Ts2J{dV-i;+V?RoPIO3=XqfaV+>7^ze35@zthVZO@Ib4c)I$ztaD0e0st)ZB(VSh literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquare_fadeOut_bt.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquare_fadeOut_bt.png.meta new file mode 100644 index 0000000..27a1460 --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/whiteSquare_fadeOut_bt.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: a40dc0d6372a9084fb45976308087290 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/yellowSquare.png b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/yellowSquare.png new file mode 100644 index 0000000000000000000000000000000000000000..c41f635d6173527df46ed81874904da9d02e1052 GIT binary patch literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9F5he4R}c>anMprDMW zi(`n!#N?XdmdTAG2aY%>NnABpmAE1!A%TIRB8Kti3H`P6f$A7MUHx3vIVCg!0K2#w A?*IS* literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/yellowSquare.png.meta b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/yellowSquare.png.meta new file mode 100644 index 0000000..54af05b --- /dev/null +++ b/Assets/Plugins/Demigiant/DemiLib/Core/Editor/Imgs/yellowSquare.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 517a5bfe18f2ee04d9925db10be034e2 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 1024 + 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: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Assets/Plugins/Demigiant/readme_DOTweenPro.txt b/Assets/Plugins/Demigiant/readme_DOTweenPro.txt new file mode 100644 index 0000000..9837c95 --- /dev/null +++ b/Assets/Plugins/Demigiant/readme_DOTweenPro.txt @@ -0,0 +1,35 @@ +DOTween and DOTween Pro are copyright (c) 2014-2018 Daniele Giardini - Demigiant + +// IMPORTANT!!! ///////////////////////////////////////////// +// Upgrading DOTween from versions older than 1.2.000 /////// +// (or DOTween Pro older than 1.0.000) ////////////////////// +------------------------------------------------------------- +If you're upgrading your project from a version of DOTween older than 1.2.000 (or DOTween Pro older than 1.0.000) please follow these instructions carefully. +1) Import the new version in the same folder as the previous one, overwriting old files. A lot of errors will appear but don't worry +2) Close and reopen Unity (and your project). This is fundamental: skipping this step will cause a bloodbath +3) Open DOTween's Utility Panel (Tools > Demigiant > DOTween Utility Panel) if it doesn't open automatically, then press "Setup DOTween...": this will run the upgrade setup +4) From the Add/Remove Modules panel that opens, activate/deactivate Modules for Unity systems and for external assets (like TextMesh Pro) + +// GET STARTED ////////////////////////////////////////////// + +- After importing a new DOTween update, select DOTween's Utility Panel from the "Tools/Demigiant" menu (if it doesn't open automatically) and press the "Setup DOTween..." button to activate/deactivate Modules. You can also access a Preferences Tab from there to choose default settings for DOTween. + +// VISUAL SCRIPTING (PRO ONLY) +- To animate a gameObject, select it and choose "Add Component > DOTween > DOTween Animation" +- To animate a gameObject along a path, select it and choose "Add Component > DOTween > DOTween Path" + +// SCRIPTING +- In your code, add "using DG.Tweening" to each class where you want to use DOTween. +- You're ready to tween. Check out the links below for full documentation and license info. + + +// LINKS /////////////////////////////////////////////////////// + +DOTween website (documentation, examples, etc): http://dotween.demigiant.com +DOTween license: http://dotween.demigiant.com/license.php +DOTween repository (Google Code): https://code.google.com/p/dotween/ +Demigiant website (documentation, examples, etc): http://www.demigiant.com + +// NOTES ////////////////////////////////////////////////////// + +- DOTween's Utility Panel can be found under "Tools > Demigiant > DOTween Utility Panel" and also contains other useful options, plus a tab to set DOTween's preferences \ No newline at end of file diff --git a/Assets/Plugins/Demigiant/readme_DOTweenPro.txt.meta b/Assets/Plugins/Demigiant/readme_DOTweenPro.txt.meta new file mode 100644 index 0000000..ef7a8e9 --- /dev/null +++ b/Assets/Plugins/Demigiant/readme_DOTweenPro.txt.meta @@ -0,0 +1,19 @@ +fileFormatVersion: 2 +guid: 24123b2fcdc15c943bed44e0c6beeec7 +labels: +- Tween +- Tweening +- Animation +- HOTween +- Paths +- VisualScripting +- VisualEditor +- iTween +- LeanTween +- DFTween +- Ease +- Easing +- Shake +- Punch +TextScriptImporter: + userData: diff --git a/Assets/Plugins/Sirenix.meta b/Assets/Plugins/Sirenix.meta new file mode 100644 index 0000000..c7c7756 --- /dev/null +++ b/Assets/Plugins/Sirenix.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f8b16eeee739e52448b12de8c6e054fd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies.meta b/Assets/Plugins/Sirenix/Assemblies.meta new file mode 100644 index 0000000..72202fb --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 416c9d29fc2bc8b459b3c1a31c21726d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEditor.meta b/Assets/Plugins/Sirenix/Assemblies/NoEditor.meta new file mode 100644 index 0000000..7e7186a --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/NoEditor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ae929bb4182e1e14088a265e67328195 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll b/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll new file mode 100644 index 0000000000000000000000000000000000000000..05c2f54d7dfd132b1555bda2f6830984ca1d803a GIT binary patch literal 324608 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
CYH)M0FH6wZDSWu){m`w6b6u4s7tS>+nIsJFekS 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 R)BA~T-2eZd|K}+1KL9}{I#B=s literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll.mdb b/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll.mdb new file mode 100644 index 0000000000000000000000000000000000000000..0cc97d2ca907d04cc7859c7d5bd69bd7d3645582 GIT binary patch literal 122915 zcmdRX2S8Iv*Y?cZ0HKJDqC&8M71UJ`3)o1&0%8Hnu2?8hBXvozyB1JXKvA)R9XodH z2r3}<28s%H>Zum+vUKpGv7k zc9xIy8LbEj4{PS9%sHJrpqk&o?#sPaKi7%utAE zYpc7m@5q(ivO9H;+2y?})!OIXzWTiq(~h3-n4jD5x2YMS<|y{xMy^#SLDS2=uQN;2 z&+fARnnX7D&!E_*2h2`)Xxwl~ynp8Y&e&Um!pgI)kcNcGyr(88M z#J_v+@DL3VFm>=49(k>)vB#{rx4gnv1SkeiSg*UfLtJv)o%)U5I4=8!f+`YIpKy7& zTpLd1+M+gF`WU;c$<3S;{~<6*viI|oEjrVy8MO4=*m~sWNoaCK!s#m?9th1Rw5z?s zT!Iv!H-BdzWeI?-`cHY7e)Nd*)KeqtE;Wki|Jrr+D66`yXEs_ie$CeTp7|B4FHe<^ zUx2p0jK_Jd&2h`?x^jZJ>ejtC9<7>X6;N3J{ME_T4@@t3d5@rwiquzsC|95?Z9qd7 z=Z<6^RCe9kI(5WDMZvjE&yRP1Zwrrd3One=0OFS7ak_3 zWgLojw|((Nu4ac_V;iXQR?f!9s_%JX*fVGL0=+-`{&}ELasir9?oc$Ea1ZhGf&N|z zxWatKl_mqY!Ncw~o;zOJGhv(g!P9MKu6&TV`aSBVh`2l;VSdZQ9T%g&egQa{JWxIY z+SW4gc}e5jS13xkj<-FQc#Zk?ZS}kK<5fKr_UoK7H{aN2=$c^m9!2~Lq}|m6 zG1|A5fwJYM?(a+_bGq*(vNd-ne7!JI|KQ|BxzjuRaRPO1{rvC|q%8ORX6r>?`3Qv) z+J6nCE-F=+!Z%zcheCMw>afdmPI-5m;b^SNU$f`Y@a%{{+}P97X+!MGJ+*^GX#6h% z#b>xSwi@E&^Ui;Z?!0_kvxy@{Umo$a*~??A1`Y`8>wo!yL$^EcDgc{CN1F2IDGwZ8 znhJW`V=!`ROaHO5ZK*TeHpiukPTrmskbSK=YLI!PvdOHmn|}#5uW_Me6|{Q0>(3lD ze}Q{^PK{%^eOFhCN$7T>b7S9ES0;q?a|zm)id5yEr!pUvPhYu@zdUR}7_`CA>d{_P zpn}Hsj>&3y?a~S7^boU${yok!Ph0l5=UY4Mnd_9@i&|vgSXcoX6XGu$6-NbZ11~xy z=UDG|PPsHYt)S7TYI57zk+M}N%2B`0+OY*bcYmqIG^o6aw^f=EYS<$_%*^$$Q$1oJ zb{Zc){>Hr}DwT8Qo8~EK(yz!zMX*oUIB#dx5flnaJAE-wuYC)H9=qF39^kxuZVQ+2 z?3bJ4_czT^4LfovK6cK(15cy91$`Peyj9hr=gQ78hN)XF_f2ixW%k!^M;{$y9P?h9 z2hTy{eu4ISC}Dz5ze;HCLR`6lmwc>>YgVAVjTwFD z%ss}mbD~*oH{a;@p?fBEotl4NN3_J(KBwJddnt-9|6X3mHcmr=S%tN|c!c&=i0dqYzEhdnm&-@d<~hw)^|$Wcwke*3=#TT>9`8*hsm za>=9Hlzs0ukCC_@@)-Nt*gayKbfiPg6Z0MhEv?vDPRTJdXz_4Fo!?`;hV@ul?`WTW zeeavvHlHz8wD8T>7azvEXJ5`5i~cP4+N|mI`60YJjG{C&fb`pMc8yG)(8+JZ~0xJ?y=~?MJf3KUjP)yIg_J$j5a=cEse2qFbx15(={H^1GC&LdNUh6@3atp4vdUf(; zVFhcd^n?pE75;eQ`?R;8yY8$yC_Z`2!m874{0c3Ob|04$_^Nf~&3%?vK%=WE$VzV+ z%&$hv{bdT)>;avJ(klFm!WyGwA1)b6xci3C8t*1*+sA^n^xe64lZIx<{*kF6s zH8m^sC>nO9xZ(7oCRy19UH5+&Yv&N2U|O+eD@_sSYCO&#o{i`^F-VKXxs!f8FBI1#C|no4W@}hCbxIE z)4BrYOPU;0db`QT_4f%3m-qHj2u2N1)3?|?ZPqS4;JVQxpmtHubhj$`JzgaB4edI>RrO_b1(&DbaKhf&`BRigv8I-lz{%b?Zd+=I5uk8~LO+d+k`%Onrd@6JlkH5J=( zdV~iCmayGHnR-}tbd#W{r?Q9{o}C-CYn1h2ZJXW)o%jFt=B>h5CnxVj#SUV6hbdqU z0($2kG`0Bhi!NKg;~=Zpepy&0(c~`ZYTECQ zcg^=)ElvFE(XuN^*KMx<88Vf`y}xp8NsDGj9hbF2;T1XHD`BY9hPB&Z-=AGGC%Z;Q z%su_IL5~&b1A+(1O*(kEyvpwSd~;$z#Wq%&$)UDU7?fpFsmk?>=V$d;vpTs88Tmn( zacb+6hY@01)BQ(AS@yHMRIx>!j@3OweM+p`+?bx{HgQRKmyOSdxUX9iG~v{Ss15Uf zA9^v@&Ek_mkFTTab|It>fn)ohWhd;ES* z1r%`BS}qM&szQP^xkjh-y+Z;Oe&Zm|*6H2QHHo<^ircz!yQ3skI*&&I%iks5seq9b z4@$}J=wa5)GplHrUd9bO9|{X$63ed#e@z4uPqwjsm+WmK6@Rj8JJ13Dxl?Nb4!hf z&8sfHAz><)v3~MU+7>{TolGl6VaB~(BJbMexkm2t7ROi>>%Tfwav!G1P4hohNtPqI~}Q){Ln1qW9bjDuo zw)xT%mx0!LLlXy$oO|zE_doTwb(^u^ZkL7?prR6x#;N4OZ@|+*v|vupdKHXEI?^Ys1fFLuD~iwh){~}IUjD%UuU!$_M$K+< zCoN*|K;`ZFoi6$vuYjSg5Wmu!?uiVPkELTIfedO2UD~*>-5>AW=VUc*QuA{++gDqQ zoEv{|_+y1ry9kQc3*J5uVdriSEkNw(l&Wqt7hJ= zi`={pr}ms*0pnUBezkQ@pn#H^e9WlTd!V)J{AW>yJ+62R{3BAY>-MT!b*daU&@~pV zlvi+BatRLC3@6z!h;5%5&8u2|@4h@ICt;$i{?uE)AKUS@*wrXX^j3P@XNXP(anZ>#zaE=N^jW8+`>U1 zK!z=Sv|!7g`i{;A{@T3xp`PqkQlP{9p!5fwhIPsfk67HMO~nIh)v^SjDJ~vlSkJg_ zGxi-Cv!=`X1H#Zu;KpwArdF~*SHy*Kr<68w9f4ua}|I}q`-;+~@ zq(s#^lAOGxf>q?{T)GFzYJbJn;*UYS=6!z?FTu$^sp4`ubSw&%<&C+`ZgbAer?Ujz$rn>ZRdYi1~h%q_LjJU5%v4A8R{cFvZDFRh8_uh>T$}THBx+i8HupB{FLFaO5M0 zjCQyB4H)nX5S40(4m6Uq*{OrOrd^qRq{X)@EgC+Yn>e>lXrlc?_b&T-pXgk{0}z^P zrCXxE?$-q7EIpwyh{3W?~Fhb%d_qLTX3-N zHzcf8OKo(~MpswHt{x~|(sX*a35D;>_iWxVV8PlaJyu=0)1rIIZKLu%An?!VoC8Bj z?#Lguznxz0Ww&0N&8HZBlX_g*lb5pM!PluhB{i>kh=MAOE8m@t{|r!Dc~b{^=&44Y z?Q-b*@;--*X1`u=$$D|pyptOX|037dc`WEvzH8_IfGsQ}Tm=VuwDHyJX@2VQoZMTY1yH?dKr?)UV@!@fU%stJQq6Ou;$?Hde!je8LGkS)HhJy8n+svxj9|4Ts zKB|$u!$L+YIJ4s9f_=e$3wOz4hD;pV^WKXtP1~7fWp-JrQ%v&4rR=E_i&p&`sMQ<4 zOC(7fxwfrsMt+ArK4Wsa$8BFaaC@Zzljm<+G@^?v#r@gjxJ&0N&yPZj{*5H`hvOU} zVJ&}}0%)vE(!6yCozw5Uc*UmPdy|TXuMtI<6sShs%&Oh7mB|Cclz$U=tG@$2`+c)V zijdu169WwgH8RTkR(I3rOCi2r-&k&onVCH`Gv?m}ZvS_{cR$#Z*v@x^Z2y>secS2l znq3_Ir}f~v!vi~Q!@dh!#QUM?6djAGawm&O{b7=0u%Dt`aTn>NNU#j!@ zUCZH*`d9TG*mP+?dccOEdzFRdyD0x-lc&*{piT`5)YvrX$blN4_qc9cogb!5={mL3 zjp|qSWH#xTb?suqlq-Y7ejz+i9D7b$8{R|3sA~)Vn(4e`MN*S)%6)4GTc6MNTx~zX zTDElTjO=-%eqoR1?lVpv*3(B>;(Xo%*UvvY}9&}H7=!4(kEz4iMi+0)mX#ble>#Hm0MLNZP zk1gMgPk&qd`a*NB4XyfwB75n8FpoViH^n(LuVO1}VIF8@lU;4}O#ik;8(mY-tO{;v zG*i^F&(^bJd%D{js)?;*_&ATd-+N5IYi&Ab#fIgvZu6|}H#j~iarM!+l7e*(zc8O! z9lMN%W>H(2x(DY@3V6D$^NIya&)9jJnVrA3bX&E3G1(!LJ~!BE(w>KY3rdG9+*`YaTf>Wy0{;PqW>k+t#_|F~VTP;E??x?-G}+QJwzyC||zvuZph0 zEHHIWvsv05E?MC3Ux1uF5vL-dzTcgfR&qnlgZb$5>9oNv! zJ^qPoiPMp_`!2k$Vz>IT{muRRLf%iPdNAOZqqEmW*WBz@$m$MjdZoGg?Ue0}Fwbi@ zbd^E7t3!s$FIy`n9Gi}YmS>edI56N!Ju~Yp^_{X@fiW zbUO9DGX8!4W;6d#tlLo&1yl?GDO{x>_wOkW3JDwMsS1<(1Ob@XqUXJ~bYAAM>!~7U zOuO?7N%OGnBkH*I^+;W7(r?}_PYFSf0jgy_DCl^Wm?W!*F zTH0gD_e&w&&&~4vLn2$GTT%I@fznT<2!u9@T~A&sn)+mw?&GeDkGa~qi3^wYnbGL> zB7ae}T9$X4`c^eMHFIi%;pq?|AAaZc&9x6P3g-z;=Ixf>!R?kSh8Cx*<_R7*Jp&>HB2t=4h4(7g94Dfy$^wZ*j zy{^h04s%Q!?C{4e`;7A4m{TS)cSZ1@CA9VY+Oql=JZE?;EgpR5zRlXak7E5^_I*R$ z?d%s;Dl9y>?-ytbxTJ8Sy7)}T!Pl$pFK2sqS+x;tvCyEZ z#{H0y)jEa0*jBGzuNB`dPE?+_OBR|k>RF4C+1m^H=H*ZFsClh?w-9QyqFo_jdw4jqaAbqYI5>P`R>;(Q&Vh{UjkIeg5A>ZK_7cAn(ESY zt<8StBl1&&H>4ffQ1h>=lXnK!X@~sEb9^j-V#lTIAelCu{gQ6Zw8`zZ-mEx#?x6d+ zI{ByDX1B6DH2&75=|wO9yj@Xchy_vhaYI0rGUwe@5BCC>+1u=$Hpk7p_FGsSl02KA zw{ns5;A@{P)5>@3Qc5*+$gUv)n79~}X8g_CbxYOxCl98@9eKk)C7AEk;GXSz$yCyX6S&B**c&N`RrzACMtZY#U7U(90~IK*rimszQ< zq_0^Um&^)PPWPaoaQ1>ddL#^#Gxx~GnupSFxG!zp{po{Mcb@8;>HVmCPJuz6+Lsp2 z{MP$SMb&mzIa~+VB~am`)C^ewlkK|KeWD6pciDRE($SXE*GHGG8(a7Nm42HVjqf$^ zXv4I}6;<0yV-l{U15oq4bFEU+Bi*;pTqnEq!0>aS{=hm#xyrhRbLR)FYj@&g`R=kT zRf@C}rQMqVtQ+sI7WH{9?y-IAidHSlkyl$zVM<$Gq**H{s_iYP8AfN@Fl{ z`7<1D1XYdGD&?sk@c3KIntmk%TdE??lgaS;&y{|eT|#6E8p464_K5w!{r(x zz{xV*W3>C^!mfL!zs;Nc)$6_TS;xsWmTia(*t_I%lF{o31b4N<<*W=saI-61=BkU3 z9zt+!E8N;@fRG_VMhI0x$QYr@2vtF-Dniu|s*aEeLZ%3rA!LqF4TNeUR0|;sge(z~ zAY_G5ZG`F|R2QLoa3?H6HVD;6r~yI^5o&}`V}zO@WQ&j;LQN5BhEQ{aenY4QLU18% zD}?M3YK@Qs+%JnzTZGyn)E*&6gy5#x4hVHbs1rh+5$b}FGeS~?WC*z+yhfsfn1|T#Lq2Ceu1EE0(c_TC!p&I2%^{J{)tc+LP~^G2!$gw z8lf==jYVi2LgNvdfY3yQCL#0}LX#1if)SbupK0)kfKMcRro(3je4^kp6F#%xGaEk9 z@QHy>EPUp`XD)mY#`Kom%8+MF9Spy4#&(P{x8t+m&_AF$Q}P}7eRn&)rzYEAr6Z+( z0K&)Z_>-F61UpWk^tc@u&D(+JgTn^XiVb`t{M@tyZ&p*=v(z;BnZ5%bVW|Qj5#b<_ zTwq+@fp7A@SULqo-T>w84*X7F@UTeiPK@U4#B;%+f8d1&Mm7Lx<4(Lu;IPohQ6L=K zi8BN`3yxd^!u6dvUrlE?P|PbJyxxh6wdoWTGiw({vv=WWaM-9Bh6ly00n*xCI7#5} zpqNx39o~i01P%*|xdMc|UHGa%XF)M9fben`E@J6wjhP^kh^fcri)hAfjG}hqIB-}L zBBl|SGop<^+O!*Q7C0?vE{Ki+A!9er6zFYP`gI`W@5Tjcx{f*yo!3Ar-i_Y~96k=6 zm=ug+Q}7&c*w}R#HV&QjK-iFiHwtt%4xKb0q^IB`YPzmE4&5t2%1gml1r8sFZV`}P zrQp{BhmAvb_8yF)_uv?C*tm5WHV)l2Kv=s6CsBH3BnpOGqA}KirJb;Gm{jtY`vv;Y z=>;ACV8$Sbz2Vh^3W@ZUiV?v+^fpYaQ)L8qjbfLu5#jW@X(iU>W$BCw>luYB<(?XG zvC$YGWtSjd#fWe?pM~{JmFmN5+J{()0ah`FSRpbJ`-F{WO!Yo1j4EE9Dc|vdJ0)apoded64dqv zA6^Xd*8n;V zA%6|d1OGxAzQ&3{7zRvpHh&G?0p)!f{va?MDHMab=@`YO<9XneNB$ZxuK&~gHP`@g zXQt!Z6oL-Y4}>WkYX=}$M4uT(o#i4CR_N$Jw(IKh3OK-PqWVt$q2@aNp|y+?8LTEu zUWU0U$+m5vm!BW~g)JD9!Tp0~qS;yt%M4AiX%7vI4wa#-A#A}h z*n9+|i$`$OQSHnjNMs1T6DZm688Dt7#qTH|8rC46Q6XVasDc#1;1V6*a7Ca$X2kS# zF1@A$MnzCYVXP$=3YH;bhb=5DEImCvz1*eM?L4d74KnqofyW$!8hQ*L0Eex)hD zG`;;rM~BBXo3G;o7xG~aRX>cL#Z$&lr)Db$lDei;%~Vd~;kKIAGFfqN+n=d(f(LRF?FEdf>E0pWcX{!p4e=QzCa z;y8{2hlN>{sm02#2f~Kqcw=dL8W7Tt<0C9xjn$OKV~L%lQX172;N>01x7A*&aS*C~ z1j47|_;YFcyljl-XX6Fnun?+o5UOng!scwer8NC05RPTz41unWy4p3MUC+k(EK7~9 z4-!=eJ=!g^oGx~g0K)2Tfd4ide=8wY4~a~;Jfc}-l5hf}#1nWOID)ooAdxAI&z)p8 zGLSJ%2j-Cz_#`U>$~NWtEYo{HC_I7h3v_3yRMXEu_;Lb&73e)!`ht@f#h=6r!C^IE z$_!-bTY!*!5^ojg-q=R&E~jcX%>ZiVNt`7xRoGolIk$my=On%>a3*2a%O{|GK8e3j zh8P)!%H;uae;0OK36%|olZ1%nV-+fTQvhKM)I&gd7{gaUMn~u?M7mt16zM^OsHvH7 z{F|*9#%Fl-+w|rLedBn-L3|X$q#Me;)-VrLH;2J8SIhp5dP=>#k|d|Sz1G2~fnb?K zGkd9oc|qGFI+`;BnuVoB0~?u1Ygd_rz0|}G*w58$b6|V1nX}*&%mYv1xYHV?MvK@n zi0PCw7)?Ecr-376ZCfNVV{EZ|ygRMFX3Kz?a0Vx_GLW@qOgrqppt^fJWu^f&{R}=L zFxh-G%LhWi8GJ*a_oex0Rt$tUXYgBr{s&8sK8sPzSsV)vo9||fFOKPuKwD0;wLnZd zi`NM}CGhfDUOEtuoW(~e4eTE;2#CPynutY^gKq(&f^4dc;6Q=TYAm* z0crnvd_dqxSS?-z!lm;#ho!44J=9clp{ANY2IiCVxLEDioPqWgWAoSxF#EoM=Yqq= zX3oeoHOzb+P}g6;8w92|SHsMY0V(4G&J;Lu7NdCqP;OknHw8v8_M;KK1zmE z9_GT$XrOhc6ppLQKC>e+k)Bu;(#KTxhC77q^#38Ht*=^BXWqn;sAh3Hk%XUQ}? zu`yQY^OJjYm7k+JyK#+3@L8UaiNEss7eik1EzKhGkbl}oZu3tsNh3sTJ@9-5!(bLfc|~yu+G8Rybv5} zF0d5yBW@9H-!`H)m$%6M1Fit&&TFIwPj*&;n=T&+nir~WRN^tS~(9Jq#$ zasGZD-KUb??ty&KHT>}(qg$z40_L*oV353ycY^b`smmjRonkv4M zFG7%WY!#2ikqjMz2n7jjOpqp6tyk~UXKMY=D_PS3N7S|e?b0)z@mjV za=^V=%;RSCw6NL({9dIKU=MiP2+%p;PPUZT)=L|D9 zuu64TsoTvn`T!@{(LLEw=5KA~$=8kan;4zFi64Li@cD)q`!fXli*y*6-)Y8>@qFD^ zXP5g}E~XfKm~S&~;^{;^HPrzHd{M{P!5fAk?63q(s16_UT>R&&IOJJ8#-1LBf zAg3GS7^x)iX#td=QM9XVKvTO9f;{s8-=`s)AR|9|;S#*=(lyX$1jf827ZcjVV8+mw zzJU$mgroihh9&UJD+HbyJw1v9oJURy`wazv4=QU;WBP)UP|N zT*$$rK@|g4h~`ICMjq^MP>q%FgbR)WsYG><(EKn}$82cE#cXJf6-Gu}>d|e!p>B}H zS1gxf{KKGh{^8HX{KHbLCSAsAf7kJOK7`NsH2<`O%;ukBm=pX{B0RxzG*k&Xd)6tn zKvEf&t*gSKb#+*;Hbdr+6>E&KcWrNpdq=TtlAj%&v#~>;Xyz+F4sG8C#)}-$ktbHc z?Sa&i3c>`0!4qoRiyf0>0d_!ehL4qc;AD))z!nqV48 zLt6V3X5>%t32?wfFXqR&NZHo5jOW0N$XGh6jnu)N?HiL@ z4+0(NU^o8T2m+wbn(sP}l6*I*B%i57R}37%@Q!Od2N==M@XBX^1|u;{ue-x#lw&pN zXbg0SZbcRB|lW)~gHvf)tf}shZ zyk#%I?(qUAf}?JBHL&$L*pI5PbIQFSlJ){;mnB)5lYCu;o#NKG4Kj~j;8#?Xi|`{P zJzv5$yU{Pf2=Wrgg2OXsRK@-8bIgrE-SiS~rc4piqwN4xOhV{*fnm6M$cWT6Q`0s@ z@ik36Q zV%!H&T`$6K$~DGoe;4DXSI`o_!VkdtpJ;VGuT`Vz{6mLntc_i**H2Y(pjxjJe$;Hj zYbY?U@pW*@GuGwR{x;Tm#V`>r#uvb$&84OU>4wRbaAz#T(4qtj3|wcTqb^FY)WeQy z(G_)~)hj%*K^$lBHg-LSH)2AuI>G{R39xdUU?Xvq`bS4c)5RTi>0+x_)EkU;zrlIn zK+|0YnjeZZJ2VDcD~C_${?zzjVU`7I6vaPuc*er0OakG8K*0pq3*`0R&rgIdUUWR=qRhu+KiBD)43V(4VC zWD!_sf>of`Ee`Gg7OJVNwVN9)tJ;6G+|s=a4I(4~Y`IaH=>?i1rKjWRB0XzIbEm&)c-8<0SnDqsAKz+f{ z;6QJuA0`j-VXuwWba}T}3p#YErm$jY0MQ>xNU%4P1m^m0kpv|73g$Y^B=EoU3qC}H z;bN%Ec9Bnk@azkI&eHizfen75noKvWoU_6mAk>Wbic#cO919NXm*c@`q8euT8-TI# zE8ZmV{jpn)l+GV&W&`oWSA0_7sj!VSM=FtCmP)0bROBA;3cup}g2-H~kzplfe1nn4 zH#`#@9ssOZv%zl!(xz{Cv%uMkVUaI~hIYrZ?Ai)|`Lt>zzQV0BeFh~HpZRp_u<1Z^ekIs%XnVCBKW z31GTO9!au~}4g6CYzRo}0!RL7S zX(X9{iiRiHudAI`+zv6wv4fff2g*ujnJHuyJ15~MDh9ZHS2HJfmuM@mQk=@TeYX;s zyKNdl5fS8K#DBMLzEp&6PDK*5ayofF{l8l`(0B4Ry&TKUgBb)JiXyXS{&(wUil_o~ zGi??@d9%p6+5g?TIaU$6SrJW8aWpv^^WUwTNSz8OHwR-0nmdQwnDgJQo8uLsn=5k( z+7d@T##OX#uJS#x*ABj$4u>5c?9gf+-pD_tV;DQLvN**r--C(3UCQJb*7c>(+7jB}rM2ydfJGjwF(%oeQJzGZJg2T@= zH;7>_S|F2(tD8#m#V|z2HRmS~v><`RgTo6Q<%M!UCYOrr1K$1wazGHd&WlJv#D$7n z2VQ;xDG)^7a3XF}Q@4D&Kd|Ok;C)LV-vyCaeGUy3VMAG!NYLs;vIZPAU`~V$g%!yF zUS=Z65=4$_iLenp0N%qy@<VVSj@pxMhwG&p=j#ULWLk>{g4H^+X(XWA5yqvrdMAE59J}3?r>u}A5D+pS&f-DAy z2a=-+f{$en@b<1C`vj3^oQP|Isr2Rz8p>7RU0Xq}3nHM>oEB90YnG|9`3hhEI9Q^n-(wV9zIhDIvj7!*i~F&~ z1HA59O|obRrl?x5T<))I;Q-eS(fwWY-8OK9LolAu?VTcFWt7p?UNcp%tm^2ijo~^5 zV19N9_SZ4gXU))Xk)KM($dF%&Wq%n9q3KrE4o$BrXSxz54jaTwv}^A7 zzn+}?TW`9b08H1QxngSe^^**83IMd+A_a~AJA|FMf$Z5(4pGc9E;EX|5cc;CWXZ;I zh+<{gQDi~bcQ=yH|8W%Kc|`^AiW(^>YL6z0fRd`(xQU>wP2?sx|5>m;E9gb@pr4+0^F+ka~|-`%o@@VFydBv(;qo)A(Kd+S+;t z1O(Vg{A6JEhjKw{OoIuuT)YMV30p||mQpy>4Un*K{8KdV`DPbA;vd=%}w2Z}BYT+jcaaf9S{`J{~uXp{MTDtF$$lSygC$MbP|$($m_{on15%zSKDfjU=wQ zc{>bbwv(^m{BMyhP$P>djciIOWXDP&v)6#)SGGz(%iIAYxgBKjPJjl3Z|)$hX7JsF z8+?C&Z5DQNe^?U3HE)6BFz_0{7T1lEDh8D~&!9)nXd4>sPfN0O#Q@Qlt*07MvG_)h#%&Ko&Ag zRT@aGsNDq3+)ZYI!^TvL@nY#)fRMbKY!&FgV`&EUkpZO4-6Tukj9|}M)Vcwbo4d&^ z%7C>eb{~yKD{eHAwHPIweF)y-Mn_(?-htrv-DGA8$ir6OU^w|ikJ7_dHyDJ$8WZfj z=`Le*s?i6^@KpJPso32-B3+&<(ldhBtA)ZvEgW5}13y(^n)Rntemv25C;xCCzvhQ0 z@5w5jHjg<9i=J95wMYy|V_}s{Y$vspCFY8y5*KljxS4knks7rYOKn;*KZOS`TS?n?ly_(P;B2%`0~6R&B9melUNOR2P$Oj1d-_1h7X2YJCI` zpZ1W?)E_Lh!4_(F?sPQ|7JcRO*Y_2KM*toyFUiFAPKo)pbpW5O#7+i}l7QOm$%|S$ z_Y#!0ms|vg&(%{zz+s||qdUc68NeQfs5NyTLDTk;2yhUije~(b8$R&%4cI;=9QQ8f z(JjJ{_@^V}7GXG50>&aj4+d~Bttm`6)t{JeEeX8m4m#0Z5rTD}Hd1c0a;*apdCora ziei922xl)GPZOIZG=sg})|Ry79NrJf+fUNL;YISOh}95{#BE^R*-!2Y5^#2-gv7K1 zu(EW3M1lh<*Be3K(?_>A@jZM3ukeO5c!e((fqzSx3XrdXk9mNdi68u@p!`@+Nf6TZ z1LPPD5dHx7N!E+|#6A4!m0E9s_wE3BFNi#&B4!hWq%Ao}(9(ls8900>u{u=bo*;4v zc&P`;VL@aY6{)eHDT}DN2GLEBxCL*qqJlp^5>bn}qdud+Zv3hhb%>z&Lu5HPf9q|! zE`LOU^Ogqkrw@_bfAY4eq_?*qKP{C+r)m;>T9+pHOf#{RCWYP2Un?2dTT{t4DuvNc z4>HtZ-j@vh5_q_sN*@2CzXZJ!iJ5(vpe2XNYH#8X6=Kz|CFZI{B1ClXC^>cnwXOPIupG4}!i7f~InoP3gXJQ>Vu}t8f%p{k7 zCf1P?dkXxbO!Dz(Vx2g#`B?-l&LXS8DN`YxIk5x4Ps<|NKNIW1iQNYN{Vek0XJXEr zSk!TXVvduA;IPHj0`Bbq0|2(z29)i`$qs?h1nvN;1m{xSrBWGL%a7qKvO(a)adJ|S z^JkC5TD$~G(Q)!hU<9g-1Qs*137VBnW`o1WIvEFeN(0&B^%hA$UYAYQ3)}@5*xccJ zi(^2}$R?QrcP(t!kxBC@>f1oQlTGdlOt7X0M6=tbEWQHuTQ>PFFb~0wC*J3>6EJx^ zK@!11M9ZixoQJ;5SH;b!_aCih;ct1OVwCfbvEpSo@4xsUz z2GW^Re1PvSL^8t)Wol*+a?V{SOMR1b=`33F;7846(Yza9BA?2JV z_l2mU87``oX9!w#hO7pMhX=DuHYW}M>EIc1NZ^1ak%gB7q}(&)vcTEI@OpR-v=?W{ zOM$gp&6;@@ivL+M8yr5S!wi`H6R7&u0x{_!ObmS~KDsV0{w0E+&29)b( zNxs0i!SH5ki`PIbK1<$E-aqt`lPDUhO4wOS&D3fuwZ)usP#@2cZQ#Hm3pNjgaX6Go zcC{Dsfpst9X@o%gMIfLrFzo%iJb^xu>&3Kkt3OTAC5S5j9C=@6jOukSb&SvP3Qdd& zFr@vv7$=rpKxmwq=LtG{o;(JJ!iQrQe0@i-w9Qu8BO>e`6JQ#kBu+-A;)&GL{tM6; zUmz#IK@5Le6Aa_2df@gNemD;%d{#AX>N7&aSMrpVI14j0HZXTuFqa{Gsj0v8hRoe7 zv9xM*ag#A>8sEUwVy~^i7SAE}Zx=|?MHYFPCIJiPgGgf%uy_rUUoMjAm%xJ#f((U= z%NV#02oBw}5HYOVQY6w13<(Jc57i`NFMnT~(H{Px`a1rhVQh(8$1IpA9Xc3d^VZ%y zB&PU{t&Nx1P|SW=w{{`YO2x&k%la=VE|xGmKwFiG1UF&4h!I=D*89tkoT5iW=K(fIccQ@~Z%iqUc}dLs@~CRtO~Hu6dDz@HDeuQOGb zW+VeieoAm)>weaUJZo5|dU<)8)~^wmAc+;LtZhx%uNl^dY)wmjdFM;&yF}WW!v921 z(@1L*{=cnBWQqS~5FndWFKcU0b2v*SzVQswWom70LsPc)DnXa7k{96cMfS9aEjnMX zK^t+6dNMk^l2B_1UhZ9oRbeL!uezeIDD$WE-_Iic9*5d3S`e@UUW&` zG6&eX`Q)-7wN(eJQV&UvQ|?C~f66DH1#TMU2ABr2CkZVV7r-c}fGh=vD#%X*ZUEPs zI1S(wb&>iC9>X4*wcH2NsRiUL^#p%_+zOL^3_EGGd^S>umC9`h8PJkOE9vn6#3Dc40n`AE#_T3=+1$tNRE*i->Af3NKE(n}H*rtP&dU^!3 z$2Z6mfi;v3EaE0XkvGY7aQH}uvGfEWB;F*;1^P(XHbO(%4WyKtWRJl46SL>EC1-(j z?j|`;Idt+&ua4q}0tg1=Y=_q-jOt9njHj2*Omt5SSOBLUl`d{HpI%6vi0t)~gOG-8XcjGOxi3;fwkw3hCkGIf@)rMKPyhJmNW^~2S7(!LdOY}u5WI<>8xl6@ew{~kFY z$g&1jOE=!uDY*xn!h7VtAP_@somOXffLwAS3kjNDNM?Y;N14o8M9YeDGYD-dB*|3v z=jKcab5&GAu~$I;ULkq*Pu|{?^cH&`mSFCawczl`=CFoXHGbAEDaizO)_rnZkYa7I zrBe9>*iY}1XM)r@8WwM5lf*p$+s^|s9~`i{Yc5tT%jBNHuVlqy_0uxuAfq<9OPI$x zbTTZqceIwICRn+O?V%HJbd%(Y1K=C(XDWn}QV%}rn`goB&fXj**$$B(e?ST;hQCwp zM%@z1-Te?IL=VYHaCj{p1MBV2isKUyd-{+(6Qu7_Td#?x&@6cb*6&AT890Amc|Mke zaR5AIKOz_Y(ceP767XMvhwqQb%*Pt|+c|SBUr4!3-URH;kI5D)1*%s1a>HJ>!PSgL z)CXv)t>Rl=vuK!C&}0y3&CcjyC-rdLQk4lu&t0A}MeHEk90u9d3A-96IS*0XeoVdy zcpm9taU$)3B?q3si0KJA1P%l$3Z}PCtGhJTR4QTK>al&vWe~aXgghuqvNG2leAi>o znMuBbOw>~n_mmB^v~^O#G-XXxlFh*1{*>(hnOHMU>>}{5JSDe&Cf1x2`vCl}PsxmD zKZ*1=PHZLclb(^SKND-gi5&<2>1QPOXJRcmvFE^l{fvD6nOG}MEdDu^z~^KQIH2Vp z6=Khc9RmK5=j7zi#5k+2<7iUjU77)SS4vtwQn6#I(I z0f&bIH#gF8m(>;^CBGtD1hd09X_{)%J^JTOqm#78La4iN9YBKHK|KJHMb z)mI>Wdqutr9Jq``Ttq!Behow4*JLR;JPg>BL!7Em-Yy{SeoayY-Zk)cm9owO?fh$U zL14kTN#5IIAU=6bo(jBT4R3le82*b%6gYfzQ;6E%Y9OvDCTj&AST;!q7Rq5DrWKQP zfwv57jx#BgYe2hRO!5U5T!F-UdjrI`#pIp910yC6Gwuy^es9QpaCj(3HN0dXZhb?x z2|PHG$oo41#FKBxDS-#uvUy%15bwVs4+I`8Q1e)(yafyBTQUtCK0dg;P`rvJArWZH z-;x!S#UN&+d@LdS)@laUy*1-l^+l_0>Kg}V<3;>H_9>2o1#mjg5&m#mG`>M&5!-jj67_-Qu? z%jN96qZ)rjnOTs!6SQKA8SPFm<0*eX4ebEwvKdX#6$t#{douL{53Dv*pVDg|1j3;Y zB$d+tqpRqlX0bS`Lgiy0>~?6)l4~=+VXvNE{lL=6SwGo(=#!XtY>#XNfT|EUCS*$U zruHR>^yLQ<{So2@FoONN4HvRuQ`)E2W`+v(E#5j<9XD~6u+xIt=fHQ)M^Z=wfj8S%3;==DbTY!=LiR_{L|0v;4)Cq@1f=l={t%TQM9N><2 zPffzP3;2_MdI5i((-85aPbBg)#1F;;uv2PZz5hEGg>f&=ZPbNL1%MC06RB$HS`1vF zu66T%6R>p|z-2wvY2r>psFy#J7c_9HlsZgZHqjfufbs1M*$fUus>i)%LrJi{AKVV* z>*ELJU-dk92mcVfgK%-zWjezGtReg}E);J~bjpA~h^y`q2rTalc|ya4W9HiSOIdIA@38B3f zyF<4_0DD~m{1W@Z7yP8R)QYLb>(2iM=F4y7COE9d>oU-(QO2_GU~KwM62ajaYcN() z&Tb&3d?$MZ4lIaM##x}8`%cbNhCW<{91^UOk5$3ed)6olb}DE;8CqIs+exqP*U`nJ zb@lLQJu&>yoJzmQ=iqRD-|Gy#j8A4VF5;g~YEHDh$LcEz6UaW^=K*q_z>B1ya%!0n zU=vqe<{S z7}jNOgAbWqzUgx6>pFAr;O&M0~aQ8;@n!zXyL>V zI&3x7BpR9*?L^b&g~quVf=r2I&T=91(zD z06aaJ&U{t}Y7IA=)5ghq$qWW9oxv;vN9YBDkjRFq2k&?pG-ybn*aYNkc7njJ8O$Ln z2RHw7b3lHlB{A}cyVpkes957UZ1gPowj$V2NpIg%VIA$)7U^oe>PGK}*W6&Su_Aah zG)weM4Sl^L*4KV%jzP)y7#Ws)k5MJ8f=*qnfsjpi7ukCJGtkDBEZxZfBKl&J6ZgCix7A?>lBg*E)qN(3JV z@)#S#OOLGR>yI?w5+<7+Nx-G~9pM#7vIbD^#5tDDlolrBcS8xh5Xsc;pWcZSt^H1< zfO2^!l7rWl)?P`8WU!&R9ekM`RuOMQQzb3eHrJp`rOjm4%z~l??|Fl=1TV`dmHR|H z_ZjV8ti<7$v5_9C$07y6b+ZO$ICh{Fq3ibPJ;I* z9X`apKFOQcz1oNcr(=30a<5OaNr`6AtQclP46RAf64@}Hs9_h|d;2UBz z42kMP6-yp8$Xg730_<%A(faYRQ1@e*72vR8)Q2};IZ;MBP>#ehM+FAELQwxI5U#~C z*D2kwbhQ*i@duMQ9M5Fbrack&#s?i(q}J8E^#R@#6(Ap{BWCa8)rXp(YXD!GS9_`N znrfHB7xC#>{S=EcdD=5v$m{e0dBH!uAhX!ZyS20n8O*-h3liTQds!|F=+~>Cx41g@ zUM5k83@`P=9IPJaEWq1f?8*ZNurTnL z_&f>lv9EM;w{pwKurRT(1ZXxg<{=A<4oy1KVGm;ktq(iQtp5fu#lTA?mQ5j$1DYh&G-heYD_b}!G53|n8zFx7@cXMYH$$P;AJ)we-)RzHmAXN&NnCLzBYFmUIUSJp%T*aJSb{?q(!@NfZ) zU*ee^@!I)qfkX`%cwg2KTE!cF2i}y0%&dicPB-M=mDO+!P}VMFk_1Lun$ryr0U>oE zbC}ZMHcY-;6T%ksGK%+lbvawXKh&DeKm0M2s{upD3m0QHgm+&|v{Wb5qeQuWT&i4K zs>^l5902ojA(OBOFd39?cGPVR!?iVZ-@cB}*66Zr4J^)u zRk!gEP1Fx9)z@y%(_E!{6rbeNb`lq2VHbkd9q*v~Q1<0uu(7dJaVu5Su4`JC#{ZAE z_kho;$oj|cJTo_WQV1Pak|(+nT^Ax2V13tw70iREd9Wqwz7kzS5)cW+Bq&V<5<&|| z2|e^)r59-;z4zXG3mv7X@c*8fx%WN^VRiTSe*V!gH|NZpnK^T&ojG&H8D0Kz7ImC4 zh+i9os>1iKdXkN)1(2)QRg(tPrVxAawA@b0h414@B|XOW^p3$;kPYTH5XcVyG^Tet z8hv{55N=Ev!lxpTh`-_$BihLQ^+!Nf4&kdD#M2}ne?17mp&|S*!C||ox0iAcq&a9n zv530eFa2Q~S{S-SRSsXNFh{8uk(ZwLH!Kb2#6*y=(?Xq2)2rS9vCczz{!mFXG#M5W z%^Rh+m6v2#SQ;!P652Lz)H0nOm9(eVMkB|fy^_P zvRDh+=Z5l5!;nRoQQmrXC>bwLsu!9w@t&6b7#`)!T;=V*UrS4Gm6jo)+`}*l0`Eu;{)^jGxcB zLdy`#t<^mh(p9Rw1i@H9+CAx}2rHKKd0x7#YzqIhyi6qp(}|m=Wvb+ME1lAh%pU+*}^$B;=i;S|NPEezq?CE+lUdP^IuGW|J&zckT*PVb>fq2v#jYK=G2OgM}JFRkX zPhSZQ1ykZIY?N@)DM9XRnMWp zP=3-l>k7f%jy_2Ic&NKoM$1-mUcvK1P1Dj-i_9_C_1?NG@2gdKBE%*yu$|gyuOrSwNg?F!hJqp%1%#8$}Ugs6uv{2 zTS|c}_wy)s3YGcFByJ3!%r{L&nehXWe@|MxRvkNq8{?+%@d(gWR1Y&68loEi3r<(v zyQ+Am0$gng@JpxgH53g6aSXqpww1jy7$2Zpjn`qHjC0q{ay2MJE8l7-k>cDG{)?n9 zBmA%2<5Vk{iV{ubBM`_ERpV(O%&N@;VE$CTfZzcSU1efD? zV%wkUtFU@~7qt^A)<&N1$Zgs0ysR8O={s)B`;Kox;P9@BA)Wzu`u7JnpXoJ|8@*@p zK?vvvnEzpJdbi}6?*N)Plh1N6(1#LYJs=xq@{JPV*C5sX8>IRPpij=^g;w(Fx21Tfsw5+o~@@ z#(QS*>y$rO{l`w*s_WMHozu4Ji)Lf%GMgVl;4}oZ7SBTK4W2$ba1J*H&EcaEpp~r^ zw#8h;p{O<4YdH-PDEfTF`(X}WPtoxM+#Ay3;@Q)HoSDPVI*3H(%c3Or0J=Yicbsb{ zNs&1Z24KisKGcCXSLY4S&ID-ITt1sHki3VTH$2OGGgi+!Z+LbCqHmkak301KEc59& zj~kul@y-Yw4xD3#cn-(RALFS0l&e9hX+C!>3j5q(#2PY>kCl;8zvs}H1YZrnnt6OJ z!9z-zzb$oqv6=mO7Y|aNBIugA2vOge_#@M02I{|D0YMqbEt(~^%t}tj9<3>N2h!h| z{?%JMv`^QoDFYLbl(@h2)*qLdbr^bsjnUhe1+LxtYajpZp=!YAFyhJC`7KP&1^9zH zcI#Dzr{a268aFOAt|z@VE!R|@4sZe1lm8@#Uj`LmX$-$!jkNT!A<)MrA=>rIWtZqcj_xK%I*GExTauww(a6jis zp-JJnkqfzTcp>k!NXlj)yw^8P@p~~xzK!`Dzl@7LG-N$@2Jx;f;&)YaIx5 zc#)LdlqyV``XZuJGd+5#2~z@WFXhqJa|6ET#?bHiR0QZ056ifVOJ{r(@h*JNZ>Z=G z&$y?wfc|$G_g>76{)_oI1Wy0KH26FeE%r3{{63)fFXks?EL7=vUR_Ru&));&{$k#7 z36k4KXT_8^HI%yIc_?BMqvPT#E&=PFAA}SWm++aC5I>;!CSC-t2)Sd=Zv$}q628O2 zy#S>y;4c&caA^s@OmOt@7XIdvk;Lg2pz=$P$6BAgkh7Ec(a_;KrhS$ zWY$tXTOzEH5U&Z=fI5f$U!7#mHz1AvR{?agsd^1wL*6WN)7lrU zZZeqC8C~1+j;xI!5>Q~R*_RSM}17{gKm9>1C)v~-d z)?TQY@nKh1l95O)4$JMtw`|M!npF}9B)Drw$9NJG8uANLI)X6xKZ?QsZ*djFsXBdE zapTA;p0}D9##B9At|EoiM*@mNhII%~$&y&l=L(aV$2hSLH@9l>ql{shq;wvyx~FE& zA;T#()uJP*N6u*GsdWq)|F)WsUW5FdffQOEKf|a$s|+mDhQDEvr%W6Eb_~g`uHl{5 zQnO(o{F^py_}d6TMy}WV1E{&h-}zH&l>U3S_1Flk=lu{! zUi_WTfv60Bp90X-^?aIz!D%P+M%DJ6ChSYA0A9VGuaQ`bGAuG;P|{dgiI@|>om|fg zDGGDBE$zKM?OVPKCa?{d@m)yT0Ja`U4Ri3D1d|U8)Rj>SwK{;$lxuSDe^i8M-3 zLE5s2^sE$&L2|70J`th6tR)g`+g=72V!ChS@EO3TA;5O2IC(B$aFWS|U3FW5+gN9q zs=`-3bWXxzcpuypEIIdQ4~Lvp-6Kb^z&`1wc-Kv^&0h^a|>K^mrD z>83FBoFc-+d5BEUFe)z9iBpV8tghA(vC?CWpoIf=2$ijcpLRNc4ne%p{3 z>LyZVV+BM3wo1$uV)Y~X%d|zy72wY?yi01!8VuAWiyB(WsIzQ*HmDc(geT#N$fVS-Y|vX#9olQGuR5gAQ#}D~`NU&Xa@ppuHl)8bU&%D0EcQh- zSHvtqMQ(571Gb|+=z@)#W@Ki?wQSxznX!<}G#E{$>c3PmjedG*5W{D3RwXJiXJe(0 z(xC;dNX^7z@^)}z(hfcw0ZyO7l2fu;C#TbjPo4|0($MVVBq614MiTWB&pw{aGRV}N7 zIQ?GqYg%(OfLV&viR=&yg}}(k4x@#<=cz5NLeT^;P9GYPR5c>@-H13ykz#BAs_qxtdo(6uSq&prTY7qE=_zmd*m!!mpMEEXcNeTmwP+9B{8rk^4v9(8 zA62UsjlZc&MaC!S3dr%=WHla(ZdfHeE-pMTKHQV~M0j|3hn{@BtRiVMV{p5k%AUI$ zO4r?d2Lj#6b_&*r_K`6^?tvO-4_}4Az)?7kcQRmf8>$=Lo7O7pQ)XWx)WtU%Dd~Fo zZK9`UoBb&IXAw1Y!6QG5Nso@I(a>IRyaW??x!sI8jGXT6;ot6+X|R69JgCpHD6hUk<6M@be(;kr;1IX9|e4K+Q!09r{bL?WkmK@+q9TbdAXf+bM2cW$N_&x_SOBrv+ zUIpmd0e+n@4-Un+bV#j*=hCx@Opk-y$Un%3BPb#Arz$em)lk4cmgjNHtQR2iii3Ou zrEwW<*gen$hC|Wf!~Pd)3ldAKToAAvQaqOG(Ha)aM!_yzY>{Lyf?mf%y!)ZwBb#oK zg@;U^+xBzuAXyrWV}As_y@&WQB8wl?9n*s^4OS6yy%am-Ff=QN`7i_;KglIc!(tZ! z^!;JJ*uhMfc7?G!0oiq!@0JK_j(gG&wfQSpgvG^Eb!ry^d+9L$*-Bj-23VA*MD{(x zjebXXe*`kq+B}Iwq4o>_zB|HaI&kTNr1lyB)*j*O9C%w6GkMbqO;X44> zd6e&R;D1r;=YL!P=;BdcXklJP7strWUd}lN1;{a;i$GTQWnNXft9^MmAR~_Pkrtv3 zuE?OkAuN^#ggWy9UvP{sbkHxeq^u;`G09n*;_L=;&oRE&iSriAg0@=5AZFLO1JvDP z{1+$2Cl62=cAOgp$N6vsvV?VTAXSvga-e=V&Q~}wI;#(?AsKd`<9opFENsMwosYqT%^xG$Sr&D%GI^oPeA)!cX zjRSW4DL%o81h>3Yp!I-kIK?+ggeB*glj`a@sqP72PM+e0R?511PO6)Inj1N%c^3qd z19iEYlj;@#GW;|j;UMIkRFQV3YEG&<54icK`2r`3o|EeC18Dzge!#(~IjQb-KyIAo zHywnWlj`<7gFVX`-V1>)hMarqjs;-c89v^Dca$}*yBLrqXZX?w5W4``eTMIG5NeL8 zdkK)sXZV!|5V>a|b7y%s1Uhdu`P3Z=$f&b?^aF^6fGj%8zjqMUtW0-ZmcedJ`e$DF|Gjs$enIX>D!ZpFY=#gpTyLg*!c zFFnVX5gPBiJM)cRm((S3t4q&^`ckYpCNinm9Fszn4uZtlbNuSVC_S$z!9@vj#}M)g zejlJD%QXHxw8ZE6_Xu=-U?VB>xB}4C^Zc5F!F=M(H+8#Tz%t+h?}5@AU`PVruW-y2lxl|w)rzQE5E!8b5O9Dkm<({Or&|LANr z?pMV4?E=resPm44Qav#pj-5)oq`iVQsK$*)j0qR{M2g5txUQx-|E(@eU8{Yr|Wcn?DM;JygeS0lDKB`3)y~416;GipBCDSBOENkWWA$nG^@@4OL(Z09yIg&!}GUjOuL#p|h9x9V?@HI-`0cFGKb(^U(ZqkJUNE z>zQx1PERLIG7l<^%bP8~j7!ecrfNJmIK}xRlob1=@Q)b=tK?K1be2|a7*Ix#b8b9l z^95N!1(w4pu)Dna12=}6rUq41e*{%3as(3mNU=f&{|S+UAJq%fkjjCXty6Gdml+x! z(lpcdJQf-e1{FioCM~GYRM=3D-}ytSNR?OEV}8KWkC#hMhf=Kt?q0pxGNU>4N@*Eo z{_Iz~vQMC5<*Jkrt$dUsSpG@GsPGj2srVNKsr0l8ANi{a|5R0lk5*G*<;uF_O{%Cq zhPg&+2XU|o*9SZ!-4iryf_tO>nisTE--B8iyj|ao+8%N=R8ct^da0E9x?E~ZdG*yf z>{>bXH8gCp{+b!KF-*q`JE3o9T@UM`zq*zlufOJ&KB~XYmcFdN`juTaUFz&Q++YdNX=U5q$y->x$jnGAbF5&|^SG zWh2~(Fg!-2@tEjcoei7y4huUd?(lugd!$C1h8jjrw)`{wX@4p=atx z(FvaP=$?`9SE+$~DpZND>8^zmY$P9iE;co(=0^?c;cs8KH{P?kW|#N<$^+FDW1l2^ z`I`R!t=AITxZB6j7PJ0n3PQ+0b00F_3@>!~78c6;Ft)ORgJ zkW^IRiEDd^$p{ERhY1XI3hJg2#I{|Xq%Bnci4~C?{@dsqw%yo7jrx_1&|gDbm|mth;`fmh4SR&nSL%1V4O6z;eB&KGde_IHGepSU(7kwSj=MrO z4hbmQn!DHz-sS5M7{50=t@cjMftt5Y_aD4e_3UDgV&OC|IFoj?tkM12;Kda=lzB# zU`uOUepIqxJVyfm2F{NAhgZt?kX67Nvk`0IZ+rzs{=Lj`1HIV7BOZrcMHU|MM?vV; zZ@l|GDj#x-$88|WDE>P@X5Qno2=RLvJ-EX06<-hd)`8Hmd;GeUkxz5nH~2md-0t(C z2>y$V8Whi{!7LD3f1e*DdQ_tZI->@iItrt6N0E)-cQe9np&0AlES}MuLqTYEN3n|N zQATg-jNZHe$ij zyE=*8g!s?f=l(ei1dyej#WIPoq!XH*cW|hWg1oaEh&`Rf zQ7hp)P$Nb4Cd^L&{oGmHaxhYn^v<{0!swGN`XYeP7gyN5LW2JeYzw1`5AW|xM2cD2 z;(JPnAH*7>9Hzf>44~uL;sjxEB8cr7EYqbyin1WU=v?#~=pL&k+NhwzXbl+6*66P_ zY!{=9qb_KhNmB;u*bn9E9$46Fs}@ zjNa23y*CSx+1WDzVr|U2!1!C2gj=q zijP+x%mJZ|J;Y(6had5Q9G8vcA@M(#Al9m$VzVSBadB*zLY)WfLQiqgK`EEs|IEn~MwdL1 zi$Ip_f1$FIcHsXz9H0?-Vx)tqsWA%xT9_vmIhe;8^8erM0PM&UJ1zK!l9r_Q;duZr zAgA>f)15dku!c!H>4(r;0pHeJY?o-Osp=Ub$zev)WgxHg7Pl=DN$>-unUU1* zTVeG7R^%g)%t%tqNSXn_ci)Pc5^m9jrs*R%&qBT*tpQ@~w_=->?j!!9gr5Q6?6=~a z1DDo2AKe4s{@e+>j`P+u{s zNDLSue4=bhKUoOGqQ2rs!aq1+qW@6Ts%%`;cu@OfAEKS;D=t!OZg99rhAgyUF6Jo5 zy|g}}W%wuX1e4fv7bVN>CyW98#0UhK@{oY}B}h@nU7zq**~*m^dnux==_j^QZ2X91 z)p*Gl0VwPzE)o2}qDn1kGDas9RTefmyT34c^%nyXkPQtA`#fV5z~MN`z)=Rl+S$UK zPA@y6;51et&sr=Yz30?JC{XeoP}tI6>?K0nD!$7vX)d!Woy_Z^7F3PoUlF}~zUZH? ztI>#isLdM924GIUm`m^nt0Db?H^LE>tcI*eqYa3+ZuG7E=Ohy|)q7#~>_nb3_s@CXN&>S;BOd9~w!oO8vau92cqEziV+Ct2N*s4rOXFt!9cOl!8}gfN!bR#_JLxD z1y6iVF^=md11*B#i7qA_sxYB^3fg`^eM+K!y(zBP7BqAcQ}S!@nJ4 zY4d=XKS(SmJSGOEZq@bZB*(Tiuxr@x#4o%XJ+a{x4w9`?+HOQYJV>0CR8grk{!ccn z;ME(zle#~x=U`#v4Hmr+$l|1N-0=C=NkUBpY}#NkU81Z4!6{N>G`MowQRwx;Fs2J4 zH(rBSYX^&M6xo@mrL_%S_rr;FCN9w0L-=S-uJRj}EH>tKSYm#?-1qud!ninK0MWbw zV!eilkwbLZ8skQsx0zprwZNFk$o@Ch`!-GBkDOgr*Y!oH$HOa&VGf(;op?IZUjQaI3~?hWHGtz=7`C zyHV-S4gh&@m^fvn{fvJ?0`%EE0PYVH9Sd}RpK(~jdh?qvN%JmAlmDesw1L16DiDKZ zG%E|pVKWpR_-0FiSXLm`7QsguA{_@HqheDKCH*jPM+(GQ83jT|C>(2)Q^S0E$KjZB zhl|b#WX03DypESX5`a;|#b|;fE9ZuWejFj$)AV9V5g}2Q?T*LX@Zwpi3jfWd}1H-4ux2k;3RYQglP$ z3`O8@b9IE&d?XN~MvBQ2kHR)r!r6Q|06&ZrD~iMS0^P&jNuORN#k>Z+@8Ej5NkOJ zu*svv6bD5ED0S+VD*;-RRju#^kXv_~9GasM@Q*jN<^Em>^CP29GeOB&U1|`&m6rN7K-gfgMQfIGW%x zenG69iK5rUk|MvLBEJRuhdIM3_9R4`HBo#|vGD^!kIGtR>;Yu&M6pjIth{LL#VfOy zkTUZMFjpsvI}{<%MW)PTX9@dM4zpbtVZYac4g#U^r$5XPKUhGhgaw8{ab)|^9Ic&9 zBplUuAwR%7GIBw6i7nFF{G0aIX^uB&B(~80>TFIo)sxTUhJt*Ago!LHhm*2l^;iL` zi}Dzn}TMoF5m98GftG59N~%-}tjE(Nfx zK9jJ&pCpD%){T+Hx68pj>*N$+oSGs|Bap3>#dj#guYmkEMci``u*4%$1EvaN;8ZaP zf#G<@C4HTBI^%a?3@*7OFaMFE!W8Rhr5jVv5UDLemNYz1i>go4Kp7Sv4h5YjLjM~P zAMuq{#Xn(^phC<*?rW!tLMjC0mh8P9y+dmf#Vih|RQayg$PszgoN4IA)5K~7MtN9O zTc@s+2J^PoWpY2abEr-LT^@srtEO(ZywwyGRCI?Q6pWXVCRdha%Hp50h$lT!5$=`z zw3JX9X&=K#3-lBCt=Sl|6G#ExxzR$S9G6;jPbW*tuX@1(bl;5hPzp=`%GzqS}#PDMf1c; zius^k0(vb<^C9*L>3Q)Th?)4Mg>UN!j^*fl_Np zDJDLy2(4lBu|k+HmLfnQf?B}RM&6jU=X?0Bkp;nyAhveF>4MYgUNU~=j<%CZf0Hkc31J6U9caNE%`C-ZOMG zzo_g(d+BRYIrkTOA-GyT0BG7e}U@KRaRy}po=~`>s zdTnqO&v`oYvMyai>qxBq9;TMLtvRd$54A=*8$HHcYwP`dZ5uXxJ9}>w3UW zo#1HT58D3ehI>vBR%BG=qJyFM0-B{H*ImZTG1u#*=`v0tFq~*P5H?E?=vIt91zB@hfe2V9XH*8ypQH*X#6Wt!SARP?{A={;~CHUyGdS_+k1gz~1UVZXQy-fmkW1}@bN`vw0Mue!t`7xu-$Wx_bL zOdLi~!k`pIW5E|3*WjeF4*TL3;&oasdMvj|!EBZ2OaNr!axsYzq1F|=(rBKyle0d3 zTel5vmH~n*VYpM};^Y9Gn*j;}6CNz0TH?ZX5KQ)(rcyG2%VcH{O9==LX@mzHkciqk zFhtq1xkFWGTkhP}Z=QNuspgJup~B8=pq}!kG3#dEEY@AGjz;iYJ>|{icz;=T_QQZV z_s;yS#IVuK(woF zDfe!luS2~1Dg2+&Kf@i9;ZFIz|7kVz#d5H8#t$NA1vqOO**T8{U^3BIG)meBE|hie(KQvy;4u~Z~aBiQcqq|=lp~b zIqvZvWVp-!&i@B9+~FB+nhw7h@*@--KZ+9wIP(??S;?RPaVU8C_vozf0 zm%$3OdCM=-0?U@AQoT;TBO52DNR|ecgX2>|*45^<(xbi>7~@yX+Q%){4rkWu8Jk_d zXygoTZ4lPlUxS2&-Gr|S)ZTKwEH-pvoG4;)2~lXzvYx8w^?AR-4v?{e4%rD6vlGkD zjd!O&g(16FWOTOYJ$>PjZnD?uj9+ZP;p_mf24nau!*a{doq92`LtauUt$gH&8NJh! zWBXsEE*ZeeC#7Dr@%kZi_EH^c`)^kZe1+9D2Zez{l@w@$aZL457!P? z$&Ql0^5!MhT86w0QxZ$QE?c~S%!qVAA>*>gP(z}JhR z8&Gw(p(PyKV>~l1JEGv06BZNq;R8%lI(iHYP}o2@c&qMePrCDT@uQlknpM-`v)bL# zr!aAmRc>p2bYkON?&4Ad>42-MsOG*bT4T|YCc^iZ=y*?}_Qn!~{bU8GJji*7tYFPl z_wJ-;6W#S{COny>_ld#a!((bz{4#f=Fjj9A*_%*Rc_%il6*K{*Q(9v$kB+Lh?>NbH zbow<^K`T6OEoZ*uw_L0M1D`5T(v$jLB5iI%(DWot*N{P<&0_Rspp1qT` z6M??WvSeAyEZhlLNhyY{;nr9(Nt`ah=`MU1DaXjt0=q1l8Z(mD{Y+lca-TQL<16rW z@Fb#B_jZR?c+*{BZbACk-iIo@T_vezN^>`j4DV74Bex=nQ14id~LE-3cy zMDOE6V`%O4C23cpeMwJN%y}`ZBE}o`Cd&(A|2Js|84HA41p}dO?+|dxAaXs@6J=0)Q ztp{Z&G3!aaMKWoAX@p<`!B`X@K}}_MZ%2Vh+*1OK}A;eEgXC+;8+c$7w`h%ZUJR# zGikRle%viCA)qoTU%$?EYIPjbvT{ewO#n5)0F&h|NI@cY?l>z^>8noN2IX|5a)w{_CiEwDhfIhUn! zoeG74w_&qp%{=&rw)bsD9~8!vgJKQ>;z-d{yQHqE4PR>|LrR&HLYaIo(j7Y}E|i!Y zS2bjN!6BV5iE@=c@DfcwwTc0t3Sn&q9zy#Z5|a@;SQ->wk{ij{TXy0suOjD>fh2Mo zsV^TAw}}XTATadgd5wgMagt9{4hv)IVKEJXMj!V_uLpd?VX@IcV}e2Ih7BvmH%yQe z&H;D+u(;qv>4gW*i$v*p1ST*?L@xw7lkqwVJ^ckr^rNWFK%DQ6h?!2*)enohA8`&G z5eF&i1C0gyZ>sBQ!Qy@1gp`z&iufm$xSDemHZMoTKm-paTdmu;qiLl>Qkj-QnSL=6 zt~x5Vl$ajw`enXjDSZ;^dfn5GDMe`c+s8X+zr#IF19b<6;m3R9X${Mxr6w@@i~)gZHGNQrqu< zoq1d=l977tZZ3`vVc{Q6{q+I8f`K(+&}W$~ zTSyca!St;V_9$visjwoD6Y8@c`j6*r`9~}&#v2zG8(t+mI>r|t@2!H5GviT#w%1UO zStrEC6RJ4MiQYqs^RD!;S3+?V;tv<63kIo&m8auL7>=A22M|csx8*Z&DoncmwtY@v zEq6-vLjZXzg)t?o?Yr8Eh`kK+>Nbg^=59;=N@DwG#$@W*tRc~v3Ia<`iOoa@KZvy% zwn8$C8-U$BC4Tz1S;XlqU@A(94^S4(ie}OKGzOg0VkQCun+$!lZZ)=xW35%Z#E-;U zyNk9QzPcJm#d%=4q09X*`8rkGJ)n2_w7CCA$iAjZS-Flwwy%q|z}6|YS$t8l)6ZZ_ zbVlq!@ZXenj;rL-=A0Eq!C5gK!S9kSp|pD*Qrd%{cjK(cIR~;hB!D(CEg8PZb))Eo zmI3=>YMh_(w&YmUb_{-#sPShb*^+Z&bIGY+(o|sNMX50ed8hiPzKUdb&xxMr|4810 zkh)0TGmvcId9l9a)W!0iTs-eWB>VZi=z0NpE3sW5Rcvji05bK0m_~?)_6zHMOu0R2 z%kc_aY_tBTT04s|E0KKH1##LT4>w!HvF;aPc5+elMDT~npLl@$7$l!_QLG{=emz2u zH@rxX(5q6bM{sIK4jFqt78^3T>H9?WhjXCTu~76a`~yVmtETt$qn5Jy~K&&w|?hOQO$Z*)qj@ z!qZxopHi~i#bj7z)R~Q6*%6i?)tbv!*W9N+VytVRbysOf{qI@P8Fh_Gev~|3pQpeR7ZW>Y-oatu&GipS zjwE|$qJUSfis9E#PL~lTX8>IIe_MOJaW;^0!Zwb&l-{8o$HFN!CfrB=d(v}KupW{7 zu=>7KU)08U&&CGvp45%L_;CF5CUDfAw0dl}4>{eqCVry~X?SSI;gD`<_`8v(B1!L8 z8NZe0MZ@*r8xi3YfBkhVNUw{H2xu6!H?*oe@>seZnbE){WYHVj?d~8+_6?DDL#A|I zOR;wa1LfMU9p8n)cO1Ah*W<3|$@9pAzjkww?1vj-gG&97d^_?I^1X&6zuXWxH<7O} z!dgRnm66_79}nSh#7~{hUH*STd#TlX_6B{hsd`5%xRa4Jp6NQNr;sjuvEGaB76VP< zrn1m)#|OaWSOrgkuchav$LCFSNB%q)&0jFrv$}!T-O>Hb*h3NZ+#@3AKITsJyq6gH zS{8Wz3VtJz%JEzl0$nvVz*N-Zdi)N_Br?w$mJBqE@PM6)NO-Z3=&w?db8Q=H8n(^he@({n2KIt^?jo z)1X|wqR63CJAT{E64RpHRVqfudFsW)W<_UCqe+yGN)nqxv7MKY6>x8J>QS7L#9oY`>f*O%wJ7(?srA-=AzhSPzSOJ2nL3`Rg$ZGF zggaYy_4YlSRN<1Vv~`fC)ol+M%aubu*yJCfu3%~{&~^SC)apd{Dc z?f4`(3{CU$+WHK?Ec;+!COB6vVyb7)u!@nfF+K=i8CLJ$!Gn?g`!DptRISaDEH@q% zg3;v*xG;d@r686a*}LGyRdD0c;k|foW>ywDmlDtP{5hWa!#q*3&{(l{IlsWJ`d4xG zS8yCV?xLOZC7N^F@q?i(v0^05A^S%}(XO=J&%a^1|4nqeheQwQql%qH`=}qx?xQ_5 zV-kDlj}JTQkBQ8h4i7Rcx+MGN@WNu9^kI3${NL_2Xnd-Cp-+S-Ty;1E)PF(R3hzxP3MIJ9#B%Z zmgjHute0?W0~PoMp%>HOqZa;dGn1R7nIT2|00o5l_3(gF`gBVg6q5yK5Ls~A0=i9e zELyMEUc0T?m32^mbYj*ZaK$ypf^o|#VKBE~cliiSYlPS;%33oHCOI^7N!o5m$L3Nr zB&2zxyfiNK!|$JB3rSl{ll|YSL`7BS&$%MV9EE&kR$#SOR;d65X-JjuO;1M0L?*o7 z5Ra+ioo3%b-VKdh8e<@D@ABY%EN8^Hi>8^-$;|DHwNJ3KM6i6ckll~md~xnS5#Z4@ zEGDFDPt(*}UI-q{ad`8VscyF)i*a1=na$7TdP@Fqss8w6j{ayeS${MisXwy%>W`hw z`Z~z&X(n!P-Pg?S&cEj+ADy=2cfwe7TzFEw)R*1T;dX3HT#VP3IV>*T*M6MlW6h+b zxUu8n7S~9R8@GvOb7HRL*}M{a>D%UUbK@3=C&i81xG8QK-zpi2M`3skW#L*`i90O_ z+ZAM+#?RU2?i?`lfi90X#;D7mE6pJRIPqvZ z%a?m-#H;soYrbi{7Wm#74N2OkKc+D2Yc^Z0Vbg5$)>Zrvcg~0&+HZ`qVDe9;Sz7H_ zYx<1Hi7s*nB#6NetG9h(`@~FJ3L183me4-2zBiR#OQQwdi_s_JYUO0t$jOeckpqRb zbjkBrL)-KZ2Na#)y$P;-u@eYuS7Px}PSjF-95iG1E%3k_H zseyd&m$u$L8sfrJrxLQkHYVQc`pI^DF1ZQ5{ZN)gdwc`3VtsMDeBK7s9o#SBpGxT! z>J>z|>V+jn#66c)&zlIC>?bja`rzmh)R12Kkjs$SDEE;bX78RTzA#Gp3zoLXr(r^y zY^!n^+M?@e{YFXjCkkHs6HFcU>b!3`jELZT2&?!uia=|lh&SVKc{D~}xS-SdFz}t2 zcn#V2%`<1`p%f)N!(!bEuvg#K%JtFla`o*J?Lb~W$Fis#+OEa4tc&4U7d>qT09+Nn zUdrSasQ2$>PU!XjoXNh2XL1PCZ}&2L_C_X-Vuhuk=qa{FRzD$9LF)vnY9$D&!Ecvi zGh&)Wc<>vMIzFGuy#lm$^foX4w{yB@SF(8SStGfSrBKT?EH{dG&&#&h8l%29f2c z_(~d%%YnvzX)+K9Im*z2{i_S0alNmZ-4CQ(oVnw(izUEJ{X%(UY`np$t)9Bsb9E3n}<7-?~CiqMM zX7x8`6CC!k@ZV^+fmA?!jU#So;n~;g5Myh9bDu-tRY~9)0N4AQHyrp|65c)EG(8?s#$Fvzg4M*}t{-yG|pnz0TFwFI!G`Q|bQ)q&+G)Ly{$<(vBng?+a&-f~XO zt!n>S?Xth--Es36%6QsTe|;T^x(qOT4?tRsy>eiMaUiTO@wjyEqvrMRO**B9w zV(lPv8&L{?4`_PH2_wHvQkpGrJmBXNCLUr)ZqCh8G9=q3T65T=nq{E)bVpr<=h_ry z>Njwe;jR`-QvnUi5jEN;H0uznEdoR3bU;t@vTv@VFp~zGD+g=-e#7OfK;PsJF^#T6 z%x(xE)mq!A`vv6Q5Z~bDMjTNXfhZG(nBP%MYN2mnv_SB60IVNkZcr2+%6mCZeZ#+a z_&D{=F_5@1#QarJB9=hFyiGHRB{t9Brb2aOFiuB(FW@)QT{BW!1Il;IrB1&in=%xG z)KGI30yKhXoSxi-v5F}zo40D3PEUm6Wf0hlrApc^Yi+?TgMVQe{L|x#dO2Y~TvbtD zTl=!0n22|xV&!?F;uGDekyRGc0z$46^7Xojtft+{UZWGcg_6x5W^Ny*`H95xMYB$9 zaDizIDKLj3K%0~x;g&p0o+90Q4`*s8HXCHt7MR&EuiAh5 zR#Vj7aAjZ!(5p+X?-jicHpi-BVI@~Iomr<5rja|s9E1Rb>>Y!aR_Tu^n{haV^3&&% z=w`DGNV02$d6-h-xjnmYE5{u!Wu(T`8%-F|=$TO%;56lUX$TL#=v|jFT(2VCdU?N> z_0o_-tfQ;AQ4fj&<+?B4{Y=4T-_pE#F>&cI@ohl13rZ?tqnm59zA(r|DC8nR7B*)j z1Y@Lm2!ZTqAT$<+AYb{ua@UL+k(CwU^Uyz$XJqVIqfBG=D02=1G_O0gC6sR;J3H-V-*`c%{ax-%dpS&^FuI;+Q; zdx@NY{xPGawsOU^fS0b+v;u=`D~kaAVGliLbzbFkPyA}5ZYTIA5U9)<&S+PnRzB`k zx|QUWY+CzZ)PeF3A8$~x5?wEc>KJ6nt8}hzZBUxca>ikyGtS(Ez>+_x8+y>*CY#L~ z4{;lB&Ou-yy9f)p1<FD6~Tr~R7hFmj9nqfZG|5KY>>Y&Ll!STWID zjKE^WEnVCFfE}1<9`r+XHrX3=5RuJp0{YWL^JhZ3jNqo$#RbaDG0E1)*^kGlH3qW& z)@0Qp`bW_CLGyh?iZ+yym62v7lcqvXsqVxwJ$sx;1m&_t7g3_aI| z(p*67pC_63DG`1MzsN4?$jPQLYO*;RL5UQjHN{n+==D~?@C}Mf5PRKZb2}x1+soqh z3$g(?kx++nwwSk9+rjL^5~t*r6fw8Ca`Xz+w}p~3XO&|oVTcIcHrKbQ4F>}uCK4cqEkslRr) z=4lI0>{hY%fH5y|^;eU*8kUNwCI9opJp8{%PwiM=wdz^3eZGoGsHt2+#AT07i0hy4 zch`fSzyy|*(X?`hT%ooLrkdxc%El@_653MG1w$+~Gt$ZJ{jUKS$5FDBTE+hJq!j-T zC6hUwpJp1rPBU|-|NESJ6w7HJz0v4u7*;HwS`XyoNwIR;i7d`cH?OLklzQB*3A|EB zdF>(B2ia`t4AWRM!`zAh(#o>zh~y1I#_Sg)=MdlNME6fLLKAB}F}fcGvYB|0MRf|0 zxH7}MqbL<$X*{o~EeT>{Q}bnlx!;+_vhU2b2+*hPCs{EI!x_G{thdYaxZS6Z2QhDK zj+)X=Bk}$3%x*J5L-)k%K`if*%wRI0Q)Ze|3HjjK2OCLQzfQr3@0G6~WwSMiyKSbq z-;drva^wL~xdYhUndUEkC>)hZRQ@c}7%u9bG9Gq zltyg?Y}0IWGogyKeTrtyWlVr{L=Q_>IedDeJ-a+wZ-$AWv0@uKDK4~|k*wz6|9UQ_E z@dO@zJ?@{vNjzz`j;!XTRk0ideBoN(NE-?D6g##&WiW?5R?QY-Ch$D@@J7ZX$jQ-YW=hydGwxd4w{dw@I%9Ck5KDU zeKuPK`0DxQ8bYIUsEXQ4zaqElk#amz`dzEfW+##E(tPtCB`<>q#*?#PqKY+hNNQT+ zrm(@p#veXog8Z1}wqAL!Go3&{9Wea&&q4m*H985S@2?&u}>cCLC ze1g=tqLP*AE*5u=trv_5;oqoTyGGj*;u$GDMO-l%$mJ&WqD$VV= zG+mP_!zdngGJYKOB8NrzZbW~pE0@mScQqd8;2|tE3sGc=b-dE-rTR&Ks{$y^#!6(z zEWqHm&^)@x5!n;uek&@?mnH|ATZ^IAUToe$V99jnF#iaHmp~1$#2kvi5DW)g^2jl@ zL2@g#oeOrvQwT?h>^+`#0#fNM)o4$=p~9!?2&IR=I?p9f8Wg3DE9wVLUAXfd&g zS9ksVsVsG-+Y;b_7TPn+I?ukuR%+Nf*C_op zom*eCc|TF|kt(>gRJBl4S~{%0qT*^d@ID#qj*g7=J?6Xlcw)}uBz(lin$P4nz}>!6 zslEmUxXPK-(DNAm0wd)nuHLwh5?6Whd7+dm8qOcVaxOgaF+N#BDuMS6v4vJUh8tjH z;WBg5a`2NIephXwRK%bH12M%zYiHU-wRGKvmcA1uzfu~qg$KK-pU8%`j|t@S)!A(2 z52kVS2lFZdOnk1)Mv^$*Q^l*%u9Di27imMmKEwTBr&aAW{T*GZBka2VI>S!bXK!+_ zAUW)gjTp)o8&NOT{Zx1a{)zNOHS@TidQ2|&iETAwqtdJ7wFj(9UI%{8W}Qb}e9dN) zR)9|{%pN~VxeLm|<|i{DEe*GMr1L6zFd5fL6I;f8nwHWGZf~2qOj7Wum46uBE(0rJ z!$=D@(;WyEKc$8=H4Q9<3$0KY;yS8*XLOpbPV7GwyFcou0cm)W5QV#6`ZIXvmml-k z5&gB0Sx=q+#B%Ig&(?tHhILXY;>J124NrnM)<-?lf3U$-UqD{LFGe+!(GV!nv9UG6 z-9EiRFdYt-X=C2z5|cotd#ih^ISQUF{8 zb62l4`>X=k)WIeV$5^3lU5ypmYBO&QN`N0?*DvzmIGb$;Y{wdNC!t^{o{3`7bp1ZLTCi8& zQmu_dIpw6ju@UM9PU3<@c%^i;vMEIR-`1G9Yn>cM;Ow=6+TYFrc>T=&`_`GqRdn784~1(< zRFAnJa!nZedei9WDu>-eye{j_-s`F6Rz#@JyD*$?0nmj_2WrN8bAgP3+<>Xe=-8tR z+X~pW_2zazR6Q1(LMqrU>;j+{*PDfY$oCb+t{Y6F+Xk~c0@{06gnC`7$eCmzhj1I%WPMKzYoNt3W-m7%Maz)4o=X z)Sbb{rW_UevuVY40VpL*i=)!s_>*@5bar8^L3|}|Of;lYjoCG;74_#SSZWe*vj6Mx zJczyYV$D}cQoFDv8!;YkH2ZCGIC~o8Ka$8_0R457`I{f|I+M;nyRgBVvGmw%4n<%! z$z2OK7r=R&&G~+~zcP17W0mDLfVXcpcSx)yK)4MKN9U1{1>~H|E(3XGvw7R109+LF zl9=SOep_Hsu*J+r0P%*d2!pN{egJH##kr59_5w?7hOrMxW+3k3E#|6+CPB}UN#a;4 zX-ab0aYVhm#k@r+T)4cX%#57OY(c808tT!iO2dnSzRe=+anonB9Bn|uNJmM%|5hBe zZ8aAmD7gw1b$L=r%5&K@M7+1v?7Hn?@gLXmTd=tv#ih}RJ7b%=a_eE+E z-9nD9vQTs?z@NacW#$Is9a8A#vc;%p{tk1|4&tgMyDmd?r4u#)y0R%dO=Id#b1ni5 zNJaFDcypdyg*A|81kA;oVA;WoE8%R$KLhA3o{MzdfVRfy)}*kKs3O0mL? z-exqIcV(N9Z>L>m|6Rx)>p->7Rcg(WvbU-*lUeIPWYLet7av}r#Oe~1)3XLB+8aUi z@-FjsNwk&ovm#ZqXwUVh{ez;NNQT5Atni{YMHhVHZqwMX+uViVfr9@V;ye6_U-B>b zMQ?a4Q`D=v-ET{Mo(cwf``eb^f{ZQKw{91EV68OL|s5<&&N@ zP}OJ3KGWE|&)kdP0fzmX_PFQIusxI$@*&?eh3=kUnBN2udccV#vRAQSPD);}4pP4$7hgK`3=^V*b6@RkRm#Ifz)&I)fMC z18j(?5Q&LtJ~RV1>gaH)wbS#Od78@xS6{l#yBxx@^^my?0S5CRv_Z*5DAG8p2%=cy zEYxe8nXCr~HOz8S>q7(Om;k$2R-w>BiD;F~Ovw-`TuNp$oB?2Ppgs&h3ni7^4x7gE z!{$x|5Sjm|gcg&mV^NfcO4AQJAe%+S#-u4nOk@8M^CSY|$A8i!0&lrxwa$=k%2^DI*{^YgPW<*wfQoFPDBTF^(9hw!qm~M`QbDrPDhb{ zzf!Q8(`BO;)D4(>23_Kec>uxxnQ-0JCEMg0_aNtRz(K-qaqhHS zib1?e;-fB1>%BLYP`_ajSSVQlJcq>I|tn!i8KuqW+*_z3e5sPj5OEm&gKF%uh5+Dhrz>Nl+PA`wicS( z{4gIW%sGJ07n&FRFpU(Z^Cb*km&_alRtY{+m;!)?UouDdVOlE8e1H~QG8g(`zEqfP z0Byfy?(oBWqc9f$x_HSf^uxgDm{d;PSIh&*ub9XDP#ZMr4q$h$n7{a;c4}1qRh++HH3uTF zig8$@z5{ILRdbdf>WoHh0Bqw`bCVzHvPPW-?95g3tRL!@Ms>Uf0la2*MquUD)#b?a zFu)70nZy0i`EW8sjrKiYi?5kW{7~e7h)}x$+jGs_>xUYoQC9)GcFnx*hZ?L=J+GTa z-gUDV0;?!PG-?816R(?-{7@q_Y6W0FUN=|zp~h*{A;1n_H;?$CCTr9!z;0hR@A#o+ zX;i-(P(R%;^AT9Zn6FXO0h@8d{LT-xLZj9Jw*H2>!4Cz0f07#~0XucWJne^q+fya^ z_W-?2f>y^bL&~1K8M~%yE9G+ZweLuw_4)%l%NlY1BTz_Wxua z@I!T$<`v!94Zv>xWd7ub>Z(z_e>RP8e>VFdu!@nVQIi3i^0PVB57k$rRspv9XLF4o z3YMahiAMoD_Op514>e4q?gIA9|JT=@z{^xOjvt?K-4oJAibTm$ma zd*;l!#LH=hro@MapSSFax=o?v4yMl0@D_rPh6B{$PsGFR*OFeY%_iP`NSP* zh8=|_cFx~SJAOX#M4BNV=Z+2axZu5o3yHlb<@z?qhbEdf=|bYoX2_A>Vngdq`|M)khBQNVMU4%8Z`uzR6MsxIbS6G@!L*AP6aP*#=hAmlC^C%C&iaA$G2@rj5IlI6lqLg!s^M(^gzcT$yHQYJ6y?X}c~Z z?oKl_D?W76wBIi!o=P)h&x+V}^}d`K>2o=;FQwd!#qpsjrcJ$^I4#YP-@aq#T5H-T zmlM~e8Cnw`+GpB#mlOA=8CoA7`qQ+(E+?K#GqgEAH1MCq$e@1`2UE(;*d8C6ZQ7iF z66dBF+8rO-XxgTK5;vzA+7}=C$+Uz2Bp!+lrMz@16iMGVnsBeLA3W}E^o?FJdikHk z9{gu|LJ`x*JhDd1RVN)2}4XNHbC|dE^t5)?G>bG|k9s z$s_wr`tC~N{xlCY>Pf2A2|l|0hFa}XKOIT%POx1dw<$PANab`EBx8SyTC zY$kka+WOAHXK99fy-957fN9@%4t_{8G&w$W-n0vygNtc~K8nVkT>3_bbO|Cuy9C21 zb~BQq3B}@zDk(bO)Q`FZ3(^dhjW4RC=r&WgcL{c+8H~NoO^W_%(y=bVZ)rwiuXB^4 zUAqR6Ze4@!lyYsc*SSg2u_le{8jMdf5__GS6kTT0@~**(G$XM^l@$HTq_4XMJJXEB z7FAO8HK5!yGm^ZhlAX-U>>lZz1>Yv?%ztRk*Jl^_62lWUd zgL?!+D0Wkv^Re(U`$gxOG`~miQJN8lPzpyjoAh~)U`v`2A502I4w`hRM{qdJNcH5A zOD0|J5&V;8B=*lx82h>YwNjG~lV&@(n;`$ZR;wy0OI zIL(mXRbuybyJY`!6KqK{ct`Tt zj+k_`Pw;a%5{;yM_wdy>O~ZQ>Nk1UmW8venyRvo9u%mm1?Jjaa^k3)b(>EB}H$G>a z#wWbOk>w_>=o_p|Gg2{mH$MpB+{GDgx53@_h#2S$$@I?*@yD?CL)@_yPi znsl&lNapw+EU~>fqyDJhvSq{6uO>fq^-nA=>K^Yz6!E`)rH)ohSMIvH>BdH{d#Yl% zH}t@0|0L^ZQm~5L-T!ge8@tlPZcB~WaRLTLPde4Pq~J<;;`mPE$u}lrc(|P8Tat1w zIwb#v*45XIU42s7A}{5vnITuB*wv2iXT9tftR_2KragOx)-9fB*!egzlOEs58Fge3{7-}@Ktuo~`t zmGX^$;qlhP9aocgTQ%F?i`FfB^r>g6m93b!`$E9scH|$kH2B3RufBv`-u9Etn|@}dDEOMDZT@D{6x3KE-K@HUsTE`72;PH?v>^3 zFvm!%6x)F*wkjO44h$X;3>s)v$nyVN6;c*V@pS1^7EE#9SQK9a?6;ggL&`}?BxXuE zNr~XvlrvQ4JjunneoPyHQ**|K$etCDRu45DJLnFIa|saV7KL~yDatA)A=_Tn;xNKSrZ-%N`Avf6k71$EGaY`2Gbc%Rk($ zAbI&0zIu}XbNQ#9?0+uX)a9Rgn*X_uq%QxPW6S>3ATQpA1Ve^e_P$Z6ar0MwY9V}t zKi1@RkL~cgU0TF5A#*srMl<_3h9l`SwQh0shxn|GycoV1PWjuOS+Fi$w21dnW4j{d zj(@X^z0+O~r-k=C<;WA)NAHi_oa4hhWeg8K8t&#~4)>mF(Ja0#il*5tWwcp}9qq?H z_LAoAw0u>Vh8t6o|1T7>lSH$4r2GAR(KZoA>B3Z!_^<`vzd@7_Cd?= zKthInvyeLw)&V)7~yaa8!&y7EBEUhw0iUPr|yt-rcw{8p9v#aSu4YsSCcBV0Yc zP3I`y{uJ}*A>3N{;gV&asy1e9sh3OH*(!NEkh-coP^9qHtwWlrxoTFfSt)C5&i!qc z^&1ha8DY+u5W6u}&-B+MB)?mE&61HpWa-FYErtIXNPd>TW{)X*M+V=-22#$MA(B3O z?2sGL?7tg0H8Qx6a>ncl`NC($>;pyxk%6OvK@_{d>x2WdOqo48m=haFxvuLX>GLGC4sUy&^#(p09c)iIW1fVrv6nn~ z4w-Uzba3Rq&S*B~OZX;sf_#^ZTpk_t7!$wBd9o&#~H+kH-dUQU{XXM=iA5ls#jEy{Q8|lh1L| zl;6h&r&0$Tm@&Mlp5uZ@uW>T3 zYg2ZP3wEUrY)KyY&6MNgf)l9&z7{GxN4N1or2F`w2gR?vd+dFnLSs!CH$E7jI^eUH z;W?I?vTS^?JRC5g?bTP3mt(IaizWE|H^a^8>Rnsz*ZAQ3lnX1C za5x$r8jf_G;N|y(pgXy=gcji!p~W9R+$@{t&wb8S;iVvtqcySF1Ssj$ygd zRm~i`f~C&+>BL}H@&!16PV95kSMOcyaBQu^E1jD!{D5KWb57W0QqXr&>Fm;`(mj&Nzm-~6^6yrZn3_5xM+ zHq%X+F(sIpI^dAO;YEF7%DO4Rr{O@lNVK7O`^we%TQm9PdfSA@qi;1Gefx7cpR*5d zwC%S}d~izeTgrvCwMvB3`%MiZ{ig;4D89I3U-@};c211nmq1t$Z4(+r%Wr=xYliKO zvL0!a&C^b_?NsMoFg5rrya@j}O_$gn@zt`t8*@>>;c zN18HfS}-~s@O4lXYve0i{=xe7WBX^dDt7fQ##W)W=6vi^#7WWEVvV+4=xiIN1v^qN z)^QTT8+gi;)6;@K!hv+wh}Z}GW4iiL5&Ia&7FmV(@keGxzlf#__bp1Fay=OmdZhFB zX4e|7GqKfUk+`~gWVqE&XHtg#Yt6}Ui^<_y(zf^XATnZlu$WTUlAFWtwE8i&k!d$% zhSyOug0U2vHSH2k$KKIwx7d^=GlHezfQM!LQRP)ud{v8m4!1)>(hbqE`3~HEAh&Dl zu-%Ejoe>;Nxv&liTeE~Sq(kSK7QoD)E5)v*L&C8v(f7iUQ6`O^8H|aIq+IqR;Q_mz zjJ{N@;#=7&4s)`Oi;XXt8LUaUfQ~*k5KjNjg#9yv1F6#+$EKe#;q1)d&(!J7qt(Lo zvSZ&_K_qEb(2rs_rDH;esBK!b<5W|o%?hTc4)lwry$Nd!teq8nk~%&*v*)2(wy1B+|-dTqtUvl zb7F&mjkAMIspE%|ukDB_M`s5=rw*J*9{9(Ue`g0*QV0G@xfvhMv3kr2MpFD{__ZT; zGZvb(Xil&=b!2F|v^Qg$f$ejG9jW6EJQ&{T>o3X;Am2-nt;fP04>^N%)F@v(GT&5(fd1H|G~MzKd~E_vXX zTXf&NAoAV3;4sDRo}sz1M^d-wWz+td7yO%M$lp9VI<8IZoFnFY6K;Mmic-$GBRoW$ z3teW~^7+AvG()p9BoBRU+RpjGu5ie=H^;vlJLOBVug;yd@t6Fy;~&Y`>nmh!!aYxQ zb2;(ZvpD=czG?W9KKZGrqv{)b>Ph~X)b-I#r91r}qnn3?+vRT26K>3v`N5cv+@{z; zWWodXUfr@!PFYaid`xro2|F`5wrzOn5BcY|rc?YITMGZgp7xTT2g8k7w`k`DUOg@d z#*&YTUcJwWulZDiqfEvpq)(qb;p(qFL*viTj@J>t34^cJuykL==g?%8KAbZVAJj`b zcYX-xPSr-EZ*LmTm-rlNT1_XT-9H$?NOZ@ZFFlxx(uRS5+V7h#eK!`V#xOV*Cx1o1*`T&6oL${IOzDuz=!g zkQ2t9t2T$%mm!}Y!<*s3_GpHx{)s<{Todg(Aa(&4ob%$M;P2Q4q^#e5d$99c?Dvjd z(UpsX$g0J`XB4qlpO=qUmuv6%86Ixvb)|iUTz>Msm>zW+KmFeiu0GNIF7(ji;Lq@~ z9a<{b{X!)21$=*KaGa08alV6u7bB5N+DBG{oH{EUXFVv+h2gi>pbA&O_4;+Lj~jGn zZigH7XdVOyXAYL|YRDDOrKj_|D6Ma(ABh~(_v^=WX*{T#a2=GO5#mGfnUFXm@;W=HL3!;X8k}II5_IpyKA!_OF+!4>~u{;b`<6sHTg;guq&KqEH z2fy$ESWLn7ue#0Jq6tdq0x%nc=ea7(mcTyck=I~W1U!FYC#BI@6f5-!n zq!;mY^wVGPdi2*fydH^M)&q1?{WJ#Ze%uj*^lToB!FmI)!VrCccVnoIyy0=Ghw1G4 zMhw@b`5t_z|HG9rLchWFF;aKocdglqF>j~VVxe&{qd>Z%Nwy?U)RjM(x2(d zx)e6(j_m6eBOCP+o`OxfU31$BY}O@OSg-Wwx|@CrTXfO4ZFBTiy+akXd-R8G z%-hzH$X@-E-hpp)^S15_zSWa>DE8^=+C?JA^>@0U&V~KD23N%a-HBV{dp(8+;0L{e z=iopWeI>kGP^4a3iVzNl+=^AZ$) z>o(mzr{R(w+{3mUm-W1!wtx6XZ|N0@w8X#qXm9rgS9G+m`_d;8{=OOHvccHoXTQP( zW%`--e)eJ_sMX*3{OnbC&_llqFSCQ$JRFI72d_e)PxJTif;z}Lz-7ZL=-__N3%_6o zwfS*4zEaSUo8VeKf&0N9GlTW~5xk)j9Oa$x@yZ~>K=VZ3pzqPy;VXfHr}#nmw0_W> zUxMF-gTdShS@ja01RvTB_V5Pyz-(}VkKz`cbCBB$2a^uUb75rHb@&JgW2P#=0u*(kFQ<^6K|L z^xOq+s|VMOuwH9#r3d5myYTjT@W4p7A9w4WJQ?@sgi+?3E~rcC0w|ubk3ukNYu(>c*gSLgERtvhf-c&QvL zgLMU+7ejOlu8yI4 z9Djge`eUAl;d(!B$A>!CMC&_7=qg+uBXvuD1Ecgn?uya+3h%-gU0{-R4P*7wTnXcJ zYkmvk^%x$433@%R#6*3Jf5Iev<7AIrOx6$ZeVC%_aV<>MJ-8#L>A5@w)AcUiiW&NE z{sS|0o+%zfn57@$;+U;p;i{OU-{Y2;t4DAW=INz81M~GR-iVL%X+Dev`nstRH_Ucl z7vfx4qgC)K+jQZXp5OF#-9SHu9r`HG!58|LS+*_s zQg7xq_)6!SZQGBpbvZ7Dow^o3ja|AKH^y!~hI?R-UdD5 z-3t43#(9l3^eKj=*JZHx4ex{$sNKk54XEDq|9+yaO6 zEFO--`cqzsBYHo7jidS;AIH!7`j5;9{GtnRZv3hr<@<3=*WqXJn;y;Gaa@1GvvESd zyuj~kIH`woGyJZ1@HCv#r}%rE)^{)T+=V~%GyDL~=#E?uXZ39Ehd=dRUWLE(dHxya zbgo4n`#7(kJcjgwjsF(9}{H?#|&A6l!7Q4Orvc5}a#XovFzlDFp)AM#*(bq0< zdL40uBG}6H4TaS2`-C3x8x?cMvvp6$e=gyYGl;M z`4BScEXz#8wYm%!LuTE8U%+*`7k9$-dOlCX4SEl6$Bp_jpT$i&?{e!EvgoQ@0a^7s z{045;BY7aQ=}&kWZqfVrOWdmexIquY_`3UmpOe-xD+@mOuYQ4_!hO0GzmB4MAa_GCJ)0+> zxX!=Yda6t43c55(>bhJVrS!Yp6s7er?v4BP0-lNo^cG%+2lc%lTaQpiSLSkfNPo)1 z;5f=bu*Ty)9Mie=Ehw+c^Zj^4ujT%DROei4ozai!lDaS|>R#Lem2~1KwokgU?yno; zaXp>Kp^9F|%kYHW$6w(|y=|S>XsD_eed_lhJf(N=dQ{U1>unG8(>j;V3J2;8+VOKC zdKu4wgPR9m@+Q>M*M4R_!SgyF=fsP;8ka?FJ!7NikPY5f(akrR4|qxU;!b#3FX9QP zr?>HX)Ypf3KN{#?HhW!zhPvzL?jK&!b9giw=?%OZuj&K58;$jMTWkmLnr^w(GQ{h8 zIQPXHdOlA>6TOMo;!Ry=oAn)U>B`$}W6)HOgYj!Sh@N zo%F!a_(0F(3FxfX@d|X&&G&k&psU`%qtQ+O#s|<{CwyZYuY2g6IxBkWG5jWa>BzU9 z+jW0^m(Gp>x-6H#AYF^AVX%IWn_-9^#z`2e=kinx(?#}qKGDNRCJqBlNet z9V7K0{3}N3Yrpdxg3&rJ=foIYj!R;^ZpE)+qE6y&n50+mR7}=i@#mPLvmD_4#`Hct z2-9?i?>)ci>H0Z+A7p%D~=IBg6xSg1*D{^Vf)AhLq=IeIc0w3uq zJQ54^$GjMe^!L0w{8^vplUSl}_|bD9mg>9t4lL6dezJYg%k@It8!Ply{uC?qVg3%Q z^+N|epWtKt99P8}J(-iRR;NGY^^5*Q@6r>nPS-eW+mH2nF!#h~dNxnOM!k=>VUs?~ z$FNynd&KiQw&;?a7hCmHToK!JBYp|n^?Te3U+8f>6kqD)JP%*#J-iuT>kE7mJM}9^ z-A?S%9l0fT>;1eCd&1NFZ24lZ&hm@P)8FW?bVq!v&+t#!r;GmTxgFo>D?Azd^)tsj zx8Q(o|C{Gee6LF%H?Dus&+5wfQGd!G;-Egn`*28K;xjm`Z$9Dm3y$aqI3JGc>Rbgs z>o>U}e$idI1Af(`c?gc_MLZk7>8-pT$Ms?U4kz?wK8uq&+expL@VmZ`^W&6$lFQ?? zZp5|mhkl=1;f$Wm6LD7mz&r4#F8#aLS@=u$H{)7ehKnP!uFg;5I^B#L;(9%td*TK?kEh{Ay^+`8CjC9{K^A?UPa>fC?0f4E&&;QNqE*Wv2O zty}Y(xI_2n?zmIW;Bm;KH}G=Yr4RCMh61`RH^bd}Aos*Q zdL~amLA{MvppZVw`%zf`%YUJWzU8d>jeGTdTmbj!DqJ2#bpw6@#dLdq8^!ey?t>C~ z4o^l&y@6Mwl>U)-qqM%rr*OZ{@~3%-2Xs-s3lHjN_z{%RBe@kG(ua5r9@dxn49e=; z|FRyToW7rnpuGMMKaNVe1;38UdL;M4S4UMni$~xo zy`ER%X`SVK#ER~9nl8+D;aUA2H$inhjFaFy$%46;JU{#$iPY48>RqU%%lu;-aM`@p z4fKXToCniEv}0CdKwQ!1HF?s;1zw>6^|!0(hqY9 zG}cMn9UV;|d&L#ei5skc~ zi$L>USwAOEM1GLdy`CYWtqj?D0>F}5db`grS*YmPVGy6W)b?coRGyX%`0?Bs=>x*`7uy>thD2YvLH zyaIjoaSnGO>!%-1AB_}5e_fNG!ayBG0#aOTwS^b&1i)B|TIZ(77;Nx8+yy zq4o_hk)9Z-KjIk}r4R5|7_HCq35?Y@20n6yak>!SiSfD;KZJ?8F4x2){Vq4fWIc>~ zW2&AT8q@S~{sA*|?rVH6C1&c!_&&_m4f#3D(LK05=ITj29P{-`UWkwMKK>dD^dEc- z3w6c}_LRUPoriN^u`a{Ku~OIO>R6@U;U-wE`*0U*&~tbaHtKEs88+#Q{5v-5Vi}{6 z{PzO4&Up4`8WKab7!`U@RKgX_u+_s zjjQ9RUd7Y#v-YLzk*)YuJIGJuERN}H*F__laa`Za`Ef!&$>nfTH|E+nrQhc^IITx< zfBd1B@+_RyJ9s1h)PL|%{G~HqZ@J@~F2*@OeH^VJ@F!#c(dKOPYc70bCj|H7W57aN=w(vAO0Xg+&yb`zT z!@LW*^kqJa+&Xtw*N;2&gM1(E)HV4D%VmY z{d_jt8$aKzTj$!*=zZ|Zt@RFC5RsGt||EIg(&=kYvn zXEah#uhPv>N$=vVsH`vZaXhZO-W83!fGWCEK99w`=ACYz-+aQ8`qcuKHLB|EJQGjp z=kD>?x;q;2b&m1H1*#=rM&n*W+1Tw6J-rtLxdiC!W)Fidbh+L-*m1sHs=* z9Msas`8zzXbKmQ6gBNsdeiSe2Vf-Fy>#e*Db#%u2Y`64F`bAv?b@e!Y4=?MFc^>NN z{k$FZ^}l=^4RoHOwy|iat8sC>qT6v@G}7~V6kgT8^Vevs%NO%F#%sDaH^l3DGLOU? zdNZ#=6Mclg!JE2OarYZDTyKG}m3YEn4U;yclomJ4@Pb;T_$M zUq(y)1usD>oxhZA6yfBjThmyZGZ z<#N_%4Akwo83yTN<;@Qa*0~=spD{$AA<0-El^denC7sO&chI?U&KFWKr zRJX5Y{l_vrnEPP4Ud@ZJLhs^jSgCV8ZF{I!=_a}gR_jd9c#Wn%*7ow>U85F7Q~oC}-u6Z{}H>lxe| zpX+mc09*8w=WJ`SRj=bE*rvbdud!WU;NP)BkEvlhhA;FsUW+gF&wK!1>4chI)9J5u zU0nt{^-|Okz z5kKf}cq@L=IbZbLfrI)%E`me)Ev}2hx+izU5j}}V;HdtZH{fS|f)C*reNAnzJ@qkt zm(GsgbU7}GW~xTs%lXnTvl^{20RU4~1# zVk56Haaq^nn)pXg<39LTf5yvjMIYqdh&bZH6+VNguJEeu57Ozk`Bfz72|O5y`cqzk zKp)_pxJF;(lgOa6Huk)OjQU>A7yhj0b9-E?o4w}sDKhK6+zHp|={yG4>-D@GH|U>u z7jD$)UpGJWP5Mrq4Ow&zu7a$(2Y0~D`Y^9WHl6hiw*|N8$N3@LsvGeO$gbz{c;wJy zn|O_e5_&B!MM+)mP1|;q(xdnTl-B2XKknDH-txG{19};c2!GbMH??ea8QoLY!$bNQ ze~yQB(`L4rD67x&dX&>0n!ArEuWxVRF{B^SeRWejsx!WAeb*KA2f8*M(`WfhRMc7D z@%s}h>C&7JmG##=6_4u|TY4RZD*6I%#uIu-E3c36q%PLlx`V2^CRe~y`dw~}YWi2+ zgr{|#Hs%eU(Ve&z{-a0oKvdU@cou5uZ+RP@*Jt<`UeKA_S~uYU2|)qQh1&X2egJiJ z9j=a-bZdSKb@c%5ftU46o`8CKJ+DN4eSmkNfj-A4(NJe;XMM*j`aaH!M*2y91h48> zxei{_A8;GIu1E7AyrGx!95m5i@g}^fkMlvirGs}prgc-DN8gHOx-6GKbNvE8jTX8k zzk#=Pf9{5N^jsc~mU=ULy$t?R9tV z5TYmWaJ;8i@d9+zdw3h(*QfbsbkdnSSby+=zMFHQv#!VwqKmG_HPKbK=N9OuhjCwY z*B|jT^w3**9eV1cydS-ExC7=n-CO6>H=&QdpNpWcuFh4Eq?__9=%;(}`{=JH^GFQP zYj`mR>I3`*2I=#B5`%S?j<$;!qVMIr7^%{jxC+IQyPJIi;>atuMzJmCaRE%%PjLmz(64b_%+y`D9cJmVJOs1#a-N4ddMAI5x%wm@ z#yp+n1J6I0uZwbCe59Y`N3lRR;yPHU-{;m?q(|@oEY=HoCYI=JydF#SQ9giW`U;=J za-E~I=O3)lCAkn*>SwqTR_P{OAFFkD?tqW=L>`VcdJQkcTKye=flu_Gd>rfa^<6yQ z;!}MO-+}e|F)oA8bX~524Z1Bi!$v)bdtsBF&6BWMZ{XGVT>rp(uti_wQ`o9+?&|pw z+jLRRkL|iDKZ+f?F~5W_bXRVRFZBc-im&uaUVyLlF5Zfr`XnF0E`3cmuTAuBokwTK z9{n(vz+PR8tKl2nf?vb8x(|28K0Sp;<2${Umteo%$6w-r{*!;h_xgtJ<}H5Eh4@bV zs4Mfs_(?b5=W$TK$M4{f9>M)^Sg+&-IHLFRR{X3_^DiN~U=NQ${HiPRLpY{i=9>6T zf52^VT>r?Q;)KrJ(`zxD)X(#y_+2;bZGG%zndz7N>OLNa`h;GEKXie9=3kQ6nfeL+ z2+rw-{30&uF5Dh}>rp%ym-IrOh0A&ie~K&mH$Dhk(jcL~^XaI*U1vo)U7Cv^gRaF- zBa?2naFagB`;b##=09+|&NjenM>aemyPt8jVb(GBZRFQOxDN{GIXoG6>kYgb_vr6=Hwx)W zv>wPk@PJ;$AK@W=gmbLoIbklvf zGrH@kJPJMZT3&*l`Un03z4Uqh9liC9A9~%0KDsd9iN3lrKaBo*J9ov0`gcBpQ99!Y zk3a25Nx?n(HaLh-P?5{PL3M(9ToaS@8J>t)`ni$TRV>nXj`EzNSLru(aje&K_&t2B zckl-6)&)oVeN=nIN8Uy{X$Cc*e zJgzi9FXjULj4QvJ5Ai+R)r}~~H@gvqcm@~d2i=$=yo>MUSKX-l_-`)Cz1_HCoXd?X z&L49Le#VU~$v<-`?%>9j=9}(}gr8xK%-{#Oj2rzRZ{{-mk{kaJ|IQC{Z+D_B=W-{? z@q8}N#od`lcpE>;4c(~lc@OS_Yg^G2@1wcOb!_yj-6AGp(1 z`6hSzDW1gDxVSt2G_U7pxQ3bVA3nm*a$7T_I$vXEJjX-12In_ZYVvZf#ZQ_!&+~qM zft#60FLF4OYSVPC!xhb}m-ryp<*sJh%beRxtH*1(KDRdW8t?;VUPC_3ukb80u@S#w zCces<%*4jLh+pICX6EaBn&03-W@-~IZl=D;+xabi_t8kCDd#YAoADxU&d-_2E%-FQ z%>&Hrcesd|-IC{VD}KmKZ_PWn4L3IP+wvK1#}h1sce#j#(4JRv2Y$lBc#n^8M}FTz zd7p2!P&)A({(vi6IGy=N?!qlCq^^9uh189wa(8~v!s@|0xF`dcK!$;9`6um*kuHe$K*WI4hUsoB0vW#*gtWT$yj>CpbGl z#X0yHzKyGMPOizf^9!7d>u_#JJp3Bp#Z5RbH|2cXg7b4rF2HU0Zhn{V z;rF;8cj7|ag$r|cF2cR|Uhd2Haepq#gSZ$EWe=^$hg^b3aY-J_rFa5+2t_9I{XC65 zbRsj^LnktaJ!B&D*+V9>kUeA~OV~ptvYb6cBCFU#B(jD*G$QNxQT~i8@FsqYx3Gso zWII>lFWIUe*~wP<$R4)JN4{mNdSpLa#UnqkRXlQ#t=f?zY?Y4u!dB_XZ){bLoMfwT zFeo-8sir*~mqO#ci~>#m6Ny|59IDVlzZ?9?#W}g7f;~c eJcax44DQQwIEg>ve!Q6b^Ku@*t9c-Q!v7C3F5mS4 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll.mdb.meta b/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll.mdb.meta new file mode 100644 index 0000000..f92a6ff --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll.mdb.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5651992cdad94894a3af7dc3f1da086f +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll.meta b/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll.meta new file mode 100644 index 0000000..61f7b8c --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll.meta @@ -0,0 +1,80 @@ +fileFormatVersion: 2 +guid: 5651992cdad94894a3af7dc3f1da9170 +timeCreated: 1488828285 +licenseType: Store +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + Any: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude N3DS: 0 + Exclude OSXIntel: 1 + Exclude OSXIntel64: 1 + Exclude OSXUniversal: 1 + Exclude PS4: 0 + Exclude PSM: 0 + Exclude PSP2: 0 + Exclude SamsungTV: 0 + Exclude Tizen: 0 + Exclude WebGL: 0 + Exclude WiiU: 0 + Exclude Win: 1 + Exclude Win64: 1 + Exclude WindowsStoreApps: 0 + Exclude XboxOne: 0 + Exclude iOS: 0 + Exclude tvOS: 0 + Editor: + enabled: 0 + settings: + DefaultValueInitialized: true + N3DS: + enabled: 1 + settings: {} + PS4: + enabled: 1 + settings: {} + PSM: + enabled: 1 + settings: {} + PSP2: + enabled: 1 + settings: {} + SamsungTV: + enabled: 1 + settings: {} + Tizen: + enabled: 1 + settings: {} + WebGL: + enabled: 1 + settings: {} + WiiU: + enabled: 1 + settings: {} + WindowsStoreApps: + enabled: 1 + settings: + CPU: AnyCPU + XboxOne: + enabled: 1 + settings: {} + iOS: + enabled: 1 + settings: {} + tvOS: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll b/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll new file mode 100644 index 0000000000000000000000000000000000000000..86442ef00df078cf2a97f3319eadd8b8936733ba GIT binary patch literal 144896 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 OzLvuOzs%ot3j7}}6P@}1 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll.mdb b/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll.mdb new file mode 100644 index 0000000000000000000000000000000000000000..7c3bae3ae5433639c68437785d33e84f757ea2df GIT binary patch literal 46903 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 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll.mdb.meta b/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll.mdb.meta new file mode 100644 index 0000000..302cd3d --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll.mdb.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5978f8f3dd274e848fbb7a123bde086f +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll.meta b/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll.meta new file mode 100644 index 0000000..b0b64dc --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll.meta @@ -0,0 +1,80 @@ +fileFormatVersion: 2 +guid: 5978f8f3dd274e848fbb7a123bde1fb9 +timeCreated: 1488828285 +licenseType: Store +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + Any: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude N3DS: 0 + Exclude OSXIntel: 1 + Exclude OSXIntel64: 1 + Exclude OSXUniversal: 1 + Exclude PS4: 0 + Exclude PSM: 0 + Exclude PSP2: 0 + Exclude SamsungTV: 0 + Exclude Tizen: 0 + Exclude WebGL: 0 + Exclude WiiU: 0 + Exclude Win: 1 + Exclude Win64: 1 + Exclude WindowsStoreApps: 0 + Exclude XboxOne: 0 + Exclude iOS: 0 + Exclude tvOS: 0 + Editor: + enabled: 0 + settings: + DefaultValueInitialized: true + N3DS: + enabled: 1 + settings: {} + PS4: + enabled: 1 + settings: {} + PSM: + enabled: 1 + settings: {} + PSP2: + enabled: 1 + settings: {} + SamsungTV: + enabled: 1 + settings: {} + Tizen: + enabled: 1 + settings: {} + WebGL: + enabled: 1 + settings: {} + WiiU: + enabled: 1 + settings: {} + WindowsStoreApps: + enabled: 1 + settings: + CPU: AnyCPU + XboxOne: + enabled: 1 + settings: {} + iOS: + enabled: 1 + settings: {} + tvOS: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor.meta b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor.meta new file mode 100644 index 0000000..2dcc2d2 --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c6a4f09709a7f854eb914fa0dbd70c80 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll new file mode 100644 index 0000000000000000000000000000000000000000..435d9be6657316e637cdaf363de3e0a4d2ed75d4 GIT binary patch literal 314880 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 + AssetLists is used on lists and arrays and single elements of unity types, and replaces the default list drawer with a list of all possible assets with the specified filter. + Use this to both filter and include or exclude assets from a list or an array, without navigating the project window. + + + Asset lists works on all asset types such as materials, scriptable objects, prefabs, custom components, audio, textures etc, and does also show inherited types. + + + The following example will display an asset list of all prefabs located in the project window. + + public class AssetListExamples : MonoBehaviour + { + [InfoBox("The AssetList attribute work on both lists of UnityEngine.Object types and UnityEngine.Object types, but have different behaviour.")] + [AssetList] + [InlineEditor(InlineEditorModes.LargePreview)] + public GameObject Prefab; + + [AssetList] + public List<PlaceableObject> PlaceableObjects; + + [AssetList(Path = "Plugins/Sirenix/")] + [InlineEditor(InlineEditorModes.LargePreview)] + public UnityEngine.Object Object; + + [AssetList(AutoPopulate = true)] + public List<PlaceableObject> PlaceableObjectsAutoPopulated; + + [AssetList(LayerNames = "MyLayerName")] + public GameObject[] AllPrefabsWithLayerName; + + [AssetList(AssetNamePrefix = "Rock")] + public List<GameObject> PrefabsStartingWithRock; + + [AssetList(Path = "/Plugins/Sirenix/")] + public List<GameObject> AllPrefabsLocatedInFolder; + + [AssetList(Tags = "MyTagA, MyTabB", Path = "/Plugins/Sirenix/")] + public List<GameObject> GameObjectsWithTag; + + [AssetList(Path = "/Plugins/Sirenix/")] + public List<Material> AllMaterialsInSirenix; + + [AssetList(Path = "/Plugins/Sirenix/")] + public List<ScriptableObject> AllScriptableObjects; + + [InfoBox("Use a method as a custom filter for the asset list.")] + [AssetList(CustomFilterMethod = "HasRigidbodyComponent")] + public List<GameObject> MyRigidbodyPrefabs; + + private bool HasRigidbodyComponent(GameObject obj) + { + return obj.GetComponent<Rigidbody>() != null; + } + } + + + + + + If true, all assets found and displayed by the asset list, will automatically be added to the list when inspected. + + + + + Comma separated list of tags to filter the asset list. + + + + + Filter the asset list to only include assets with a specified layer. + + + + + Filter the asset list to only include assets which name begins with. + + + + + Filter the asset list to only include assets which is located at the specified path. + + + + + Filter the asset list to only include assets for which the given filter method returns true. + + + + + Initializes a new instance of the class. + + + + + The AssetSelector attribute can be used on all Unity types and will prepend a small button next to the object field that when clicked, + will present the user with a dropdown of assets to select from which can be customized from the attribute. + + + + + True by default. + + + + + True by default. If the ValueDropdown attribute is applied to a list, then disabling this, + will render all child elements normally without using the ValueDropdown. The ValueDropdown will + still show up when you click the add button on the list drawer, unless is true. + + + + + False by default. + + + + + If the ValueDropdown attribute is applied to a list, and is set to true, then enabling this, + will exclude existing values, instead of rendering a checkbox indicating whether the item is already included or not. + + + + + If the dropdown renders a tree-view, then setting this to true will ensure everything is expanded by default. + + + + + By default, the dropdown will create a tree view. + + + + + Gets or sets the width of the dropdown. Default is zero. + + + + + Gets or sets the height of the dropdown. Default is zero. + + + + + Gets or sets the title for the dropdown. Null by default. + + + + + Specify which folders to search in. Specifying no folders will make it search in your entire project. + Use the property for a more clean way of populating this array through attributes. + + + + + The filters we should use when calling AssetDatabase.FindAssets. + + + + + + Specify which folders to search in. Specifying no folders will make it search in your entire project. + You can decalir multiple paths using '|' as the seperator. + Example: [AssetList(Paths = "Assets/Textures|Assets/Other/Textures")] + + + This property is simply a more clean way of populating the array. + + + + + + AssetsOnly is used on object properties, and restricts the property to project assets, and not scene objects. + Use this when you want to ensure an object is from the project, and not from the scene. + + + The following example shows a component with a game object property, that must be a prefab from the project, and not a scene object. + + public MyComponent : MonoBehaviour + { + [AssetsOnly] + public GameObject MyPrefab; + } + + + + + + + BoxGroup is used on any property and organizes the property in a boxed group. + Use this to cleanly organize relevant values together in the inspector. + + + The following example shows how BoxGroup is used to organize properties together into a box. + + public class BoxGroupExamples : MonoBehaviour + { + // Box with a centered title. + [BoxGroup("Centered Title", centerLabel: true)] + public int A; + + [BoxGroup("Centered Title", centerLabel: true)] + public int B; + + [BoxGroup("Centered Title", centerLabel: true)] + public int C; + + // Box with a title. + [BoxGroup("Left Oriented Title")] + public int D; + + [BoxGroup("Left Oriented Title")] + public int E; + + // Box with a title recieved from a field. + [BoxGroup("$DynamicTitle1"), LabelText("Dynamic Title")] + public string DynamicTitle1 = "Dynamic box title"; + + [BoxGroup("$DynamicTitle1")] + public int F; + + // Box with a title recieved from a property. + [BoxGroup("$DynamicTitle2")] + public int G; + + [BoxGroup("$DynamicTitle2")] + public int H; + + // Box without a title. + [InfoBox("You can also hide the label of a box group.")] + [BoxGroup("NoTitle", false)] + public int I; + + [BoxGroup("NoTitle")] + public int J; + + [BoxGroup("NoTitle")] + public int K; + + #if UNITY_EDITOR + public string DynamicTitle2 + { + get { return UnityEditor.PlayerSettings.productName; } + } + #endif + + [BoxGroup("Boxed Struct"), HideLabel] + public SomeStruct BoxedStruct; + + public SomeStruct DefaultStruct; + + [Serializable] + public struct SomeStruct + { + public int One; + public int Two; + public int Three; + } + } + + + + + + + + + + + If true a label for the group will be drawn on top. + + + + + If true the header label will be places in the center of the group header. Otherwise it will be in left side. + + + + + If non-null, this is used instead of the group's name as the title label. + + + + + Adds the property to the specified box group. + + The box group. + If true a label will be drawn for the group. + If set to true the header label will be centered. + The order of the group in the inspector. + + + + Initializes a new instance of the class. Use the other constructor overloads in order to show a header-label on the box group. + + + + + Combines the box group with another group. + + The other group. + + + + Buttons are used on functions, and allows for clickable buttons in the inspector. + + + The following example shows a component that has an initialize method, that can be called from the inspector. + + public class MyComponent : MonoBehaviour + { + [Button] + private void Init() + { + // ... + } + } + + + + The following example show how a Button could be used to test a function. + + public class MyBot : MonoBehaviour + { + [Button] + private void Jump() + { + // ... + } + } + + + + The following example show how a Button can named differently than the function it's been attached to. + + public class MyComponent : MonoBehaviour + { + [Button("Function")] + private void MyFunction() + { + // ... + } + } + + + + + + + + Gets the height of the button. If it's zero or below then use default. + + + + + Use this to override the label on the button. + + + + + The style in which to draw the button. + + + + + If the button contains parameters, you can disable the foldout it creates by setting this to true. + + + + + Whether to display the button method's parameters (if any) as values in the inspector. True by default. + If this is set to false, the button method will instead be invoked through an ActionResolver or ValueResolver (based on whether it returns a value), giving access to contextual named parameter values like "InspectorProperty property" that can be passed to the button method. + + + + + Whether the containing object or scene (if there is one) should be marked dirty when the button is clicked. True by default. + + + + + If the button has a return type, set this to false to not draw the result. Default value is true. + + + + + Creates a button in the inspector named after the method. + + + + + Creates a button in the inspector named after the method. + + The size of the button. + + + + Creates a button in the inspector named after the method. + + The size of the button. + + + + Creates a button in the inspector with a custom name. + + Custom name for the button. + + + + Creates a button in the inspector with a custom name. + + Custom name for the button. + Size of the button. + + + + Creates a button in the inspector with a custom name. + + Custom name for the button. + Size of the button in pixels. + + + + Creates a button in the inspector named after the method. + + Button style for methods with parameters. + + + + Creates a button in the inspector named after the method. + + The size of the button. + Button style for methods with parameters. + + + + Creates a button in the inspector named after the method. + + The size of the button. + Button style for methods with parameters. + + + + Creates a button in the inspector with a custom name. + + Custom name for the button. + Button style for methods with parameters. + + + + Creates a button in the inspector with a custom name. + + Custom name for the button. + Size of the button. + Button style for methods with parameters. + + + + Creates a button in the inspector with a custom name. + + Custom name for the button. + Size of the button in pixels. + Button style for methods with parameters. + + + + ButtonGroup is used on any instance function, and adds buttons to the inspector organized into horizontal groups. + Use this to organize multiple button in a tidy horizontal group. + + + The following example shows how ButtonGroup is used to organize two buttons into one group. + + public class MyComponent : MonoBehaviour + { + [ButtonGroup("MyGroup")] + private void A() + { + // .. + } + + [ButtonGroup("MyGroup")] + private void B() + { + // .. + } + } + + + + The following example shows how ButtonGroup can be used to create multiple groups of buttons. + + public class MyComponent : MonoBehaviour + { + [ButtonGroup("First")] + private void A() + { } + + [ButtonGroup("First")] + private void B() + { } + + [ButtonGroup("")] + private void One() + { } + + [ButtonGroup("")] + private void Two() + { } + + [ButtonGroup("")] + private void Three() + { } + } + + + + + + + + + + + + + Organizes the button into the specified button group. + + The group to organize the button into. + The order of the group in the inspector.. + + + + Button style for methods with parameters. + + + + + Draws a foldout box around the parameters of the method with the button on the box header itself. + This is the default style of a method with parameters. + + + + + Draws a button with a foldout to expose the parameters of the method. + + + + + Draws a foldout box around the parameters of the method with the button at the bottom of the box. + + + + + The ChildGameObjectsOnly attribute can be used on Components and GameObject fields and will prepend a small button next to the object-field that + will search through all child gameobjects for assignable objects and present them in a dropdown for the user to choose from. + + + + + + Instead of making a new attribute, and a new drawer, for a one-time thing, you can with this attribute, make a method that acts as a custom property drawer. + These drawers will out of the box have support for undo/redo and multi-selection. + + + Usage: + + public class CustomDrawerExamples : MonoBehaviour + { + public float From = 2, To = 7; + + [CustomValueDrawer("MyStaticCustomDrawerStatic")] + public float CustomDrawerStatic; + + [CustomValueDrawer("MyStaticCustomDrawerInstance")] + public float CustomDrawerInstance; + + [CustomValueDrawer("MyStaticCustomDrawerArray")] + public float[] CustomDrawerArray; + + #if UNITY_EDITOR + + private static float MyStaticCustomDrawerStatic(float value, GUIContent label) + { + return EditorGUILayout.Slider(value, 0f, 10f); + } + + private float MyStaticCustomDrawerInstance(float value, GUIContent label) + { + return EditorGUILayout.Slider(value, this.From, this.To); + } + + private float MyStaticCustomDrawerArray(float value, GUIContent label) + { + return EditorGUILayout.Slider(value, this.From, this.To); + } + + #endif + } + + + + + + Name of the custom drawer method. Obsolete; use the Action member instead. + + + + + A resolved string that defines the custom drawer action to take, such as an expression or method invocation. + + + + + Instead of making a new attribute, and a new drawer, for a one-time thing, you can with this attribute, make a method that acts as a custom property drawer. + These drawers will out of the box have support for undo/redo and multi-selection. + + A resolved string that defines the custom drawer action to take, such as an expression or method invocation. + + + + Disables a property if it is drawn within an . + + + + + Disables a property if it is drawn from a non-prefab asset or instance. + + + + + Disables a property if it is drawn from a prefab asset. + + + + + Disables a property if it is drawn from a prefab instance. + + + + + Disables a property if it is drawn from a prefab asset or a prefab instance. + + + + + Indicates that the member should not be drawn as a value reference, if it becomes a reference to another value in the tree. Beware, and use with care! This may lead to infinite draw loops! + + + + + Tells the validation system that this member should not be validated. It will not show validation messages in the inspector, and it will not be scanned by the project validator. + + + + + An attribute that enables GUI. + + + + public class InlineEditorExamples : MonoBehaviour + { + [EnableGUI] + public string SomeReadonlyProperty { get { return "My GUI is usually disabled." } } + } + + + + + + + Draws an enum selector in the inspector with next and previous buttons to let you cycle through the available values for the enum property. + + + + public enum MyEnum + { + One, + Two, + Three, + } + + public class MyMonoBehaviour : MonoBehaviour + { + [EnumPaging] + public MyEnum Value; + } + + + + + + + FilePath is used on string properties, and provides an interface for file paths. + + + The following example demonstrates how FilePath is used. + + public class FilePathExamples : MonoBehaviour + { + // By default, FilePath provides a path relative to the Unity project. + [FilePath] + public string UnityProjectPath; + + // It is possible to provide custom parent path. Parent paths can be relative to the Unity project, or absolute. + [FilePath(ParentFolder = "Assets/Plugins/Sirenix")] + public string RelativeToParentPath; + + // Using parent path, FilePath can also provide a path relative to a resources folder. + [FilePath(ParentFolder = "Assets/Resources")] + public string ResourcePath; + + // Provide a comma seperated list of allowed extensions. Dots are optional. + [FilePath(Extensions = "cs")] + public string ScriptFiles; + + // By setting AbsolutePath to true, the FilePath will provide an absolute path instead. + [FilePath(AbsolutePath = true)] + [BoxGroup("Conditions")] + public string AbsolutePath; + + // FilePath can also be configured to show an error, if the provided path is invalid. + [FilePath(RequireValidPath = true)] + public string ValidPath; + + // By default, FilePath will enforce the use of forward slashes. It can also be configured to use backslashes instead. + [FilePath(UseBackslashes = true)] + public string Backslashes; + + // FilePath also supports member references with the $ symbol. + [FilePath(ParentFolder = "$DynamicParent", Extensions = "$DynamicExtensions")] + public string DynamicFilePath; + + public string DynamicParent = "Assets/Plugin/Sirenix"; + + public string DynamicExtensions = "cs, unity, jpg"; + } + + + + + + + + If true the FilePath will provide an absolute path, instead of a relative one. + + + + + Comma separated list of allowed file extensions. Dots are optional. + Supports member referencing with $. + + + + + ParentFolder provides an override for where the path is relative to. ParentFolder can be relative to the Unity project, or an absolute path. + Supports member referencing with $. + + + + + If true an error will be displayed for invalid, or missing paths. + + + + + If true an error will be displayed for non-existing paths. + + + + + By default FilePath enforces forward slashes. Set UseBackslashes to true if you want backslashes instead. + + + + + Gets or sets a value indicating whether the path should be read only. + + + + + FolderPath is used on string properties, and provides an interface for directory paths. + + + The following example demonstrates how FolderPath is used. + + public class FolderPathExamples : MonoBehaviour + { + // By default, FolderPath provides a path relative to the Unity project. + [FolderPath] + public string UnityProjectPath; + + // It is possible to provide custom parent patn. ParentFolder paths can be relative to the Unity project, or absolute. + [FolderPath(ParentFolder = "Assets/Plugins/Sirenix")] + public string RelativeToParentPath; + + // Using ParentFolder, FolderPath can also provide a path relative to a resources folder. + [FolderPath(ParentFolder = "Assets/Resources")] + public string ResourcePath; + + // By setting AbsolutePath to true, the FolderPath will provide an absolute path instead. + [FolderPath(AbsolutePath = true)] + public string AbsolutePath; + + // FolderPath can also be configured to show an error, if the provided path is invalid. + [FolderPath(RequireValidPath = true)] + public string ValidPath; + + // By default, FolderPath will enforce the use of forward slashes. It can also be configured to use backslashes instead. + [FolderPath(UseBackslashes = true)] + public string Backslashes; + + // FolderPath also supports member references with the $ symbol. + [FolderPath(ParentFolder = "$DynamicParent")] + public string DynamicFolderPath; + + public string DynamicParent = "Assets/Plugins/Sirenix"; + } + + + + + + + + If true the FolderPath will provide an absolute path, instead of a relative one. + + + + + ParentFolder provides an override for where the path is relative to. ParentFolder can be relative to the Unity project, or an absolute path. + Supports member referencing with $. + + + + + If true an error will be displayed for invalid, or missing paths. + + + + + If true an error will be displayed for non-existing paths. + + + + + By default FolderPath enforces forward slashes. Set UseBackslashes to true if you want backslashes instead. + + + + + Indicates that Odin should hide the reference box, if this property would otherwise be drawn as a reference to another property, due to duplicate reference values being encountered. + Note that if the value is referencing itself recursively, then the reference box will be drawn regardless of this attribute in all recursive draw calls. + + + + +

HideIfGroup allows for showing or hiding a group of properties based on a condition.

+

The attribute is a group attribute and can therefore be combined with other group attributes, and even be used to show or hide entire groups.

+

Note that in the vast majority of cases where you simply want to be able to control the visibility of a single group, it is better to use the VisibleIf parameter that *all* group attributes have.

+
+ + + + + +
+ + + Whether or not to visually animate group visibility changes. + + + + + The optional member value. + + + + + Name of member to use when to hide the group. Defaults to the name of the group, by can be overriden by setting this property. + + + + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + + + + + Makes a group that can be shown or hidden based on a condition. + + The group path. + If true then a fade animation will be played when the group is hidden or shown. + + + + Makes a group that can be shown or hidden based on a condition. + + The group path. + The value the member should equal for the property to shown. + If true then a fade animation will be played when the group is hidden or shown. + + + + Combines HideIfGroup attributes. + + Another ShowIfGroup attribute. + + + + Hides a property if it is drawn within an . + + + + + Hides a property if it is drawn from a non prefab instance or asset. + + + + + Hides a property if it is drawn from a prefab asset. + + + + + Hides a property if it is drawn from a prefab instance. + + + + + Hides a property if it is drawn from a prefab instance or a prefab asset. + + + + + The HideInTables attribute is used to prevent members from showing up as columns in tables drawn using the . + + + + + Apply HideNetworkBehaviourFields to your class to prevent the special "Network Channel" and "Network Send Interval" properties from being shown in the inspector for a NetworkBehaviour. + This attribute has no effect on classes that are not derived from NetworkBehaviour. + + + The following example shows how to use this attribute. + + [HideNetworkBehaviourFields] + public class MyComponent : NetworkBehaviour + { + // The "Network Channel" and "Network Send Interval" properties will not be shown for this component in the inspector + } + + + + + + + The Inline Property is used to place the contents of a type next to the label, instead of being rendered in a foldout. + + + + public class InlinePropertyExamples : MonoBehaviour + { + public Vector3 Vector3; + + public Vector3Int Vector3Int; + + [InlineProperty(LabelWidth = 12)] // It can be placed on classes as well as members + public Vector2Int Vector2Int; + + } + + [Serializable] + [InlineProperty(LabelWidth = 12)] // It can be placed on classes as well as members + public struct Vector3Int + { + [HorizontalGroup] + public int X; + + [HorizontalGroup] + public int Y; + + [HorizontalGroup] + public int Z; + } + + [Serializable] + public struct Vector2Int + { + [HorizontalGroup] + public int X; + + [HorizontalGroup] + public int Y; + } + + + + + + + Specify a label width for all child properties. + + + + + LabelWidth is used to change the width of labels for properties. + + + The following example shows how LabelText is applied to a few property fields. + + public MyComponent : MonoBehaviour + { + [LabelWidth("3")] + public int MyInt3; + } + + + + + + + The new text of the label. + + + + + Give a property a custom label. + + The width of the label. + + + + + OnCollectionChanged can be put on collections, and provides an event callback when the collection is about to be changed through the inspector, + and when the collection has been changed through the inspector. Additionally, it provides a CollectionChangeInfo struct containing information + about the exact changes made to the collection. This attribute works for all collections with a collection resolver, amongst them arrays, lists, + dictionaries, hashsets, stacks and linked lists. + + + + Note that this attribute only works in the editor! Collections changed by script will not trigger change events! + + + The following example shows how OnCollectionChanged can be used to get callbacks when a collection is being changed. + + [OnCollectionChanged("Before", "After")] + public List<string> list; + + public void Before(CollectionChangeInfo info) + { + if (info.ChangeType == CollectionChangeType.Add || info.ChangeType == CollectionChangeType.Insert) + { + Debug.Log("Adding to the list!"); + } + else if (info.ChangeType == CollectionChangeType.RemoveIndex || info.ChangeType == CollectionChangeType.RemoveValue) + { + Debug.Log("Removing from the list!"); + } + } + + public void After(CollectionChangeInfo info) + { + if (info.ChangeType == CollectionChangeType.Add || info.ChangeType == CollectionChangeType.Insert) + { + Debug.Log("Finished adding to the list!"); + } + else if (info.ChangeType == CollectionChangeType.RemoveIndex || info.ChangeType == CollectionChangeType.RemoveValue) + { + Debug.Log("Finished removing from the list!"); + } + } + + + + + + The OnInspectorDispose attribute takes in an action string as an argument (typically the name of a method to be invoked, or an expression to be executed), and executes that action when the property's drawers are disposed in the inspector. + Disposing will happen at least once, when the inspector changes selection or the property tree is collected by the garbage collector, but may also happen several times before that, most often when the type of a polymorphic property changes and it refreshes its drawer setup and recreates all its children, disposing of the old setup and children. + + + The following example demonstrates how OnInspectorDispose works. + + public class MyComponent : MonoBehaviour + { + [OnInspectorDispose(@"@UnityEngine.Debug.Log(""Dispose event invoked!"")")] + [ShowInInspector, InfoBox("When you change the type of this field, or set it to null, the former property setup is disposed. The property setup will also be disposed when you deselect this example."), DisplayAsString] + public BaseClass PolymorphicField; + + public abstract class BaseClass { public override string ToString() { return this.GetType().Name; } } + public class A : BaseClass { } + public class B : BaseClass { } + public class C : BaseClass { } + } + + + + + + This constructor should be used when the attribute is placed directly on a method. + + + + + This constructor should be used when the attribute is placed on a non-method member. + + + + + The OnInspectorInit attribute takes in an action string as an argument (typically the name of a method to be invoked, or an expression to be executed), and executes that action when the property's drawers are initialized in the inspector. + Initialization will happen at least once during the first drawn frame of any given property, but may also happen several times later, most often when the type of a polymorphic property changes and it refreshes its drawer setup and recreates all its children. + + + The following example demonstrates how OnInspectorInit works. + + public class MyComponent : MonoBehaviour + { + // Display current time for reference. + [ShowInInspector, DisplayAsString, PropertyOrder(-1)] + public string CurrentTime { get { GUIHelper.RequestRepaint(); return DateTime.Now.ToString(); } } + + // OnInspectorInit executes the first time this string is about to be drawn in the inspector. + // It will execute again when the example is reselected. + [OnInspectorInit("@TimeWhenExampleWasOpened = DateTime.Now.ToString()")] + public string TimeWhenExampleWasOpened; + + // OnInspectorInit will not execute before the property is actually "resolved" in the inspector. + // Remember, Odin's property system is lazily evaluated, and so a property does not actually exist + // and is not initialized before something is actually asking for it. + // + // Therefore, this OnInspectorInit attribute won't execute until the foldout is expanded. + [FoldoutGroup("Delayed Initialization", Expanded = false, HideWhenChildrenAreInvisible = false)] + [OnInspectorInit("@TimeFoldoutWasOpened = DateTime.Now.ToString()")] + public string TimeFoldoutWasOpened; + } + + + + + + This constructor should be used when the attribute is placed directly on a method. + + + + + This constructor should be used when the attribute is placed on a non-method member. + + + + + + OnStateUpdate provides an event callback when the property's state should be updated, when the StateUpdaters run on the property instance. + This generally happens at least once per frame, and the callback will be invoked even when the property is not visible. This can be used to + approximate custom StateUpdaters like [ShowIf] without needing to make entire attributes and StateUpdaters for one-off cases. + + + + The following example shows how OnStateUpdate can be used to control the visible state of a property. + + public class MyComponent : MonoBehaviour + { + [OnStateUpdate("@$property.State.Visible = ToggleMyInt")] + public int MyInt; + + public bool ToggleMyInt; + } + + + + The following example shows how OnStateUpdate can be used to control the expanded state of a list. + + public class MyComponent : MonoBehaviour + { + [OnStateUpdate("@$property.State.Expanded = ExpandList")] + public List<string> list; + + public bool ExpandList; + } + + The following example shows how OnStateUpdate can be used to control the state of another property. + + public class MyComponent : MonoBehaviour + { + public List>string< list; + + [OnStateUpdate("@#(list).State.Expanded = $value")] + public bool ExpandList; + } + + + + + + + Draws a square ObjectField which renders a preview for UnityEngine.Object types. + This object field also adds support for drag and drop, dragging an object to another square object field, swaps the values. + If you hold down control while letting go it will replace the value, And you can control + click the object field to quickly delete the value it holds. + + + These object fields can also be selectively enabled and customized globally from the Odin preferences window. + + + + The following example shows how PreviewField is applied to a few property fields. + + public MyComponent : MonoBehaviour + { + [PreviewField] + public UnityEngine.Object SomeObject; + + [PreviewField] + public Texture SomeTexture; + + [HorizontalGroup, HideLabel, PreviewField(30)] + public Material A, B, C, D, F; + } + + + + + + + The height of the object field + + + + + Left aligned. + + + + + Whether an alignment value is specified. + + + + + Draws a square object field which renders a preview for UnityEngine.Object type objects. + + + + + Draws a square object field which renders a preview for UnityEngine.Object type objects. + + The height of the preview field. + + + + Draws a square object field which renders a preview for UnityEngine.Object type objects. + + The height of the preview field. + The alignment of the preview field. + + + + Draws a square object field which renders a preview for UnityEngine.Object type objects. + + The alignment of the preview field. + + + + Draws a horizontal progress bar based on the value of the property. + Use it for displaying a meter to indicate how full an inventory is, or to make a visual indication of a health bar. + + + The following example shows how ProgressBar can be used. + + public class ProgressBarExample : MonoBehaviour + { + // Default progress bar. + [ProgressBar(0, 100)] + public int ProgressBar; + + // Health bar. + [ProgressBar(0, 100, ColorMember = "GetHealthBarColor")] + public float HealthBar = 50; + + private Color GetHealthBarColor(float value) + { + // Blends between red, and yellow color for when the health is below 30, + // and blends between yellow and green color for when the health is above 30. + return Color.Lerp(Color.Lerp( + Color.red, Color.yellow, MathUtilities.LinearStep(0f, 30f, value)), + Color.green, MathUtilities.LinearStep(0f, 100f, value)); + } + + // Stacked health bar. + // The ProgressBar attribute is placed on property, without a set method, so it can't be edited directly. + // So instead we have this Range attribute on a float to change the value. + [Range(0, 300)] + public float StackedHealth; + + [ProgressBar(0, 100, ColorMember = "GetStackedHealthColor", BackgroundColorMember = "GetStackHealthBackgroundColor")] + private float StackedHealthProgressBar + { + // Loops the stacked health value between 0, and 100. + get { return this.StackedHealth - 100 * (int)((this.StackedHealth - 1) / 100); } + } + + private Color GetStackedHealthColor() + { + return + this.StackedHealth > 200 ? Color.cyan : + this.StackedHealth > 100 ? Color.green : + Color.red; + } + + private Color GetStackHealthBackgroundColor() + { + return + this.StackedHealth > 200 ? Color.green : + this.StackedHealth > 100 ? Color.red : + new Color(0.16f, 0.16f, 0.16f, 1f); + } + + // Custom color and height. + [ProgressBar(-100, 100, r: 1, g: 1, b: 1, Height = 30)] + public short BigProgressBar = 50; + + // You can also reference members by name to dynamically assign the min and max progress bar values. + [ProgressBar("DynamicMin", "DynamicMax")] + public float DynamicProgressBar; + + public float DynamicMin, DynamicMax; + } + + + + + + + + + The minimum value. + + + + + The maximum value. + + + + + The name of a field, property or method to get the min values from. Obsolete; use the MinGetter member instead. + + + + + A resolved string that should evaluate to a float value, and will be used as the min bounds. + + + + + The name of a field, property or method to get the max values from. Obsolete; use the MaxGetter member instead. + + + + + A resolved string that should evaluate to a float value, and will be used as the max bounds. + + + + + The red channel of the color of the progress bar. + + + + + The green channel of the color of the progress bar. + + + + + The blue channel of the color of the progress bar. + + + + + The height of the progress bar in pixels. Defaults to 12 pixels. + + + + + Optional reference to a Color field, property or method, to dynamically change the color of the progress bar. Obsolete; use the ColorGetter member instead. + + + + + Optional resolved string that should evaluate to a Color value, to dynamically change the color of the progress bar. + + + + + Optional reference to a Color field, property or method, to dynamically change the background color of the progress bar. + Default background color is (0.16, 0.16, 0.16, 1). + Obsolete; use the BackgroundColorGetter member instead. + + + + + Optional resolved string that should evaluate to a Color value, to dynamically change the background color of the progress bar. + Default background color is (0.16, 0.16, 0.16, 1). + + + + + If true then the progress bar will be drawn in tiles. + + + + + References a member by name to get a custom value label string from. Obsolete; use the CustomValueStringGetter member instead. + + + + + A resolved string to get a custom value label string from. + + + + + Draws a progress bar for the value. + + The minimum value. + The maximum value. + The red channel of the color of the progress bar. + The green channel of the color of the progress bar. + The blue channel of the color of the progress bar. + + + + Draws a progress bar for the value. + + A resolved string that should evaluate to a float value, and will be used as the min bounds. + The maximum value. + The red channel of the color of the progress bar. + The green channel of the color of the progress bar. + The blue channel of the color of the progress bar. + + + + Draws a progress bar for the value. + + The minimum value. + A resolved string that should evaluate to a float value, and will be used as the max bounds. + The red channel of the color of the progress bar. + The green channel of the color of the progress bar. + The blue channel of the color of the progress bar. + + + + Draws a progress bar for the value. + + A resolved string that should evaluate to a float value, and will be used as the min bounds. + A resolved string that should evaluate to a float value, and will be used as the max bounds. + The red channel of the color of the progress bar. + The green channel of the color of the progress bar. + The blue channel of the color of the progress bar. + + + + If true then there will be drawn a value label on top of the progress bar. + + + + + Gets a value indicating if the user has set a custom DrawValueLabel value. + + + + + The alignment of the value label on top of the progress bar. Defaults to center. + + + + + Gets a value indicating if the user has set a custom ValueLabelAlignment value. + + + + + PropertyRange attribute creates a slider control to set the value of a property to between the specified range. + This is equivalent to Unity's Range attribute, but this attribute can be applied to both fields and property. + + The following example demonstrates how PropertyRange is used. + + public class MyComponent : MonoBehaviour + { + [PropertyRange(0, 100)] + public int MyInt; + + [PropertyRange(-100, 100)] + public float MyFloat; + + [PropertyRange(-100, -50)] + public decimal MyDouble; + + // This attribute also supports dynamically referencing members by name to assign the min and max values for the range field. + [PropertyRange("DynamicMin", "DynamicMax"] + public float MyDynamicValue; + + public float DynamicMin, DynamicMax; + } + + + + + + + + + The minimum value. + + + + + The maximum value. + + + + + The name of a field, property or method to get the min value from. Obsolete; use the MinGetter member instead. + + + + + A resolved string that should evaluate to a float value, and will be used as the min bounds. + + + + + The name of a field, property or method to get the max value from. Obsolete; use the MaxGetter member instead. + + + + + A resolved string that should evaluate to a float value, and will be used as the max bounds. + + + + + Creates a slider control to set the value of the property to between the specified range.. + + The minimum value. + The maximum value. + + + + Creates a slider control to set the value of the property to between the specified range.. + + A resolved string that should evaluate to a float value, and will be used as the min bounds. + The maximum value. + + + + Creates a slider control to set the value of the property to between the specified range.. + + The minimum value. + A resolved string that should evaluate to a float value, and will be used as the max bounds. + + + + Creates a slider control to set the value of the property to between the specified range.. + + A resolved string that should evaluate to a float value, and will be used as the min bounds. + A resolved string that should evaluate to a float value, and will be used as the max bounds. + + + + The PropertySpace attribute have the same function as Unity's existing Space attribute, but can be applied anywhere as opposed to just fields. + + + The following example demonstrates the usage of the PropertySpace attribute. + + [PropertySpace] // Defaults to a space of 8 pixels just like Unity's Space attribute. + public int MyField; + + [ShowInInspector, PropertySpace(16)] + public int MyProperty { get; set; } + + [ShowInInspector, PropertySpace(16, 16)] + public int MyProperty { get; set; } + + [Button, PropertySpace(32)] + public void MyMethod() + { + ... + } + + [PropertySpace(-8)] // A negative space can also be remove existing space between properties. + public int MovedUp; + + + + + + + + + + The space between properties in pixels. + + + + + The space between properties in pixels. + + + + + Adds a space of 8 pixels between properties. + + + + + Adds a space between properties. + + + + + Adds a space between properties. + + + + + Groups buttons into a group that will position and resize the buttons based on the amount of available layout space. + + + + [ResponsiveButtonGroup] + public void Foo() { } + + [ResponsiveButtonGroup] + public void Bar() { } + + [ResponsiveButtonGroup] + public void Baz() { } + + + + + [ResponsiveButtonGroup(UniformLayout = true)] + public void Foo() { } + + [ResponsiveButtonGroup] + public void Bar() { } + + [ResponsiveButtonGroup] + public void Baz() { } + + + + + [ResponsiveButtonGroupAttribute(UniformLayout = true, DefaultButtonSize = ButtonSizes.Large)] + public void Foo() { } + + [GUIColor(0, 1, 0))] + [Button(ButtonSizes.Large)] + [ResponsiveButtonGroup] + public void Bar() { } + + [ResponsiveButtonGroup] + public void Baz() { } + + + + + [TabGroup("SomeTabGroup", "SomeTab")] + [ResponsiveButtonGroup("SomeTabGroup/SomeTab/SomeBtnGroup")] + public void Foo() { } + + [ResponsiveButtonGroup("SomeTabGroup/SomeTab/SomeBtnGroup")] + public void Bar() { } + + [ResponsiveButtonGroup("SomeTabGroup/SomeTab/SomeBtnGroup")] + public void Baz() { } + + + + + + The default size of the button. + + + + + If true then the widths of a line of buttons will be the same. + + + + + Draws a button that will be placed in a group that will respond to the horizontal space available to the group. + + The name of the group to place the button in. + + + + Merges the values of this group with another ResponsiveButtonGroupAttribute. + + The attribute to combine with. + + + +

ShowIfGroup allows for showing or hiding a group of properties based on a condition.

+

The attribute is a group attribute and can therefore be combined with other group attributes, and even be used to show or hide entire groups.

+

Note that in the vast majority of cases where you simply want to be able to control the visibility of a single group, it is better to use the VisibleIf parameter that *all* group attributes have.

+
+ + + + + +
+ + + Whether or not to visually animate group visibility changes. Alias for AnimateVisibility. + + + + + The optional member value. + + + + + Name of member to use when to hide the group. Defaults to the name of the group, by can be overriden by setting this property. + + + + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + + + + + Makes a group that can be shown or hidden based on a condition. + + The group path. + If true then a fade animation will be played when the group is hidden or shown. + + + + Makes a group that can be shown or hidden based on a condition. + + The group path. + The value the member should equal for the property to shown. + If true then a fade animation will be played when the group is hidden or shown. + + + + Combines ShowIfGroup attributes. + + Another ShowIfGroup attribute. + + + + Only shows a property if it is drawn within an . + + + + + + ShowPropertyResolver shows the property resolver responsible for bringing the member into the property tree. + This is useful in situations where you want to debug why a particular member that is normally not shown in the inspector suddenly is. + + + + + public class MyComponent : MonoBehaviour + { + [ShowPropertyResolver] + public int IndentedInt; + } + + + + + + The SuffixLabel attribute draws a label at the end of a property. + Use this for conveying intend about a property. Is the distance measured in meters, kilometers, or in light years?. + Is the angle measured in degrees or radians? + Using SuffixLabel, you can place a neat label at the end of a property, to clearly show how the the property is used. + + + The following example demonstrates how SuffixLabel is used. + + public class MyComponent : MonoBehaviour + { + // The SuffixLabel attribute draws a label at the end of a property. + // It's useful for conveying intend about a property. + // Fx, this field is supposed to have a prefab assigned. + [SuffixLabel("Prefab")] + public GameObject GameObject; + + // Using the Overlay property, the suffix label will be drawn on top of the property instead of behind it. + // Use this for a neat inline look. + [SuffixLabel("ms", Overlay = true)] + public float Speed; + + [SuffixLabel("radians", Overlay = true)] + public float Angle; + + // The SuffixLabel attribute also supports string member references by using $. + [SuffixLabel("$Suffix", Overlay = true)] + public string Suffix = "Dynamic suffix label"; + } + + + + + + + + + + The label displayed at the end of the property. + + + + + If true the suffix label will be drawn on top of the property, instead of after. + + + + + Draws a label at the end of the property. + + The text of the label. + If true the suffix label will be drawn on top of the property, instead of after. + + + + The TableColumnWidth attribute is used to further customize the width of a column in tables drawn using the . + + + + [TableList] + public List<SomeType> TableList = new List<SomeType>(); + + [Serializable] + public class SomeType + { + [LabelWidth(30)] + [TableColumnWidth(130, false)] + [VerticalGroup("Combined")] + public string A; + + [LabelWidth(30)] + [VerticalGroup("Combined")] + public string B; + + [Multiline(2), Space(3)] + public string fields; + } + + + + + + + The width of the column. + + + + + Whether the column should be resizable. True by default. + + + + + Initializes a new instance of the class. + + The width of the column in pixels. + If true then the column can be resized in the inspector. + + + + Renders lists and arrays in the inspector as tables. + + + + + + + If ShowPaging is enabled, this will override the default setting specified in the Odin Preferences window. + + + + + Mark the table as read-only. This removes all editing capabilities from the list such as Add and delete, + but without disabling GUI for each element drawn as otherwise would be the case if the was used. + + + + + The default minimum column width - 40 by default. This can be overwriten by individual columns using the . + + + + + If true, a label is drawn for each element which shows the index of the element. + + + + + Whether to draw all rows in a scroll-view. + + + + + The number of pixels before a scroll view appears. 350 by default. + + + + + The number of pixels before a scroll view appears. 0 by default. + + + + + If true, expanding and collapsing the table from the table title-bar is no longer an option. + + + + + Whether to hide the toolbar containing the add button and pagin etc.s + + + + + The cell padding. + + + + + Whether paging buttons should be added to the title bar. The default value of this, can be customized from the Odin Preferences window. + + + + + Whether the ShowPaging property has been set. + + + + + Sets the Min and Max ScrollViewHeight. + + + + + The TableMatrix attribute is used to further specify how Odin should draw two-dimensional arrays. + + + + // Inheriting from SerializedMonoBehaviour is only needed if you want Odin to serialize the multi-dimensional arrays for you. + // If you prefer doing that yourself, you can still make Odin show them in the inspector using the ShowInInspector attribute. + public class TableMatrixExamples : SerializedMonoBehaviour + { + [InfoBox("Right-click and drag column and row labels in order to modify the tables."), PropertyOrder(-10), OnInspectorGUI] + private void ShowMessageAtOP() { } + + [BoxGroup("Two Dimensional array without the TableMatrix attribute.")] + public bool[,] BooleanTable = new bool[15, 6]; + + [BoxGroup("ReadOnly table")] + [TableMatrix(IsReadOnly = true)] + public int[,] ReadOnlyTable = new int[5, 5]; + + [BoxGroup("Labled table")] + [TableMatrix(HorizontalTitle = "X axis", VerticalTitle = "Y axis")] + public GameObject[,] LabledTable = new GameObject[15, 10]; + + [BoxGroup("Enum table")] + [TableMatrix(HorizontalTitle = "X axis")] + public InfoMessageType[,] EnumTable = new InfoMessageType[4,4]; + + [BoxGroup("Custom table")] + [TableMatrix(DrawElementMethod = "DrawColoredEnumElement", ResizableColumns = false)] + public bool[,] CustomCellDrawing = new bool[30,30]; + + #if UNITY_EDITOR + + private static bool DrawColoredEnumElement(Rect rect, bool value) + { + if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)) + { + value = !value; + GUI.changed = true; + Event.current.Use(); + } + + UnityEditor.EditorGUI.DrawRect(rect.Padding(1), value ? new Color(0.1f, 0.8f, 0.2f) : new Color(0, 0, 0, 0.5f)); + + return value; + } + + #endif + } + + + + + + If true, inserting, removing and dragging columns and rows will become unavailable. But the cells themselves will remain modifiable. + If you want to disable everything, you can use the attribute. + + + + + Whether or not columns are resizable. + + + + + The vertical title label. + + + + + The horizontal title label. + + + + + Override how Odin draws each cell. + [TableMatrix(DrawElementMethod='DrawMyElement')] + public MyType[,] myArray; + private static MyType DrawElement(Rect rect, MyType value) { return GUI.DrawMyType(rect, value); } + + + + + The height for all rows. 0 = default row height. + + + + + If true, the height of each row will be the same as the width of the first cell. + + + + + If true, no column indices drawn. + + + + + If true, no row indices drawn. + + + + + Whether the drawn table should respect the current GUI indent level. + + + + + If true, tables are drawn with rows/columns reversed (C# initialization order). + + + + + Name of any field, property or method member that implements IList. E.g. arrays or Lists. Obsolete; use the FilterGetter member instead. + + + + + A resolved string that should evaluate to a value that is assignable to IList; e.g, arrays and lists are compatible. + + + + + Gets or sets the title for the dropdown. Null by default. + + + + + If true, the value will be drawn normally after the type selector dropdown has been drawn. False by default. + + + + + Creates a dropdown menu for a property. + + A resolved string that should evaluate to a value that is assignable to IList; e.g, arrays and lists are compatible. + + + + The TypeInfoBox attribute adds an info box to the very top of a type in the inspector. + Use this to add an info box to the top of a class in the inspector, without having to use neither the PropertyOrder nor the OnInspectorGUI attribute. + + + The following example demonstrates the use of the TypeInfoBox attribute. + + [TypeInfoBox("This is my component and it is mine.")] + public class MyComponent : MonoBehaviour + { + // Class implementation. + } + + + + + + + + The message to display in the info box. + + + + + Draws an info box at the top of a type in the inspector. + + The message to display in the info box. + + + + VerticalGroup is used to gather properties together in a vertical group in the inspector. + This doesn't do much in and of itself, but in combination with other groups, such as it can be very useful. + + + The following example demonstrates how VerticalGroup can be used in conjunction with + + public class MyComponent : MonoBehaviour + { + [HorizontalGroup("Split")] + [VerticalGroup("Split/Left")] + public Vector3 Vector; + + [VerticalGroup("Split/Left")] + public GameObject First; + + [VerticalGroup("Split/Left")] + public GameObject Second; + + [VerticalGroup("Split/Right", PaddingTop = 18f)] + public int A; + + [VerticalGroup("Split/Right")] + public int B; + } + + + + + + + + + + + Space in pixels at the top of the group. + + + + + Space in pixels at the bottom of the group. + + + + + Groups properties vertically. + + The group ID. + The group order. + + + + Groups properties vertically. + GroupId: _DefaultVerticalGroup + + The group order. + + + + Combines properties that have been group vertically. + + The group attribute to combine with. + + + + Not yet documented. + + + + + Not yet documented. + + + + + Adds a search filter that can search the children of the field or type on + which it is applied. Note that this does not currently work when directly + applied to dictionaries, though a search field "above" the dictionary will + still search the dictionary's properties if it is searching recursively. + + + + + Whether to use fuzzy string matching for the search. + Default value: true. + + + + + The options for which things to use to filter the search. + Default value: All. + + + + + Whether to search recursively, or only search the top level properties. + Default value: true. + + + + + When this attribute is added is added to another attribute, then attributes from that attribute + will also be added to the property in the attribute processing step. + + + + + How the InlineEditor attribute drawer should draw the object field. + + + + + Draws the object field in a box. + + + + + Draws the object field with a foldout. + + + + + Hides the object field unless it's null. + + + + + Hidden the object field also when the object is null. + + + + + Implement this interface to create custom matching + logic for search filtering in the inspector. + + + The following example shows how you might do this: + + public class MyCustomClass : ISearchFilterable + { + public bool SearchEnabled; + public string MyStr; + + public bool IsMatch(string searchString) + { + if (SearchEnabled) + { + return MyStr.Contains(searchString); + } + + return false; + } + } + + + + + + How the square object field should be aligned. + + + + + + Left aligned. + + + + + Aligned to the center. + + + + + Right aligned. + + + + + Options for filtering search. + + + + + Title alignment enum used by various attributes. + + + + + + + Title and subtitle left aligned. + + + + + Title and subtitle centered aligned. + + + + + Title and subtitle right aligned. + + + + + Title on the left, subtitle on the right. + + + + + Groups properties vertically together with a title, an optional subtitle, and an optional horizontal line. + + + + + Optional subtitle. + + + + + Title alignment. + + + + + Gets a value indicating whether or not to draw a horizontal line below the title. + + + + + If true the title will be displayed with a bold font. + + + + + Gets a value indicating whether or not to indent all group members. + + + + + Groups properties vertically together with a title, an optional subtitle, and an optional horizontal line. + + The title- + Optional subtitle. + The text alignment. + Horizontal line. + Bold text. + Whether or not to indent all group members. + The group order. + + + + Combines TitleGroup attributes. + + The other group attribute to combine with. + + + + Various built-in button sizes. + + + + + Small button size, fits well with properties in the inspector. + + + + + A larger button. + + + + + A very large button. + + + + + A gigantic button. Twice as big as Large + + + + + ColorPalette is used on any Color property, and allows for choosing colors from different definable palettes. + Use this to allow the user to choose from a set of predefined color options. + + + See and edit the color palettes in Tools > Odin Inspector > Drawers > Color Palettes. + The color property is not tied to the color palette, and can be edited. Therefore the color will also not update if the ColorPalette is edited. + + + The following example shows how ColorPalette is applied to a property. The user can freely choose between all available ColorPalettes. + + public class ColorPaletteExamples : MonoBehaviour + { + [ColorPalette] + public Color ColorOptions; + + [ColorPalette("Underwater")] + public Color UnderwaterColor; + + [ColorPalette("Fall"), HideLabel] + public Color WideColorPalette; + + [ColorPalette("My Palette")] + public Color MyColor; + + [ColorPalette("Clovers")] + public Color[] ColorArray; + } + + + + + + Gets the name of the palette. + + + + + Indicates if the color palette should show alpha values or not. + + + + + Adds a color palette options to a Color property. + + + + + Adds color options to a Color property from a specific palette. + + Name of the palette. + + + + CustomContextMenu is used on any property, and adds a custom options to the context menu for the property. + Use this for when you want to add custom actions to the context menu of a property. + + + CustomContextMenu currently does not support static functions. + + + The following example shows how CustomContextMenu is used to add a custom option to a property. + + public class MyComponent : MonoBehaviour + { + [CustomContextMenu("My custom option", "MyAction")] + public Vector3 MyVector; + + private void MyAction() + { + MyVector = Random.onUnitSphere; + } + } + + + + + + + The name of the menu item. + + + + + The name of the callback method. Obsolete; use the Action member instead. + + + + + A resolved string defining the action to take when the context menu is clicked. + + + + + Adds a custom option to the context menu of the property. + + The name of the menu item. + A resolved string defining the action to take when the context menu is clicked. + + + + Delays applying changes to properties while they still being edited in the inspector. + Similar to Unity's built-in Delayed attribute, but this attribute can also be applied to properties. + + + + + DetailedInfoBox is used on any property, and displays a message box that can be expanded to show more details. + Use this to convey a message to a user, and give them the option to see more details. + + + The following example shows how DetailedInfoBox is used on a field. + + public class MyComponent : MonoBehaviour + { + [DetailedInfoBox("This is a message", "Here is some more details about that message")] + public int MyInt; + } + + + + + + + The message for the message box. + + + + + The hideable details of the message box. + + + + + Type of the message box. + + + + + Optional name of a member to hide or show the message box. + + + + + Displays a message box with hideable details. + + The message for the message box. + The hideable details of the message box. + Type of the message box. + Optional name of a member to hide or show the message box. + + + + Various display modes for the dictionary to draw its items. + + + + + Draws all dictionary items in two columns. The left column contains all key values, the right column displays all values. + + + + + Draws each dictionary item in a box with the key in the header and the value inside the box. + Whether or not the box is expanded or collapsed by default, is determined by the + "Expand Foldout By Default" setting found in the preferences window "Tools > Odin Inspector > Preferences > Drawers > Settings". + + + + + Draws each dictionary item in a collapsed foldout with the key in the header and the value inside the box. + + + + + Draws each dictionary item in an expanded foldout with the key in the header and the value inside the box. + + + + + Customize the behavior for dictionaries in the inspector. + + + + + Specify an alternative key label for the dictionary drawer. + + + + + Specify an alternative value label for the dictionary drawer. + + + + + Specify how the dictionary should draw its items. + + + + + Gets or sets a value indicating whether this instance is read only. + + + + + Gets or sets a value indicating the default key column width of the dictionary. + + + + + DisableContextMenu is used on any property and disables the context menu for that property. + Use this if you do not want the context menu to be available for a property. + + + The following example shows how DisableContextMenu is used on a property. + + public class MyComponent : MonoBehaviour + { + [DisableContextMenu] + public Vector3 MyVector; + } + + + + + + + Whether to disable the context menu for the member itself. + + + + + Whether to disable the context menu for collection elements. + + + + + Initializes a new instance of the class. + + Whether to disable the context menu for the member itself. + Whether to also disable the context menu of collection elements. + + + + DisableIf is used on any property, and can disable or enable the property in the inspector. + Use this to disable properties when they are irrelevant. + + + The following example shows how a property can be disabled by the state of a field. + + public class MyComponent : MonoBehaviour + { + public bool DisableProperty; + + [DisableIf("DisableProperty")] + public int MyInt; + + public SomeEnum SomeEnumField; + + [DisableIf("SomeEnumField", SomeEnum.SomeEnumMember)] + public string SomeString; + } + + + + The following examples show how a property can be disabled by a function. + + public class MyComponent : MonoBehaviour + { + [EnableIf("MyDisableFunction")] + public int MyInt; + + private bool MyDisableFunction() + { + // ... + } + } + + + + + + + + The name of a bool member field, property or method. Obsolete; use the Condition member instead. + + + + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + + + + + The optional condition value. + + + + + Disables a property in the inspector, based on the value of a resolved string. + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + + + + Disables a property in the inspector, if the resolved string evaluates to the specified value. + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + Value to check against. + + + + DisableInEditorMode is used on any property, and disables the property when not in play mode. + Use this when you only want a property to be editable when in play mode. + + + The following example shows how DisableInEditorMode is used to disable a property when in the editor. + + public class MyComponent : MonoBehaviour + { + [DisableInEditorMode] + public int MyInt; + } + + + + + + + + + DisableInPlayMode is used on any property, and disables the property when in play mode. + Use this to prevent users from editing a property when in play mode. + + + The following example shows how DisableInPlayMode is used to disable a property when in play mode. + + public class MyComponent : MonoBehaviour + { + [DisableInPlayMode] + public int MyInt; + } + + + + + + + + + + + DisplayAsString is used on any property, and displays a string in the inspector as text. + Use this for when you want to show a string in the inspector, but not allow for any editing. + + + DisplayAsString uses the property's ToString method to display the property as a string. + + + The following example shows how DisplayAsString is used to display a string property as text in the inspector. + + public class MyComponent : MonoBehaviour + { + [DisplayAsString] + public string MyInt = 5; + + // You can combine with to display a message in the inspector. + [DisplayAsString, HideLabel] + public string MyMessage = "This string will be displayed as text in the inspector"; + + [DisplayAsString(false)] + public string InlineMessage = "This string is very long, but has been configured to not overflow."; + } + + + + + + + + If true, the string will overflow past the drawn space and be clipped when there's not enough space for the text. + If false the string will expand to multiple lines, if there's not enough space when drawn. + + + + + Displays the property as a string in the inspector. + + + + + Displays the property as a string in the inspector. + + Value indicating if the string should overflow past the available space, or expand to multiple lines when there's not enough horizontal space. + + + + DontApplyToListElements is used on other attributes, and indicates that those attributes should be applied only to the list, and not to the elements of the list. + Use this on attributes that should only work on a list or array property as a whole, and not on each element of the list. + + + The following example shows how DontApplyToListElements is used on . + + [DontApplyToListElements] + [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)] + public sealed class VisibleIfAttribute : Attribute + { + public string MemberName { get; private set; } + + public VisibleIfAttribute(string memberName) + { + this.MemberName = memberName; + } + } + + + + + + DrawWithUnity can be applied to a field or property to make Odin draw it using Unity's old drawing system. Use it if you want to selectively disable Odin drawing for a particular member. + + + Note that this attribute does not mean "disable Odin completely for this property"; it is visual only in nature, and in fact represents an Odin drawer which calls into Unity's old property drawing system. As Odin is still ultimately responsible for arranging the drawing of the property, and since other attributes exist with a higher priority than this attribute, and it is not guaranteed that Unity will draw the property if another attribute is present to override this one. + + + + + The inline button adds a button to the end of a property. + + + Due to a bug, multiple inline buttons are currently not supported. + + + The following examples demonstrates how InlineButton can be used. + + public class MyComponent : MonoBehaviour + { + // Adds a button to the end of the A property. + [InlineButton("MyFunction")] + public int A; + + // This is example demonstrates how you can change the label of the button. + // InlineButton also supports refering to string members with $. + [InlineButton("MyFunction", "Button")] + public int B; + + private void MyFunction() + { + // ... + } + } + + + + + + + + Name of member method to call when the button is clicked. Obsolete; use the Action member instead. + + + + + A resolved string that defines the action to perform when the button is clicked, such as an expression or method invocation. + + + + + Optional label of the button. + + + + + Optional resolved string that specifies a condition for whether to show the inline button or not. + + + + + Draws a button to the right of the property. + + A resolved string that defines the action to perform when the button is clicked, such as an expression or method invocation. + Optional label of the button. + + + + Not yet documented. + + + + + Not yet documented. + + Not yet documented. + + + + Not yet documented. + + Not yet documented. + Not yet documented. + + + + ShowForPrefabOnlyAttribute is used on any field or property, and only shows properties from prefab assets inspector. + Use this to ensure the same value on a property, across all instances of a prefab. + + + On non-prefab objects or instances, this attribute does nothing, and allows properties to be edited as normal. + + + The following example shows how ShowForPrefabOnlyAttribute is used on properties. + + public class MyComponent + { + [ShowForPrefabOnlyAttribute] + public int MyInt; + } + + + + + + + + + + + EnableForPrefabOnly is used on any field or property, and only allows editing of values from prefab assets inspector. + Use this to ensure the same value on a property, across all instances of a prefab. + + + On non-prefab objects or instances, this attribute does nothing, and allows properties to be edited as normal. + + + The following example shows how EnableForPrefabOnly is used on properties. + + public class MyComponent + { + [EnableForPrefabOnly] + public int MyInt; + } + + + + + + + + + + + EnableIf is used on any property, and can enable or disable the property in the inspector. + Use this to enable properties when they are relevant. + + + The following example shows how a property can be enabled by the state of a field. + + public class MyComponent : MonoBehaviour + { + public bool EnableProperty; + + [EnableIf("EnableProperty")] + public int MyInt; + + public SomeEnum SomeEnumField; + + [EnableIf("SomeEnumField", SomeEnum.SomeEnumMember)] + public string SomeString; + } + + + + The following examples show how a property can be enabled by a function. + + public class MyComponent : MonoBehaviour + { + [EnableIf("MyEnableFunction")] + public int MyInt; + + private bool MyEnableFunction() + { + // ... + } + } + + + + + + + + + + + The name of a bool member field, property or method. Obsolete; use the Condition member instead. + + + + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + + + + + The optional condition value. + + + + + Enables a property in the inspector, based on the value of a resolved string. + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + + + + Enables a property in the inspector, if the resolved string evaluates to the specified value. + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + Value to check against. + + + + Draws an enum in a horizontal button group instead of a dropdown. + + + + public class MyComponent : MonoBehvaiour + { + [EnumToggleButtons] + public MyBitmaskEnum MyBitmaskEnum; + + [EnumToggleButtons] + public MyEnum MyEnum; + } + + [Flags] + public enum MyBitmaskEnum + { + A = 1 << 1, // 1 + B = 1 << 2, // 2 + C = 1 << 3, // 4 + ALL = A | B | C + } + + public enum MyEnum + { + A, + B, + C + } + + + + + + + HideIf is used on any property and can hide the property in the inspector. + Use this to hide irrelevant properties based on the current state of the object. + + + This example shows a component with fields hidden by the state of another field. + + public class MyComponent : MonoBehaviour + { + public bool HideProperties; + + [HideIf("HideProperties")] + public int MyInt; + + [HideIf("HideProperties", false)] + public string MyString; + + public SomeEnum SomeEnumField; + + [HideIf("SomeEnumField", SomeEnum.SomeEnumMember)] + public string SomeString; + } + + + + This example shows a component with a field that is hidden when the game object is inactive. + + public class MyComponent : MonoBehaviour + { + [HideIf("MyVisibleFunction")] + public int MyHideableField; + + private bool MyVisibleFunction() + { + return !this.gameObject.activeInHierarchy; + } + } + + + + + + + + + The name of a bool member field, property or method. Obsolete; use the Condition member instead. + + + + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + + + + + The optional condition value. + + + + + Whether or not to slide the property in and out when the state changes. + + + + + Hides a property in the inspector, based on the value of a resolved string. + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + Whether or not to slide the property in and out when the state changes. + + + + Hides a property in the inspector, if the resolved string evaluates to the specified value. + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + Value to check against. + Whether or not to slide the property in and out when the state changes. + + + + HideInPlayMode is used on any property, and hides the property when not in editor mode. + Use this when you only want a property to only be visible the editor. + + + The following example shows how HideInPlayMode is used to hide a property when in play mode. + + public class MyComponent : MonoBehaviour + { + [HideInPlayMode] + public int MyInt; + } + + + + + + + + + + HideInEditorMode is used on any property, and hides the property when not in play mode. + Use this when you only want a property to only be visible play mode. + + + The following example shows how HideInEditorMode is used to hide a property when in the editor. + + public class MyComponent : MonoBehaviour + { + [HideInEditorMode] + public int MyInt; + } + + + + + + + + + + Apply HideMonoScript to your class to prevent the Script property from being shown in the inspector. + + This attribute has the same effect on a single type that the global configuration option "Show Mono Script In Editor" in "Preferences -> Odin Inspector -> General -> Drawers" has globally when disabled. + + + + The following example shows how to use this attribute. + + [HideMonoScript] + public class MyComponent : MonoBehaviour + { + // The Script property will not be shown for this component in the inspector + } + + + + + + + Hides the polymorphic object-picker shown above the properties of non-Unity serialized reference types. + + + When the object picker is hidden, you can right click and set the instance to null, in order to set a new value. + If you don't want this behavior, you can use attribute to ensure people can't change the value. + + + + + public class MyComponent : SerializedMonoBehaviour + { + [Header("Hidden Object Pickers")] + [Indent] + [HideReferenceObjectPicker] + public MyCustomReferenceType OdinSerializedProperty1; + + [Indent] + [HideReferenceObjectPicker] + public MyCustomReferenceType OdinSerializedProperty2; + + [Indent] + [Header("Shown Object Pickers")] + public MyCustomReferenceType OdinSerializedProperty3; + + [Indent] + public MyCustomReferenceType OdinSerializedProperty4; + + public class MyCustomReferenceType + { + public int A; + public int B; + public int C; + } + } + + + + + + HorizontalGroup is used group multiple properties horizontally in the inspector. + The width can either be specified as percentage or pixels. + All values between 0 and 1 will be treated as a percentage. + If the width is 0 the column will be automatically sized. + Margin-left and right can only be specified in pixels. + + + The following example shows how three properties have been grouped together horizontally. + + // The width can either be specified as percentage or pixels. + // All values between 0 and 1 will be treated as a percentage. + // If the width is 0 the column will be automatically sized. + // Margin-left and right can only be specified in pixels. + + public class HorizontalGroupAttributeExamples : MonoBehaviour + { + [HorizontalGroup] + public int A; + + [HideLabel, LabelWidth (150)] + [HorizontalGroup(150)] + public LayerMask B; + + // LabelWidth can be helpfull when dealing with HorizontalGroups. + [HorizontalGroup("Group 1"), LabelWidth(15)] + public int C; + + [HorizontalGroup("Group 1"), LabelWidth(15)] + public int D; + + [HorizontalGroup("Group 1"), LabelWidth(15)] + public int E; + + // Having multiple properties in a column can be achived using multiple groups. Checkout the "Combining Group Attributes" example. + [HorizontalGroup("Split", 0.5f, PaddingRight = 15)] + [BoxGroup("Split/Left"), LabelWidth(15)] + public int L; + + [BoxGroup("Split/Right"), LabelWidth(15)] + public int M; + + [BoxGroup("Split/Left"), LabelWidth(15)] + public int N; + + [BoxGroup("Split/Right"), LabelWidth(15)] + public int O; + + // Horizontal Group also has supprot for: Title, MarginLeft, MarginRight, PaddingLeft, PaddingRight, MinWidth and MaxWidth. + [HorizontalGroup("MyButton", MarginLeft = 0.25f, MarginRight = 0.25f)] + public void SomeButton() + { + + } + } + + + + + + + + + + + The width. Values between 0 and 1 will be treated as percentage, 0 = auto, otherwise pixels. + + + + + The margin left. Values between 0 and 1 will be treated as percentage, 0 = ignore, otherwise pixels. + + + + + The margin right. Values between 0 and 1 will be treated as percentage, 0 = ignore, otherwise pixels. + + + + + The padding left. Values between 0 and 1 will be treated as percentage, 0 = ignore, otherwise pixels. + + + + + The padding right. Values between 0 and 1 will be treated as percentage, 0 = ignore, otherwise pixels. + + + + + The minimum Width. Values between 0 and 1 will be treated as percentage, 0 = ignore, otherwise pixels. + + + + + The maximum Width. Values between 0 and 1 will be treated as percentage, 0 = ignore, otherwise pixels. + + + + + Adds a title above the horizontal group. + + + + + The label width, 0 = auto. + + + + + Organizes the property in a horizontal group. + + The group for the property. + The width of the property. Values between 0 and 1 are interpolated as a percentage, otherwise pixels. + The left margin in pixels. + The right margin in pixels. + The order of the group in the inspector. + + + + Organizes the property in a horizontal group. + + The width of the property. Values between 0 and 1 are interpolated as a percentage, otherwise pixels. + The left margin in pixels. + The right margin in pixels. + The order of the group in the inspector. + + + + Merges the values of two group attributes together. + + The other group to combine with. + + + + InlineAttribute is used on any property or field with a type that inherits from UnityEngine.Object. This includes components and assets etc. + + + + public class InlineEditorExamples : MonoBehaviour + { + [DisableInInlineEditors] + public Vector3 DisabledInInlineEditors; + + [HideInInlineEditors] + public Vector3 HiddenInInlineEditors; + + [InlineEditor] + public Transform InlineComponent; + + [InlineEditor(InlineEditorModes.FullEditor)] + public Material FullInlineEditor; + + [InlineEditor(InlineEditorModes.GUIAndHeader)] + public Material InlineMaterial; + + [InlineEditor(InlineEditorModes.SmallPreview)] + public Material[] InlineMaterialList; + + [InlineEditor(InlineEditorModes.LargePreview)] + public GameObject InlineObjectPreview; + + [InlineEditor(InlineEditorModes.LargePreview)] + public Mesh InlineMeshPreview; + } + + + + + + + + If true, the inline editor will start expanded. + + + + + Draw the header editor header inline. + + + + + Draw editor GUI inline. + + + + + Draw editor preview inline. + + + + + Maximum height of the inline editor. If the inline editor exceeds the specified height, a scrollbar will appear. + Values less or equals to zero will let the InlineEditor expand to its full size. + + + + + The size of the editor preview if drawn together with GUI. + + + + + The size of the editor preview if drawn alone. + + + + + If false, this will prevent the InlineEditor attribute from incrementing the InlineEditorAttributeDrawer.CurrentInlineEditorDrawDepth. + This is helpful in cases where you want to draw the entire editor, and disregard attributes + such as [] and []. + + + + + How the InlineEditor attribute drawer should draw the object field. + + + + + Whether to set GUI.enabled = false when drawing an editor for an asset that is locked by source control. Defaults to true. + + + + + Initializes a new instance of the class. + + The inline editor mode. + How the object field should be drawn. + + + + Initializes a new instance of the class. + + How the object field should be drawn. + + + + SuppressInvalidAttributeError is used on members to suppress the inspector error message you get when applying an attribute to a value that it's not supposed to work on. + This can be very useful for applying attributes to generic parameter values, when it only applies to some of the possible types that the value might become. + + + The following example shows a case where the attribute might be useful. + + public class NamedValue<T> + { + public string Name; + + // The Range attribute will be applied if T is compatible with it, but if T is not compatible, an error will not be shown. + [SuppressInvalidAttributeError, Range(0, 10)] + public T Value; + } + + + + + + Editor modes for + + + + + + Draws only the editor GUI + + + + + Draws the editor GUI and the editor header. + + + + + Draws the editor GUI to the left, and a small editor preview to the right. + + + + + Draws a small editor preview without any GUI. + + + + + Draws a large editor preview without any GUI. + + + + + Draws the editor header and GUI to the left, and a small editor preview to the right. + + + + + + ShowDrawerChain lists all prepend, append and value drawers being used in the inspector. + This is great in situations where you want to debug, and want to know which drawers might be involved in drawing the property. + + Your own custom drawers are highlighted with a green label. + Drawers, that have not been called during the draw chain, will be greyed out in the inspector to make it clear which drawers have had an effect on the properties. + + + + public class MyComponent : MonoBehaviour + { + [ShowDrawerChain] + public int IndentedInt; + } + + + + + + Marks a type as being specially serialized. Odin uses this attribute to check whether it should include non-Unity-serialized members in the inspector. + + + + + FoldoutGroup is used on any property, and organizes properties into a foldout. + Use this to organize properties, and to allow the user to hide properties that are not relevant for them at the moment. + + + The following example shows how FoldoutGroup is used to organize properties into a foldout. + + public class MyComponent : MonoBehaviour + { + [FoldoutGroup("MyGroup")] + public int A; + + [FoldoutGroup("MyGroup")] + public int B; + + [FoldoutGroup("MyGroup")] + public int C; + } + + + + The following example shows how properties can be organizes into multiple foldouts. + + public class MyComponent : MonoBehaviour + { + [FoldoutGroup("First")] + public int A; + + [FoldoutGroup("First")] + public int B; + + [FoldoutGroup("Second")] + public int C; + } + + + + + + + + + + + Gets a value indicating whether or not the foldout should be expanded by default. + + + + + Gets a value indicating whether or not the Expanded property has been set. + + + + + Adds the property to the specified foldout group. + + Name of the foldout group. + The order of the group in the inspector. + + + + Adds the property to the specified foldout group. + + Name of the foldout group. + Whether or not the foldout should be expanded by default. + The order of the group in the inspector. + + + + Combines the foldout property with another. + + The group to combine with. + + + + GUIColor is used on any property and changes the GUI color used to draw the property. + + + The following example shows how GUIColor is used on a properties to create a rainbow effect. + + public class MyComponent : MonoBehaviour + { + [GUIColor(1f, 0f, 0f)] + public int A; + + [GUIColor(1f, 0.5f, 0f, 0.2f)] + public int B; + + [GUIColor("GetColor")] + public int C; + + private Color GetColor() { return this.A == 0 ? Color.red : Color.white; } + } + + + + + + The GUI color of the property. + + + + + The name of a local field, member or property that returns a Color. Both static and instance methods are supported. + + + + + Sets the GUI color for the property. + + The red channel. + The green channel. + The blue channel. + The alpha channel. + + + + Sets the GUI color for the property. + + Specify the name of a local field, member or property that returns a Color. + + + + HideLabel is used on any property, and hides the label in the inspector. + Use this to hide the label of properties in the inspector. + + + The following example show how HideLabel is used to hide the label of a game object property. + + public class MyComponent : MonoBehaviour + { + [HideLabel] + public GameObject MyGameObjectWithoutLabel; + } + + + + + + + Indent is used on any property and moves the property's label to the right. + Use this to clearly organize properties in the inspector. + + + The following example shows how a property is indented by Indent. + + public class MyComponent : MonoBehaviour + { + [Indent] + public int IndentedInt; + } + + + + + + Indicates how much a property should be indented. + + + + + Indents a property in the inspector. + + How much a property should be indented. + + + + InfoBox is used on any property, and display a text box above the property in the inspector. + Use this to add comments or warn about the use of different properties. + + + The following example shows different info box types. + + public class MyComponent : MonoBehaviour + { + [InfoBox("This is an int property")] + public int MyInt; + + [InfoBox("This info box is a warning", InfoMessageType.Warning)] + public float MyFloat; + + [InfoBox("This info box is an error", InfoMessageType.Error)] + public object MyObject; + + [InfoBox("This info box is just a box", InfoMessageType.None)] + public Vector3 MyVector; + } + + + + The following example how info boxes can be hidden by fields and properties. + + public class MyComponent : MonoBehaviour + { + [InfoBox("This info box is hidden by an instance field.", "InstanceShowInfoBoxField")] + public int MyInt; + public bool InstanceShowInfoBoxField; + + [InfoBox("This info box is hideable by a static field.", "StaticShowInfoBoxField")] + public float MyFloat; + public static bool StaticShowInfoBoxField; + + [InfoBox("This info box is hidden by an instance property.", "InstanceShowInfoBoxProperty")] + public int MyOtherInt; + public bool InstanceShowInfoBoxProperty { get; set; } + + [InfoBox("This info box is hideable by a static property.", "StaticShowInfoBoxProperty")] + public float MyOtherFloat; + public static bool StaticShowInfoBoxProperty { get; set; } + } + + + + The following example shows how info boxes can be hidden by functions. + + public class MyComponent : MonoBehaviour + { + [InfoBox("This info box is hidden by an instance function.", "InstanceShowFunction")] + public int MyInt; + public bool InstanceShowFunction() + { + return this.MyInt == 0; + } + + [InfoBox("This info box is hidden by a static function.", "StaticShowFunction")] + public short MyShort; + public bool StaticShowFunction() + { + return true; + } + + // You can also specify a function with the same type of parameter. + // Use this to specify the same function, for multiple different properties. + [InfoBox("This info box is hidden by an instance function with a parameter.", "InstanceShowParameterFunction")] + public GameObject MyGameObject; + public bool InstanceShowParameterFunction(GameObject property) + { + return property != null; + } + + [InfoBox("This info box is hidden by a static function with a parameter.", "StaticShowParameterFunction")] + public Vector3 MyVector; + public bool StaticShowParameterFunction(Vector3 property) + { + return property.magnitude == 0f; + } + } + + + + + + + + The message to display in the info box. + + + + + The type of the message box. + + + + + Optional member field, property or function to show and hide the info box. + + + + + When true the InfoBox will ignore the GUI.enable flag and always draw as enabled. + + + + + Displays an info box above the property. + + The message for the message box. Supports referencing a member string field, property or method by using $. + The type of the message box. + Name of member bool to show or hide the message box. + + + + Displays an info box above the property. + + The message for the message box. Supports referencing a member string field, property or method by using $. + Name of member bool to show or hide the message box. + + + + Draw a special slider the user can use to specify a range between a min and a max value. + Uses a Vector2 where x is min and y is max. + + + The following example shows how MinMaxSlider is used. + + public class Player : MonoBehaviour + { + [MinMaxSlider(4, 5)] + public Vector2 SpawnRadius; + } + + + + + + The hardcoded min value for the slider. + + + + + The hardcoded max value for the slider. + + + + + The name of a field, property or method to get the min value from. Obsolete; use MinValueGetter instead. + + + + + A resolved string that should evaluate to a float value, which is used as the min bounds. + + + + + The name of a field, property or method to get the max value from. Obsolete; use MaxValueGetter instead. + + + + + A resolved string that should evaluate to a float value, which is used as the max bounds. + + + + + The name of a Vector2 field, property or method to get the min max values from. Obsolete; use MinMaxValueGetter instead. + + + + + A resolved string that should evaluate to a Vector2 value, which is used as the min/max bounds. If this is non-null, it overrides the behaviour of the MinValue, MinValueGetter, MaxValue and MaxValueGetter members. + + + + + Draw float fields for min and max value. + + + + + Draws a min-max slider in the inspector. X will be set to min, and Y will be set to max. + + The min value. + The max value. + If true number fields will drawn next to the MinMaxSlider. + + + + Draws a min-max slider in the inspector. X will be set to min, and Y will be set to max. + + A resolved string that should evaluate to a float value, which is used as the min bounds. + The max value. + If true number fields will drawn next to the MinMaxSlider. + + + + Draws a min-max slider in the inspector. X will be set to min, and Y will be set to max. + + The min value. + A resolved string that should evaluate to a float value, which is used as the max bounds. + If true number fields will drawn next to the MinMaxSlider. + + + + Draws a min-max slider in the inspector. X will be set to min, and Y will be set to max. + + A resolved string that should evaluate to a float value, which is used as the min bounds. + A resolved string that should evaluate to a float value, which is used as the max bounds. + If true number fields will drawn next to the MinMaxSlider. + + + + Draws a min-max slider in the inspector. X will be set to min, and Y will be set to max. + + A resolved string that should evaluate to a Vector2 value, which is used as the min/max bounds. If this is non-null, it overrides the behaviour of the MinValue, MinValueGetter, MaxValue and MaxValueGetter members. + If true number fields will drawn next to the MinMaxSlider. + + + + Draws the checkbox before the label instead of after. + + ToggleLeftAttribute can be used an all fields and properties of type boolean + + + public class MyComponent : MonoBehaviour + { + [ToggleLeft] + public bool MyBoolean; + } + + + + + + LabelText is used to change the labels of properties. + Use this if you want a different label than the name of the property. + + + The following example shows how LabelText is applied to a few property fields. + + public MyComponent : MonoBehaviour + { + [LabelText("1")] + public int MyInt1; + + [LabelText("2")] + public int MyInt2; + + [LabelText("3")] + public int MyInt3; + } + + + + + + + The new text of the label. + + + + + Whether the label text should be nicified before it is displayed, IE, "m_someField" becomes "Some Field". + If the label text is resolved via a member reference, an expression, or the like, then the evaluated result + of that member reference or expression will be nicified. + + + + + Give a property a custom label. + + The new text of the label. + + + + Give a property a custom label. + + The new text of the label. + Whether to nicify the label text. + + + + Customize the behavior for lists and arrays in the inspector. + + + This example shows how you can add your own custom add button to a list. + + [ListDrawerSettings(HideAddButton = true, OnTitleBarGUI = "DrawTitleBarGUI")] + public List<MyType> SomeList; + + #if UNITY_EDITOR + private void DrawTitleBarGUI() + { + if (SirenixEditorGUI.ToolbarButton(EditorIcons.Plus)) + { + this.SomeList.Add(new MyType()); + } + } + #endif + + + + This attribute is scheduled for refactoring. + + + + + If true, the add button will not be rendered in the title toolbar. You can use OnTitleBarGUI to implement your own add button. + + + true if [hide add button]; otherwise, false. + + + + + If true, the remove button will not be rendered on list items. You can use OnBeginListElementGUI and OnEndListElementGUI to implement your own remove button. + + + true if [hide remove button]; otherwise, false. + + + + + Specify the name of a member inside each list element which defines the label being drawn for each list element. + + + + + Override the default behaviour for adding objects to the list. + If the referenced member returns the list type element, it will be called once per selected object. + If the referenced method returns void, it will only be called once regardless of how many objects are selected. + + + + + Calls a method before each list element. The member referenced must have a return type of void, and an index parameter of type int which represents the element index being drawn. + + + + + Calls a method after each list element. The member referenced must have a return type of void, and an index parameter of type int which represents the element index being drawn. + + + + + If true, object/type pickers will never be shown when the list add button is clicked, and default(T) will always be added instantly instead, where T is the element type of the list. + + + + + Whether adding a new element should copy the last element. False by default. + + + + + A resolved string with "int index" and "Color defaultColor" parameters that lets you control the color of individual elements. + + + + + Override the default setting specified in the Advanced Odin Preferences window and explicitly tell whether paging should be enabled or not. + + + + + Override the default setting specified in the Advanced Odin Preferences window and explicitly tell whether items should be draggable or not. + + + + + Override the default setting specified in the Advanced Odin Preferences window and explicitly tells how many items each page should contain. + + + + + Mark a list as read-only. This removes all editing capabilities from the list such as Add, Drag and delete, + but without disabling GUI for each element drawn as otherwise would be the case if the was used. + + + + + Override the default setting specified in the Advanced Odin Preferences window and explicitly tell whether or not item count should be shown. + + + + + Override the default setting specified in the Advanced Odin Preferences window and explicitly tell whether or not the list should be expanded or collapsed by default. + + + + + If true, a label is drawn for each element which shows the index of the element. + + + + + Use this to inject custom GUI into the title-bar of the list. + + + + + Whether the Paging property is set. + + + + + Whether the ShowItemCount property is set. + + + + + Whether the NumberOfItemsPerPage property is set. + + + + + Whether the Draggable property is set. + + + + + Whether the IsReadOnly property is set. + + + + + Whether the Expanded property is set. + + + + + Whether the ShowIndexLabels property is set. + + + + + MaxValue is used on primitive fields. It caps value of the field to a maximum value. + Use this to define a maximum value for the field. + + + Note that this attribute only works in the editor! Values changed from scripting will not be capped at a maximum. + + + The following example shows a component where a speed value must be less than or equal to 200. + + public class Car : MonoBehaviour + { + // The speed of the car must be less than or equal to 200. + [MaxValue(200)] + public float Speed; + } + + + + The following example shows how MaxValue can be combined with . + + public class Health : MonoBehaviour + { + // The speed value must be between 0 and 200. + [MinValue(0), MaxValue(200)] + public float Speed; + } + + + + + + + The maximum value for the property. + + + + + The string with which to resolve a maximum value. This could be a field, property or method name, or an expression. + + + + + Sets a maximum value for the property in the inspector. + + The max value. + + + + Sets a maximum value for the property in the inspector. + + The string with which to resolve a maximum value. This could be a field, property or method name, or an expression. + + + + MinValue is used on primitive fields. It caps value of the field to a minimum value. + Use this to define a minimum value for the field. + + + Note that this attribute only works in the editor! Values changed from scripting will not be capped at a minimum. + + + The following example shows a player component that must have at least 1 life. + + public class Player : MonoBehaviour + { + // The life value must be set to at least 1. + [MinValue(1)] + public int Life; + } + + + + The following example shows how MinValue can be combined with + + public class Health : MonoBehaviour + { + // The health value must be between 0 and 100. + [MinValue(0), MaxValue(100)] + public float Health; + } + + + + + + + The minimum value for the property. + + + + + The string with which to resolve a minimum value. This could be a field, property or method name, or an expression. + + + + + Sets a minimum value for the property in the inspector. + + The minimum value. + + + + Sets a minimum value for the property in the inspector. + + The string with which to resolve a minimum value. This could be a field, property or method name, or an expression. + + + + MultiLineProperty is used on any string property. + Use this to allow users to edit strings in a multi line textbox. + + + MultiLineProperty is similar to Unity's but can be applied to both fields and properties. + + + The following example shows how MultiLineProperty is applied to properties. + + public class MyComponent : MonoBehaviour + { + [MultiLineProperty] + public string MyString; + + [ShowInInspector, MultiLineProperty(10)] + public string PropertyString; + } + + + + + + The number of lines for the text box. + + + + + Makes a multiline textbox for editing strings. + + The number of lines for the text box. + + + + PropertyTooltip is used on any property, and creates tooltips for when hovering the property in the inspector. + Use this to explain the purpose, or how to use a property. + + + This is similar to Unity's but can be applied to both fields and properties. + + + The following example shows how PropertyTooltip is applied to various properties. + + public class MyComponent : MonoBehaviour + { + [PropertyTooltip("This is an int property.")] + public int MyField; + + [ShowInInspector, PropertyTooltip("This is another int property.")] + public int MyProperty { get; set; } + } + + + + + + + + + + + The message shown in the tooltip. + + + + + Adds a tooltip to the property in the inspector. + + The message shown in the tooltip. + + + + ReadOnly is used on any property, and disabled the property from being changed in the inspector. + Use this for when you want to see the value of a property in the inspector, but don't want it to be changed. + + + This attribute only affects the inspector! Values can still be changed by script. + + + The following example shows how a field can be displayed in the editor, but not be editable. + + public class Health : MonoBehaviour + { + public int MaxHealth; + + [ReadOnly] + public int CurrentHealth; + } + + + + ReadOnly can also be combined with . + + public class Health : MonoBehaviour + { + public int MaxHealth; + + [ShowInInspector, ReadOnly] + private int currentHealth; + } + + + + + + + OnInspectorGUI is used on any property, and will call the specified function whenever the inspector code is running. + Use this to create custom inspector GUI for an object. + + + + + public MyComponent : MonoBehaviour + { + [OnInspectorGUI] + private void MyInspectorGUI() + { + GUILayout.Label("Label drawn from callback"); + } + } + + + + The following example shows how a callback can be set before another property. + + public MyComponent : MonoBehaviour + { + [OnInspectorGUI("MyInspectorGUI", false)] + public int MyField; + + private void MyInspectorGUI() + { + GUILayout.Label("Label before My Field property"); + } + } + + + + The following example shows how callbacks can be added both before and after a property. + + public MyComponent : MonoBehaviour + { + [OnInspectorGUI("GUIBefore", "GUIAfter")] + public int MyField; + + private void GUIBefore() + { + GUILayout.Label("Label before My Field property"); + } + + private void GUIAfter() + { + GUILayout.Label("Label after My Field property"); + } + } + + + + + + The resolved action string that defines the action to be invoked before the property is drawn, if any. + + + + + The resolved action string that defines the action to be invoked after the property is drawn, if any. + + + + + The name of the method to be called before the property is drawn, if any. Obsolete; use the Prepend member instead. + + + + + The name of the method to be called after the property is drawn, if any. Obsolete; use the Append member instead. + + + + + Calls a function decorated with this attribute, when the inspector is being drawn. + + + + + Adds callbacks to the specified action when the property is being drawn. + + The resolved action string that defines the action to be invoked. + If true the method will be called after the property has been drawn. Otherwise the method will be called before. + + + + Adds callbacks to the specified actions when the property is being drawn. + + The resolved action string that defines the action to be invoked before the property is drawn, if any. + The resolved action string that defines the action to be invoked after the property is drawn, if any. + + + + + OnValueChanged works on properties and fields, and calls the specified function + whenever the value has been changed via the inspector. + + + + Note that this attribute only works in the editor! Properties changed by script will not call the function. + + + The following example shows how OnValueChanged is used to provide a callback for a property. + + public class MyComponent : MonoBehaviour + { + [OnValueChanged("MyCallback")] + public int MyInt; + + private void MyCallback() + { + // .. + } + } + + + + The following example show how OnValueChanged can be used to get a component from a prefab property. + + public class MyComponent : MonoBehaviour + { + [OnValueChanged("OnPrefabChange")] + public GameObject MyPrefab; + + // RigidBody component of MyPrefab. + [SerializeField, HideInInspector] + private RigidBody myPrefabRigidbody; + + private void OnPrefabChange() + { + if(MyPrefab != null) + { + myPrefabRigidbody = MyPrefab.GetComponent<Rigidbody>(); + } + else + { + myPrefabRigidbody = null; + } + } + } + + + + + + Name of callback member function. Obsolete; use the Action member instead. + + + + + A resolved string that defines the action to perform when the value is changed, such as an expression or method invocation. + + + + + Whether to perform the action when a child value of the property is changed. + + + + + Whether to perform the action when an undo or redo event occurs via UnityEditor.Undo.undoRedoPerformed. True by default. + + + + + Whether to perform the action when the property is initialized. This will generally happen when the property is first viewed/queried (IE when the inspector is first opened, or when its containing foldout is first expanded, etc), and whenever its type or a parent type changes, or it is otherwise forced to rebuild. + + + + + Adds a callback for when the property's value is changed. + + A resolved string that defines the action to perform when the value is changed, such as an expression or method invocation. + Whether to perform the action when a child value of the property is changed. + + + + Attribute to derive from if you wish to create a new property group type, such as box groups or tab groups. + Note that this attribute has special behaviour for "combining" several attributes into one, as one group, + may be declared across attributes in several members, completely out of order. See . + + + All group attributes for a group with the same name (and of the same attribute type) are combined into a single representative group attribute using the method, which is called by the method. + This behaviour is a little unusual, but it is important that you understand it when creating groups with many custom parameters that may have to be combined. + + + This example shows how could be implemented. + + [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)] + public class BoxGroupAttribute : PropertyGroupAttribute + { + public string Label { get; private set; } + public bool ShowLabel { get; private set; } + public bool CenterLabel { get; private set; } + + public BoxGroupAttribute(string group, bool showLabel = true, bool centerLabel = false, float order = 0) + : base(group, order) + { + this.Label = group; + this.ShowLabel = showLabel; + this.CenterLabel = centerLabel; + } + + protected override void CombineValuesWith(PropertyGroupAttribute other) + { + // The given attribute parameter is *guaranteed* to be of type BoxGroupAttribute. + var attr = other as BoxGroupAttribute; + + // If this attribute has no label, we the other group's label, thus preserving the label across combines. + if (this.Label == null) + { + this.Label = attr.Label; + } + + // Combine ShowLabel and CenterLabel parameters. + this.ShowLabel |= attr.ShowLabel; + this.CenterLabel |= attr.CenterLabel; + } + } + + + + + + + + + + + The ID used to grouping properties together. + + + + + The name of the group. This is the last part of the group ID if there is a path, otherwise it is just the group ID. + + + + + The order of the group. + + + + + Whether to hide the group by default when all its children are not visible. True by default. + + + + + If not null, this resolved string controls the group's visibility. Note that if is true, there must be *both* a visible child *and* this condition must be true, before the group is shown. + + + + + Whether to animate the visibility changes of this group or make the visual transition instantly. True by default. + + + + + Initializes a new instance of the class. + + The group identifier. + The group order. + + + + Initializes a new instance of the class. + + The group identifier. + + + + Combines this attribute with another attribute of the same type. + This method invokes the virtual method to invoke custom combine logic. + All group attributes are combined to one attribute used by a single OdinGroupDrawer. + Example: protected override void CombineValuesWith(PropertyGroupAttribute other) { this.Title = this.Title ?? (other as MyGroupAttribute).Title; } + + The attribute to combine with. + The instance that the method was invoked on. + The argument 'other' was null. + + Attributes to combine are not of the same type. + or + PropertyGroupAttributes to combine must have the same group id. + + + + + Override this method to add custom combine logic to your group attribute. This method determines how your group's parameters combine when spread across multiple attribute declarations in the same class. + Remember, in .NET, member order is not guaranteed, so you never know which order your attributes will be combined in. + + The attribute to combine with. This parameter is guaranteed to be of the correct attribute type. + + This example shows how attributes are combined. + + protected override void CombineValuesWith(PropertyGroupAttribute other) + { + // The given attribute parameter is *guaranteed* to be of type BoxGroupAttribute. + var attr = other as BoxGroupAttribute; + + // If this attribute has no label, we the other group's label, thus preserving the label across combines. + if (this.Label == null) + { + this.Label = attr.Label; + } + + // Combine ShowLabel and CenterLabel parameters. + this.ShowLabel |= attr.ShowLabel; + this.CenterLabel |= attr.CenterLabel; + } + + + + + + PropertyOrder is used on any property, and allows for ordering of properties. + Use this to define in which order your properties are shown. + + + Lower order values will be drawn before higher values. + There is unfortunately no way of ensuring that properties are in the same order, as they appear in your class. PropertyOrder overcomes this. + + + The following example shows how PropertyOrder is used to order properties in the inspector. + + public class MyComponent : MonoBehaviour + { + [PropertyOrder(1)] + public int MySecondProperty; + + [PropertyOrder(-1)] + public int MyFirstProperty; + } + + + + + + The order for the property. + + + + + Initializes a new instance of the class. + + + + + Defines a custom order for the property. + + The order for the property. + + + + Required is used on any object property, and draws a message in the inspector if the property is missing. + Use this to clearly mark fields as necessary to the object. + + + The following example shows different uses of the Required attribute. + + public class MyComponent : MonoBehaviour + { + [Required] + public GameObject MyPrefab; + + [Required(InfoMessageType.Warning)] + public Texture2D MyTexture; + + [Required("MyMesh is nessessary for this component.")] + public Mesh MyMesh; + + [Required("MyTransform might be important.", InfoMessageType.Info)] + public Transform MyTransform; + } + + + + + + + + The message of the info box. + + + + + The type of the info box. + + + + + Adds an error box to the inspector, if the property is missing. + + + + + Adds an info box to the inspector, if the property is missing. + + The message to display in the error box. + The type of info box to draw. + + + + Adds an error box to the inspector, if the property is missing. + + The message to display in the error box. + + + + Adds an info box to the inspector, if the property is missing. + + The type of info box to draw. + + + + SceneObjectsOnly is used on object properties, and restricts the property to scene objects, and not project assets. + Use this when you want to ensure an object is a scene object, and not from a project asset. + + + The following example shows a component with a game object property, that must be from a scene, and not a prefab asset. + + public MyComponent : MonoBehaviour + { + [SceneObjectsOnly] + public GameObject MyPrefab; + } + + + + + + + ValueDropdown is used on any property and creates a dropdown with configurable options. + Use this to give the user a specific set of options to select from. + + + Due to a bug in Unity, enums will sometimes not work correctly. The last example shows how this can be fixed. + + + The following example shows a how the ValueDropdown can be used on an int property. + + public class MyComponent : MonoBehaviour + { + [ValueDropdown("myValues")] + public int MyInt; + + // The selectable values for the dropdown. + private int[] myValues = { 1, 2, 3 }; + } + + + + The following example shows how ValueDropdownList can be used for objects, that do not implement a usable ToString. + + public class MyComponent : MonoBehaviour + { + [ValueDropdown("myVectorValues")] + public Vector3 MyVector; + + // The selectable values for the dropdown, with custom names. + private ValueDropdownList<Vector3> myVectorValues = new ValueDropdownList<Vector3>() + { + {"Forward", Vector3.forward }, + {"Back", Vector3.back }, + {"Up", Vector3.up }, + {"Down", Vector3.down }, + {"Right", Vector3.right }, + {"Left", Vector3.left }, + }; + } + + + + The following example shows how the ValueDropdown can on any member that implements IList. + + public class MyComponent : MonoBehaviour + { + // Member field of type float[]. + private float[] valuesField; + + [ValueDropdown("valuesField")] + public float MyFloat; + + // Member property of type List<thing>. + private List<string> ValuesProperty { get; set; } + + [ValueDropdown("ValuesProperty")] + public string MyString; + + // Member function that returns an object of type IList. + private IList<ValueDropdownItem<int>> ValuesFunction() + { + return new ValueDropdownList<int> + { + { "The first option", 1 }, + { "The second option", 2 }, + { "The third option", 3 }, + }; + } + + [ValueDropdown("ValuesFunction")] + public int MyInt; + } + + + + Due to a bug in Unity, enums member arrays will in some cases appear as empty. This example shows how you can get around that. + + public class MyComponent : MonoBehaviour + { + // Make the field static. + private static MyEnum[] MyStaticEnumArray = MyEnum[] { ... }; + + // Force Unity to serialize the field, and hide the property from the inspector. + [SerializeField, HideInInspector] + private MyEnum MySerializedEnumArray = MyEnum[] { ... }; + } + + + + + + + Name of any field, property or method member that implements IList. E.g. arrays or Lists. Obsolete; use the ValuesGetter member instead. + + + + + A resolved string that should evaluate to a value that is assignable to IList; e.g, arrays and lists are compatible. + + + + + The number of items before enabling search. Default is 10. + + + + + False by default. + + + + + True by default. If the ValueDropdown attribute is applied to a list, then disabling this, + will render all child elements normally without using the ValueDropdown. The ValueDropdown will + still show up when you click the add button on the list drawer, unless is true. + + + + + False by default. + + + + + If the ValueDropdown attribute is applied to a list, and is set to true, then enabling this, + will exclude existing values, instead of rendering a checkbox indicating whether the item is already included or not. + + + + + If the dropdown renders a tree-view, then setting this to true will ensure everything is expanded by default. + + + + + If true, instead of replacing the drawer with a wide dropdown-field, the dropdown button will be a little button, drawn next to the other drawer. + + + + + Disables the the GUI for the appended drawer. False by default. + + + + + By default, a single click selects and confirms the selection. + + + + + By default, the dropdown will create a tree view. + + + + + Gets or sets the width of the dropdown. Default is zero. + + + + + Gets or sets the height of the dropdown. Default is zero. + + + + + Gets or sets the title for the dropdown. Null by default. + + + + + False by default. + + + + + Whether to draw all child properties in a foldout. + + + + + Whether values selected by the value dropdown should be copies of the original or references (in the case of reference types). Defaults to true. + + + + + Creates a dropdown menu for a property. + + A resolved string that should evaluate to a value that is assignable to IList; e.g, arrays and lists are compatible. + + + + + + + + + Gets the label for the dropdown item. + + The label text for the item. + + + + Gets the value of the dropdown item. + + The value for the item. + + + + Use this with to specify custom names for values. + + The type of the value. + + + + Adds the specified value with a custom name. + + The name of the item. + The value. + + + + Adds the specified value. + + The value. + + + + + + + + + The name of the item. + + + + + The value of the item. + + + + + Initializes a new instance of the class. + + The text to display for the dropdown item. + The value for the dropdown item. + + + + The name of this item. + + + + + Gets the text. + + + + + Gets the value. + + + + + + + + + + The name of the item. + + + + + The value of the item. + + + + + Initializes a new instance of the class. + + The text to display for the dropdown item. + The value for the dropdown item. + + + + Gets the text. + + + + + Gets the value. + + + + + The name of this item. + + + + + ShowInInspector is used on any member, and shows the value in the inspector. Note that the value being shown due to this attribute DOES NOT mean that the value is being serialized. + + + This can for example be combined with to allow for live debugging of values. + + + + The following example shows how ShowInInspector is used to show properties in the inspector, that otherwise wouldn't. + + public class MyComponent : MonoBehaviour + { + [ShowInInspector] + private int myField; + + [ShowInInspector] + public int MyProperty { get; set; } + } + + + + + + TabGroup is used on any property, and organizes properties into different tabs. + Use this to organize different value to make a clean and easy to use inspector. + + + Use groups to create multiple tab groups, each with multiple tabs and even sub tabs. + + + The following example shows how to create a tab group with two tabs. + + public class MyComponent : MonoBehaviour + { + [TabGroup("First")] + public int MyFirstInt; + + [TabGroup("First")] + public int AnotherInt; + + [TabGroup("Second")] + public int MySecondInt; + } + + + + The following example shows how multiple groups of tabs can be created. + + public class MyComponent : MonoBehaviour + { + [TabGroup("A", "FirstGroup")] + public int FirstGroupA; + + [TabGroup("B", "FirstGroup")] + public int FirstGroupB; + + // The second tab group has been configured to have constant height across all tabs. + [TabGroup("A", "SecondGroup", true)] + public int SecondgroupA; + + [TabGroup("B", "SecondGroup")] + public int SecondGroupB; + + [TabGroup("B", "SecondGroup")] + public int AnotherInt; + } + + + + This example demonstrates how multiple tabs groups can be combined to create tabs in tabs. + + public class MyComponent : MonoBehaviour + { + [TabGroup("ParentGroup", "First Tab")] + public int A; + + [TabGroup("ParentGroup", "Second Tab")] + public int B; + + // Specify 'First Tab' as a group, and another child group to the 'First Tab' group. + [TabGroup("ParentGroup/First Tab/InnerGroup", "Inside First Tab A")] + public int C; + + [TabGroup("ParentGroup/First Tab/InnerGroup", "Inside First Tab B")] + public int D; + + [TabGroup("ParentGroup/Second Tab/InnerGroup", "Inside Second Tab")] + public int E; + } + + + + + + + The default tab group name which is used when the single-parameter constructor is called. + + + + + Name of the tab. + + + + + Should this tab be the same height as the rest of the tab group. + + + + + If true, the content of each page will not be contained in any box. + + + + + If true, the tab group will be hidden if it only contains one tab. + + + + + Organizes the property into the specified tab in the default group. + Default group name is '_DefaultTabGroup' + + The tab. + if set to true [use fixed height]. + The order. + + + + Organizes the property into the specified tab in the specified group. + + The group to attach the tab to. + The name of the tab. + Set to true to have a constant height across the entire tab group. + The order of the group. + + + + Name of all tabs in this group. + + + + + Combines the tab group with another group. + + The other group. + + + + Not yet documented. + + Not yet documented. + + + + Not yet documented. + + Not yet documented. + + + + Title is used to make a bold header above a property. + + + The following example shows how Title is used on different properties. + + public class TitleExamples : MonoBehaviour + { + [Title("Titles and Headers")] + [InfoBox( + "The Title attribute has the same purpose as Unity's Header attribute," + + "but it also supports properties, and methods." + + "\n\nTitle also offers more features such as subtitles, options for horizontal underline, bold text and text alignment." + + "\n\nBoth attributes, with Odin, supports either static strings, or refering to members strings by adding a $ in front.")] + public string MyTitle = "My Dynamic Title"; + public string MySubtitle = "My Dynamic Subtitle"; + + [Title("Static title")] + public int C; + public int D; + + [Title("Static title", "Static subtitle")] + public int E; + public int F; + + [Title("$MyTitle", "$MySubtitle")] + public int G; + public int H; + + [Title("Non bold title", "$MySubtitle", bold: false)] + public int I; + public int J; + + [Title("Non bold title", "With no line seperator", horizontalLine: false, bold: false)] + public int K; + public int L; + + [Title("$MyTitle", "$MySubtitle", TitleAlignments.Right)] + public int M; + public int N; + + [Title("$MyTitle", "$MySubtitle", TitleAlignments.Centered)] + public int O; + public int P; + + [Title("$Combined", titleAlignment: TitleAlignments.Centered)] + public int Q; + public int R; + + [ShowInInspector] + [Title("Title on a Property")] + public int S { get; set; } + + [Title("Title on a Method")] + [Button] + public void DoNothing() + { } + + public string Combined { get { return this.MyTitle + " - " + this.MySubtitle; } } + } + + + + + + + + The title displayed above the property in the inspector. + + + + + Optional subtitle. + + + + + If true the title will be displayed with a bold font. + + + + + Gets a value indicating whether or not to draw a horizontal line below the title. + + + + + Title alignment. + + + + + Creates a title above any property in the inspector. + + The title displayed above the property in the inspector. + Optional subtitle + Title alignment + Horizontal line + If true the title will be drawn with a bold font. + + + + Toggle is used on any field or property, and allows to enable or disable the property in the inspector. + Use this to create a property that can be turned off or on. + + + Toggle does current not support any static members for toggling. + + + The following example shows how Toggle is used to create a toggleable property. + + public class MyComponent : MonoBehaviour + { + [Toggle("Enabled")] + public MyToggleable MyToggler = new MyToggleable(); + } + + public class MyToggleable + { + public bool Enabled; + + public int MyValue; + } + + + + + + + + Name of any bool field or property to enable or disable the object. + + + + + If true, all other open toggle groups will collapse once another one opens. + + + + + Create a togglable property in the inspector. + + Name of any bool field or property to enable or disable the object. + + + + ToggleGroup is used on any field, and create a toggleable group of options. + Use this to create options that can be enabled or disabled. + + + The functions as the ID for the ToggleGroup, and therefore all members of a toggle group must specify the same toggle member. + This attribute does not support static members! + + + The following example shows how ToggleGroup is used to create two separate toggleable groups. + + public class MyComponent : MonoBehaviour + { + // This attribute has a title specified for the group. The title only needs to be applied to a single attribute for a group. + [ToggleGroup("FirstToggle", order: -1, groupTitle: "First")] + public bool FirstToggle; + + [ToggleGroup("FirstToggle")] + public int MyInt; + + // This group specifies a member string as the title of the group. A property or a function can also be used. + [ToggleGroup("SecondToggle", titleStringMemberName: "SecondGroupTitle")] + public bool SecondToggle { get; set; } + + [ToggleGroup("SecondToggle")] + public float MyFloat; + + [HideInInspector] + public string SecondGroupTitle = "Second"; + } + + + + "/> + + + + Title of the toggle group in the inspector. + If null will be used instead. + + + + + If true, all other open toggle groups will collapse once another one opens. + + + + + Creates a ToggleGroup. See . + + Name of any bool field or property to enable or disable the ToggleGroup. + The order of the group. + Use this to name the group differently than toggleMemberName. + + + + Creates a ToggleGroup. See . + + Name of any bool field or property to enable or disable the ToggleGroup. + Use this to name the group differently than toggleMemberName. + + + + Obsolete constructor overload. + + Obsolete overload. + Obsolete overload. + Obsolete overload. + Obsolete overload. + + + + Name of any bool field, property or function to enable or disable the ToggleGroup. + + + + + Name of any string field, property or function, to title the toggle group in the inspector. + If null will be used instead. + + + + + Combines the ToggleGroup with another ToggleGroup. + + Another ToggleGroup. + + + + ValidateInput is used on any property, and allows to validate input from inspector. + Use this to enforce correct values. + + + ValidateInput refuses invalid values. + ValidateInput only works in the editor. Values changed through scripting will not be validated. + + + The following examples shows how a speed value can be forced to be above 0. + + public class MyComponent : MonoBehaviour + { + [ValidateInput("ValidateInput")] + public float Speed; + + // Specify custom output message and message type. + [ValidateInput("ValidateInput", "Health must be more than 0!", InfoMessageType.Warning)] + public float Health; + + private bool ValidateInput(float property) + { + return property > 0f; + } + } + + + + The following example shows how a static function could also be used. + + public class MyComponent : MonoBehaviour + { + [ValidateInput("StaticValidateFunction")] + public int MyInt; + + private static bool StaticValidateFunction(int property) + { + return property != 0; + } + } + + + + + + + + Default message for invalid values. + + + + + OBSOLETE; use the Condition member instead. + A resolved string that should evaluate to a boolean value, and which should validate the input. Note that in expressions, the $value named parameter, and in methods, a parameter named value, can be used to get the validated value instead of referring to the value by its containing member. This makes it easier to reuse validation strings. + + + + + A resolved string that should evaluate to a boolean value, and which should validate the input. Note that in expressions, the $value named parameter, and in methods, a parameter named value, can be used to get the validated value instead of referring to the value by its containing member. This makes it easier to reuse validation strings. + + + + + The type of the message. + + + + + Whether to also trigger validation when changes to child values happen. This is true by default. + + + + + If true, the validation method will not only be executed when the User has changed the value. It'll run once every frame in the inspector. + + + + + Initializes a new instance of the class. + + A resolved string that should evaluate to a boolean value, and which should validate the input. Note that in expressions, the $value named parameter, and in methods, a parameter named value, can be used to get the validated value instead of referring to the value by its containing member. This makes it easier to reuse validation strings. + Default message for invalid values. + Type of the message. + + + + Obsolete. Rejecting invalid input is no longer supported. Use the other constructors instead. + + Obsolete overload. + Obsolete overload. + Obsolete overload. + Obsolete overload. + + + + ShowIf is used on any property and can hide the property in the inspector. + Use this to hide irrelevant properties based on the current state of the object. + + + This example shows a component with fields hidden by the state of another field. + + public class MyComponent : MonoBehaviour + { + public bool ShowProperties; + + [ShowIf("showProperties")] + public int MyInt; + + [ShowIf("showProperties", false)] + public string MyString; + + public SomeEnum SomeEnumField; + + [ShowIf("SomeEnumField", SomeEnum.SomeEnumMember)] + public string SomeString; + } + + + + This example shows a component with a field that is hidden when the game object is inactive. + + public class MyComponent : MonoBehaviour + { + [ShowIf("MyVisibleFunction")] + public int MyHideableField; + + private bool MyVisibleFunction() + { + return this.gameObject.activeInHierarchy; + } + } + + + + + + + + + The name of a bool member field, property or method. Obsolete; use the Condition member instead. + + + + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + + + + + The optional condition value. + + + + + Whether or not to slide the property in and out when the state changes. + + + + + Shows a property in the inspector, based on the value of a resolved string. + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + Whether or not to slide the property in and out when the state changes. + + + + Shows a property in the inspector, if the resolved string evaluates to the specified value. + + A resolved string that defines the condition to check the value of, such as a member name or an expression. + Value to check against. + Whether or not to slide the property in and out when the state changes. + + + + Wrap is used on most primitive property, and allows for wrapping the value when it goes out of the defined range. + Use this when you want a value that goes around in circle, like for example an angle. + + + Currently unsigned primitives are not supported. + + + The following example show how Wrap is used on a property. + + public class MyComponent : MonoBehaviour + { + [Wrap(-100, 100)] + public float MyFloat; + } + + + + + + + The lowest value for the property. + + + + + The highest value for the property. + + + + + Wraps the value of the property round when the values goes out of range. + + The lowest value for the property. + The highest value for the property. + + + + Type of info message box. This enum matches Unity's MessageType enum which could not be used since it is located in the UnityEditor assembly. + + + + + Generic message box with no type. + + + + + Information message box. + + + + + Warning message box. + + + + + Error message box. + + + + diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.xml.meta b/Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.xml.meta new file mode 100644 index 0000000..69c0201 --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.xml.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 47a84ebde4ec47fabb620b30cc7a096f +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.dll b/Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.dll new file mode 100644 index 0000000000000000000000000000000000000000..7edfb7f2d8fddcdf507145a3fe7379c55450f910 GIT binary patch literal 1506816 zcmd?S37A|()i-|U_U(Inn@R5UqF@>eQ*KQ+w6HM_+G548ySS|MJU*aX(D{mdW>(KjZLj>wU1zxG(ZW!Qgx?XMdnhfSTc{BsK>wCyjTEf2XJ(Dr0qnJyeKpnvI|ldup>TuepL)^x zaCiIxX@sAoRr4L70er$>sa!f40O5^kx8e8;!i0XykX?hNQ_uE+NL~%_EHe1#6ucFo zU}Aj><%%D9GmWTm{Yu-o_KBHBi$MSV&s?)&wHS#U%qY#HOwWdCMydpxR#l*ek=`X@ z>{{ z(V@V865eYyxE|I|5u8i!;uvp{^crqQ2^?(b+}s6L1~Mw@M7z=6GC6CxVe~lH@>}dU zk4Cb+MZ2v99r@&BhCsg+G`9|9ReDqHW_x6E)*5)kujLm(X|%RSv|9%yPzCkcm=wrs zhBjwv)1_Ie$&cQUAAQYeRXmXf%JFcRsKb!sN+rkrv?v(F7P?A~3$+|c!>;fva)f-_ zNwq?vwtW3GtdOtJKM?f!>pS~{)*l;W%?PHEwNMsWYwS9CzXL(mlCEQX88lJlkOvEq z2VJ#1Al3gc4;b@*kOu>uD)DKn-D;0c&N>3Q<3_KgQOul2BOPsz1`wTv1c$TG=-I_G zN~pt8q^Ud$oQ!Ai*~U`hWnuF=@hNuK0i~;vZm$c_ayLGkwq1%+D5!o9+@(*z+n){F z_#Ax3_$g$>DE%E?y}S8y>Dh}a#-m-r4EiFdN_&m63j(+Xf4<%)MC*>&5 zhndWz7GK{2{SupKZMP<85ux3xla2cW!15O0a|csYeI0D=mI7Bjaky567H?;KsyTe( zS-6dSItmK}lTX`m4<$99b^t)u=hLxv%Z+wSMyf?cAzFyLQGXDQe6)n}xS_gGc{oJc z1$H-9ScE{a%C2w>6zv5HjnM%(1f!6Kzf~c`TZE6WGDayCc8`nrGX8FGrQ>dVOJS#W zOZ?n;X2O3xz~@tHjfA(ir;%1S;qOjzDganM>vrE82rjk(tQDZnwx9u5)9)-ej7 zE^@YYjD-UZ$}#5ep&U$LG3L0IznI|c+Eff#H+uTy%P%|rFhJu=@TupDhq9I*-wUvu zVJz1T)MKbuP=LlZ{I|nCAEl~$Opv;Tqg=PJ0)x!LAW_yy)3^}$Xky$@6jEyK@>1Yz zDv#hBj(-&Hq$yg`gBDMuGOhWX6Zecy?`T-0`8a5<^eg z{@yUjgJrOha=?Q~$ZR+Kec)9v?OX|3X~PU7qb?YrR8Y zH7gLY)p>le2YBP7q0f^~95hls6e#(qcNh$BH9igyjAh;$x(~;v(>ns+5Zxa&(9QlQ zbdRjjt;bus5Q0J*16~X5%JhyR6RfMKYL~)WaJ)AFkZN!7*1`m{%a*P6*1;MpAB}Iu zdn3NB-ZA)k#|q#$eAB3J@e_uTSi?IWZiIvIPN>;VBo6c^;E%8LP7+sdk9RUGW2<6@ zHBihh7&`!#NqhSY!!Dl!kAZRecqokdu>%`%o~z@~N8udQi1Q=joF;VWv8BZ@S(*Emiw?+a{uw(c z*MLk=%?(3&zZI~gGj=VEthX6oCzHu$vfdV0f$`oI-gU64EVv#vyRsE|+L}pQi*JHB zxNQKP5o#ZLqQyrJZ&sq;}Vd+9l{lAdogR)Z1Zgr*0iz=Dj0izX^8N@lY=k zMaO#=46Te6ldkPXb!<1oPlczpbFJ)JQEF&>Pk8y|m%Rx9CC%tvN)rHs@xwrOfgz1i z@7+YYRXMfDP?S)XqQ=KzCZ#N~;x4%p&eHR!t=?@w@9^G(FG{rOy%!cn@jgZ6@fGVp zdjFN)R^^6%MV(>UM_o$TPUQ|5{+;+#@4|<;EAZ)Cp?sVQq2&+YV@n9{Zdkp06zao7 zeSA4S?^Pc`6kq>?K=D6>kJN>TF#v`!wsboZqGUR}55q6%6k0{yI351Ia3hjAs8%Y? zmT?Tiv?7d$gy%hk&L`{+?_)qL43thZk$Ct5=6wPnaPg0oQ512IE$a0I>joajBJCG4>Ehl;RPH z?6V}M#(f7NjbH$2MDEx{GXn($(O88(?_ppiywBmA^gfSo%64Mj7hov>E1NUDoe`oi zQ<)L}i{g_7Q!J|&fi9GUoAn+6yp%??W~Cd1y+`53$jo~Trf}kY2{x@3zD(pikV8F% zf^B+5MCCnBJdb^aLa$lr0kKT^c{G~?+3FE&OtaM^VfbGG0(dYD1Y+OS9XlpyYTpRU zr2PV$+OGm@V4ObC6{KbRUt_>kXl558w(=8jc~2@@jJ6bi^m z3G1O?Xf{pn8}LFm&qLoiQDvG<@0*H_Wmr&@9iUVGE0{>wk+EYNd3%w(Jq7H6ar$^D zKl!oa8gYI@oNoyZeLUn}zWg0VwjR#N*zt|%za{#21)VlhpCtoJM<<~ZW?#&}O@r1{5sy!27=p4y1>r+U2fX^uCdqO??$M|s;3 zv;Q1Ea|h8`P=aFFgFZPLCVvX5C2?9~Y=5qEL?6Y`>5VvlsdGf1I!BN|58~N^IG{{i zUAQ?mE&m7{Raw+kwEmCbPUKgk9{&Wkq*FNzl#0up%270joXX)a3$CLq-Y{farI$hw z4?1Q1P+dchY?UNH@TVYHyc0b#4ARh!20b!pUKDiGm}eY!Db=!)Ngqt=*fA6i%M6+j z4)ma}y`O;;?H#!NAl2=HZkc8e!t zHT~bh&NTdYX_I-=e~Glw()2MYY2CmJy+05EO_)_0Nicx87r@O43L2{-Dm>{$ zyg!oR?lBU`trD7%fpNM5ACh7iA;~Br-k($$AqpRw5}Ecv;$Fu<&u?2X z+P}xu^VGaR*!z(`pE25h=0it}_J91=g;Tw|tP4i_FaFhOqy5J{c)(QecR#vpwEw=x zcOUJ){PVe~-e*4arx9?~KH4Aq&@)q6d-tR79qE7gJwF)fUvvL$Q@uCd*g4w&^z9!V z!Dqu%@7^nuqx~N(eP9Hs+d9?zYwsHv?LXo9!$yE}##HY$_irERU-<0&k^TYuvZYg` zcHiTl8tMPX*gYft)=^ughTiFi7mxPu|Km-g{UV@dnLqMpZv+y#W~Be#{eIj`++WGe z%lP}i@c$ah*_)bk_J@BT8|}aCrPD|IQ|1d(nGo?EwmCc6zwAMw*uNBjSIx7*D54#l^%S$vYX$!{-a@t>xEeCMM0X#btJ>^*|QIeV%A zL_T{ycc|d(HKl+Ek5Z}=Pv1V(d(Y?m(f;B4-ZIkPe);F8=FQT?(<4gmFRorZHSSOS zv8t=I-+uX?Q{qlMeKPCpeIxyk^?h_IabfNGZ9f_5pEmU7cMgvBKl#M9BmEB^keV8I z>_hJ!>EHXUXOHxM=b~RtC4T2EkB;>J>0jR-LBYIhs<#xDcR$+4xFb`=B8B;w>-t%7 zr>T^$l4EP`9~p(JK*jykAOAI#c;e}mqy3V)X^PE2zepN7Wu$-N=9{N-F2(WUU;TUp zh3>p&?;RGp4>cFMC!aW5GjZX=z0GBJ0HtA>7VL@>PMs=z(cq#pBnOz2VP!38mr^DA zsnL6fJU-OSqZFOt`yOA~KW*7P?!lc$LyR`YGN2UFowv-VYMQ15NWHo5@uR3c-aj>k zqLmQ$$n#a4~f6woqn##n!pE`WBU!oEf-<-nO zhxVfC`TbH9^dqK*-utbo(S9jN)3!_Z{JzBcg<>##-~Llez?CnYH`@P&ub#-JZI`Lu zKm7Y~qy3_G=6!T%s`rymJTXGLBT(-bO=V5m9I1ZO)UO?i@4L<7lM*16{HJ&9IUN%R zu@ZH$$1x3$QhxXU@juw~PviaWM}I`E*tY{6z#b2}6li`Qeoyz*xDVRn>ZPh_l~UZ8 zbvsPqi_IxK^P$}oZ75fnJ8Z0I(w!ph{_OX^K2^*+{qXNfL-b$vj>uFVdlnwczQrj! z=p9HN3UMh0jY$~j?^*clUP$387NUciiSICl|7cF3v`tb}Pk4S?vpyT>|G<~>y609t zld~VnpcxscFq|ODiBU?6`NosiB3W^gyNa-W*yaB2DF= z{&oHiLd&4w%^9SjIkfaGL`R7tZ}gs$H&qT-Oz&?T)?nW9b)2_c;bFqV<^&@q&p5$& z6$W#(DnP*%|6-yv8yV{Tok6>0q7VjW3Sn@nkmJl2&gvVOgLKC*k!ls}((?#|DUEXx z1110`GoLjLQ#L z@1IjVu%n1vbPn33V};I*{N5yt7H2CNq?Li$L8d=5*#c>Bc9Ro?>k&9KK?v!c2?)oo zJ(&CKG7STh46gS+E`od*pF&a+uLkfk5nKKjnDQs_Nq8^g+qoIDo7g?nd(5o^+1`b> z`k3j!w2GkF^7UE(0UIg1^cc96snb@w^g>`yTXDg|5{RWNcG*Obw4;oe8!f#IWIsY+ zB9l($&u|lNaw45_Q^HBQHCA}Na5pVCrDUtI!ELpD3k3WqKC;f6Zq2)Ht0U0tT7joq zUB_+pZJ@YGEP^E6q?_2Xe&~AF4zbXdNzVWaZSIVT^h|fAVgWldUX=xR3JWe+a2r{0 z-I(ht7G{8j8SV_XjV!2=#%&wLm?{P7xaW}5cy`cnjKpk9vSv&l=~`wYv8n#;Pk<&<{QhEwLn88ZHmUMcL>0Riz!kRK;me&Rgyk@{CKBMNzj-NVD<`~{Wqm8s54oxa9 zno%#6j`8nTTtg*4&wrWU1^@)n!GXXl8Sr zxh0rf6J6oCK+nz1st_`tg9%>)Q{nCyCd#d1e%no)#>}z~^x%{AFvErwlA=>ulQA~r zu`<)n7>O()a!b52vmy;BtK!zNT}h{>bSBU*rQO4fWgd#j#e(fHgx0E`<`m+lzm z^{0y)I!eWTiH^I2aT8fW+bVs88O02Nkd5_zn`&~E#)z{ue_+Q3|CY-b~md94=CAMb~F_)`Ij zi_HpIFe^-o|1a=g=)#n52!@qwTgc^8W@hv5SjZKZ3J+zibX5C+ z=33P*7z5gWBao}z0Hn4Xu>v-mk>{?#Smdyn-vcI^b9D3xY}(;qr<-#(QU-sqX`DR*`V(~isq=gC;akQxf95*1BmHOuw;7g zVnIcdygRUR+m#tvgw=@3C?KFzN38cSt>{{Cc=Zh%vb55y!|;yBlRoSZcY{Hu*kjEkRk4} zW@$vCVOSv>Q7j6vh(8w*DU=$YWGIOHn}{3p?x@qy>Q=GUEcYTnm5%%Y3K;SG04nU+ zBU>y7GNr>1A9evpwhnZb&JcT-&PJA+tpnYqdkOXCA(-k)l>dRHoP@pYRH%Q^rq%PX zhGG@w*=8i_byGGa0BpNL!%t90`LN~Z+tF(osCusQrXfB7d;U~ya*Bwwy`2zKadt!sm~!+* zRACUG`T0dwc1?5}R%+EA*VWmam3cLQN=E@zkm3i!{(K64mZijkMVB>EyF$rnaviI& zYng4bWqcdvJn}7Jhp&aRiOeO6N-<_vD8+m-Ba*}P2bUG)r< z1udiE|yCSN5c8|t10<7{9SqW@z$NIK{*_ismB+$bWpcMpo?9(;1}BO9&QLiy*ix~WD7+#}RVS6Zt^k3Ur)@H|aE@`zx(iRyBsgIX4DM3W^LQ z;a`<`;l0qRc}_{bA|+JGlCQ7Cyc$<5HFhs6-dXnV0)JQob$jFbctk1DB`PSCcWiU| z1loo6r@NFBdygtjTL)&B)(T*bYBshG%q^WpfH#O_B_vmiZFcEQz+_;W$Pabv$k1?Q zOYfJ^o%QU$_Ipq`TL-$rWNdFCs8Oa7V-#a(^mBB%S)n<-odxidreSl7`0HZviH)5o zL)>InnB`g#|8g`#+mo^hP<4=He|QYzzHey?mw`euleV$J+_iOZ?5#y`rxrZs2K{Rn z-7#(-bU@)7n!;6}fRW11%Bg`;Gkyr4L9`V0xjo#l3bxi5oOz+ETEB-~C-rpxUD8QsIFk?D53 z12UZ;)9H2!ha^M6r_*k_I2Y3iNxv@gwy=vBoN!pO3$|S5j1~^AjGU3!%}BD}Y#8g& zc?#?=8>wWAhA(eP9UR!-)iUz~f&ICbnJ+1OBAYwTtU#$@{>k)ql?qK)WJ2w$U>6Vgd!=H!wq!wWB1_!sR%$h!)E$da?!06IgfOs&J zVt{068)}z2tN;~6m}&aE!>E$G?a73_$;=4+8FOq8fXa*M$*42Q{CvfdGl5Oh1jYQl zAZSSfj*9@`WY;D!AxK)t&~HMf(C-}0w|Pc{GBsg$^Xil(2Fgo-h`wONI1gAzH~8EW zpk_V^1D|`rs4k^FQx#B%!x4Zn7zT$#uqUX1VR7ml+QOk8G!aQST%ZD|e2H*QMa!O{ zRqixM8~)_C32$nyXu8M;Boi7+bd_bi1*OWPu382V_Lwe*k#sWt3Ybo5P7mhXR>Hc# zDIE;ES;2VBx)z;Y>>$4vl}7n+s&$>ziTTg8vuse;@uI$N%DA;Nz4| z7DD@hP*!L-rLzRGe+Y7+Kn`GJ*v8nR5EtJi;hV7+Uq3C_DNRcxf9llu@~d}*ym%_R z`T0{}Q%O3d%Owe`8k69Z-UqN2sZ0X2ZpY?Y%o(Bkk$5Ja;~6G2A9Bp~0^|+0>vIpj z{JtA4q|DM?H3DWt5i(03uETJa1V_R?NxZ>kRzIJSYZLJjdR!YDss`}+W+ z0CQiM*+~;K#EDtC?(%+cZVGCH3Xd`(J7W9$1H(TJl*$-YB>V&5l!6@bSHU{; zEDPCzu*n?O4#R$7hhYz5*rPBIi}o|=WBX#We20f}m(LyD2yL?zczWbB%}ATo7PX?~ zgF&&)_SP`g4}K6H;!=6F0(=&_K~yklB1DX&hAxy8?be;O7~*4v2aJK-q}O zUh$n#Hp+(~6^XVej;OUo{nc<_SFCqEx-2H6u)Vc4%H3l}pkO1H$HfdW`RgVo#mzEg z8|dMnHG{7CIdCGqvwJV`*DywV3o5{t_1Rqyo)dKPK8Ny)zL#L?0c2+>JDWh&$6F-! z9t0Bw!Cu~e1WBh(O<0?DWWmYJqVeEjNh7rmXN1QR| ze+&p$j>RXi9|ya4JU;1|Sz#u}CS;HH2?WK>3QI#6gmEV`Jq${^asNb;OeiBM28JMu zKa7HhrL$K5BvQj5q;fJX7<=pk$w|A4KA(X;jFCSL-TAi4De(7C#iw{~&F!}NrvZ{b z#*H^%98_}$7)#KZ57Wri+yO?X+ja?gn9N|P(IO3g`E(+jqi)Mng20u3#M5Tm* zp&NB}xbdwz7u*DFB78TwHIKZJ?4Na;oXQTBKB>#2=llytv@;{0foz@4EQ#s%Ogf#% zVHXB-({E3AxE-0HxZCb_*lv1atDD9c2?HLe@Sz`=71pJ~3CgUi2)BL9`oTCBYv`R{ z&f%OF!f|Iw$p_6@6LqxiU=$a^6eforRS-;RV=&ng!;CWNYP7$io}s#~1qACpja75e zLR13!piN0t<{>%UD&Ae5;#9f-sb1f_`G!ULQ)CHxHlk*~r!^m51s533X~X zR%TNyu0DOj@?anS-;LhGsIM1w5HDWBAp5x9bwwE{1drkm#=WKQ7_~!wZNzcs> zxwGB56X{;Jw}P7;5^k5MmEtUS4j^SfWUS@(`sdSkE(9>wor_r34}EES40JXE{EVwd z!y%?sndz2cuAZ~{jJ5oqRty}Y?Xrx$VHT-BWo;e}uLVj;+gXV7Teh<(hWSCxs^_w) ze79-G*7+B}6>+p>5Li-7on3#DmG*1|^aeo>{nvpIA9h`KNyoboGzwS_R_$R^5g2-$ z6YJ~~>;zh9AKhqXjgp!*fk_p!BWFk2&1idzf058}aCAe`(u(XxTa0sR%>5$HOis?a z5KUAp#}x=~5Tejwss%Xa4LJWdpG zquTidoZibUhEasa0o5ttznovhDXH$p@V3{&NFhj0K}`wtlmk&pABFkMpXrYwdO5=< zBb34}W__gMS18cAVaO$bY(qNLLi{2*)yH!4I?FJ2g{-AI6|qc6kr&X`P=v)+EV%G$ z8%p2FMZAAen2;#;$gGL@oZni4?x7Kp`I_OUYgXm{a^1~A)bOVp-7=^WR)=q$&Zmjx zOH?dEnp1)&#?*@E{zw$&%{XHu9C6Q!oraR4Dvrx3;li$NH0Iw7jCR{cUm#KFbM49) zEm>`GEw3M{r{HAD1-alaD~IngIlT2ZLhsN+GT3D2ZK; z5XE=6=vBx~0n!D)vEy^095U%teqYrvxv2@x8Y1bf5tZ~dopcLr@D-q;OCXEvWD7Q0 ztjVgRyD3mcqpIj2_4jh~&Y%*8-oR7na%U>CDy0c9-l>D@EjTsdeMz+!g_s@*dCAT#vhJO|;vq`o%<2@NU+g8-Sdn;%pjp@n_)05)L+4TI9IWwq-f zz34D#%(LM)^hhWIiL%hGAUd`yfK+3z-UAKsqWa4v4dE^UO_J8ZqeF1%ho(_7SyX&_ zD@fXHSI57K2{)||f&~dgbId*{`v`7YbzK85TNG1af0ez3Wp-#|z#`@8GtWcWKiH#@ zSeFWp&PZJx8dL!K>b9{P^fNX~sRFm`gz~NglR1@EY~ZBjWj(=omof4ZE!E~QQZ8yN z>XiYnngioN@c;s3h^sh>W)>z(=K!c;#jKo+xXM?7P3$Q-nT9HgRrYiTqE%LuR&1Pv z;xi*S6dmPNSvG{nS{|1kWk_3F_2$vUwI0Cq-V6fUW9SXBfeP-L_@c2skM0zH+(TG_ z4qgO#mj6dq_|58tSpBiB>IE?VZ^#(4kQ_GH6-F>oJ)g0u${v8q3PiyNpp67oh+Ev} zwPk|}sYmEj^TH_q6Uj|FcC`YcIw!C&L%~)r0?3hUsa{NLM|Bg7NY=j(z6+d+04v0j zj8Xtyr?`j5sgS57Q0?ZSntcWTRBZU;DAloz?1?YIB?xHKq&jW_vFzYNtji!`zltuf zsDmY#><3B>xb2o;m%^TB!bkBVdoinTLCmU%WHbKHN#%Mdq1MHD;KlvxU}rx=VjIRL zIRkdtzO*kaA}fac)HXt`y5aePZhG`UyV=C!fXhH z;L>i{@X^9!UTbiBRJ9$O+^7&JbZCp#+t(me@mLKjrrc;f=^Ch`9BvG!Vq?}8vHz80 zTFGapLXeId*L!i?7WYRWswH2=7OCxX;|0{crEou^a;%V2N$C)2M~9P;n69+4Nl>SV z#X6KYZDq;kPQRegFx`%nEk#tKZ=k?(=f4$9p(IK+=c~fdoptoI$tWWAx)zxum*>8P6!&(KJ!#K zXVU%`PlNNa1OI0zOd+*oEXUdz<}ZxjKypj*pNl}caPvp_b8znlGYwrO3*{RA63olt zR{~rV8r;-rUqPVPqkR6~&|g8*fHp!k7XQ^YB4`v;(QdWl?UpM1ZI~TagM(*rz8V9D zXe{t6c4yO3QCFWl6m z`zaf*=B$A3HObCID+EVhvtVIkbM)C0LCB5yH?a7uM7VS!zc1!`meY#4A1s)@jiqS_ zcgNjGO9zyOZbvauQ6(&o6?N_HCV4AKUcjKjN>}{Y_F1mlnJSYl4)%~sqxyGWOq;rP(6Yy+n>YV-2*2!X87-5PR^AQDEV)D^H~CEM?qDl75wY-u&ty=byueyTn!}*g%EC8&gZd4b5o?3q4S}!R8${V?lc@*S6zB&xX zq@VvU=46nMFKrF-(K0@Oy1E$o7%e7CcXPlXcWq9pRYXv^MBE6*pzI{jN=M^nMp@itf& z1Wn!dwx=*xlTaPMKLRDOPY%6l)Ztu~rD)%go7TtX2DaNY-;;28Kj`#F*NW$@-)% zbMD>(WLPR%Je+f}D=3Vu6gbNtC(|8u72Hm6mf?)}??h)x=VTkPZwD0Zz&iH9P>S%4 z`R@m8=)U|}(d?qrRfy6jQH*5cV%la2T^d7wOCrK7UO1w;a55s-R_nir!%=ZGlvEwZ z1K6<}^RQB3+cEzR1oQ6X=PrC&J!lg>2K2d2up{H&1|y94?0M)!hvYYgS!!$98US?< zdj6}-vOJ4TO~6$h;$USEmn7;1LDcQ}*s>=#j9R1cZE8QY>u zeujdC3C)zu2g(L(rJ)5Th1yL?4OXI`q3Z5TbRk(+QQvA+7FDulSJl@=^>tPC#jZwo zMy>kJblY|Hbyc5{)z?M!b#?Wf=}YxZW9*ey)wct6zC+bAuol>ofemO1Mnc~;WnvVoSGt3r>RxxUyjR^h&wasuEkd} zca)dgH6c0_YhNluu;TRw3<=XcuPHBPBQIvFyufmp+f&PnPAp$3RXV$#7qgKUvvpo{ zp-y5|PP2g->$5Opjnz2Gp}EMRxhjWxk^bIV4h6Pk00UYrhvqir5Vq0&dur2Ieu>hL zSD`#pZ+;wR3MPNB8ehhTeM4>$2|g&D?&YBN3x*mvR7mdx+si1bq!7~TzJTr??@pfR75=V&)#akVrQgL;wt za8!0YzCGcfTcI+;R#La}I6J4L9>u-tO6btH%F?&ITS?7O{7#K%jrsYGF+YHxfiw?zkce;p4O)wSTzCBT&U2>F| zVh~eIi7AdTcOWKhfta)nNHsCV8pI^~XieNKx#2^BoE|oYepi>%3e@GjL{4ngN>2y! zf%@i>yPEft>4T&*+zDinWXh>4mDYF>C$sAs1v6x#P$0BO9lX~K$dIW2VG&pU-1ew< zua=9nb?kZtZR%>*5fQ5s*jmJBBb6H>c9boEXc1$e-_$B13kK6tZkP+23k2alN8}<0~^jru-Xv8YJ={AYfQ(7X28x* ze!bU8AG2olJh%~W58kNw3$g}tCT@8Kbocm4AezmV|Am9C<0r#D_6YG#a=$FXvm*alUhR%yKs+^L*&cnBhq%2#6kr(kJ~`=5qUJUh-iS@XqH#z>ea zU=NcMu<`0Aamo}AEqItUwX2_2j%{FB6TP3Iov{aCkR_X-u%G1|b*uo8bdY(s!>ORHT&2VNbTZOW58H$=*Tu!sFCm4vI@$3* z1Jd3@_@rZ*bbRrxgk#ARy%cl+n5-pN092O%pqP+M6wY&T@jO#|MpJ6tgibCHLg{rA zq4b0kJUd8m1I9Ed#ti{$x%TSfK*{J@HdMjD#P&Z6Mn?;PsbXADKFc1;f@!QaHg6B= z`4Zz^T@G7Imhi&}xL7ro*TRf40PHLjqX?l;qJfGDnp}cJW zQ9yX0zx)_1Rm$A-(7och)`;v20WEjzG{AAR)&COdbYc5F1d{i#y)~auezuP)n~2)7 z`ImdRyGUcj7*_tQGN!;2<0OG|)tE*2G^&Q0MW~l=Q;Ih{ze&$H0&EI#OM(xe_#;-y z2ec2ya`2_{om*%!IngL;e>&E1Iq>=_sNmI?(-E}MF)#%_Nf{mFJ%88J3t@el_Wydkkk%f+2Y0I4s-V=y`&2R6r!Cl;F_h8=Mb|xzW zltm)rKgsB4WLvQt%=;BWUPc-E$>@QnaZCtm=6tE zAbEK^aQ6=3CLKsL(>kWmO)cga#oX!?&UQj#Mx_PQ>s+gQ@Cauc2sMa#aW>Te#9}>i zhO;{vscn>U9i>qE6z&VxO@5sz%Kug;V129Xn&TU?f7WqadfQ4o`YLn z5BU)+llG5^^Ap0x>EoeGpO+&VyoEepJ`}4TV)F)B^LZEoYfW_~9sg$t<*=ewn0i%D zsfYGO`mu@md3c+ZpX1A;=)Zu8%`KMyOIUK;Q$#`5^w%K>w;#equ0<{H@qY!RTHqE5 zjN*Wk!oMaN*rJyI0<0SS#hTT@WiYs>AuF+iC!Vpy2#;^JVNab1P7c(4kv;NA5pnz$ zVQsnf;U(Do-{E6ceoyNkXtk?Ez>Ezc+#kaRLty&ZiS7rVN6UN`g(1`zlV+_MD>K6`3{t2tvt2oO3hzjig z3s8TOST;KA*n>waPO^~^bUg6hSpvIQB~5Umx19h|3!xm-V3qY9q0VS5k8QZ*Ne77e zCNTX7J_}sL&HY|lJ{Dj@PvM;0Ot$+!HHK!X_Wcl*E7l#%VL!@{xuH-_)f~*_TqCwE z*uOT*4lGsSW0uN+a*Pm`KeLS6{S#Ft&y+`&s?09aO90wXK~bhyC%+5x0M^MQ5cp6+ z3MT4gD~$@jQYUF?u9Iywl%P(&6~t5^T_+iAx;i-n@Ssl4qB2|qWIHUAHr@{i z>Lh)nPBzrPIzvJItJk|#s@|dJjLe&bFY8?fChOhp%#6l*$GYJoIS1D3T^87QWTF!W zI^SI|QYzzOxH|?eor^uNVjH3tk1lG{neER8EZ?rN;}V^~WH+Hb^zHBvJSa11WA!Pj zuSi}FMLj)ehxK$0=&O1<7dBl_dui46ln71r6g>*5w^QrsF=mBiYW0-jVm%dcxvsTk zy{>|k$Y4-$>DWv`vf@e*)Yv`-mD-ODv?3){MTg#`aQt~d@cZ%M-dT(TccK-$j>rJk zzJvP7w7@C#6RSXQN&UoN5pSjFT@akKMg3&dW<>%xs(uatvLNWED=)vXe*VxHYE|`f zmCiC%Kbdc}8p({UIhb0gP|=~+z&yCAoTv(p32YXZR7{FXtD+sBT3pf=*S_{}t>P?s zS`ly8Ng;9MUB%)o9Z*A6agx&|di~2DdUSiDKKKG-O7C%v?W11BIP+M z34QH+=9jvb6%=eoaWWsEh1eO5ByfK;*5#(*H<)_IdhO6djm!qTo_R%`*AxFYb+0>a z4eq$M{iLzB1+q#TE00p~L&GjWu2rQZ&8kY>Q5u#SMr&9WP_1EE)^K+szKt3-(68t% zxMjRoDEf70n9#4-M+5!Jujp4=n)NH5K+!0T`jxm^ztTFLek}kV=+`3c)9Tkj_=tX8 z2+O1mEfeTh`b^cYb%u7RUw1`7+;WBQYtXM3Hs>hwM>si8HS^I zC7dlm4RhI-Pd`#Ceb@`|qZ0GB^+zKPdm(zAf+LM7m~IuA6#;^Zg$XY_3rsh}i3w1uW`N zk<}qQ`=*E%+ZD-TLJ{QrnvQOUGW~-Z3tfunP-JtKKZcS>d;sR5LIFcbQWeBrE0}oDjK}^+g*z>1^kTBzb+W^*Xeiwar5CFH?%ur+; z+nLzPGu9454ZWa%K@8b-n(k4Ed@H6cPBJUx4Oec}Q3f@o*o6NEpy7GjH=tBwx}XZo zxE$Gx$>lRD2+-C7jkD)t>tGp#VqqGv2W6`?!U5%>8)d!~iPU$}klt&#lSc5S-bn*G z+*|!POzc0!TGl0`hXF2U%H$m^kt>$59RFxAhVjT7VHBL0e+-=+tsQA=8^l#Eu!kV&p8*S+3=H z$AgGWp+Q{2xGl41w!WKicVqd5>aHeC88Loby>pGJ+5)17uQQ^2Ob>VQaLNt!Jz<;x z^9ag>Z+F`M9;jG}Na=KBR!}wLSokrN3iNf{2!fB-&sYBJ`A2k1Ti+^((7ysJy;vb$zKM!#$hs>yyi}UN-bDwRHeXEqbjG^B*1@#z{tDi&F0F~mm%9GOuT@4 zfmdHE+l-VQ1zB^_R2Dj0OttcdH&9Ot7CN1Txec0D3-EM^xv;mn4N5i)>1sE^urq)q zOP!dOfJZ%e-6Pd*$YPwJjWKVr@Qw8~RraDrAIiZSz*|J!Q^u<^3X3D!#rP2yAW86bTr(jf|Z&B6uRTr)&imK7HD9^=k#~X zUytOfx8vf$ilL}1M0! z7J=y`NZ(Ha`Dc^f=OTO)FfY20bK`3vt1;FIs;+Z@QS6L(=fXUnr7WSmY~Ke&D%{&B zm)%Y8GMHuslaK0_5wX<3*9Ks*KqpwnHxbu5#MQX^7Qu4cf&I0$xLU!kt;HQnPg#o_ zL#dO6#0_M!T)G85-g&TJdp}wxF7_qr6+^PAT!JsuZW%^veC&J}rpmvKu=*F^6Cb;f z){F3oZNqkPwUFXp4EOnTCRD7pzX=fAui%@+vA8iL-toE0P&*5bB?|6qko474WtXsaF3|xUR@o9rODs84wx#h!!kRpT-6yC{=}Y#+gf)kwJG!FG}sJ$z6dWe?C@Vd(@qMw;>%k(io(p=8Nm-Jlq{-_hICG zY0~Ti+PH^PS2pU;X|^AlIE6eBA@2E%`R1(Li{;6k`}jiDwh$SyvglLDrI_VM9x^1UdkDza{uLoE)HrVQ;o0!u}T|3p97}Uk-nwYtbP0Wlyy`znJJNVUY%nx3< zjaeT=^PjXaHO8iIW5~sS*v70gidO|~%nIX>>w`At9^-<(ppCJNXOQv7uzYMo71AQQ zA6YQ`Hh7rZu#GJQEG!$Nq|wHz_6Yao%f_1q#0L>tS`9QU^=3-99y<(QkNrOhUvH|W zib8=f7z$Pt$M1Vxe57h`V;sTu<)jUCf`oS`Y(b7XG7TQ z_+kvz1-f7D1v!psWG&%dkjsI}y&%%gu%soF7tY+3j$H-dSu|d6k0g=c!nr{-#fzJ%2Bh=M`Bs$Uj6cK(I zwq0XGOkK^&yaCot&{vMH9xfc;lyFCx74nYT zLdA^u?|=)}X;z3yC`}FhuIb+dS8--T2cJ_y>im7JJ{02KI~g2aS#_81izrzqi~QaN z5C3L-GLvS)E*zuELTTQ7PCxQ!2;YqmqzNEl%Zadu3Q5zc+`{1G(W$(f)?4w>%mRnZ zhHx|?iEWp=?ZR26e;e^tXO6cB74}ySeU*Urk)6cfLM4&=3R3wQC`=d!x5k4T2h_Im zUrn9PQ@f3yL{K%hH;qpkJ=;|KOWlmoyn!ux;eHtECHIxceMa@=Y8;6`rAj)gTuT?r zk&ag?i~F-fi!IpdOvKn!%t1^P%6KHSS~K(*?`*W>4q%K&Qfb|X@y^xJU<1vA9<-;1vn9{1N^uK0a`sPp#E0}#;b z0zLMpp`UT4+@7$#tqjlieIjVYUQ~D%$1cX{z$@PlZ|>Q6Khdn}9W)}~t4Q ziG*WgNkvOmQqkUGSBO;IA4#Hv0jsOva6;)*@7|xm^r<2tms;Se1lu1+epA`(U;Y3> zrebFGZkRErdJhaUHfetlriwbEqmJ~bs3WloktDXb#HQ5E(0%I8%c(N>5YVTW0Y(jO z`NQz04DKbGRs9H!NcE#ID1(o|Y?6Upp{GuJS4|)c7?!~*v;1*_n6|26+G2aAbXvuX+J4(kVKxq1OoXK?D2XCh1lSH$spP~_|ei{bTaX-wabj+@?PNeF7 zIxiV8oDP%~mg(8`vW0SOPgpEo4**wK!kpUBucYjs1H7}y&x7zIKc68^wE7T@NcFQc ztm?xs$kyjzHnBCQ#ujmFY%xTwypdR#M>Hl0fP(VfUFUTM?p7eDpNDsi(-(lqG?CY{ z$?F&3OJ2W7tZ4NS8ju&RHTD>=dVrQEiG_JZoYYmA4`Tdo zB(pHsq!=0nKZ;@@*TS)uq;LYz`!dMrlK#6Oovg>_lK;oyN&deA6C8h)Mx^>R7-akj zm`#j#*BB>KjaLQ?^BTx?-_mNdAf`;(%It)?Pml8R5x-e^5&^Tjn6q*i@qQil-ua6X z7@vLv)?|K(^6%UgcLploH!hlwsd@>tPC<@c)NW=q-a2oagaf(u7TnACO}KC|ab`$v zwHNudu>U3Zy!Q-< z$cmOMH^|lU8io}%1-p$!HpDi z+mI|ZwkS#H=OE~WtS%>25wWw5cO-v z{et#s_cHwwKC+neD_AD&UlUR7-=@#hy-an6cDR@61q3uJFXHd^a6H_&YaPLbCg1$3~0UsVbp%n5LEiD_RzNJ z_p!|~)}5>R)SMrDW6LY;8~qIur}i`b7B;<~=_OkAekLM>ddR#pdmJeZb+H?_cw-fn zlxq8#D81T#CS1m{WqmuQdusw3>~C<^_B2T_y{D<2cdv%TCX)cp=*6;~iHJMg&O}bI zhGoFu9&e@#&eyVslw@^)>9;e9j4WW)_jv!p80u1UhHH?CvaK?dXSpQ}*&TAC1x|#V zEH}BMnkZZd-~y~Isxw#6l}+Vr+8sqRTH;~3HN?-G6qa)*CkmVsVl%&B%3e;8(fdwA zc)_F{`eZ}*hevws+o=6rvyGBoza!u1tN(B7$87BCe5LyEqaD?U1Df^}N$$?7O4(NH z$kYaUPZ0}^-c!U()_aP&$9@L~G~yS6)>pSJUq`x7Q=8f?IYv?I1a7_ofvUeJHQjZX z&i@ba$AlQ>8;Kb!{}JDV^M(g&prZo;tk3r^{fR_J+PZFwR5Qlu%!_KV; zvZ}Z3r@=0atemOtnNUZ61e5K(Ej(-t@$fIi80_dM?j4afGcu*Q#BJV_ zWG&*o45MsVWRp4S9nMl>R)kEjzk+?ic}Oc7Be&cFT(;>ZOtk3{8k4pKqa4MD^*X?Z zHgd~0fW&u*7^%i+Oxkf6_dX!JNs-q2-FFjX$K zkyp{aMAc|B09-IdC(jhWUwCLxkmmD-+fD<~`sK{RhZJ z#wL`=@D{+P7s`dY_$lP6qB%S)w2){begv}7o~%X@85Bt^NyQ3S0+HBj5{)@opEsUs zY2KY13uEw%m|5vS5(Yt&^?`Glmhm_AH!#$}m~s~U{0u$~N{`{H42Gwmp-XWy4b_=E z>qSjx^93@oIM99K726tG_yH2kta3HHb@i07l?f{5fu(iQ%>reJ)-pq3o^)s-tVz)Gk^h zoy_7cDO|&oQqESn>7~`53!0f-6S$s7&bQ$LwN_kepfBRq3hk@PbVNH1;sF9ya=#ZL zLz(S!+BJU&uH?y&inirVjMTP{Hbv_eUorGdw+)*^@f?Vb_|q~Yqp}I7;dkXL)#~1l zyN#Wm2-Z@6Ys^ixq)?n?EVd6!(E)NlhiWPK7J+)7K)KhkhIg8_vsS-GAO_nSDT@ke z=(%ietKJ621e@hPq?qq|!-|vZIKCkg=*KsARHzAh3drNSH5bjyRT|MxSkE&mQV+SE zLJMzd^P0-zEV?wWxO3qF1fJ5kI(WjIZL40vXVX0N1lm?SE>1;C{eBzbx&(2R=L1Fs zIsntI@GFBTTABw@3u-8O5LG-@h0r4?hMCeNKq=!c|Jn%3qrEbgt1r8*Cn!K{M!v7HgPFrYTopT7+?M0I<;rKn<3G0_s)UJh8fKuw1FkRtOH4YU@7 zX{k=FhgviZG3BYLVPLG}8sT0)W30y8;-+XZiv(e3hIR|ZV|$}P3`x$^O~aUc5{xMq-QRYiLw4hANt{g;hsG$f|0l)T-qJk^1#F=&h=CC%(vmzGf#T>+AhV zD=N%O|4`%c+O44<@D7L=>TQ*kLJtCt3QbP#gX%rb@?Tph9;|O27g;#QHz12~*6~5$ zv5qf$nz)(22R@hE2|?wTyHhUwP+PM`5zqKCe41g)0n6b5oE0#6=6)s24$O;Y8n&)A z&c&Ic=NO546pnirKZ3D^-i6}r4H|{n7zXSEOLbp-tfB|!esnSdyqM$dPsah`hb0Pc z6`f>4=G-BA1KH`0k!7>qd}6NnKtLdk^WO@Ej~#+@F=|Sga<^oGi&SRDTlM6v+6L7jr_NCrxVJ4R7W&&##s zr6bwQ4SHRNB1~~<%v&j(>=rMef3}(_*g5X){TjJzinq?4(s`5>wynOBtiHbkS)n^r zlNE-X{~cLf^~$osLd&bj3Tuhrq)}E_D}GJf?MPNz>Lqm%GGCQcya~txXj-b^L5{4~ zN5gzG(olW_{HQnA!o<4RI-<%pPrE`83VnzawBFGG%2csXwJQuzXy+Q*8|lMtkBaCj zv%+|b7;La|_{ZRrQ?Q7CEFBy-&H^9o=R|a01|!Ae;HO9Fiq`{x!=LFL4==oLyqqQb zO2hnID)r7ZsL0sQ z0G*C-$okV>D%?*o3BrG?~Xl!MH2s1ki^hMIZlH^Y|=Hl9=zHfM3=|)Hm$a| z3bsNt+OZl-AWC;-ox+TWoDj)IZLh+#iMPpz5^Sie7@tM3Tb<&(n4m4{G9xl+AaFT? zvoCH+#WoK_5sM4XU@{VKB&TG(Gx)v+e4D~^!q(Ghsl4l8r_||SJ=B{YdO^1lQRAZs zht1|LI8%zJkdB%b9?Io|V(OLG)p=j3#=@{N(fjny0L3J(wgt+>m;(uurMak?k#sdg7(J{oCwiEVwTQe7dE26gVHf_HOvHice`V3G++@mr z8hv06V=sMRE(_Z`q0M=8t_uZ`%%_^T$$7}X1pR4?YLq&tuW;Cnp*YTP?%NyvY7P^=|%jj(}44e#b z<qwC&fy+^Y&zJS?*9g#e^*Mk3o@Y=jgd+i;vFw1u$P9ohEVMhG77v%PCj z)Nqs%ssr2k_|7mM6|wEH&*K3Q>E?Y77938Ui3dJPU~yoaKHfnn9%El<#92w4vf$9i zL-#809fA*b!Ae=+8rNpZYJXr-FMkPW=GYe-$?RQ^iarum(ykDPD(KCx+Vhn_RESBseO^iJXsblbFV>gp`In(cWm%>05J0I!E z?24VO8)3mNVCqNi-M9|nML+r{pjKf1$?;BYhkPaNfG@o31-_tBczzGl zUF_?)RB5&)h|P`V~ucLkDF--NH06TTU2!PYU~EwBIJ=&-*D5#egj1?@=>k6hszbzG2s2`mmP%H{ZA4s2AVa`$|1Gqn+ZUe?trNo?)mOvKw_7WW z#k(5O+m***9Vm7#;N4{h232JsovqRXmp`-W@_jdNH7&C&To?UTlF5`00(QF7?JPZl zo`EJ>d4QBZ3$0fD3T$|;bkaVURIf!Ce=`H(?&ZwTftK5)vb@`LyAhbljkfpjoie*n zgsd6ExS7n*KDZD!ql%%T<=>#Ol~c;8LZ}Bs5FN8b zm0uM{;@*aE>Dd;pi&n`5Qg&^CcH=7&?SJx#Czh^NJhfx$5|@O>{I?^>=%tve%%tb! z&*I~%k_&imwVn%nsMSZ`Jdy6p=iNRZ1BFC-UfiAMzXPH1`m;L^=oFD8%Yw&E@K^v; zOjjj}Phirw50k!qs+_uW5IJteR*?_AwW&lHZJzcd#0s5NAqe{5Oxp}@X5viPxx zoi6!6<4*as=$K8tVMe=mYzEj(&`&o+!3AqTTU5C46DFTp?`eet)T(2hL{ zV5kY)H%Q08IDNb$!K#n(X(GA!D-eO>kHVgcDOy`Wt99`^0B?_Yx5JUPdXt-P5kZ%} zjOv9$!01+yt@@~zPYu2xeqHb*>#{$I4-PsD7^KIP>bP}acIjXN%n9&n_arg5Epb1RwU4U&`MEV>%Bzop$*;a%{vB| z^?W)9>%&m+*gcl$9b7cK^g+a@JWG$kD&umA1}mh&1yeFzKlHe%WS#NvK=hJ)?@rjx zXLC?}2;|KQzao<~?x=SbzXTboK)4=)p?FDNU2v|w=lg(B7w)3hiEvGw_Ri7?9sylw zh}g}fFh3xWo-i5hH@ozr_|1Wz$iG3ZT#bb^ad&SxbEZl+V0VBIkN9_i=llX}*prk6 zk$wPBNifd6<2bZFpi;kNtX3jNUxuntVK?5%MiVz?44;LTUZt?P_NJ5NyD22RHsap{ zi~m8oS{LIM1*3czYbn-W(B6HB@qZ1X#-pt?rd0*$8QJtqcgB|WZj$#V3`X!8x;wM5 zGoL}7?apxB2|N(sPIw;%u>wwg&&;<4kDfBb&@=AL;qOWQi85%Lv{wg}NGSs-)Zz-I z4EO*;h!s`;YoL3{E{mVrjxEJ7O{HJjl@dsWgZdu$@OQ{RT$l9C}a90pH7kg@@aE17xN~=mb zTO(rytyTjx?%dLGg4>I?-)lAc0|eD;G_sT}$C6H7gp$Jhybd5s0eL2q?pVAtbAJtU zf0izs9jY#6T)e>MW>kIp7=`=9rq{U z7>~1ut4e1HBLP;%scGykwTo9s9`gk-N5??Lb}k|HH0KWu62qF-AvLW%Q|Ia9Ob=D8 zE-bSq?Za#3?WlHtSPZg8@+74rd{TU7CC zd>1+}w?X3;+k@~-bhjkh?M9S%az4cO(9PN0@>8HCkV|Xv{{j4CHC`>M!bA>X0ufMp1RYa-X>WhX8+UhOxuew?`vTF z{eHR}^uIB)&KNO`Asz5oM>^gQb`7XXM>@r-E7qFNp-xCw47UU`1eUJZ=}gbS3pO_N zSz@=CI|HHGppx}tfloG8CSG+U-AKF)kQpjyGBIU3ctC)oo_dEA5Da(@K+^I%HR6I! zt-tGJfW)4t>UhW0u4MMP`3BC+{0WXbQ}wO!nzS1mT!mqT+{Bbp4+t$W32w96+f{En zr=w~Q*ixZG5xRWfhHSYrQF5Tu^>s}*L97pektMfMjmZ7AzpHf&!kLiH?~500BnLQ@ z;K(D5=V+9mGx>J(-9^w@$Ia@lZANu%pNBv*&`ue>8zLJ58i%}$T2YSS8+^@Y*n@tyrhHu47lh7 z7oCa=5xi9&>qKzb%x4jg>~kJa5z8E&cQoj=#&MSv3OtJa|6%P-;N&W*{_oE1p4-dJ zB85c5Wl>yE!XgIT_kCAH zTpmRY;I2dw#eMft@zL@9{!ZQQzC9Dr$NxL|q;D;!PMz9MojP?Yv5fy^{&-EI%WB1HN&1#(=&3xSsGhJU!j?lHL`Amptk% zz{7TOe(J;#m#1PjwZyTK1XghF+WP;x#;@o;-V}`tsR0Q=Zt4}yo|=kycb3-#FzCy4xNLD#~zbV zM5dV@hW=&RXP(emfFiOnoy0o)38QskzDI=r&Jms!;lpJWVu>P_#+hW5qB!2+D!Z_4 zu|yHJTgB^EZD~cQ;T9bSex$seDk>nBQ6(KdGCg%N-F(!m-_ML>{?nZQJMv40 zTBl#!NSiw0b#LPfNCnayqnDL_XoUT5Rme9?i$ComF=AZtXGcjrN{I0O9T$NoU4qe$vd~ zS9m%|=i1m1AL`x3isQtOPHI^`wt4|oF!foo?n~}^pcU(^{$w-ZJw)`EGT``}T-mA5 z^BGLBISjvmtNswxk?CDSMI?5;t(7{$y&@TWQP8X_E}1XEQ#)C{r?+&*vWGZ}CqdP z*5rs4&$796+VHre{G9zfM7m6S+J~dpuN;Bo@zE`Ci<5DBbVEr8*j57iA}h7ihYWxzVKu20SF?RA-8O++b9||#c>bLeFqFqpVq5En+4u3#miTbWzr*eB) z-jK4zdTkHhn32&QSYqRzjkS%~lohH#GcwwWjvE>6apxo$8C|Qh)IHi6?SZ#GT5DNu z?X|%C3sa+X6mcVieRPY|K)>TE`oO_{z}WcXSdO}R5dy^LSUO{?nCRk$OvQ8&U^flL zSq;u>k%X;P>pphogPEE2uZQa%e~Gh-!;PcxHQ*hscw^ptjN92=#!ZCizPMur?5x_I ztzk7y?_(%sSY8O)aFXTyg`G+Ob;qSW5Xvr;*W@}MEEUuJY^5SmdlMzoX#i1jhgg)^Ncr+Xa}{^C}_L|=cUG7b!5sTus!yq z;lt{kEOnSJP-ftIqLMs5dY}xk!)AKxlk}|})W7F!_1#O2p(wZ)dcaaf9znk_{4w}B z%L|#sFiO*xiDZ6};^9w-UH$FIX60}qzn`-^BmQp{xR-&u@gat(ZrgsDQBhgy?RsyE z4RV)qat^?^=XLDN)lWR1iREUc?K~|cEGCZ_tzOPlX;Ou;(dxA^_iZuv-7)vC9>YC% z{|=rY<~}UuJ|X6=w%twfG#$;yre?5Chiqyh>##LV&1buw+$wcb)7mb!jBYM$YIf_e zhD}X!Q8{;Z@)Jii^$3-n^LH(5C7t>y0i)IT09L(Qus_2e{+u6w7j}Id{s`!s0{U?` zP*ePptKwgfsCkz%`6aI2^se8x(ucnyU@X1sS1tNm0pFb&fKbL|*@F1P3>?kR#4@;I zCUl!SZY6KC;;n#oowWkmb=nHxo#!qRns+P5&2+rxXXW~}ig}M*zme;6a{X2=9a&EO zPA+Xz?9SoO>A$zo2d8dgLTG-G;K-ioX!Q@&qcbnZ8A?=xzgOZfwY`6k_se(-*KK9} zXx@u+WZ8B9i(I1l6}jiT@UP-F`=c6gQyOqGKDuiQX>6%11b+lm-|pnt?i11DJt~vk zafu?On%!6}Sv}9)V)b0>7GujDz4p7d_=w_K2 z?IiC+9OCVI`W|p}!aAVc7D?44EsLbm&$^s7=2qx0c2KSrg2>+s@&bRnXyWTlz}5D}*qh=1Z3B`g1b}{7P?&o#-Ih%;`F!I~GdM zz|7(*%cMKgz5ZAd_G03(50gI*AcU`rPm-#ALor0zo9LcZ_Z`phksEC!oTt>P5HM_ zpBT_GTjnT#YS^OusR2oB?LK`ar*QWYA(>M$G|*B=B!E`57rq`8yEB*)RfOH~bN7ws zCo;o{jM9kbMpZlU2Gv#VQL?s+1MBuB%nNQNeR!ofq5^j8Q>A@$=53trN8#?=%Zd~9 zke-z~&BHFI^@o(yf4-6K>s$e#yZP8garm0xi#oZU%C(N3ohYO$^Spf8)JN;0qqLMK z;(J>iIhNKb%)Bo~ZDl*MFwH#d%*JRKc4nQtqpj9(_30L~FyriTvl+X{0v5Ysw0C3< zY)K1jX?3T-+#XB1s$A-@YGGa~8KI64wb<=yG1aN3w-fBotNo3#R5r9yiLaEQ*u`~) zN3km$%9ic0D1$wLDwqEyq3PUq^7#AgJkC}g3ioOj`#5>b0EOo^#bJ8UKa>^v_WC-e z{3z(hO5x+^+ouvRU5T9DryKv|Q>j$nyP6?`UWDuZ?&X7@64p6G*J2@nH0SS@ zr7l=TPCe-y{*fQ97Yy)1rznyr>QWYAuY7oQzX=`8TPl0~`O=Qxu4#Ujq?V`MDR!Cx z?d*(FtRM7HT-SaJCy-2VT)f3Ii)UI& zR)}${Ufx6WjCjqNg;}&m`p`*%oE)$kmYQmt;2CnMd9V_{p#Grdj0N@G`Xqy=@^CWu za-XSg{(XYDK{x{>d>SAQE*bFhFt?vRp%K9BWC{5GKna)AlgvSY@)&=U`xaJ50S^B9 zb627Nt&}c$$2b~ye8}{w0@eHum^Cr zLtg!0(x2ivN;jV*6IX%rP3mh8seV|Kd_XG~$JZn;OcPe!7b>lL>|%v=%-#QCc}jU* z%ago0mnZxT=>0IuucjeRNd560dK=kq{t%+vmLNxLQ#6hYU8lk|RnGDECBv7{KIP@^ z+qv&HJTWf{I*op&MnXSc=d2sNMB>e=cQ1G&&1lI(!PI}E3UHx8FS*qpRzOX^#d;qB z-c-MWe@uY6sQ)!(Th2O|bgM0GRuZtOkcrVV`8Fy#6P`{^jsug1=v?rvy@3ea$HANJ zdS7cBGSQg2NJ3DAKbi1ikk%iOth2|_mkC3H+G;B+ZVl&wDR^%dxSs*1RdIwv;h*Bp z*iAduMKj$nAGp@i=VC&;Yj?j_Q@Ic|<$);jUj2!V02b0X0qK8_fP6a2Tlwj6aba~l zQLNfkS(g3!k0P}3!vTQc5eoyEU{Fp}HH@gNB`0)mAcocUyOme34$i~W!IV(Qd zvQwQ*{E!a8R*`cibqW?qb*tWVZ6RsO^;rJJ{X+&U&pfJ#8Aq_%D_jJmvC)Ujildt> zCRV+o5PpE#8-wHR38z$#Z|A4QCuLXPW1~Hm-Rc`z98}!pi9~aKuoq}ftuNu%g{Esu zao0!q33kJRg+JhD=>)8s8wKrh2MAnqh3g=CPOvx5F$Ymh*Ouec%Llw4i7VVka3~tQ zhl*-pvDWlwG>&*RM<|`t+ReIfI4Ue-{Lp>&<%1E|`^@pS2=SmRn2S_l^k0z>;zR&b7g)Ol+kGyap zY#d_7$}bD!)hImezDN&Sk&m$Yh!>!O`M#CDBCDm(rk4D1+UWPRk>)FdN$L&y#M{)L ziuGR-!w1oaR?}bWQ$-x^UOm9n>2v|Xk2B%#l#Tx&5NDF#*1IGBf5F9~`&$r0pw`gy z{{O`3rD|m=)fF*StH^DoPSsY*tujk;TmPL(CYilIeuBq1mR}M(zpm<2-N_CH<51@U zbYjH^gS1ZB8ycTl1upu%FqaR*#FP@-T=Xr5Y;S2n+KlP;A$-i}Ox6$Cx1%tBI2t~c zhj*XSHq!n5nQ8k=W2mG6W>0Y>!~02G9`vVBWcNq&srnz4(*YpMI%N0n&Y?8J{a5Lj zVUKq&IzeJ(V(%wARU(htU44slKaVr+i&+skHxax)KF?J-t#r9-ug_;1(#2n>Iy+saUvC?XDVp5LaNKHd6EK$Uz zh(CJ0k@+scg7l?N(%9>F-&A;@%IPh2u}jirG*J4%!kbYa#1>JX&pg{gSQuaJ)zqJo zrzK?oQTx@CslRtx{izpm>%+CL*7=Ioc^jMQ@E~$QM_G*-O)D(*<~43&Et1DXZ^qV)ZI zk9F?K@@QgSLoS-d2*>PIE?A2{c&ln+u*m$Mn2g}o865gbhvMLK7$3#2--_oAz?&y{ zf(xFU47L)+b-ZsvS+?Bg3boY=6{~<~p|{!!4=3&VyLBd``J%_{ORu1gli>vvw(NQT zK_65a^`u-^_Z^tU5Fto#W8NS4s}IwMJ=-eT-Rf}~^j)GO-j2=_s?{pJk>_oAhSUY< z?ulgWPqcc}1>$WQE51v2=$+lo>L2>5?tp%4=B#UFH0ss%{n_#Ym>x|?D^baBMV20l zwQI1R8Vx4-5gR}^u@>H-K(#O?bF49Y;*HreqcLODwwg2Emd2>LqPq6$VFk4IOPQVg zcdOo5qavy{l6NjyMq4J>Bxk7)a~`5cL~^)gvu^>DLKG`Fg0NoJdz+Ep$quo+0;4Q8 zpSy|Jw&v6Rcj#hfa5wx36{B7|8Sk~6{Is(Oo(N9s*497AZyTESk0fa7D1Mrno*I8- zlAQMIQWCI0ODW5?mrY~uSKOY>|BECX}PqC2g2CD<+jV@O?c!?KqiH`dKx{e62Z zsMm85ra2eg2|fgT?*$*3FNB*r@EZScMMgQDQ@lai(7NW-iYw;q_s1*{rmVful8pu zufnqHT;Z{*?H5GBeLO?-Gg`VXpa?+A?D%t?huhMY-d0FnE)IQ9!l5N;&n7+FoaVy|C4O&M%f8b3TyA8L7$4cAGy z`+3}_oeg}&QwS>$`=;MxS!avEQwcM7E4|y~hfgDX^@siHt*rud({wV?<9~2uy5E|} zjGT%^yIf_cox)Esm=E!FIce6n!y}D}{e346+IK1S=HYjZVv+X@q-ULQS zI5V^JGpyaEcCnN=kx2M-;)i!MJ%uvpW1+70C zt$C_vke^3$2tj&?j?Q3jJ%s)u4R+3&KOA#E5Oe=A=I&k7fnO1GZ)m%lzA`@xe>08C z75Nz|V@465Bf`CY*iemBa@C(GH2n9n(ym}odTfup|{?cj=i{S$3 zGeM2w!d#RU<=oPr9a+uK)M?7{f5{>pevtBUCa@UJ2g#W&bM9CX8>q!X@Mq==qKq4t z3UUe+6Fi{o|^x{t=!*p4`G+qi4t(szUT^&Lph%7kbm+T-~JI zjKqu!v~%4vSb2jA&jKdjzx4t;Hyy|i*%4?yFMYpV_qBR%pl7Z|2j`dP4$R{ME;lh! zYi?C-&D{lG>w34{pD&+8(7o-TR%2`NDXp`@u((cQKRiHpI#i#NCijHZl;kL9ezU7V^P38_EQ$(as#9K=T zsvb5aHowXh)5D_6bM9#E%MVP{-tF88EY!T|+5afsnOG z&=OYcfK6-#8mO9c&57K4WUM97^c1=<-^C=*I|M-WiC&`Tt z!k?y|oFPePdGY`x64-+%VCUv}^mALZ(zW+5lCIr$JTHi@rJC7A0Hs6N4?j;eoo z!QbfgFshv~UEHb))@|D-XR=#{PaRCT2{L69Bo;{Lpo0Earpe%PxEXDzD)ZSl*B&J( zyqpp~+hnb)SYe7%u|V#604)XDO!k0x0{z5JUQ~Z2!d~3s@MGXPSUJH6m{x__PZ>YBy}vgx|$9LV~05y#?FgFNxVJ&7%h z(T}JuD=A4WQssd^`8YOnG5MIi@h@5u8xi}3c_qZNreg<~EvOA15t}k6lWh74NaA$?^ zK$^^Y|Em}=uJ;=ohCCZ3*xaQ){YEm3wHFe<3ueS+#0qT-YFhSO(`#AS62`Vg$=>*7 z00%SawX8(wsg^IuXISukTcFF84nwx^I^iEJcpT|B#Fe37o%h{izk}H|Y*iC`1_o$! zxI<1m#a+s;E3Y<77|+X+H^dyaQ@%ubAxv`3G#n$WLs02iaopn_7BY^zAwIIJ9Hq*h zAs?d!+r~O)9HUlEA z6l;1$!?Bkp7dq`F;SA1T)v>frd#S&4i34<|)T5KL8OY)O3}=-0;j^OSxtkV~UU$6` z-lIIwfhFis3cu6z(PGrCuQ8=LFw<~CU!|vX^sJXKz2F}jM*F3XO``QPfh^=qijv%% zN*$|prMTs(`E)DMoyWtDwQlw6Y0URJ`Qu7@!t1Hy|GREcR&w9O$4J`{+pcrm1_O58 z>j*8{dFg0DN)XDJ_ka)u7)R*sx}eqX9B1gQps@V?_6o-oy5Vj-Ri=I`+}psMhPESh z>^#W*QSoZ8H+KhB>*;#Wb@BRb#HX#yIY*rzUIB6L-9pyQ#K%Rqc37gjNmOMJZ4|0A z=R#2xYQyt#MB)>If3t_!S!MbRMHuSC{xu2KiZ%6&5$w;xlrhKdy1P}xf|~)EYYM?x zG)`Zpaxr~pF|&CrQGgd!s|M9m@5LsH%nr>ogE1UNE<&O>?CpuGE?9C!6!=p})qB5KR?W`3%FRlUx zRjnJxc{6$KOyjL8e#vj3%!TxQkLECk1`;ju{{GhA-+%m>o5`Px6c-u(NS?Ks3Y(`s zXU}JrGto@Xn#(#tAyM9K&rK@>zcVSWT2@^mhmgw_gNV}d! z0+-zhbGzu5YM1n4(vCJ26FkeNmTs791oJF9z-V)hU|1AN+?l4#=BZAkgmgUhYz#uw0y6P`QWyE%a=l zuym$SKjc+Ve|&X>?`0t2NphEI8)LAelTDkF;8wvNjAXH0H0$er;zat6{=DJqs6JNz z<=CCu#Lw*;gI7X3ya1j=!hV8RDWtBd^$1wD!9u5AO=$2Me(EZJ>vUCpGm|)pv>Hph zJ`Z-Mi>b+_`W9_n_QD0zb)aAUI^L1tq1H6Hi%#dDcMgR&g1I>#%nkjN{bF+-Uu;(E zQ$c!7m$=;GNWU;*VZzsv>XIdFaWuA^%}8d&eB*V5SN|>^PZ!~N2}wH@7gGc8KTYd)7aL^(`B|HI~*N?B6|ey=zE zfN6RKZzmQT-^ZE)X#}>Y4c4E107H10j05Y-JSn(`#=Q24G=2nIY{R-YVOYGb6(2nA z+J*gjQnsoR_oz?g)sZHG1=J84=DqBAaWxgXdr4pQu)`7;Wv1Q%LAHOh9^oPrmQpkI zJ5_aA3`9Mf0}J+Mm8Fq;mjbNccP`g4W%_o?5lfNu?WE#Lfon78_J`?2VM$_%_R(X( zyT}5okK?Nw+;?NS{sSc*e@Wxr1S8wn3yP=SBN}gDA94xo`<$ktKxMLs3OvH+C~L3? zz{=cUp+4#0y?~VWo{fZwCXOU{pWu*M1n1gpRH*ZkLCP=G3;I-FM-7D^0A$(2>|YnU zyU=}&K_Z8@H1$E?2)TY^0QdP8asCwZXfFKNo`XLKGQWBcc&D}r>_hSg@5dQO5qv;# zA5`e9YUnP(?up)i1ycPsxurYpygQ+~bM3G`@v%n}6KV(X{pV1ZOlNs!zvlYb&yJfG z9zOMCs0mJ-L8t+3+v*CAhjXU3yScv0J%yzOUOwPwxEOqxVh5XB7^~+$A*v7R;v+;w z3&BSP^)Y^WEz}P`j@y=@zBHLF+h{*lS-8IVnT#m-^tLU*CzQ~#3Z6n- zE`{1!s>KS(WsZRHZPww7!Ji1W{uh1*(DBAH?eUxHQOo`Wxz^9BkASMF0W!XHC|FJ> zrx7I=xe*BDarvnmBOYmbt1n$1Roz^^DSQ?wGuGdhCz?+^g1}Wr z1b36I^)|nz)a9cy;RS*Vxl+S%7OzXnHsWi=D1BCifiEj@e7&~=u+=1TKn3$jOSHJwjU1wGFeQt3TaCV5_c-ucG&V zl^m=4AITf*PPg!D_`P5kzrlU{xP|h5TqyJ00$6YLL;R+Vv56&7p&kHg{C!uzaHWEm zNl>+*`iKzQDl&BqAx*_OfNSxN-`xQ&_jkg*l?AT@Z%8~FnP6WM!@k#1-Pjf903z&d zV6dB8;T`M>stQSjUF~r#?eQhrBPi2UYp=xDn$r&;z^#7W)Bf!E?$xn+l9Bm)^~vCC z{Pqoa!PluPeRtvCJ8{>!u#OtrYxoT?R%8Y%7 zC!Re!_Zid~{KONkz}R!DHmH$x2?jobgF#$b9<1b3US^To3q;oT>W@Q|dxF)Xz|C*k zvvT;9uU=1yg3yL#G=C-DEq=bRsk2)8_@ltsDm*h#Yw-BVR+vh^eTpl4T&Z22bfm<+ zZj4781UG#9F$4JqYN+FD4`%D)!AV5s97cP4H~0owiKyE*1ZNWGTxY0~ze!B>Eh^Ku za8YK}deJ3d77=2gCpT^l1m3IluDLNdPDwipTNFA8hF+KL#3>3RyKfUFk%;pt9j?S= z@EyV}^YHD$^?+Nl~e%7#ZyFM^Hu_#^rRU6{_f{-H8nwPX7 z7EUsUCE_&n#2R`r4ZZd?&=Cup(fF4S^o$0ta^zmLVN398ocW$Tmf}IOkCj3|ty0vE zPFyr2kLp!~x$85#Nf^uKiyO9DHkM#UcP*dzf6x5Wt;`MAjC@Pa41S<$6DRc;sDId1 zt`3`I;H?sVMWxZGs`eZcFPC+Lh0}A|U2p%5!9yT43t;pM^`^pb@FRk%iDtrV{RM(LDmE2mSGPP1F^V?u)pt{7Ac`&EL{?BJkQ z;qro?kRX~1D6ai^HJdino5~ZBXGS+Vwt5H1Jl6uBHm6Z}6van7se4W;?^XTBV?$T_ zk4;=;_p)C|?q6YE@TMMts9e%MSaA5MN*er(-*n8q|7Jh@c`T;m-v3}f{6#FL8i(#)gq=&icQVLjit1Y3Cot? znD%cK*K-cJj5ZZx=gFhR@K=O{=kh~YJ?T;>kj&+)@1gX;uL-_{+T*Jo1KnbjXTFZDDi}9YyZA7vANN5@0&R5WzMZ?y79)ukm?N{;(wrQ zyb)XsZPChd*J^RbqepaB7UTWeGNq|MlcZjv99~VowZGsm)c?w_3kWvTcdKWsrXE!w z*rJuBfp=Lro+BV{VTxMlpk?A+v%~n;I;gg*IHs$hr@)^IL=<~gLRf9 z`PxfTM+R70*~zs#S%k~@(Z>IR)yWJ4Uc6xFVcEks0ia(f6pD?%6JHGeVR>UAM&i%s ztA#aJ;Jz#7p8upy_)}xEjSf~T?SUI@>8l{=wlgGPhnaarKj-~^lsik8+yw6qS0LAZKD@EW2!mw}c{^ygC<%g-qqcM`VN zb96l_a4zNb$oS`8Nts7osnUUOu9ckNP##CDxl#dM8@F ze^#{X8-9ZGWczC@qX9-M`;3|BVCo8RjgI8Q9x@#*6h?B~tGtS^@M?aVf^F<=3HBSa z4N;T;{UIeNhQ3QzSQJa81lF-eE2XYfMVD%1Xk@5Ra0y6X`VOGF`YwTmdYsaeVPN1@KgtzFMos6N{p>Z_AA_R?5!?GaCa`B=TplE9< zQgtZ#A@T&hL!q7Pl}%D8zoi?ak{nwS9!7f+IY4e7gdHNSLxaqAYND$#kGBKU%&Qfvas4QMHLCrS)kEI z%sivA9@VD>nKGJaJ;5+ZT;=Py#TqU`ypWi|jF->U1L~1$k{V)zsp4QyrqW|lChJ+Q z9Wv*i3YJOO+m}O+Yqmu~kRCwEW!9L#*inhTRjs1JE$Q~>(~ZR>E`)pWTham<7ZTbE zRY@;D`|L*!FNqazI+0-^SOU29;4TEgQi8p94gptU-CARn;fm6dWv>%-A2g5X%ktiqT;Z`E~kiBx}SRgI#oY)yUERx^<@;< zuj#k8uS&l-=CQdUYJo3M;Zal&hm&Wfuq1|pXSW=3OJr+Ibj7An-;bt@V#kGYLCj;v zI7sqPtwDs(V^+&36q@53rf!4q{%i!gl609J^$|W^wx&;Q6+gj~s8(L!oAzHXrte-2 zjJ-kNwD%oBN{U{>yCX~`yyfG)$XCWUTFH;aB5QlM5pz^2_9qq@a~hnnKWSQQIk~3G zXGZb+DU+wgJXTDuLp`4fE*`vsWVSl$a+H-FWs0a&$Ryv;RVvGbNldbA$pydR<}e#_ zyCQx9qd(gTZY7^g7AKPhtta>8=b=4lXmpCQ&MhjDS5YwBkeo8T#QPPX9 z`=^V!lbF6t_0Nh?hs;!YzUiX6x=$uJfo83Kcyp9rUDX){{c2tl?N56gY7g$F z;2j+b6w^)ZA>FX=?7%9fo7#mfYUiHZrgl=!|EIcL(@nve;W{N^f1) zP2+nyG%BWx#;CWBy5T6aqt$!BVQ5E#Co{C_ngmCyzuiWtWGGzSi_C7_jYJeOgAm<)?Gu&sEp5*vm5WvPXq5^-FV;E!K;`qyiq$))M$d) z?{silS zq>L!=&+4XN;j{NZ!E4%qd!XR(ZVEoop+GTR6tpU7xK&9%1+lB7;*3g4pWP;LiJY-Y zdf7R9Ao0)bKqIkx7GB>?;s-kiXv(Sn&T3z#;s5GOE4c%Bi zEG%OzS))zG)WxTE#;j*{^)YXppZX+#(z`ke09M;iwQ@HeLMEP~JCldAVqyis%n#_L z)Z>!A|zp*bREU(~j@pN!G-Up?x+^m4{ z#(uHj_lQ;QoM$NNU&X6*8%2gnXAT06Yz3HufK3Wm&AYWwQ&WM^TQX15ir0z?|ET(E zMTLKok5Xx0roFmyti-va3n>`iX%1LWpNSe;sF_k6R zsK<#~v|ozPN{+7ngh{j=x7dPT^HiSUWlTdmh=GKNxJP{i{XT7 zhw~+*l=?Z1AB=CfO40kyBt^&fVRFl-8V3sa74+_W3b81{D6Da7+tr-h8XQF2z?{)e z(3ap}f_RUZwB=>#g~1{6y3EsygEja}3b(}+D7^4u;7lPgBDF&g*Gf8qS0`sMK+`9& z^SbrHTF{v^)k#}j0ixCoe-7#~ckHn{?FZ@`GP<~7FZF4}D*Q)6m{`Yubdv1vWLI|G zx-eX(zB&F%Nu3YeWD}BSFM+zgTdZqF@&ZII{`lcZ)4g;Jh!PfiC(kt5gqYd&X#xdL z^V9WnER|0!YKq^+>f)w&I(GG0Z68B|Q&1V1MDvDE@B+%?^#rfhXKEd#sUJs#rp(s& zNs(W9*_bj10LUy|fH??2KIj6>ajaKUR&E*y_hG&hRt4#+>tsWLlqeLH09 z;d2WylCjJn5B)?LtC&WB7u+GrpVCeF*E*Cd#!*g1o-Pc0pP}yyyxOUJD=bQ`HNFm} zx`JGUHG#ZXU5GbVpys+US(zUTH6@~$-*ZYt+fbXn-_5S4io#@l8=rAm$@!iOKGOxC zp--y*EXAsQHCFD@{2R6Jiy#e+V+^#v1{Z3_T5arc1Q+5ghDd(kB~ZCceAm*#3z(L& zC$7N16dfUsyJT*r$->1O&=#C4Wzx=Ed(OXfKeTgE<3zpxFgnh7biU&y^5Fa)I3fJU z5H8N@Txj)GM>arItITSy-tNnqFf*(jj4Qc$+;dc1t@j+>WTZn zmafo3TJkHt*&jhU^9qQ^oW>JKP)5LdINtzq2Q-=i1Nw!H7V=a5y_m25+)%YqU=NwQ zcKjx_p-C}SUgy;~&Q4Xvyy|nA2)sb`YLXDIb`}xArCL4LlUZGG4mw1KnWNb4&lG^E z?x+h1+|+RD3Xfv1mEI0?h^B2uk!Z59-y!1A|AdHSxYVdfcJkysff~AwDc+4^>3TCI znVJ;k3Ue{mrR8-r`KA~ApxP%H-VD5(G&mmBw81qwre&KjnBg^tGMh3l&-F5uWC2m~ z`8KgOZXssr#5h$Tm{we4hf9DJw+$dWbz87ewAfT^fWapG<;B?N9>liP5qOeZNZbJx zcDE_L`scwD3DmrvN^I##Bz9XrIs>#7ogPtO*P2zJ2NuD3kdl8;(TX@XM5sOf8lC{3BImrv^ zlt}jp%a=985V^iGafmxb<)J~N)s>s$)s!v6rQ^H88}0Ce_LPhxhA0_RY7E^Kt#DrL zUExZb4v(Y-f}_+>%yt59a1P*-#}}Bx-vWOhTZPt9bFJpNlmu(9mfx*C>ELMaVSkST z%Xp$I%=3XNpF)+mYOscVp0Z-8W!mWYS#oprrxW9C*RMM%i~&T>{~~UyJ3A~L6V-GK z%1#>N{>MXWxa=5`R^?Vt!d2@=Dr(SC5wEDCR}*1eeLY5%CpD!tFI8`C1s~fAE?r7H z^8#fA{&q@c;H78G#@YevBtKZ(OINnWzVeiVcCtjWC5^vLkXg&RjRM z#WbG@odzs_tLeAwd(C6yi$=5+FT8~s@oLXfJQKLSUUCH4D><5}-i}lS! z46&&&7V-p=^p>8Cg2t0^^<{?Y;=K5Xb>t%!kB_)cK4Q|6m2}24D8D?Hr@Rf&x2Q~x zyZpD3CFnMTuJRTvAIzC9l-iaL>|GQOdj(IwIDsy+yDOm<`609wazpGFZT%FtTfums zJZ`^Mf?<@eb}K*qJiB5$bu2X;%HB$Qb={J;`@nU223BMp(fXEj;=eC6w*Dq*27i>bar;aIe(;Yf~R<`nfh5JtktZwWQUMf zzZ%wZoRg)rsP?AU9t)Bo*Paf1-W-RoJsaD?ti}mYbS-hKRLe$mYJC#5iroaS_H4?e zhS%3Myu%`Zb>Ct_#^yk#Jf1B_)ILSc(Zf6Mr2_i{+sd~yEGG%ahRr3jW6p5%ItP6m z|5_>`S~PK(R}5f(eAfs*4~6=!5xB6*HTc&OMTphyPaZrPa+nO;mTfpHGYGR56E(PW z@52$8@AC3aK1J27^#_ZV=%^rtGhT7XXWT&UL z&8Uwf)+GT(dTAn`U8~DfSgtS`Pd@7%D#dypY!luWgR!KSV_%4aocchFm5F?A^%qL# zbf_MtvikG=+0)9H-?zP6r*N!@@RXRa;Hhe0XAh9K$$d znuN$foD4)Xo(ASDKX6VTlo~I3f*kxsMYNqG{C9iwAmUU~F8tm}hK;9bd!lmzw=ul0 zv%OMG@O-M3_8&jeOUjf@Y_F_)qrY}Lor|=$k^j%mf2sW1ApO(%FIOJP`gR5H@M@ZZ zD!h)W*|)a+s}3 zP5NJ|V3YXx+uUekuNCmpB1R>G8Xwzu%n0Ka>@!IA< zX=AG*PTqwY=AOXMYk`{s@NEJ=&#RrUN??II6@OhG7i6gA70d+@%+m!Uj|(ywdAXIF zw96-+xx|V(m-tZUvK7~2tL-qY*e+I!uycu(b1t!F&L!r^xx~Ubmljdy((>tCTF#tn zd)p;W)wBIBv$Oq8eSx|b55e;TN{bv_XpO7bP*<)|q_UOs_6>EFXmq4#WsG7)^62u7 zr@!&=y7F~*N3c6!e=ZNt_6;tPR}&70$g8Pd>iWSdoNA`7AKa>&x_)r0cIx`Ut<36{ zqgNA!j!ds666;2%S5qNeNxYhBr>-B;s*J9nUQLu5xrD2Z>iWU0TB_^E`n#X_o#)Ci zQffW=QK9c~ldoq(&!CS4&*VpsF}}g#7kk@P)>-j;RqwO- zCEj+Ge^&g`>Z2CVOZD4TDYF20o^kX%(KXWRZC6#zhUlw4+d=eu+f{+HA?8+Jmc&pc2)Llh=J;(4gxMp?GT(s1%#(tEsP9RC(bt_7kJy%CS8$*>M1U= z=xtX^&Bi@ky~;sQ&1%2d5R0lGbP!au8g%;^WL)jNpu06j_NwLyqOz!O13Pn%U`tzI zBN5nHdjwn70^2(Rd)6MomRA?LOxf?LgFOaq`?Ro)MqqoUZL9^hZv?hy+JY9?ei7K7 zX&bLji8lA}%w;Sv%o9C{zei)(8(He+G^T*2n*t>3y=a3CToe0luyN}x-*MB{^)^%$ zIyq@06&Ba#GD5C)(~2S!8*I1|X%iSBn>X0tw8-@~HofK3Uw{7L%fI*Nrw(6Ux~kw7 z8e2nbxOxPhygv5xq(ic9^{LmX;3)Oc5B=?M)XmP0r?$CJL@2QH({vlUx_0N$HGbBY z7vj@8^CEq*>ma`|>k7P0fjZzZ$4cHIECea|f-$Ynk-I18wUBMGkhAF{QE(hEXMoTo zyJ4sD{Sn+wvf>Aqt5F&+P}a{OX)-*Q-&|?b56{EVYcU>smh#&ZFphm)o^Lt=7 zSLV1&X*b#}MN8*#QR0B(+!>hi761P)@_lNQZx1gK zd0w^7&>Nb%gowJjmKS_qFac*rx+og6;9q|w(GeeZ26X7}Kc(Ya|0W$+VYQBrjPq9{ z={i5vS@VFGNIa}Qy0#Y=$2qT15t8*A_#{J}dsNmXqf_G64ly6wAr{@JM zT&TJegG@3LU%Xo8dm)ow+Q&=hF7x_LnKAR}tZFe>2V+Ke;UfSqs{_wGTMc zM9*5{tugp5u>=wPmaYAz%Ux~~{VZ1#+oiL|&uuG!&GqfPyiVyKD?hB&Ma9|Lr=qA} zTl#g`3Ze6SN0^F}8$BVjCq!BN*x@DqrL4s78L zP&&v2KO!hy+X>v-6WKkx4c`xlT!K(LQ&;csYA@xta6phws|%#;$rJl2#MI$0)^wrh z(q0ihn2w_%YZ!(3{VmZ@Tf4RIEe#V8<$wG!*MPH_7+sd+oF%-(Rrvo`GJc zI!wCgnoCPyky?FMiIGaq*vZ##PZThvHlW>DKy;SvRQ!&9;aJm`pa8j#l@_98MxwYL&| zelcde;rYNup82o!Rh3w!Q!Os=&3jvK0%X{PGYYhtwDlX@4A=l zmvVNT_G@n;d%yN3euGD-vby|1jabaxF&T>ZwLKowNKG8f+P^Ww(L)r>M?nsSy_|vQ zsXx2+IDxpa)aMq9=>;64&p{0N6>{M9M1IRy`q%K1^*W~6Kn6luJOEGML{ef0iwLp~ zl++NE1TVWsbaI@`^8N?EMBB#AddD$aiU@zB+1+}*YCWgCrWjjV;AMUdDN_wH4C<^k zjVrqo^(oO6#Ev!<6Ep<#f^L|8!88p}fpdA!*2P)zUw(edJLnE8SkHyFh@bv)Q5 zUQ^|!h-QZvLGfOhrfaMHTl<8OIR`zpCD%+P4x zOQpeWe5ZWolXlTuJxjtrLIQfl+|W`}LLP z`O790kdBgM);`31#Oakp@~+GhuNTMtW$F`?T(6I)Tz5B4&P!YogBOA>)FB!cS!?h@ zIz`hFza58{7vgB2L#o-cIDG)y34RE$DvzK{Lqbg%vDI#HB>TxnY#Aua&bVRri+y;N4avYT)kMg zyOG$+LL9Mj<$K-c2+QCz%azUdI*!_vtB-Q^xpKj{MCe?(`rOp3a`jQJzNlQ-JDwnnVWgR+-rM)vSCLV`?d_M0^kOuMt5HQdpAm1in;PDBt<0nk=L%`r32pH*~ zC^~vWJ2A2`>Uwiw+}R>{{+xYoar3H|D9yR%L+uAI7#MrleCWBgDuaU7#Ue~u5SaT=Z~KOtG1Sj!xy?T+KaYm#A<2bq-G zt4-0?11T7_gWM9~U6XLrnV% zG-cd?->k0-4d*KfLLur^d{9}#K7s! zb%0Tq#|4=nM_x(hUazktbLJr6?X3WFP!8$uwd<)^R~=D1+T`&OTg~TA_j#lHyh$HZ zk~1F48yT*PwF6E#Tb4g{PKKC2@e7qH{30~w+)IP&*tP2XTqf*CR;?UJrOfzdTffz*spO>F4l31$sVI;{CSOc&=QX0G-omu{FTz0+r~yu;tjOI zFFS3MG`@D-b%Z9{Pc5wCsRc4Mtxr=?oX^GDLf_P4I&yz-? zr#q6kN4r;RjWl)G(aJEdF=>V-YDrg=+E(UQ^C{i7?ajCs4T@VQULEO!`icL6vR^^( z)KXIB{J99(lvS#JgFZd=SL)-}Rhx!AFJPr>pRNw#T#PnLnqitIZQDI>#n)UWmR~gF3b5t28?spj+fam!>DUg-R1I zGZeg+A-L{cif0fjG@TsG%JQCUQlvsV8LHhmsj@52bLFmofaW`y#ee zM++nI5s=TB&a)=&&H)4XQ)2|o#v3}ie-P$$k zd@toHwl_HsBlwQ;q?bv@x}b1l11RxZaPz3Cwz0_~uTIUOzoNJGWBk!r^%7;^eh1vp zRKYrGvi>r4&{X{zeR}HG>ca@WjxRJ`~W=`LcpOB zeE&Uq-U6iPc`IM&d7C~p`%zn);ozL z>o@3Av)^fdf8u6k{rMSH5sk^A#Nj7(>Oy(5CgrCNi1NN;PkFD7@_wVs`%cT-ey9D3 z|0wUnx&F{OH}%F(Mv-1>ze#7^uaB`bM)Mh8w+I^Vf=17FoSb{k<#_ON+MLgJKK~jH zCL)59t|6*(i9ZXURdKE~;`Hl!(~bl~jT<&FXX&D2sqe(kGL@&BQ;SviOLMz zb33?=Vz&|d#Y|LfT#NSZ;5u*yt_9t=(ymkybq{x=Y|*xN(80HI2EKW1d_i9I9bx); zH>OTG(Gbgl!gR-&KNEjZzd11KH*dCnqgyH%7qxk!{w9JDRr2d@pG^8SL7}+~>u^w4 zw<#^h`bY;p{3vzrpo4eNE38SpaS;2EQ-6yg)^GXXIL?E+aSnS!2s;f{`NlD&FXg0x zYcb_=ro3OqERi6n&gjugml^K>2JgbdEz98Dtw0)GbK?fejy#?9W5)W*+wdc+!uJ54 z^A}9?CXGEfG3A{&p7aX7ahCWnPh(5pq4lHTTFOK*&fV!x%>_lnqsp0~N+ZEo#Ew4+G2!5$RY`vkTOu&TVqNhTdXd5XIG z{k$%BVsV_;vlmajAJC>a@bR;wBkyGWecBp1HAVOqHmEvJ*bmzOs`{wCpRgRpO_FYF z$Q>YVux?jqCLN&5kA3Cz#1CA#_neLnl)L2LNcX7a_kr&G4q#0sKZTOt%l4Gt%ygFD zzme{5mfr`v^IPrmQz-eN%{se$Gt*gqkChIE6xFKjv<*^Arw1_Nl0X+w*Cd@v5rz zA9u&>f1wYR&_irAdi8gx*K6mj2D6>BIXI~mmZV`B|CEc?v4Lf4qWxr`YkFfXKy45? z2q=lS;bgZ1H|)aN7)|Y!TVaMj6@GxugW8NsAQ_$$ZnVKasQ8F}@ng%ZejRbzAu`Kz zvSoSrIzDzWA0j3SWyPqe;-#pquNQt;C^f%NfDe7As6XnSw0fYVvPiSlIh01zQ9nCm3+;c`rB{6M0Ov#?{coQnptxetolcleX9O3Wdw}m9VhVBn;>3Ik-A-} z@3>bJ(6!7Ii*3qMaonrI@hIL{?!W~fSHkK~7?vOxAGtTU{{il)L#X`#qmnQO;U|FN z4#4z+{h`imkGA(!@R5mW(Nd^?5~yVK#*4%r$xw%&BMVLUYZs@|jt?Ih4nGBCpL^j?ejS41RLH*I=4VMIc!Y*Np0cQyHgX_JmS_UjtBk;Cf&R=LIk4Q+Z}Gl!ibd8GM5%o(o+dx)4%)6R(UD5>`Ei+LD32 zwp%3_NEPZ87nYwx{3_h}loiW1J>j>&kZc=0_%=Q}n{%gfjKl8`Qd-!7_-;2uC*phE z5w?$H{z=TCEn@xS`+(&Nrm5@)58~-fzft`T_@r#9COm69tq+%~klc51xBcHJA1swh z&^r6=^=m3z`4FcZMHAev=M5$&gWX`p#ToUP063Sdi*t|o2SmBcc5Bk*gZ}N5{n_A$ zt(58VVwcYNBS+KJLyDFCaq$#hLSu{a#Lmbnt6d`50X4DvkxFqCKjmTSvHNfdDejMm z@oM_T6rE|RIL}I#S|^JOC-#0!oaru{f|kI&U}%%>Sb?gQQrR8|nxAwVY&*8oL4mDH zS5PL~cLWbZl^yq)f||xy`8kd(I|yAiv8_YoqKV@@OHk(GzY;nV8e?G1m0H^iFCF}t zsEC8_-d+ShA;#g;NkwbFe{5pWv)o)+b@L3(eDuaG{4U$X&lfiZj~KL@>;A;Nkfd*Q z=!z@a6(^qXn02wDlZ5++Nuv{67hN=UK$c8$qLD}jKUMrBwceXf7th;zTH!p5p`^=) zW-4nQD<=uoI0jGGe@5C;o~2lh2`(6)XF&w~oPg8P69efA9DqDR>&~3}dG=~LnK=y; zm@Z)(PFOl{cAIM-M+4P#*QDL`#D$^#lc2Zp3&8DmaW-@M+PesE!~SlA!3MtsBK#FU z=R4=G%?U$-L@>MdN|I#C$Gc0CYlGhqIp~atEY~$va*A&0nDVqUD(@R2XW2h(K^zct z!lI7asW@qswQgbRKDv8xpz&MsGSZd$ck<{GuFWk^gQ}F~mQKs)Wjd=+e`44}sN{V9 z*{79MTh-$KrOd&0elOfYQM$SQ{wY9Fz0;aOd&5D_*o*S z0S`jx9GO4S6L4n5N>xVPEc~Y;(D^DMABFBzVwAR&Y|p4DXR1$O>C2Vaw6Uv2*}yjr zfwPu5cwJlgi96IQTV)MAV#d7GTocnrh4gqSBVNcqb z$1Wt#EAOF@*)p%!b&8nmaeMS9waO@dt=ymL^b;;YTI~U>Rj~gQ*#y*X=IlHf0{n#rSUZ)`aS?&^u(D6o^WQA}e963jgrDr0X zH{6;L4RI%tnMgPUN&abhe`1v-3^Pi7z$W!B$RmJFJrv5}KY1$MK~;^i;D`_jXf*M?TEcP>qCHm}*8L%Ypk zvz^&MtTkOtaSNgBqd+!t6okdM^o%XZs ziZy>zOn$K`7I*ymD>Pb z4U3hZn14sZUU(xK6thPfmc(d?+(v`Bsc=dsacZ5#NS=2Rro908z|6-E_AIQ?YAHis^>EqSL z`E6Yg7rVQJ3*v>kLT5k*CBifhYAun*dM|Y~RVGl@jVgRus#ogc*Yqix)_-Fa&R8w* z_C>3Nis_UvxDh(*2M|VjeZmywK~=TBT49Cyg!>$*&w~0v`moX;%-0sg`XLIjoZS#6 za*ZO#DYTPIc82hqTpJ@ewF(S>$HeEH$?(sb1jpf6wM47Dk}YXn>1+25l#V;;lHsxR zn_Owg50AkCKcqHEJ3J9*{^Q-KY9hxly)sa*1tPj?IP+$F044O(Wjz-Gh7Br-XK2$*XAsu#tS2IohM>33#JXq!>4f zg2QpH)#}d+IylQucHeM4o?L0%4<~W-x*c|s%O@M~raMwCw@sE5F{**DKKOBv#VVnu znZl~BuQZ;qs_T!?Ia;&fMj*1bhIP*$RHH3w}i;@NmH$#@@NUa_^JedS&+`{}oIFln%!Inu(Y2{WQB1+!Vq;<7V#{ z(2|Ms5;SR!65#%5;^5!5+;is~u-={5pXnwv)T@tZ6)pUsVQ};HO{ASmU+YYaIbZgo zlC~w*lXKmBbOaGGtyZ`B4w9FOYv4E{l2OQ43|>bqhwAI))*c*VAMB{5a$}-#<^rcA zylCb&yED7F`6+(Ja3mOKpG_$A@y{kY=}dMXolQJmx_O!(YDabFcMxUcY(k;rNA=A< zE0~$i^82^b9lgi=6#Dr2b<)N2d#rTQSJ0nVI|j^^3%uggcW9Tod@jtZ9g91(ONj>L zE`zwp@VGXd6EIHuPa(}&alb4Lo#I~o6rxFpP{b_h36>i1Yj+M3Rm&^pSGTJjeyzdpyXA!eb4wqe3mgY@FS!g=k5m z+z+3rio@7-hhOp&KZCa%B5mwaAWunOt9pI~{oJO0cZ<%1`E5~c)aP}V)h;)ZiDb+D z>CEZb)7KWj8i%kuN{fPHK|7W$qxMK zs*;bjtK>Mm9s9Xi7*$Eprp_`NPbHF*@fg=+%GsRpuv@Zm-mW)YE@+21BjZtkjtFdd zp_ZN{wAZ2GJ12NH&gv;hNQ%LCMG`j;TSy<$B-O!|PuanUUn~YUK({?fWMfd=(*oLj z>TGa{M?Qxy)5CN0N!8EQCpeGa`uXO(K+X&KLB=JR`g0X*&hCRhnBh=hoq{u8TtrA` zK6S|mzF5KcLVWl`I(9p_+76Z+N&0x!_$f5>=Jo_TSf(UT$t2JyP0-8oQ&S|!q5O6U z-$L)))X<4@dxlQzumMXZHds++4pqt1$H`4=qz(uR2E2X;^uC-!w7!?k!eu1vAdp~#faHNu*g zQJ$gZ<*JZo&3?D@>#}UBUTs!y*4u$bM?=+sj-R8ffoHBP`Cox!s>#oZ#pt%8c7YxG zmP~$unrjGIaHW3UOJ`a8e!?84#tR6XR9|)(^fg3YAp9k6p6P3Cyj~s zv%u&r1}`Mc6~@@Xxjl^+5n`+0i*Zc*FX4CUDup!_b7JYhh6-J-6q@?BQe7xni%Evp;|^cWkNG26 zW-@#QA-wk|k!g5CD>fOvQqZsBr&FJm(O7dYoZZ~MZ*|s@6VFe2mRAqQ`^<da3?55k*ykh(a{ z=%&WIhHM!mUIQ4^M z;<>J<39s?PmafMSOxNT2()B=`$#_#ta0}h8@lZF+WrBH*!6+uk2;i0dRSZ#<|{)>O!WM0k^`Yaq#XRtt6T zYD&509eM?ROaVX)s2VRYoVu*yd>L;GJPM3Chpjs>xd>| zg>fYacTk`;9M@9<71<~nOs{z>C7)_SxfJxdnIrn@KZE>yrlyahl$#aKo5wbZ=;anq zE((f_1sT2EDnxBRXLoa;H|ywiHvphFXY_JP4guxWQTlK@+)H_%e6JIqMZxk~`CJCn)AkGmUVyHL0bs){LuKcJ>u)s98VCN*{INZBOX0NzB|IvYR+ zuCqh((!?3RXvr-0n)8WoJDG+0`4Lp#BKjC6)2&oGE>?Mrk*<`y+C$`lnPwNst*nwa zvJ&x?U}QQ)gU{|i@^PLl)M7H3%Z9ytyJB(;at*hjf0SbZ4Is z$Z(nNo{$Vn5|$+F;0CxrBAW;*AYSN6K$vtpfTAGF>#ji%!j1~AxFHHCAd8Os0*o83 zh$5oCZt?s5Pu<&nXC{Dt-}`*?JkwS8)TvWdr?yk4s!p9|yW6!JnHt$Xej(FRo)>AI z@!k%$n01td{$nBWv$Rd~8LjwVc&_+d*L}YD-*~S0T%xo1R=3B*V`4fuoxFL$hg5d8 zyv8plH{OOC?^`I*(lLcNmHn?KLm^Iyag_$I5An0Kn&EV&s-~`=!L7kHq)_P!wkr1pN%4)}5N(_PX3>$z@7`{* zyBMFK9qDiUUM+5rgmPBxwVz6$p@HSb9*1Z{Kee6TkUFD(*YH{u;1^Bkfr73K7YX;b zP3Wr<&|fy8Z%;sf)r5X20cAZLrS{_l^fygtHnh~PQy!iYR2iww6?8Y3hu<}!s}j&B zo6z+M=m20l$I!CUBn zI+|+l!MNH>r7ou)^{=jvjS_nc{*frKA(|+g8cG49ZpwIHxI45qDl_3t(6?et1(r{2 zsO~6_oGA1-8JNCVQB;G3$(a_GNaJ*+!R#|BjV5sM&pA3@3cf&YD*X*rX>>ev!1&x( zy5vDlr-rwX;GlyP6A)w>Y(`N|_UQ6)In%+_^b213m|wdEuJQaB#B1M)890)KfxJrQ zhaXWXR5`wJ<9ekOT*VYKcw$V84a<&naE)~~1!xZ746fecYNlsxFt`V*Ico;I{-Eqy zTR=WBzgmLd-paYP5WgbhP*PT}HK3JM8W?3axpgDd6)pMsacr}-KD znKvqWm9E;d8m!UyH0X_raa?%(Wec>;|2*t=Gtk4Z*|ni`il$;jUHI)PbBR-TeR<6HLmMZRVpbBOJoCnHT+U?B=Lp)~CC=Js zpcgkgYoEzWNNnfjwg#UkZjR?+Hu%{s!58?@nMJ!IUAv3e?yAr#7B5rs);kGw2N4I5 z>yl_+6wF?k(Gj4lgFE>SzKQ6plSaXpl$782G7e(a7pZaAUHW(*EeSL#jrS9+_F&8% zJ*ZK8toha1_+Oe+0jna8%VSje+WJS(5yQt0*ay{#H){7p1IF6w#Aw_#l*KMU&L zan)WZ6bpSsEadyP6lQz**@=jMZ$|7RVqYF}B8q4oC>n;MI}6994!_l{We#J<>kFin z=rP=Uv3`Y!t}Z8A@kL#S5wJ1|cxv1rrw8ffF)OVNYQ#?T-coQE)g@buX}i0)1AU_} zS1xjDRrh5|T@wqsJ98bu-C#{f7qcFN7Q6n`U6?5jX4J3Tof)cgW~yr^K6MsB3)>~o z8o87)Mau4{8Bpv+x~}%P`3CnubZasE3Ql*ir?b#r#Qp`#r+mj2PQq4ah16A&jlZ&-~$oHpTO`(g%@@~ z2NM|sy_uj}Ue?-)q`Zj%e^l7m*iedK&BUpG6YD>jZN=kttHDliIIK+gRZ5_=FQ1+^ z403lL zx0Cqlk)hm_*zU&S{{9rO5e-DB@dpZJYEw5gy!#ukqC6Brj2tU$Z0?65OC9WhEh3ewA;7 zCPpm25c8uuV`b{eR`$)*z6!JyJV0F6QWjcE=|6@$mpu@Wawhl;*`3rp9?1ls1=eXH z(N^yJk~du4oaXANoI3set}jX!nMWDy9+{hfI1i=)d(w5WsO@*AI%m22Vmc!uNgB0X&XTqBQtc?YV;UuE z@4`E#k*fBsIzA0OoCnIL4rQ(zpbl&bi$vL-Pw`i^J z;LWv4c{fbawT8kt+~$La;DZ}alhnjk(y;?Lmt#z#0~=Kxu7}k=LK0>dBOW!LbJC+v zAMEEd(X>aeHWM1nCNg!dtbIq+qdB4zU7Afzc@ExcKGGcbiSbv`f!#t`nvmMBiP66~ ze3&e=aQQmUreA^4)tU>rB%_%Si$~wUnVO{LVkd24XeSs4W5B9r>U@YDkHmb~<>tc~ z#llSHL#Dhfg;`9Cvs~Wu=>8&aFH=;nn-6DF3hZ#@XHblX^0~x(h!wC_UCPR7zT2Xp zgSWfDS-0>sW=xu~;<0S6)TWO)+rLY=j(M|&iaWi{ogV!eLtnXS(W`Y{sLsktH0R#g zQ(%OGDYhKO@}dX$6kynF(rZ+K5cW%2gpQj+NP!W`WI_t43A;t8kR`X-fCEqS#SZ>0(30v2$&k#7O3D>TCSwyM1Uq~JTa91xDZvsje1 zaE(GbpoizUQTSb zl*xnystG$HL>A`(vOJpy00%7{z&zwR2cX&Vzdj`?1x6^7lTtuU*sVOHs%Q~faM9$# zE703)D3b{ZR1d9DaTnrp{u%u<6J1E55stc$wIS)GV{>2 z8%_y+%>Wksg4_f*B2m^C5OwhD-sUuJ@Jqned0y>GIp=>GzfF@d zR8wYPP)%$x)cgkhJSoOd^BYu?Knyj%K{W!$Q1cs9!)XjPzdP(m&?TQ;)UmILO3o*-h>;_;CXl>Tbh6rE-pHT$vatsK;?)}6 z*`!qOt8IkblJ8%8#=eQ4<_))z|DmGBG*H*Zg*WB>qbYc*?%L4h;BhZt-^9-pJT->e z+k|)A=MP)Xsuyo$0FKsGXB-(PD>9N|RanJxS zfI)5VjLT~FH}W^4jqO5MVy88^jXO9wD7gt+R?t_qS633-pHxzu9^w4o?12Ql<6RMa ztU`nlb|iCSReTMRW>;2Zs<~Q0XlP4vdMtApu<-9>%^O8=({B5mwviru6AV+F$cmAL z{R6b17vUn_$2gyo1=4Y~;&L?PBuCW`{|SCqLpjJK+8s8>_RWl{&DoKZN_$^Vd2xi* zYKh$K?Hb=L&7p1;nTHgV18h6~3z~LJB+B|WzE@mEhO|$)k^JmJezbux_U_p3q>Gyl z{|)MZC6w+9N1!S@Gs_$uE;BlyN;Yp_nsD~tZ)9A z^arPZRjLnCvL;)`HAAp1s)a@{$&0-tqGUnbm?UI(`ul&dmjLDFKJDmhgy^8b;K{ zG1`!-MErQB)yBimP{8Wa)~OcHnWHLrArnQemU|DvdUz#B6}_~e5y5Qjl>!viIy%4& z%XDR>1-Qcj8+~c@GU;JLZ0M-W!zQE-ZdCI2oj60lo{ajR@>ZRew{-DHY?CQ_GbW8h zR9;`Mp`ohMYfhw2-1rO$v+*J`mthA@qKjt@d|WTMnY?z(zCgwRos}KamX*%dafTx; z4F|9ya5VTVZzMzfx>~Pi194r$No?ZW^z|?9;4u#JUL0FNP;CkP8o5pa%CJ6HHa~aM z=aJ3N-Sv5D^K%bAN6v!bV|&W?1l9z{Rtn{OP=ec_muq|yR*ZC#pRwhHv}^*qb4b4h z(as^6ot2)3aOju6gVMlM+!tHRlwfzXR6xorSiAH=C2T@Zk3PB&oyrkp} zk0ZMyS@D^VPm?*!t8ZZA=XQD7IUMIYlbd;p;lrxNeSj^V0^7x9G#j2tMyvD35p!G| ztf8yTR6AuC{f#6AWz%zC`PgsC5HoxRh;1emCPlS0Sa zwMB1Y2RTqyV{I_SLk?Z|rNJ$jYWU1ZHQXv^ewJ&qN91R1ry#SQtst|e7sL@#L1wvv zB=yU0<(Z133p#C@yX=%TN4SSF{B6ZOnZjJ@T)lUb-R_pRr`Bjz6Ws4nVS3A(dV7Nz z@)lbCIbU$)Sf4NS_618B5DK&NvoYV9pB-w9t>*B7G!uWmufpS7F&tkEFSwzk(%n$= z1gZ*|@CPQ+0~09{oh3r&Pb}!|-Bvt>Rfo%YZ$4R$+I7tw7h7$)Feg7}oV#k#PJuO7 zAPg>3ARKs_0(r?a9PC6*!MSA`1l{puoI*vyYkaCm)^OKt@HBp zY(QFlwc60UunreiOHji)zH?^eP7<6K1eqQf(1ZQnJn9m?h29UK>yxb&8|mfqJw&o2oV z5usFA45~GWhuHVsA(?P~F*e0Mi^xQd`jdIk8=tK<&z!ZcyDjCx&JNZsr{adV-MIP_ z{5$-g4eSMc*ygYT_`8Phm*PHyD^(7%6<96!Un4m7#M9H>@vFecNa>?f;6LGeCHO4KCgI-)T;*Cm1^y~v6NIfvz;9@1G6`>C z8fa)9aXw8U&ZpVKe1j3@hntw@GfeXtrhGBxN1B-CGfeXtrhJ3yAq(_3;>&X*kJOOEnQjyeP!$x-5u{A(ju{x}Tuq2cm6A317o;twq= z@9s;E@{yy;_=X0`JNd{_{XTNkyz(5&Y*)ExjOr@SXeg6iWxt^ec6siM{xat_w-|?b z=z{Jf!FNWcGrJ|co}zX&7qGv}jCQiBXLlw&n+}nuTMe$TUf@|L82pQ+8c=LkLFNk> ze9D%5;#0Y3eFh%}WpGPl70~M3kxrd;n_rw)9C<5KU-&kD#uQ}XgEIE@aq@++uL8Ll z{B1)L2bV4bk_~pz&mcc`yc`3tcuOXeL~pgM2AKnGd*RT%>`Vm5JyWPW^Gi~xkFASt zz19ZbC#~xJ3~lb7>Nn&&hOCr=d-yHdO*D?giC&SISFa6vVMtxyK>?qPvsz-KO3N}* zI|!n7%c>Z>5+bM?wlWChYOe>**#gR4I~T8QpVr>l0zTaY9`b&yE+5WM(5Ey?z8#+m z?$F}Qwp#rFi=(;VOyv{}#JRYx0JFg#Aj5l;o8(!Ma@==g3($n=HIN@ za6QmkEf*Kn{K7d;j$j9HD;diWSCx;Yj%-_hdfs|6t3I!ihFgdkEFqfnRxuKDGobO?mFb+fUDW!xs3wWOz+2M0$V<#D2H$p5)Xrc~Q6DF2=eFYM&8RLv z>n%UQfwUmb9wU5tsmr{fJKVcoUh4ba;=ek-`VVS`)C%>V@GA1h;rvo=QcJ^*Zla~7 zpQEL5S#5ed>rRJTMR$H@P$tV9eTzCsg|8F3SAJBDa257zIM>%~iq2c@OK-O+^5Fdi zw1)q@De_>X7#NM718LquO81p>ttKAcsG7GC{(0M3dRk9aJL{a%&f2E6v$SK~v$V4) z^gn55X*XC|JL{mGb+~rsr}O^gcIHRztfSS=cp4*<2{|uxSeHM z?Tq7v|3N#uy>006_+7bww=M2>?M(7YiFP)ub~d_%&VY)~ukMF9uxoo*g@4&_h~Km; zzz#I=LVLE#G0Gf|b@9fh--q5IQhvDz;WF@7+|AYaXB(TXy=|vO4!9hwx?cTPZF2iK z>auoUBQeI*&SK1Q(QB`n%T&n`phz};(yl@(4dl8YprF!Y>?RynD9K=KeM%Cn75&Lvz`nQw- zb18mfm_lK=w7wfIvXmS)VNd|=uF~!yXh(fdIhZh9i95I=!eSu<(dc7UGUPnsH$%=( zeu%O*xkT6GC@&Szx^|;~Izs92&lLNTb;wxPAIVQ{qGv!RKIG4E-r6@iLqti0Ei9}(yilKq#i-4S)3X>3!|~75I<02t%mNyK0v(R=WqzJiopl z)EoQrQ>oDG^c9}gnes1HS?UMyIURbSpng~bEsAlFAftvos?d>x`KcemkNT3ij1xxu zP=Kx86R!s!Bd-~>S(cMkcktCX3`BOPMYP!JBBlWI!naeR>bVQ!eW$IIh<&Gs7iYo? zZ9Wa|BIsN%d@tBG@@faF{R4u|k8n2`?t4ta;CLjdzeP z0bgGT61N9mB&T#VW`e?tNomC|T~X7C7W86J)LM)M=fb#XY^hRG{V^h1<9P{q6N?5S z0^ul_6Ei1&nmuF5uKJrXBQ^6ik)CPB!qm)P;E$70H8#^cJ^As5s?&!tHMZV1SJTPCD~794C*Y=iPFDFf)Tg^2P)fb{ zh5|;0VTHYK4!QN7p}Q6z40J=9_)BMIHe&TBs~{TbuT|W zoIDi6Bly(|9{mm8=VXIPZLrgznegvGv`1!7cSMcx2iPICW(h4Xe7|U|b+H^Ry>we% zV#Km84fbx7NRwJ@LOLS&otU7@;_w=Ybwi2VAloT^M9h7(h(-5+B4YRJ;VQ;!YXR-y zYgCsE&hFFtkAwZz)#UtWRIpM<+0?`-fgy_3>U8blkp#It*%w=HVJTJ3TGy`Z!4{$V zc%`q^R-LFaG`}=B73Q?*X42LAX?yTek&c_-dz9^I!@mYq%XVV;S9@v^4{Z2XHsW#c zF!H(5#_X2?rFvhE(}gJXVJ4ITFA&uIhOfZ;dWSH2l!1jidNe=5dVXFPZs1qPK3*x; z>D@$smC-*2;B@+edVzk!WBGY5`lp1)fg$?G%WctLZS+q7IGw(rUZCIbRs1{`{Zqpe z!4Umd%YC}Vgp>I80{w<3^YdIpPE+$SBCnPE`xcSc@$Cir4Nozzac_H!e0_MT;*t?Y zRBKP|sRN_-)S~x#Bck7su{IYl#y)4xf>5XozDD^>xzN;laAX>7MrHD<-;gmmH+nsb zsYK167Wq~6rv(hulaOzGK4kZF!6u@qj128oMn84+w0xXxr1cvz=;ubyvF|41wwI3< zGPBuQ|PZ%FK;qR`VEh zgM7h%gZ$>_Lmv4%nlsIbRzPOMsC~4ju4PW)OdawEv!ZSuo}t;~Vg#AUE13oft==rg`5@># z7jJKdMDyL#5hi@E_?;UIlD3eKWRX4H7P6qvZ40>-&+MaZLNLLm@$<)f>2}i-^tsb( z#Y?95{PAA4-Sh-~?(|ymlIcy0$1>ztXxV{Q^8h$L2ABuH2{FJt0A3XX%mW~d0p{7_ zjUER;PYB9I1UUw$FF0Ca9zcB!dbWM`2zpeu&*p3U3_7n>2$nnB(baN-gf5*6{zNy9 z>s@=#`_NWKeoj2uA6-gB43F+0CtcqWhl8GHKm~)N`l_FZpT`7fZCx0}dKYegu)e;N z@Uc$<{rY10H@AL+7XdxxwBW@!li=@i@OMvzW71Ff@0|+2!olAoxId}{>Psx$`a(Iy zdcSiP$?2;vki*UE$0^###~9@d(zwlb3KZxp{--%EF(#mRBKiJuc(Si}@+-%a;2$uo zzB3WpZAO&Zd(G}MW_pnoWErc=C4;(Wdf?o@zXi-}11-S;`%aY5z7r+0?*wPCqGG9@ za+)K@r)F9{<&6A-Jo4h=d8p&-17tBXs^6$-l>AX;o2MRrDIVzNyP0^kWrcfYB|?Es zzn+BRVgmk66Z|vS;J{1n`SVTt*44b-cPV^=Fw6P7X%NAC^z&YRqP$j@IlOd}ON-Yz zY2bYzxv<4F=2R(s8bals7(Hx-I~y*k)OD$qkEYU2-_>Dj)Gx7~?@gtROKD?{)sX!J zH&JHK$A8=YW|Eppmh7{fx?V#aw>Ak_mib14SA&T&l>|>9{gJG>e$$Z}ApU=lt}}ye zX}Y(ST%1;_!TZIk5AfspoE~lU&x4ZtWU^4LvAsR@3esI`W4jt9bMoyjuTQNb!%sP; zHr7)yOG`(O$z5>l-1VmgTS%bG4?gLT@82Kf_wFBjiqA}N1!3W*@v3l|KXiO-9ciTP zsb&n|?8AJA4duSN1|L*88g5X+_L&EDlED6^n;7vO>O#+bg&!1YZGGFucz8RVtjzIE zqgOz)GbJd`>53jQ(!%!athMLLF5TgNsxx-1%540eO`CVdWj)I&-M}bk{fx_EhVe{! z%Ovy0L($6V_VX4|C@@t{%^OOW$$4wCvv>gPEFNI&bd0oI`@F|7%26?UQdVwotBykS zVWY#_{7Sz2f~!>TA-nWGPu4nMu`l?LL3;$X@#uBzukUYlo(AUH&W~Z!BHmW>Mm6Kr zU(OGH%|`WC@DnV9>1fK%lz&(J1_+nqV>qt~dsKsZSEe#Z=AErD6z3Yh3)&ae0OgHp ztUql;T`0JZy7NYrj$U(3IJ*9tKsE`(w!xLM^0A15bN-`JYnir!|0 z*Z}6>8_<@Zh!Kie;OSD`hy0>TRTV@zIGJ*JA!jyxXTChl$y-#DxkcHilk+Sm+H~l{ z8&%s<{mZrbZ{@EOwNL*xV_XYZ8s5|R>5Yn^!-K{~Z&Z9V8`70I#$#_(OdjqEDx}gE zd{~7WeKnx|+%jt9GvuK~bK$U_4pb=b6UlKw9}&M2M-BSBhuCF!4dLwgn|qn=wTKo^ zOwyV&lJ|z|1H|ZKz-Gn1JsXQc4Vxvc&R3`y5a$S9gc(EE2ut!YUps#pRnGn z>(dMWK(*%lO=DULW&MqE*`4*PosA8Ica<@J#_Ebkjl z4q0=^ITPksm*ioh8PV;4CIqek*w7Jv2A@@H)>v%}ot z_A1>Rh*SLkoE1)pe*z}7GQOz|=~suuoy556C#2RmibAaVUhK>FIJ=8|;U|e|HuV3` z^3%7qeCBfyi@9md?pe7D%T9-}+O>4m6aj)Xt!gVzTQmlu>OhSxqZ-LH z(6wp&v682^L`^Zhg(DxOOtd&SFcXe5{6$}T`jviP=C=IcQ?yHKgw`s%v02S^biX{i z6qKNu2|q(tCo)C*dejSl%TQF|TBlpIhMe$3ZqXivmpU=kd8&p=$(8BUzPJZ%Cy%OS z^5{o7S?GtKC56iDVmwE!CY#b;d=9Y5sOi)K8M76;s+1)dJTcb;E3L@$^r`Oi=)#l`IZ&b<=&8Bi~ zHkF*)k*bSf{CTZqmZw>M?UWzW+|{L1pqZW^XYsF@Vr+%Zi?gknrFdy;J}F-M6DYe` z1bTz}*QH_bMur$`>Jk?{J;{?B{Q9^?2HRw=y&HXA|K>n;jm9)K6ivpPYwHV_&X{H$ z%pe4xr;5CQ8wKV17w`rvXbtew8`YO>#|A3_)$edsY3)L58vTv0WBu(?yj3YiMtr{r zYC}KOooe?2A3vYT&h374x;IyQ`zVC+tph|bvkhAH4+lcB!^FxOB} zb?I}{i&T%#r}sSR|4{GwY0BbmExN>G_3~g#6*;TTGVg5`M>FA<`Aw=K-z)d=-CzN)B(gbfbHt7f)-V2e5fwU=ohZnjxJ=}3(ZarX0J8d5} zs6YB2VNF*STMd<>(o0#KJ)v?qM(FOtJ2;KkQxJCs@qQsr(+GbJXhI`Qe{y5+&29Ao zZ$SM^WAH(^htLmrXn^vB(oah_ypx}Cwb$)g)n!nI!=LM|>K*{eDUGSN?>PjgmUcAh zwy8s>)9e>b6}Cn5K`4cj$UQQd9C`dN_1E(n7ij2NvNdZUaK?bu`Sf`>>r z@RY*)1FOxz$8<^|~iWQSIPTF^E4eSW3w%onA12 zTiuLkL6IAExKs(fKmx)h-9oFJ*x76 zMbK0mpF?}>?u>+tOlK*SNY-rEKXba4C!xI~az&#-{MA3>t28F>`~_x~yqc+f0G@L< z{fjuc@wdiPQR_CMYX?6j*zT(O{d3HwL-0*f+bH}oF>?HE&l|JWbtRKvGPdH3iQiLG z+aFA4p^_$^FY%Vg#Q4&fYL=6PwGR<&Cy>m1eAEYKrM~gwRL@S-w{(r@ z>r*JM^R8B`3sf_%fegAHA$y>Hb--1mHSpwBsCh#jTxS|4Nm3E>HPLAib(|sN-lU5Cwz>bQdeg1&e}yE;ttcz{EYk* zfpSbNt!=m(*oFK!m^fFoP9=eH!YG=+_+z{+fl*%xf$=ANTK`X{INxZ033>5?Yg+Q+ zPr*zCB}K`f5!6sPqTdxn8NWF0g|=XuB1)EL8gB48^`4(As^TMs*0w%h)ImdaQt0DE z8ay@HzCDK~x`|2HW81D2T&sS;c-)b?5c%{aR%hC?MXAW5;m74sw_L6#4__Bqmx zq}5FIu=ytXFD=$iyiO+&ORaN2I;{A91J1>&KPiOk__>5(&eMrScQz3tEnI}V3t@jS z-tD)Ie$O`gu|9IT+53s!Y2evRcV=jCx)?lV=RdREo&StGRxtg1WRwRhyti4+q0^*Y zV~PWy$OG(-Z~YQqQcBJy_U9#+R*sDz)Ar;QDycOSp2<=cJrRef={D5EB!Tr?QGE3$ z=gqcG3~*FkEmZQV-0UQIwO#URvpq*)PF`&<=98;jE^F!JK|~CBRm6C0Dw0>reF-`O zo4jfwCPuNR7I;nsk&K!5PpAZ$Z15}mgIF<|a-87TfF}u$k`W~1Y)4i!xlTMot`ox| zSuq@iYt88txlUoRnE2nzb)+pj#b01SdpP}K>Wudgt=P?YS2CPT4eh-?4!vqSp)YHO zeu&VK-?PD)YlsZCibPjxVE?fLNV%ctKt<0%hXhqLprYfTbAb9rqIL;Dp1{#sxgN0h z8i8*&a9{lJh3=5J!F+3O*oy^-(SP#^~C<2`m>ZzE=BM{0`XH@*iW*oUJ4AF%A>cUD(+c zCT0@WWU>q6wl49+6~daFc42H06Q;7pVPcsJ+tI=-tNSeG6i)nd%>sW^*{lYw?7Ik3 z?>d+Y?qCzZ{88~FPC(prVRtKRoBs!G!2gC0I`&?g0f46j_^kl%aezMx@Pq*G1JKwN zYTNw3HKV=XVLdIt?}YUM2l$f!PYSTb0iF@y_X2!S09OqKQv9<5{-A&>2q@q(=* zA2lsKz2X*|!_u0%E;IjJ&t4hRgr!(cUE*{<^BPx^KP?8$C5`#?Wv1KI5t3u2jN*D_ zsv$;(do$4H8seDGhRRcvt|7+gm7f{y;UD>)=w(a!UJv0jlL_v_JvVc%dL6pWR4SVq z98UG-Xx`EuoPYSElOys(Q)>G+;z2Lur~^sRp{PR zoxvUS9G#b6c?F-mJGrIMG5&=Z6Rn-CVK(FW42ac{e8)KPB09DpsvOU|DxV`z&kE)$ zM}Way7l#qFlPM_yE2}YNxWx<|iB4rSYk=)l;fl%{xI6FFQzG_D> zi%FkXa%C!>_}47u1IrOY_RRW@(>Lr#L0%4T5&>qSOuUhavJUc8T@r=*e7N_ZROnp8 zkl1Ji%t49qlQBZ-^uO!q&>P>449`uFb+Phz@b`^QFxmB`FJ$ozrfnV3ZojhG<-RMO z4r0c>VpNXGT`x-Q_8a6BUH#}3@~^)H=`JIErm!9TmUp;qFx~p9c4A>vXoKwu;B5HQ z4T#5|*GIOvmsCN-I9?vkEGYIDXnh(_LQUFgvfE$#~P_(A@_&m`965!L*;8;hEXdlKYgS=yri6PHDyMx?%DHmrTCn z+F8&m`0bWz{K-QzqjN+fV~$zP=J8a2bgl!+5#ji(ah&HBH=_fz=#Le2jcm*Mpl4Cj_Pd9! z0VTfGtUOC5ZNDyDRNc1=S8mdlF@?hk^;s|VJZbIrJZZV`XHQGvMV&JaPM3^D6rnuPlI&Hhy8So+KuyB z06U;cFb$|I7_fhr5c7^XYu53&efEEmrqyFQSWKdpULs|y(Ps%VMz&&2&V|aoh&))| z-Et@Nd@mz(p>l;gX`rN%AX1HhHMxcDOadCp(_2;Un#%UQ4k8AHa5VPeKqnDP?C z*y^zqqUL*X{G}FLQ6Gsy)yga0?6`lWQ_P?C*Q~?oo{`gtG^X)pdRPQ`YK=qEVDxNA zYcF5xkTgvczqk7kj~xy7`$NIhBkDb$&Rd z8o}B-EUJStK`qgMyhkKFg*)mCIb__k5o&V9KDJ4zbks`6zSaO56G1eCv!%{D`b=`$5;OtM*ED z9pv`g<^}Ju1f_@7zSsuR8~HoyTdcWt$2Y%EhA7is?M8Fw)E+T+ZY_JO;PYy`m^;6= z$=n6CPnx^1_Jp~MYO`+>UVpZBg!ANTZ*rcl+Kuwmm$PcORRW9ae`s;N6y}8k;v{*} zehj*}6v_(ry>^cIx*EG%i1jvkU&~a?;zHMKckyMdl$WT=q4=gv%w$irshlGk_EM#uyB@ZKsiOF{v%Q$JJ97JdfBD94u z+M?Q4#S5gzb|OcVl~+ozQAS-xY_DW7yv6cczLk0@V5NlF-%6Js1|W~^!q4Eh(x#EG z%trW-YTn(fzJYe5ywNi7>bh7K6CLdZ%&!X`h3@Dw zTMBtom5aDh*0+bcJsCfsMnDv zs8ftngtw?Os=Z5Jq`!2fGF@6c<6}`toz1;VAD3vXow>njg5`Emhg3w@uO1`~?6mQ= zr7M_THRn!E$hlu>e!`=0X%AVw-%Q>lm8poXL6oB%w3W=F-RWw9opkGs+WQD50G7|} zOb3t1^STK2VhWnp!#c~zLvynx^Kt725$$;EWW7PzKCl$0Z`n9A=W6P1b1t|N;zb7W zV(>BXaS6Lj=An!lPjwLWILcboj`$)k6P`uX{+)(+zu0+q9Bwb=%00H8=e!}ID}Ly& zLVcDB*7AWJ_;olv*1Xi9o(hEQV=S}cVth}0yu zka9;ZCqRv|MX`{j{QXKyf%me0N2uGPsZ`C&A69c`t;XNuW4 zsh$Oe0Wqa5(&kZ!fmV_&d@9{anf$9`B~*@OwC z_qB1gHRkO}+$m$;Yc%Ewju9V)KF63h1@-yIh2|>q`NxIrqBh3`FSQ#yJ^>!P5t9)h zaKnCUt{5(I{@-kDXeO|sf2COEY`*Kh(yOeFRsp2LMJEX_fnDK4M9?Xn;RG-n-Vao2 zH8-{tB9B?-m`lg(DtAVQ?!T6)beGI3S!Au0!D%(AWGbs7n_dMfyHfGPy@0wS__L#H z#~3>4ng(qYoE`0nn~{brj=G zz`+9C4`7f<zsR{e=A zdiWwe2#epTU_Sz?6WDiT&Bg9uWbxY@RawJ+JKt~g_6N@!RawIW%xi_xHTjTN5#d;y z?SITqb?)fibM;dB)WDu8yHcX{3w<=Tm_gE&L>IJFBFCJFMMjP1h5VsYB8Vh{$}x!# zYb2#1&d*r-CZx!s%bcNssi65og{h!G~B;sys|pyX!JX)-l$DR^B4ro#(}nDdJ(@(@?pvQAcU*2cV1RcvLRbJN%p=+TZ# zE>m2oa2GttJj^#za8@;I6DpCte0=SzNRlsuNap>2cpc5|XN!o}p{ zB$d6mBAa%_S>ca-pLTPuYhq~>+E{-!6?E`DN?UoEUn%(3#v+XHAj0E{QSCY|)A7Cw zKHL2~)b7)))WXt!c<|(g<%c}N>GSr335n{Il9&F6e6h0Ie!kQ`m9Il4Dz$6I8~GP&BASyJ5_}P9dt{pcY8U%M zhdUDVA9YO?@`u!gj$&vGscu(hDAfun34|9SDT39_~GM3fsvx8F>X8b=0x8?L=d<8G57KAtS;oKz$cARspHSm+IWcAK&*f_3e?}g&wf5(x z?`iplY8N3tIf;3w_Q$4Qk^UIR{*yd^p?1u=;S1obtQ)=%7n^S{lH-la8F?{3^_K{M z5xB$6?WiAtOQuGTluJWZyvt6JB_jF4mkJzzyi6b9iUuou!$@Ddj#=L3>obsN^w&@x zR&fJ5)p$8RMmQzr5W`pCUCk+CT7>xG7Fnk=epOFy9xQtGCn6EqFk;p7hYgB|Y*2TO zXkN_;&hwMhG*LGfjji{A+=EYEa1=SPjL9sb3N8i-5XWK`&M#SK<76u zYzISpN?=5{Yg}Vl@lnh@5MpR-es&Ct9 zQXNJssz>ORD}GRvu}E>r#SPzu#NX^WQ@-A>uohcBpwGB!4|8GZXuI-wW%c%FX`a=B zYvVD4U0X)xQ^VJTXKEhRg@_;WMD5s3P1du1&VWDob+=Qf4v^rWS)o+#w&vu_klo1` zJ*IxnuHXrBY~9ia&$M^wwQ5YG`m2O+VM4D{^Goaw8QiMg?EF6KNcugEq|on3JqG>P zMsmr`JOSp`DD8bmV9^q!YL_>%g*8fD9}dJjPRtk|1-R;RB6k#z#FoJ|$a_b$AHG^s zDw?XOK@~pfG*zt)Xt&8Vr*^!B%;l8IyxJ!7Gx8``VSKLf8iR7TO{%N$A2Cq4P1(;g z?-aL0ZE#WTUqW-wmYF`JqjY3@a3b6}B9rFm!K?9cO2YNwg}ASytR4m6m@)%vIdgoa zn;pxOK&zk3Pb9Cmr{-)IH-n`YhbH+!V(N5yn2lHsVt<+31h1iRjt_q7 zt>pXE|KIY%A@6O)R(@D0+(m}EI(*C15v=GX)6XYQr>PxUvy**MwK&)8d~+rpS(swT z^0kyM{G#UXgzRwer{d;}j!hV@{9bA{X{k>|;}Ay!g4Ypj$6{lgUBG$0^3ytjV3&L7 z=ORT9I7LxzAm?Uy(8WvJ`wf$6w>tx(r@9Pi9Ng>qXh&v*MLax>cpO=H8AG`Zo9Ee# zitz9Y_#>&OZk|_oqdx$kTOe{TD{f08X>Ew0-4XN@o{a377_U&jdMAwcN~;Wu%Bd2aDWkt$hdYEAPa`E-w8ppn;8q`E*ZKyiP}7lX7N zB@14nyul;&v7g|cPCZD6(ptDMF4c}`R&NJir!>EqR+h%fxuM}=txkw%N3~7ZcCQ;I z)pg$*c_j(5*t(R8Ypbg`baNFO9l;9-;>g!Na!TQTavC&dmacebv{!rlk;Ca`brr0< z97y8`MA)U((m>;IJlp&o>5?Nq17+!$LV}8VBd1i#7RB$V|3nEj%YFo8{>OE3GJvN1tv=M)x)s$eT#xFL>jjeIZ>!?3w zys^HpEA1hKA03ySVyR0d-Q#y;wpcpWqzPK_WSUcr!DX!7{NQNu@)b=$hqXKhb^S|i z?LVPO*Nmv`t6n;VPDg4P3R%`I)=v*?){eJ{ed)I9d~eg0atq!jp3P{Z0$(bWEZjNQ zfhs&JtZp^bRr~#vpuTPC^zoH+aaLQpGRF}_$6|!Tm%wrhVk^Q(SLQmmyEA+__0yBR ztdi*rPG`X322aKdmm*9^312>f%|55V9~xfc*5%yqZLgIwmy<=RQN zGmaR6TK{L_y%Z}#YiH2Z|JU1i(&g#lz)5EeyKDC>UUR(iOAJbEffHpHda|< ze)5>75#TLUfs<7+xxCctjO(&kyMmBu<9%d!+3M$8Zi|Gevgl&%I8?0d^x5siauWkv z#68^C?%)lu6UpXfryT8`0aIW5jh|`F8g4IncisSTm`;m~!8lDR84QfsQ`lR!#yh_1 z$SZytw;p|bW$KW#bVmCoroZ`>nM^Gk<#RJl51%7vh|?NrkYH_|ibn2ex|%a}xHMjO%gYpX2 zVMM;9n}<3v;9mQUpthYnxTr}@%CKiA^khtEe?yxeQRdc7g7U&7WpXXK@lagKfG$gn zsO)Jop!qY_1vY8zalL+W{v~qsC~<Rt)PkD;`Ehovl#2Uo5)XORcFLI=Y9j;73to z%$`EGE92-E(v=x$=MT@MW~yFhFk0TX61t<6klt>qfrs(Q5gbWDsurxBISEcynAC8J zTTti{s177o@`78tz1C_@gN*8~(vj{vf~|Fjx#PWU$hVg!i-a11Fseq+q6@Em{}^~rTeD=^zw5EzJL zwT$+NQybw2w(2!KE=1&MAoaCp;LJJVjBdt^KNe>_zLexRvvf{7h3#-0>TaM~Z7+_0 zC&rDr2u>-&+1hDH#>Ji{7l;2}aj|*Ds>#=_#yHznGuCx*I^jv?tjhi!(W}j?IW6B} zW=G>(O6an^B^{O~-D1a)ne(^us!F z#BBA=n`vayH%D^2>n2WacTF@QU%T~-6Ybm@CK79{KRM~jbv!pHx}}JdNL^oZ0y;Z= z^bEHSaQ)4Vu3n%K%T@#I)Eq3ojj?Xva>KHd=ba6NP0cZdi!}@??4u+G70u2Z!Rq!h zHZ=z}s@nq=h7}D~@%n%@q5av@x$gbk25cHr3msW3q5Dnx6bIur^lV*aOr6rTgfTV0 z!F@SNW7-I9qOoYC^Z!$DEjY~s;9oJoJOH-E0P_I&cMLEO0N!79G|U5_Ee4nefENSI zgWm25XoO=FWbpjN2g2OwZ$&+VohO8^ms#lk0cbHipKs?6FOWCbOgWbS)PdYr_-4g{ zgKASN=$`uXHvftE!NoM#)kR*Q|3@{IXObjp&0Ji5{3pEdbYz#1u)}`#On=M<{ zjEcLOE}e$dhGy2pA?^9WFVz!aGTbx0=WQa1|I+}j{klV;;ljy$OYJ1Tj!?F(%57LD6K~wvdk;e zh5n+bbG?y^RFC>lACub`UJS_j!?)x0m;cgz`Qasec4exwJ%8ja^azwvios=-O9`+u zJnC~VB~AT#BbNcLtD}3f>%WsT@+bC(>gvj#TkEK)cq5k!PtD33`5$?Wv$N~}D@dvS z4>@*x!s!&X@8M)aMWK0HiwxgEOxGVr7sAo-oqP{Pt=5T;LeGTn0{&d$qp*xvQhd}I zKgo_~8!u0X|BUlqAdlOkvs>Qmz_O-9xxEfgSH_ITHBGHxvFMZ35Y~PPtUfZ4_cxtH z4s8D0p!-mY1|T|=E(HKn_ua71jDSMIU(Q^uW3eWcifMQN(FRiLby0C0vF5wx7m zm{p$yY0}8IJYAVvdo5B5YwvxzvtpYT>EK{wi*i00U`u39sU4fH?7bk~O;AKcAlIsO z-1Te&%#Da?D?ytetU%IEQYx=hN9M%`_ z!x`LAI}d)jvBDNorVfqEl_ejGwT?m=ejTkraJ6MkPv@vjjXp)*v>o(*h}HEmZKx11 z`~boJu9!kH>0umFUWf#O)`K4g0wHC>EnxN8ajsOxj$UWCc;St-`iVu7JKg18#Pr}k zVs-0WWOUBR8D_F5te5XjmyYbL^md+`F0yPAX+OLI(wJ5u-);|bLu%HksYN^Ssk5Co zL}k-BuKRY{)8%Zb7u>0w+SI~fzP`HV7)Mbmbt~BiA?yaS%I;Lxj>*AJ4_w<2XG34O zh29aZ{RFk)am6>>`19Q35J!PDdzN>mfz5Ui+(;Cj1I=jR+8TKt^Mad{@rd1A420e9 z;Gjluu7O7$gr~u!@&|T|?(2L%%fxDSF>iryoTsEXN`&3bsUzjcm9W9a;PSz6VbCG^ zZnV@mh5U+vT8&eQ<6#jqS{c9J#S5>38tRn+_nAm68-7Uq4$sm+b2VP8`2>QE+biy) zqFp`jo9aBsofp%&U8bGXsFlMy$7@hyz|qA{=17cs88_ZZQR|rNL?sP~ZnS$iV(ml5 z+J!m;!$7%XibJW7Lo||N!Z`#?WO+}x2&IXXjhBA-3ourEr_~nMr)IywB(6O6UbOB)teOWg zFKF&I9_=hl-HnB*<%c%UV&5DO&G9kp``pmnLT+A3NFKnJ&78-+*RBL!Pli@&!^2Hb zt2DtR#oGg!uGZdXKuN-@?=Y{8F-_Tg)r|myYiKL0ue4y3dZim#t!pZgbX`wM*NDav zxlOvRyxL{=PFc@7DysITRL@cDy*_V8v5&cLB`ilblRc*Row82Y6I)j{zAR4UMz6sWk$Y-<6^dY32RK10A>_sSrt@r`B}lW zWbcH+EPU7Di)4>kQ3Rd#afZkWGxIaC4Me-+`viSecqe!<5<;h4CZNgF8Gv@kv|5ft zJA&&Wn4hug1LTYxt!2zhx$65e)whbXYGhdK>&3vM9FDmLs>z4;~Qjg9TK zWXlKUu37TL6Q`|#wQJV|*pniU#`E6ZUa@e0kU}QdV7{71_eB2n>*S- z(c0-C60Q^!9@W_iM0pRCOIDzKZ$4iNF6G;bvhs)4Fq;jvG>lztb)wpvs39-VnXT5| zWpp3nM#{1B>d6u3tkq!*UT|Z9v9#Jf5DjtC;T8({LWRp|BHL`Wzk<98Q}L;=7v14n zZK2gl)P7sfZzd9FxOSNomFLLhW75+DSfR>~jTxDwP z1$O?@siq6F^Rx4PBe!dQbYnJ~BD>~ME40>bjF9@k!b5A_#*@+$QS9z(_g^YIMisTVKQ{DWZ$PoJm{&mw@f9Er) zNVkExemPFV;XvVsNmTQReVM3dnjusy8|n}QAU;0{46eK=+{>icwBDta^+qQ@7_vnYO}-TnDyTieS_z-Djmx;o9blXx!W>K%Zbd zmG;IP)zaQBg6GoJ4!a0whvz@3zyzXG0R&&LI5xF0WhkdQC@%$7HA{230Z(~dG^Y%? zfDm!YuV5%r`ZT*}l7J6oBl(|K9$dklFf80v@3INQqM16)_eU!5kD08-tatE?JMrmt9^$iX#`5h(dbOjz{ahspE?3S zzT!?S1b`>iwd4 zJ_1F!Bm5QvYj_skvJRQycE+TrEPNU16%mtlJ`=>hsI_To|UxQCUu=1l$?*4X$ zZxG#r4$1MXlEj8`n{U9F7iR#A%&NW$uN~k)%Xx?&N+?z9><_|ELs1LS;)-r8e=@0l z7%mjrIli-fp6vq9!kSVWfVc>4A5XkBJg_7gyEoJ};!9Y1tu9uD9|UklyPj_3ZEzv@ z#`W+mhAedrW!%XRrHO%!Qo{JAgbAgDp>aqF6G{o=&b95$Tr*SitJ5{u=KWGPCTbS9 z8twD?0@24&l3bGJmkC>edYl!AEgFHJXzTbJ#9?XzxkrlMthMn%xDb zeRDCAD3d5Lgjt5pCl}h>kjBpL)U(h^y+z}Io7E>PPPmR3DNe#K5+T-`{3cTFy(v=e z-A*&>DZi*U9ehR&j<#o`r#r$kl;;eU8GbWOysf?auzPDtt}dCvjh7HiE1D+lWX}T- z`z*w&w{Ryiy{-5;_OqS-ev(4b1e}A4Jkl@}t=)55Tr#Z0D}DK{I2qRSaWXolmdm4! zjOMRT+wJb*T+k zxVa;h`fe&a;ozy%&TZLU+YCo@{aw`Ug{oWA!B#dUsw-FCpW0M)F(7`L+0!Ps&aAz> z`o{au-*hr;;+wO3Fl)q_cF}ZwrxV^lX)MgsMEQ zq+Fts{)1|7=~1a9`;Z>h$+}i@l+11`_auhqxcJm>RD9QynEPFiirO))qZw}E_P&W8 zRhZQ~%XE>2ndODOGp$dl8MuqUU4`C!Zxoq8Q%(NJi9KF8p^nOc(sndIoPN(95VwK8 z)Zr(^ZQ!a@_QtpkJeA7+E%q;O>)qeA2U+&(d3Ef6Ut9KS=hs^JZYaN1?ZhUi9Pha~ z4=*i6I{XzlUFC)D)6L$dNl4qg z?1D4ZJ(|juOPJSDu9ywhUz&d|=A9ujS)<}!qA=Bm%w|Y6JD`mVt-+3>Ja3~sBUnz# zjrE}YERN0Kck$0ynaz#gR;Ya0G?M$_Z?8_fe?$ER^3O2oQ89Edv>7L*?9CAPtBdJk=iB3^G4k4dDx zt`7%NJbk%%2A>?S5XJk6;_1U1)vw~ob@2>7IbL5Bj}>ftT_4`4eicuyi)ZjeJoqa< zOZNO<&BddOL7o1Nx1i7c&UGu^yVyD1$iXDN!`F`XKQ4)$NDA8`f?9p++fa}~P22@Z9hJI&;9Gz`Ud1UgeQ zOQ|&PTQQU1pO>1W`A0W@e@BTpZkZ1LfX54-vfs#Ph3mzalRkzV- z(zqWU1>>su+Q(sNq>TLrtAyx~so{jL0ELal@UJRMv92Qk>B<^cgRS}vzC<3XJJj~Q z8}+S;{dVxOrD!%YP-R|RFbYn3_rkj&YMW19c(1&6*r}_w=RJDqLVG!0a6j2P$ z60R=gts;H%piuZvJgw(6>T^}#Qe9}?s6O=ks}%n3D=MD7vSGSZoeEN;)p~rs+^iS; zQMB6zUGDlq+y0`jcy_B@q2lYJW+RV)4GaLn_|Ftxk0aTiW-w<@{gvBkvn>>vg!B6|U3 zKr@pb7#JvadEq})giNW+J*OFpe5P`|7yQf8F(&KKS>=UpK_(N&97A^8|C2i!5Ya%Ey(N<+k41Ie84>GTE~~844s~-oE&iVBUe2x_zGw)iSVmSp@ z_I?ilZhDtd4Of-DP_*nqHR!_?(siZ2@O^ZjfoV#iL{Iu!bdR}*gQ-sEGNEqzIhN#3 z(K7y1vS>$-<72d*JH_kFG5>_nu$ysmu%UQAR=YAIK&ALx{MNppUE!}#_>;|WUaA!I z4TAow1-19bJQrgLOGArFo9{^d9Nw_2WV(<9nQ%;Jh`MV1_s80dbmj0;Pud8fIkfOR zTYW>i#uUh&?_61qI+tiV5VOVLvtsMK4u8dCSxBDTB-zJ}8h_;{;JQbhE2>sV)djU9 zzeX$ZZR@wT5x-qZc1o4JU(L~gbh$TI-l#`JaltHicLZt`An|- z;^wB&#n3{&^6fT`_KNN_z+56OC8DIPVbq(P1d3AMx-_}<6X(FK)m)j@tV7d2y*B;m z)VgQc3lF3vV<*FX977BAhqKN;t81i_l?#&r(v@-)$|a-O%+1Y+x}7#c!E%XMEaois7H?Z&bP05- z^V5*u=66XFcnHo1_fr706au(+-}2;1e_ko<1UP}AtSg|J&>@{ZJ)PmwpXbgKehnTt@5n#0SaE5b5bshRZ@ZNHYL^l{DZ7*kskgOr3U-vy zJbXYgTQaIQxOF;7y4Q9P$w$`gJh*&32%+k+p4V6FeIRv)+69?=NWe@(H#o~34Q+5x zbq@m^`G08p5;!@E>i^#EneN%yBiSP}yGh7yLK2!eHpwo>ZopjJ$dN>jge&m?+4fi33914oU^8bF{>uWX#@c;NrK096Y zUe&8tukNZ>ukL2LWA;6CkMieU{B*j@A#gmM{v&*Q%(q5*PZc>{rn(1)}czt~;-Gd^e_61y&}B)|-k?ZVzcnR6*Br-4$h^bA(y zS^EnqZ^BRYA^e!?f0+J9=pTNR&d0?0IGs<#&L_qB6roSknXgjLrh7jU!+F@9@;P@g zM$RfTiKPJB?)xx3=DSbsZ_tUjcj3o!{|Yp%>vXD1*Cjyd9Qpr>M_&Dl2Q+I#-C%~1 zy=>WHI7F;ol&AR9P~n3iXKy$YLyjEzSR3$?s#$vmd8x8Nz`_s90R3Si_sA3X6qaI4 zJrDgUZ9fkF6F{><5jx%!%o}jSl&5R!aL8j~)7oqFUgkO5@l@^MCT;0xPS!fqgL&C! zA=YpvraTCZ^suU;r z_Mi%uUHGrDH{Vn_c+Z0qyEI4HE$tA@OJ%}3Ihgum@ENoJhH&v?S+r>^^ek^8moHE1 zG9PDrki@+j{{&xROKXi*!n76PWR$jTZ*OV(=w=^z54BjhtOeBu)%p1}?m( zrE^A}QOTU~X$VT%TFQ6<@jeThLldUmx}nd3$;_nP&f$j>H)I~Wxhx2tKTqnLU}4)GYmT5aGVrP_GVK}v zWcCEFQD_IZXQtrd^Iaf0b)`FsPe)^WW73LU*2TGEwlo_GV-KM9K_5=b4;%3`?MPvl zUVyq{l-H+Ye;@p2h0_G9J>|WQZ+Ws_8+?P+6+1D4gUrX^Zv*w{0I=Qk-emZpfF94X z6X z5`a?j7Nnj@scqTc1zRbXY{CeO(`25|B-Tv(8Yg}aV#U9MqA`$nz&wZf-Cu{G;AlhC z+djl;)UL=-pdV7<4AJs3489qTQ^o)%x`3ZSIu}BAm~Bl*1!7d&YeZC8dTzFVA_2TC z@cs8{Xs-#L(I=XaU2CrTk9q(5+`;V32 z`HSE=Aqp_fqv2-gX;G)Xsn`nbdg|1-H0sfCgPvRAXqZ`)lmZUOfBpOfEJ%C*G`=k~3xl{H7O0Fh1KkS|nH<09tY+B#o4#Shjp8%}_(Pd$50#WEgU6ZV=j zTVv132z$XiQ8T&?_LA$wQRX=D)E1XZ@g{YQm0gn&E+Au=dpK6{r(8C>%c9%rS&Z^5@)nIaT zD_foHy8pCr)$md1{zmq|%6j+^y13LHK9(-7wucX(i&kz5ll}cpG1e50kyW_mEdipO zvGVTS7_SO>pnr`@Q0VV{98+0+H@Gm(awi}Y{7&R|vj10x;eKZk`RGL*lnZ+_>}*&v zdcYoqfO7K09aQ$So6@uK!%45|t7VPJGmSJ?wX-E8%{7-{K9B!2X;wKTOh_C6zygr6A`So!A^_jRLWDQ~ zz>5VMQXBxR2m#{w5bT=*z#R>j>NHjQ6h?9@!@%MI09QMdoH+VT*GD981FDLgjq%J8 zIxEQkkqDSLbHv8=6r2GPiZj4_P#HEm0~{Yuw!hwXJZxERAw5F3on9O-ncmjoU5or- zpB{ZL4mxnsvJCXgN15&#N?`$h%K5mNt3-8UbkOw91sXjP1#I`ZW*}+}G|Gx96>}h? z<16a4dm_^?Ift^{GwF6m@S7jlLCaf?@J(+Ru$-)aVW#>Ol*DY)aXkPF*hZJH_6gLd z{4&aB_#g}s(4nfX!4{ouRXu*j?1Q;?$DPh5J+_~e9MzzW_Z2KCpdzgWPE7*Gdjh|v z`#~gygE0BZ{(xN}N$-5JfHXN~9gOc+nD){jZC}$q6`ur2uz@v}vaxmQj1*Ak9%Ucq zrI)hKVT4(U_N(&%&I*o=eC-WmlTcPBY?ydb%})W1_6Do^A$)85qey7Yq#X^uJZE$x z=8{qtp=k+?BRke&=_RW%Y_9_mYA`94vN4P7ghy^?)eZn8H~MTyW~2WRFyfxd6cg-qHxY&B|iNn*hGCWzmfm9NB_qg$xSiPMOPf77}LS zCVGlifT#~Cp=fxF{e@H7g>+@HwFe~YovI|IW$LJeeH=mW12m#lIaC#AZYfqGpoBt# zc%%y%z*MBO%FY}g_LbVs8)V*rrfv-H$7Vbk*&bn;=u&J7y_8G>%ciH;sl>7^1-4q) zhzds}dsE3P56v(#xfg;Dj!@enT48c+8b270_QRq{=5suwNf|ej8T<=gBXbV|`Y-In zXItgiI`q+~8>mK!DOhOC_hrFAi&KUH)n*{sa+fd>@NgdI#}gXFlsI-ic=d+)fx6l;(FD|$ zP2?vFwe1-_D^!LqWp1)i$bd1hSOQ{Md;WnK2!h-k`G1$20xnwz>^jP>E)YU?^+n-C zP2BAVtbi)z|4Y6SNtR&WJ8B8?LRxdNDX!kl!K=qze9Dw1A=Ne0$G19XLfF_fa%b@? zWA`A~{~E{c*#L3gumirBH@NuV%!QS$ehA+Yki?3FHgdEP@~+QkKuI&0fXuq8a)icJ<4vW02#Ov|bBOmohGtt@w5@P+--6D(7;n1$^tc1^%U;EF zcf#-R&iJWHm#lqK9!>Icl)E(E(iBTyNaCo56nts~^ho{dk=%tZq7U#<{1&Qd**NG((7C zqY|pd9I2T|L~UFJxGyBAEDoSHrHg$DZcuL+KOm-_m{@eyCH>m%T-qI>g0yr!5A%B7 zE)XEh8i{-ZQ~t6E0i0A)4Iu6EAgvmPRc=)A?vgL4qcd*my6e|BC0`g1lXXcM*OtO( z&fVn@sEj3+aU*D7A?=k?RkjS% z{(O9|Wc$D~H+aA(euWWLcL<?abxS#F!#x+*=xP+ONHVbam|A3YjvjTX4&_ zsW{nDSKk&w_9z>FxsarzW1VyYHmFn59NWaBEx0mDHBuR*;Fbi-{!z78dRv%=)C z#$A9i(W#+ zoPrk&ad?SU6S?_5&IZ9CJ4{v=-XoHwPDfVRk;dAA2Wp$!0tf<(fu%gI_q^9`Yf(mU zZ9^F89BZKIjPk@b7{(At5L{pi5t409eOA5$R$xTh?V4B+MKEo_Z6GpvQCl;a46+xU zb7C3+^PX=~<-wea?n`Uhi9v~WOq7Bz_q9z_8O_Rfv=#GqTU%UiQZ{Xn1}>2>p+~z4 z`HuGDG^vzr6YaKk3G3~Kidr_i3vKNPi(4iP`zIvG`UG_*=@WJi)9uK2bb`cdSev%t zB37r8_&2;lq7x)wjv^qz3#hEK{iuppOS?)GBIZ<5wPE1H9%@Gj#dYSqOIZRm0`vhh zBaKeC#^05Q?A?JdrJext1$wX=lRkkS?_~UxoBc5~dsVfbq^(SQuoe^Mc=kc|k^}YU z5>1U0v{nLd0;n3wTDGZqc8A?DsehcC6uW#wgT!Vh6FU|?4Xh)485{eB z`p{f3?~ho8!xDp)3}B=!c}*LiL|(5!UT0v-eX;zQF4mJ-T57`lKMT-hi&w@ljO7Ab zv~n0#EbIOXDlhJ-==!q$w0oebl*{MccZ0m^16Jzs4?7T5Vi;~!t6q%YfinEB82u&) z&Ak&q(|v-OWcFN3S1X1aSvA4$Rf7^sxE+CcC-5vWX^pLGLd%=VOH?ylw=d?KB1wW zE0E2D1Q%!BFjgSG0ed_m0H*s{6+olAmLjLL-2;%!+ogEf;;mBjucJubF~!~`Tc`MH z9Yq)Ki(vfsr;Q>VsNQ6~AA|i0CQ8}nI{sGxk_pTfQ9?mQfHVR*WYo$L<*_=DhfwwR z2WiK>8RZEbMJw&5Aexe$a&JaLXb(Jlx*7ug7Rt4DGIpZoZ-8%j8TcBZw`ZpNexzMH z4co`^BFZ{A#_Yqm>jk|P=)V%<+L#*g{wAhn?{d8B;b<0W8QC}WmV;cWBLV63-UCok zlhi;N0Xcg8;K!Trsw+0$<;+~-;X0ys2;x8uOl`~TW$d>>&(B{rz56k~`!!_M`v&I_ z+bd*>Jp9nD_wq*_p@SLw8jwJ((qsfKGS;uBQ9pO@|F3rTKz_^ z{0meCRJqTv%56_!wOXTJPsDZHTMz>0av3a4pGOg6W?+qCZ4jqSOL-WK0e4{@hw5^N zL989A#tkRPJp^DlXt|BJd>}Uv{L!+p#&2st`TQ0c?sk8NUlIuQA`!FyURt^DOK@Uw z-#SipbZ(swB^TkyA&oD@vUxCpwMMZCp1}R74);vLr*9aeUK`hl+ z#UE<{O#prYf0yBJBmP(usJ;ceUB=z`L$_`qN!c30sk8z6Gsd8aG&&1$VHe_(E{sOS zT!>d{h0&;h3&X=`ez`6u-%>hwcO^(CWn2s$x9gCf z;rAj+){ZMeO*`1bS!C}6&U-(8aQYI~-~hiuiZsSYRVKi%B>vbKAN3Uh{s`iai}6wA z3h+k~e|(IOsz!i6iue!4_^7r7_@jwGA;w27Ilv!7{E0C>YTE&R74av<_^7f4_|?Rp z9OI+<7vSGZJkHlb`9+m7z`u`poQa0`sD}vf?l!TZmlej zWmuf$hP1|)<#ELOF@Ahm9#8ymj2~Z?A0&Qlj2~Z?ClHTn6{bJFEKejJ!+3}vUzR5k zj~*q&k1xxUiT|G%KfWwaA^syVetcPei1^cE{P?o;h_A%>@nyM&`1LV0iQd*T0C9KMhKkr;mv{b$Dhlj;8&%wY!cH_(4ph!5YowB$X)o4A(Z>AUT& z!T^n_AZFal)pglo_Yw5+S=+yq6lALWQ=r`2_`~^f;W*qIfo`3NcxUh7VQE5RX~%&Y z^_A}71Tv5bZOeTZeV2Q$Xt%ikt4X|fPsGga>3$zx?+5s?{kxeKC;7t$Qt+OwEl21#D?p~aD{Ui9PJVtWoV@)b|WY!?39!;_3yvd;I{)t&V2%5j+VYir-QxLP%sd^(V zvEInEfff_1*iDF8We^QmxW)2Fe0eWWay% z^54G}N4J4Bjge0vV2wZJnf`5nkG>dcHR$d6voAq~rGkfS=@cZWdp*)0`J^O)J|S&f zin0599J@aS7;Q9t8sF+?@Ka-`@~mx>)_e8^+paK*$W^uslYVYmVgr~LqN`^klwINP z{4eu+=?PM&nz&p3`8F#?A zC9fV%L4%&yAQ?8-vp5_Ni_Cyg?+(oGy*u%<4zGetDXmie70f$nYLlrbHksBki0r2- z&r5-aZpt!FYR>`T@YGQZGToJ=M8)yJOCXaZP*S}OwQFc(97Yn(3s&GZG%cTcXiunY3TN3LQEZn$bylK1Ue` z2y!d1R?giS zOZDXbR8J1{OxaF=Jvofsk{#YWB#%wl|KR4ZvZ6N)pVKkeH1-D%{8t-69~<7p@K@Z2 z?(6eNbcEm}Zi?WBe}N_$<9fF9zJS0IF320tR4{*1(*it;XnCJd^|WAfuidi8$UxpqG4nUjjTEz_Ei3@a)vN*h6aI1C`r5jp?O$;|a{KC2XV9cu9Jx_Z5Vaf|A=M zss0BXF*48$4M*NOa)xV|z)JaHT?yWA`2XO&#zNy&OPHg`mKy!(Cm3sB;AeJ?1y`Si zmn91dkFs!0kcAef(ROb~1~vxFzEICB%ad*B7<_-o@~nV<`7rl$Xnp?t-$Rs_BDW~u zqd8&xD%_ZsUB*w|`x-yp-bQ@fAtV9N<#3OXgwPQJdG87W*8?arNz2^$Mx^C`9`sGW z^AETq8ai|aPZRV=nmVC@J&YWHzDECX<^8oHjSQ!?g%Y&^z3bW z(9VbQ2UPO2HLOK+V;GATYz%*tYpHL6%&ZY&+}~pEI|u*`mFxHch7$N6{2(r@B?H)~CPI4lc7zc}8NpmJ$;iiIMu-{D2n_ToBe2Mr zV5GVBy+q>8$;5F>OcK}K>YlwblDNK6T*H`~O#I_<;>3(k97g;!aUA>B{+9`+HMgzF z1aY%W67;^05VS~X_H=sFPy(1M*-}U_ttx&TV|U_a_%-O!+OR}&e}D+496sT$Ldy66 z+S-p%-%Q{5BgO|V`+)u@DjyEzKFuZ1-vL5zIygBpX@lotPx&rY9=jYl`GZ!c|2x`a zkvCy2$2$WJ&|Qmo(#B#uL0%#5->q42bOmm0Kph^ zYQT4BUs9tC{|X_H34fRS(J*g^2in>G5%8el#Y@;=nbz&E7R+R&uPO_Ue;j~N)LqZa z23oEykcqxn!vpcx!Caxwy^qUSa?cg^9sFKeyAvPvSgOC*0UI-bS>9d5SXBvkz3#K{ zY-}wO3+|s!I#IOh zM#xv3{}G9WaseX^RO|Y;A)$02YnH?D8ac}JxTZ~5)=5Jzk z5fTB7KZG<=-tQAMmVm~sZ%tzY?#1I7*pMLT{V}AM_WqEd$0N>PzC(HwU@UnoA`aU3 zEA5Qan)3dr#F^hCK^t3;TaZ&-e(QLxqdg%tmNTp%7f9!UD4n!-f0$0jn2vOM(QjDW zERbbv{wRlxQ4YeVHV2tT2#kG z9ickuu%=P+LX`Q!0#|9iBj)O8Zb{;xk9O>0wODi?fYjOhrd*u)72OBvT>x*|#e)S! z_fPag6(N;IzWzeUp9#T+D2-&+ot&nltjQ;X^<+L05!{EJLH=T7qK& z&J3{ciQ(X321wbGECO);GYR-#3myht+(#H7Z3`cyz%pz1*YitsZfANNR^=x>s^Lh?H>FT-sw5F;Xi1Dl}*_`_i^N6J!2U8lmiIV)7lytkNTxOLrMxGJ zgh1R~xjTPBupyrtKA&@gr+}=I2;Lojn(hmjij>(*$P!Zr+%F-_^8N}mMj{60#^*Ee z&bFQ5XYnN`aiGG9QQFS|8KRzNz+=?s{Y?;(l@|z?GS+uL??ReZu77vj5t;{%=M01d zk_>n+A{I@GYO*hphJO}EK5QjrPv>oQ5lu??jKubGl$IqrW_L5KfTh0!ccS+X{6h2h zD66y6dj)Pq+LC*$Hr<`UQVUGZzY1J4Zf&|{0HE@0b$b5GWQMFEB7bwmqiUf1&058(-cL!~Ru+VPMuIbDIAEiaE^*ak1(P>`Xla}Z4MA^=VFo{e7{aFIy$L{v-O2Sz$*7ptS?8BO3QR31LjUf2(HXUl6K6qQ2th(2cQelv^;k+G-a9RGwY?0zSc3l!CIui;?UI(a{c*V8ZvXI*g9ly3cf)Su?># z^{WVL4)26$)vwX1Paof+TV+hZ$75=1MlOOYH*yJnYv*G!K4xDO&b{5~*c{L{#j@f* zvw{uOmsM{-#qml{5yd2n_2=zu7WR#o9@0~;Uv>Nh@T^|cDjAZ z5hq}b5_sOtGUnZgsUZ{~$7~p%ZKDfvW53*Pgj0Yb=$Lk^?LLVXSh&NI0y}bIgZ~Gz z7MzGQf$GEtE3aa`51k5p67mSHdb9?x-+LPLu}W;)c3!gfa5E@2nLYhg3R|?NvqNVh zvg5S?(>&aYUl^L1fR8s3KV4oMeiMM4*A4*e#>xhFqx%%t*LE!h2E$@;Q{My&NO)oA zU04f@Rzbd6@12AUK3AIvmCBPbYRTjWGXjQ(AFNEKgLC zl}<6;m7rEUR!F#bsvg@I>K;WY&33#=$Ri9$GgFydJFHQnh>DG+jz-z3&&|vFYaR@; zRVSt`NoUifj+FmQ7(A8&GAnX8!*IVI${}Zb?{;Gnu|i=GZf zo%m{5Fu$#nrOJJT`GDfu*SgoRE-GbHx#jj+It!`%ayJi&1jUTa zwE={5P>HQoIaqVy*TQ5?{S9a{rs10?DwdWE7?^8b4q0NZxsjiA^$LD4*SwP7T=gpb zd>x;3F9$mp*QxE&k?G#mpyM7*&q3+lvp~>2lAgus$r7ZTP4`UHz1i6X({iEOmKB>eWg?l5Ss@QSi-OuD*U*b1Exnh%pzlyJ0T_}D#CEgZsk^~ z#PSR2#z8~6nr#T9E~ex|NbVJIB;qHeJP@W0@g^fp6CTP*8B2&*JX2LP#|0$O^p)@O zAwecrD~T}8n18G+HNWp5O$^LzJKad-cc|;b7h|yEC25?#rqE}v{~Y%U-;W$saSn+Z zSx)urQZ##Za^J<%0-Or!KKU2m7_+~^Scf0J4nvHF z`C5ILtK%@lXqb)lVZOmIlSMwnxX&T)E=-pc!};4s(WTsndSd04k3un8PpeG5l530k zsREvDb@A4P?9X>PnM-gjt+8<(180lD7W{@2`e9=B26QszF4M!ClUY7M3H2vA)zYwb zsS9_49>cN3a@%_ZAF8Qn3i>PS{2sJwTwuigOH=J@b?djup1c}+)Kid^(xGTK~~ zbKO_KLunuVHrvxy;}$lL;z~G~;n$mr(B(-PZ#%}q@`PUjmQo~<$-C2tN!vXWS7+0u zp0w8kzi^{2(ZA2w(j~9XTKQF&!HS76#_0v5YZaF4*g1I=`5|o4Y6$CZkZ%dGMj%`I zUkLo{hUkAW^rMZEs&<07o)-1ejBTJZL}=5t0=AAtqlE$7_u`}Hox3&}#vj;~@6{27zcJ;32?B4hw)b^Ij}v^dl1>5bqg$M9yyKRxm}{wE^0 z)q55wuWCjXqk#uc6{;9B8G){DwtBKkHJ#~sV^wpemn!{pch5+%K*6Z1Z=JgPYJ=Da zGcq!~_MM^ecRNc!jI-Ov;T*)45rP<8m~4-DfcMo9h4?cg)NUVR&~wFaB52=-5tLsK zLHRwtIPCZrML8KHX~(}m0u(>&_;ddf3aog7<6jf|j&yv?4Fh2o4|M#~V&6i?|4;0j z=lHig6ouR#;(pjzLp!U;kJ?%F|N28r;HXKbW#f1mRG-|u4k)$obV5$=oSe4=1((tq zIt24js7AdqBoAF6oWBorgTf7J5X$!U2w3zImAVX6`y*la;vpzL6k}BKhs3BMlrYHa zu!vY!$EazJzt^M28g8#fd6Bi@TW7<=Bc;%ar-hYp=s>|f5Mc** z7r?y7!rXl*hva ziVFaq5r7Yk!8-&g%XAPi&WllKE9ob~_y}f(4BiY@9ep3J;bN!TAJ$k6P{t;Dm^)EH@(fei7Hs`N{YG3_LqT@ zG(*VP49oL7a0TJW(9l=mw|(>3An4$E#D`0QX-?2}mmPo7bMlPcZun@eFYXamgJdvI zgPk1*o0=f<1I6AMVIBVkxRYZ^)Q&EPU2kN@WwA7WjiyZui5RQAv!N&x!1iemOw=lko8~m|^8+tyJz~D6k_)P=|SRCRO zDTJH~D+D^7R}pB-#acWbK_T_1Bir|HVFDOewId7b&b2WLUG!UW%xZr03n8^_bKE3y8YYxM+6zuAs|>os+<_iHcJ4PDyCgU+4RD=xS-n@8T`<%k$ggKbeU z3&gS{80bnEe_|S?cS2)Z!U>1b*{IOLG;L@y+=;}7vf`JnNP5nHQ!YK7G7_TV8irpX z|K7VTbS>;({Kw#zal9ivii6;A0?zh{j6n7d$W7|B|c8s;x)?#f_n!$W8XZ7r> zbq=+9$G?ZQdRtL#Z+i@`x+mXb8pa^pyKlKX9tQtq=G}HYvRwvmhQ{{=#Qm;L_cPN3r7JC#|XCg*U zCxzN8n3_$Q>(*Yycj_F3$8M|!>FcmZ_YK4M+5V(g5#ArguihOH3xT?mJ9=>#Ntbsx zB=joE`bYjL*+MyFOGla>xXI?{&NRKFScwQN<2^2VMtj1%xIfgWuWM8yb$@A!zvf@8 zp#qT_dMo_OLXhAIrnerkV`2k`o3Y3J5pcOnpw1`!*#3)%UvLruf~1$fM!2S$^S=k5 zqfLTV5t9j)8^I3Nq#IC5Q~xblor3a=@9v5XW)%DBf`m32W*=qS-{(IF>)*)VOL?a3 zuEiZFY~J07ohUP1;f`KB&{uy1FY8pwco!P+{isv%{iE#`l>nPy&I;{U^e$d01_9h7 zQ4>t}4BiPlpKUC%FOYSi4S)kkk{yR?N=-1`-H;)B1sp374ez6D#K)b9dL4k=S#WD~ zm`ViwvLlufifMN?Fmk1ALc^@kmcz&*wdJq{kTt`Ay$$!>NB|r7>N!9>CQeT&4Be~K z*>wQnZk>AqI@kokhhf&@AVjQ>)+?_E8>lV8^kbM_F zU1FJ{knU0xcofu*2~@rw^)RFz#KLQsmisJs37*5xNg9>@0PlVgoR+7|xa8vQ1&N=# zesjQr;e&xHc7vOdg^8aCEr1PjZ0H?7uSm9+5<|4+&oU+>zyqi&o$bchq*mz3 z;B_U(Hl zZ~GmCI6b?{0ax`F2zo+;TLy*F1Qe3n2Uqo0K#Ndb{T@P2)qn({O3euZn(kZ%`~?HH z+kWdCAUQ!p5{COW{8WFfZbq)&PIs<)2R~-@=lporLj-0CDznmJhmU|)ZXennbrFO8 zjRTSAKe2DFklWnw23)g*O6Qn;8U!!lV+|O(NM9dnq*Z^vZ91N0_HcK-*yPZ5 zeb(;FJ7T-OE-W8N*SI;4Z%*fNj!8=TPVxRpvLisde+R)5w2b1^?gXTzu~G)dB`DMi z#}CR_EMcH04|{C6=FHG9P;Y~z63^B^Dd)35;DW??I68(cSLmItMRAnY;ugWD5Ls-( zcJ&<7b-fruTs~cNT-&5|05BGyel25X3qaQ0Y6g7yTx@#dg4P+rTcu!b|Xy z8~CAu_xuk)#RhK&r|@=gDmdKMyz8Ufs&lin;qt#X;CTTZd)A>pdr0aDE1BED3E@tb zBs|V=j9FobalmeOchpzCS{&zp0Oi8+p0;Wlj!rF=40D*Zhn^6@N^O|9s%PRD9ttUU zY1T^<^&3cscatj|V7gXyjp0praZg?~d8`55ED7XSRLF*$62kzJe|l<=OJ94YW#3|=PFQv{eS2fC#V=OMT@ z!@~yN0x6|4VmZeyryJ?eL`txks6IKgfaUUW0?7}cDUnIx9xtLbF+g7X5!09hkxbxO zxDKS23*~ss190=xmLWB4O`LH{MR4UZ|75W=2A!1?*(XhQvC!j(=EDko{@)J7uyZr& zIY9lGBFbFDGImE=52L(;sl>?Bd$>dBn8bWqnPZW&M=_00ZV#7zIeI9uv*u!B25r;( z3Bt-5_)ehn2e+{FGX7zPA{T;U)Mfz_Ul>;TigFi2o?#?+GyD z?}aapGWX`ELXW#A&s|7nANV3N`$is_JDmeMkCD!PfRn)f_=4QK`AJm|;KyE1pnEaI zq%V*jD9{SScn9I9dN2X%=fx`A{={RYcVbOdT?!2Du5{ZKx-vK-^Nv6W?@0W7S?miU zX#XSNavAW-CFgV>0bh@kujK%fulL{!z7FBXUQb_wp+gC+5a+#z)Wu?`ZT*XJY?8e5MABSK0K6vx^{wasJnYSPClL_ec?H4Nv4`$Akvw4SZiupaHq+? z9Vy{@g>EMD#pwqH(2an>1)#}(yTve5!aGk>{Xqd>D!&nY=;fznxq|a>{(-RxxVbd= zFvd8$@eH;=hGO*rmuOVfbA8nd4g z@FbIA-s!(va~04Hz|;Ivin;H>Q+JwM8sz}9yzUatC5b)m995UZBj`j$y!nJs)5wD%^lk0%}x=dTsihas+t+pmD5!?_A#6K_v@lx>C6Kn#( zB05wU3c#<^|1*#}1utfNDclh0Ta|;g*F!UHEg-zF)z+efar-Y>uBEq)&Hf55ss0ZP0Rm4xEnRFdIXUJU-ghKT&--d7HFnQ6FA{R7hT| z^kuE}PoR!#+qJ|*i~fqy0hy-_v?n2VaQ@MdYj&jiwK(V699vT~?@&@&QIo>(8PtM} zFh@r>o72Xq{QK{*GnR{o+cAhXwx{#%N;ET!wQ1PKYfD!jCtt5%@F}1TOW$}18!|MG zN3jeG_RE&5O^ycg!b3?k^Ik|_msyvtvbA+9?S zTbs*dNk%VxCDL&+Wh)O6t&koN#*V{W$~!91o_>{iQvFqq|4(zQI09ME+Ue?%_+rR7 ziXXFjG(V~8G5o;d89v&>pKiG~L2PkV$1c~&;IiOf%U{xV3|wI_{yMI1v?lAuoTx4Y zwPWT$TOR#5Yme5Brs9rqt`n(ct;$m<9eq|*BQ!bgYVcQ{ZkMK7A{fX28<>$fY(hGn zg`WRueg_o|=Ezf-$vF3yih{R+?XgMCIPS(vnVIlfu2V+81n*rK{Ivvy?OO=%BMG$Ka8&J9`w8&nGDtCdv03APuFVvW*kfe<;pLKS$df)4F`^kvd0U0j2ZP?Tz$y&3v7 zqV3YVV(ETUS$8Pc=}po ze_;aXFD>IUkTL&Rd+}NdCYVMe{;0Q*#~*bUX5p`dzXALe@#f-vjB8eYub)5Y=a2fi zUq3Kk#~=^t=TG|iGd}1gr>!(AbZ$6d4lan%1<>V95O!hskLU|d*L6A{QF<2j#9Ytx zWDG5p0*_>^S3L<(GLyxIg1Me7Mlr<`#-t~}6SP@O<|>LQo-igo=K2V+hlHPo9hG z37eCpriNRzYNWK%2c=z)XEliMQl|BIf+D<>Ts@wk2ruPRk0&U?ODWXj35xI{>v}vv z5nd!(k0&U^hjQH+axI3EWN=7wI%b@r{@EHJf=H1t@A1EZj??n*#INqZiOmSKc=i$4 z7}<)9@%X4TPxf13gG;aov^2W_Jzl~<3n)O37ckHQ3ee-_3$%a&^my?CEua8BUb;XF zC_s-FF3})G?ZN(-Z1$!o22j2To zF(xF-02FN$V7zP@fUqdQcx~Y3Af}DV!=tTpf3F))j;lk5oRVt!#3}56w;x1jD|L*Lt^p9#V4 z`!KsOGYR5BOw2zx*TAulPC2kgXBuaN!53orxQj6C;~Zo$KFzQYz64*`=~>p8n}_Ai zGHmJ2#zB;9Sfw&;DcPS;{hf?|@3%rF8DdzbG93-kR18+P?k)6xGb0+o9qFXaf4saI z+|O+>POa(vt;0-rIp&lQ-zEwyRecB_T!vJmuAIlg&Oq$pL)eINC8|#e59QE&Y+%6> z)89u~sqp;|O1Lna7ufG7gjd0p5dDsS`DBjqvP={GeutnrqzsK%p|loo zMonWF?U!xTgo=iDHNaL0_6F#{VlpL;bjePO1C@$aZ-{J7!x=zvkrD+aPzO#&ote@! z2%|%U(I~=Th?wyw3w?4EXM~+Yy;Uoowamdd2mMLfxafj4kw*|n&0W)&wFfKN*?wEs zbc&QsS9MzMmynWKc|XSuiD`KsfIIN$LU~p|6F2Bnr7rb!%4%NSxhgSs(_gNJfSQXK zEO1j0L&!R4o;H+UlB55!nK?b<-e#hWIT`m?_?{lC1Z+1Dbm%@-`)e}ZE+`fMz2ZC; z%!od1BE7t%7cli#GKGiQa!4`&$?jlB;CT{wu{G7S3D4_{O}Ycgn7O`%tOgA zfpN^Evj>hu~F9mM?;|oYVw7d<+%0glfmr0WnLO zfO{W7sfWUls0x12^|>q--|>Jm%UC6*eW81`W5663s=ea$;e zD|HSxYpbmA?MA-JR>1E&&TU-LQ>{@2&AYcj6oqSRKgX5NG5d$S19}|V<_L=}0Nxk@ zSvs_zlA&EQ16t5++JC(a__T9Rfnl|gzcb$dqR|c?Pcr|g_r4N&KS=DW_1=HNJKBa) zmfGXL4{Y|hom1pAXjU$+SA6z7I*`L=X{<=i6O}u|a~vF+j&29-NTIf|)4dRVz{tPq z(>Ptz2(87AvW`i3?*uRyMtTjArpU?5$iLyttMfl_y2ql+gT2kcZ=hgtAMVG}Lyltn zQ8GFA?@&9CS9{mP(A*_!iNV2gy25#{*u0@4$XezaK+b~Q-=jn}?Tg1PpGBP;j$(c*cR!~J!i|f3R#DRk+vGk9aq~&Y-yzPGw=K6NiP<;s8KT%< zV%D|;hJ~pLlcAw?v+lZ;{qAhaEEA1Ucm9d1fq zJP`#Q|9S$_vf&X=WjF1bDXS@CDso+vDNnNTw1*NZPBimE5wovM^+Txb0o(Vmc?a{> zJ&cL(F$T3Cwv5%tAFkoHS$HZ%8-`}|am0|RbB!ZxTpLg+kAf0&c?Rt8+u&V}_Os&x z+42yXX|J7x(NXx2z7Er4No!o_cR*4pa&E}CD2MQUjrDL0EaE6%Y{k6+Hx1}`$bGrP za{q>mWNQMoy)^)CavU`YC-XDaF>N+x&gBw~bWH>2sm8xSclcEH7iQ0Tu}9+V$)n2R zNw^CH2P_r88=v@zxxVEYJ;d$RFKj=FUSX!ubs(qG0PHvUpjRwp^jLR>epxwGbr8e1 z2F*aVM8XDkkk3tSb_L}~>&72GTlcyy7=8hn9C;l%*O}2U(ivfv)ifN%qcTewI2SPf zLz&4GYApl433NU`4C8!wv+6n2x$0FZBQ=6shbghz=FP_pgHw=SVNQm3E1ENI208Lh zL*$mhF9O);eHd=$q>@G~PCwj61S#+28||#r0+w3_{sI6-u~5_Li@>CEi(RV0{Xh-3 z@OFssa=&W78kwOI#Zn;Jp=?wAfdJ})@~&3(dWEMdHXJ8cZ@@3qV^U3qJ@`C|6%l5? zecEx*x1xQ%(%!Y6_TJmzI}Z95w2OmVqaudY^FrZapx!o!SJ3Pt2q;I_OGEZ?XoiAzX0 zhxblGD5^_0AVevzU(}^b8DTvl41JrmMFH-=L75fL@;-!$Jahq3>2)ysVu~Vkk0op2 zQeM9v*Tkq8Kf=;u(QybH(fI{x(OT9|PKwvfgkuPY|3)WNqEeNwBI(>ERIzcfM^P*{ z`L9G-g+8EWrme9(>s7(uY`o-NEN9x9y%U%dTJpaU6X~|bf%dkhw(J02bcbqTE>H$+ z#xxr0gBkBc1n&Pev~1qn(-`Wb-qE4jERE7&IHbOO7Y%=RTb{nXG}&L!$skkOngRvY zss2)dKwUC`Op_a!s+g+QNrN0hwI>guwPnFVHp~PR%WKF4O=X?}B$o(hz`tp?*%-Q7 zp|LLo;a`J9!ZJ9F%Y^3$XpKj$;U7cB8r9HUd@25gQ&9Vy!eT0B;~zB9jRMMneGIm= zjXVUOgx>-9AOIY<`uyHWVFlwJ0TqhISidS3tH#ezg6fopBdx^Cq6hG90w$;jEs1(i zZ0N*+Hq3D`y2PuHRzJs3h%I;wlEg?qh* zVcTQ-;&IZOiS}hyOy*+*(#94W-7f5Z22Mocx?xAefrQ#>?7cY`KNF#`86$>{r2b|V zWqW6lPT_iU_&6|MB{_5Wm+ULar>O(MM-isVmKYcn#U|Fr0D|?}@EC<1JG~h6d8*Px z?=HA=Nr(G!hLyZ*54IY>m*wGX3YP-(W&w0@inymzuq!BTSnz!VjaAPtE@3|K&kP)pD`}-{y?-^Sz-ZKgAtddFWnC68aZrkn-F>>2>G6X?B zIRD4m+^|^garu-R3RufmSYAyDFxuc62z%4wX49z>Y5E(`O(jBjCju}1wQuJQ>{oN4 zp)-5R9-OemHyKP@_n7lWXVF-!b9K|$6Yvyx8SVfbb`4~-${)B%p~@e)Nk(YF-91FR+e4KR8?NG|hFhFhJnccKB>|YD5JAVB?&Xi1zDmM1E{3y9>jp^Eu9# z?ib<5iG)(|CPSP`hvAA)y$gS@EVZSip z=^CxZnC{UYa2jk8dfXy}fW|D?$t88$8wGJQk-WKHn3ZgxE?$gKvaK%;NaGR$`uqjp zMW2#uCrw}7(ZusY9!@oKc326JUmIf3!gOO@% zE!9>=CdxR%ApP2xkYRa2`^#{^3?zPsFC}b*n4I@r#Ky)zK8T!&Z|_NFw6JlJ?+TW@ zR2#1wbXywdUjT@;v{PD#wKS-fOEKvRu11_TjZ-XK0+M|4ZX+jN*F*A{cxfex_A;Ip z=#(IVE+i13ruwBkBj8!YSX_zsG^hEWAYQgXq{_z}<)jT;OXVFSZQHmQD>a~u4s@ya zRR{p%YA7}i389<4f9R$-5&ANO#?&o^ZQqn``(nYSyS;ylv+th+b`U`NCYoB2gr!r` zKIsn)dvu$F?2|THUCN>VIN~G(;!o@fb?Dh6L1zL-nq)S9z~yW7p*nwr6?chFLVk;; zFv4aLwBHM(_PY^4ZTeB;yd0pn-8gZI6ztMtGym;0PN81kILU*#UN{LG=N06YXKvy^ zZmuMtZ!}6y=Qvau%CH|wRDpGSgQZzn_bSBDIY!!8iE#Xqj+B@uh+n;tCV4D>a7Y9*}Ixil7&SvF^?$&Gd%7sv;{1)m9P6c z>PQw>slJO^1m$jJTQD3aS{j3K!fBKt0&}--fSe3FGU!PBCTP1z{2ez#lL+@50y0>i z37w`O#d2d9HDh&49t);>4N|Cl6F;!`;3(mYrR}WXc(-Ds0}HTk0nbs4>6UXkfY}=O z(J*j0ieZZe4~5iIYb-4&~4 zh_4=b9U|z%)qR`cz8m4@u(hE)8Vw#7^Z4lk&1e-l3@_lqbOiT zFNsS4vqFNM{OA4vQ+Dm2w4)3N=DhDAbu6D2;FS!?#{ZI=PBd%n8#F0>dD?I3Mn54$ z6`=QQq>q5GzK@uN2a)d|z)`s#KUGK$8vy*p3$EIH0`v_`2099Mbsn&gv1xn=dH%KJ zSt1-`x<5o9??(K{GsOLvh+yKz@S1!C#pa>hB+uZj&qf5tOATVQJE|LDar-+U2O@?- zSgFAHj}S!||1lhupWvt3FO2gy!MLD*3bZmlK*qr{=U(SVyh|K(b3a44&3I>&x8%L+ zT)c3DyL~-#zA`J{bJSNnEEKb1h+k%4Vr0GaHnVmUxKJKb#y;SY|4jF0Kr27TPiZJB zl?WEp;hiXfu*d{?3nFOFcb1&9o?>Me)Ki9+dP+xBH5pQ?<}6fAp;;kJD&-byCBsCu z(nYP5w12_0leLmWRFYbpD8^e6rm&#)OMJ?9?Kb-Ig^f`jeg#0~cKqNNgU(;$$HnIn-3vGJ z`&)d%JN{{dV=w=~&LH5G`|wj5j6@N^0`%{J4xE30bNF)ff$ju~=8y2gyoStuf)Mw| zff?^)mEi+~)`fd84o9LvxIe)uvTihf3;tj?1hQr-CD<(IHKDl9DgUUF4#ZfV6Q~MUWH4?_>Y5jv($e^jjAjI#8pHdv?mH*(UbkZp2gtFE)-3YAqBM%Pt8@L;hM81xQ0pXJ6KZS~#!0N_C zd@q|bm7t9Vq26G+r*4)m!J6)&o2M(tM7sUfEZM&C51bsO&M=A8qYaVz)W^1*I>B2_ zU65~)I>T%ubq+IcB1qvH(>0nQec0#8CgwR2OhNCTGlu0 zzK=_Vqy&HE0_aOLTh6R<%WTb4qF&7EW2ev+@p8)OIXks}01+XMni13aua~kVBCQw~I*&8Ki(y_*<5f&qotQ>$|QMN(E zq32V-N7|xiY`G_~^gU00hw&@6=q=r*TYycqQc2I^@Zh%v^yy}R{}df|>#H;aTjQsO{$m`p&QzYJxl+r=}?V7GXNnewI(E9V^00Wv0{t<~=vLlIN< zjg6e{8{?Es_Kh*UiZ?U4_p2MfA$Ut0zw6kq%I>c%M-ZFu{sx_m>=>^*j?0&+%%Hm+ ze*Z7_YU7sh|GQON*w$XH%D&W-%$DqvU&-Ree(W^ltC-pN_Av}Tv+1v&+Z%<5bZv~?tclrKUtlFOO*Wbd`*M);W9B@uvCN*Dk&JR z2(Zotc*nY3iZ2C{#tUv0l_Nzukg+Qze9J>Ar&5N)lHb1W2@Sa< zU}b)#JBkynVz$QJE4LqWl`}~kO>2v!KwK+4Xuc^Hum(h?7PK(lRY)^S}G!0mg ztWP5e*hU(eNdw2jNLghrVlT&+g+FOvD3y#ZJSPF$pvMct6lFl_a!Te*{^Sd7scd@# zs*Q{L!r7+5dvIL40-3$r|Z`o*pPjqU#q7aAY0b6AiXtO8vVJOeRVw;q7L#D&gux$>W zyp(IF0^Hu+RZkc z){D5C2TRy!y3~|Zs?zX#dPRmJ8?&dg%H|d5hD`P^Mj61Q*A4s>^0|C&cqgC%S-qVg zHt6U1Uic332c|cyfpy&Boe{>}g#j@x;W`Mdf~^D&pQ?VotDom)2ymzE@!8*h3?HPh zYZP17iEPjOH+&}u%`z)1F$bxB5I=AqLH7yjJ`$hW@4^|wZ)L{tYt9%3L2uRwF>WWC zwYwJAaH}UGG)}9aYd#4ub>--iF_L$upv#83cof2IeV5hpC(H~c<>5o2j<*}q^KOH! zr!vglh-Y^|91n_1*{3v_MX885P_ zt$8^f@h830yh!{q?CaRw!ZC8P5X|0pF3tWoJDD7AOL~g{nVo4#>Z~^EIA!9({B}ob z9)4DPKV(>*;VwpSF?Btwr`1d2EM=Cv1R!q@{ERS+1T5TL`vAkwcJ~a!j}RbGZ!f@R zd3)n`yA|FQ=qCk?e&04Y?(v_AC*e?2s;dwQ?(6AZO?QP5-1#=Wn+SWa;00LT(Vv2H zG`;Is#mZ3U!#}C%ayS}4=~A5R@56u zL%-sF>5tHLiTP+)sJVkmNg~2%%%Mu6+?vze?FuT*#hD5D zh>C9u#P|kJANL~B%V?nHP9Dk0+j~v~Z-n9_F{}gg1+daV%C8{>YCdFL9!sQ-Hiy;G%nED^??$U z$1^FUAbNSs8Mn6eA?FH*V()NB1GBOsEE}$%)6Pil+U&|GhhiR{Q^N4yOaDrQLC_=c zDgS0uYkPVuw=Z@gRFOTS(qL{jHI;1yx@%skvmhuQ8Bg|pmBtC%P%34U=8K{2*6B*69}&f^ShR!+itnooreay ztyv6m$IB6NxD2C?@+36EVV5ggz6bfU#&WB0^D$7=7qsKM!>|h~eF|TYwuj#U8}7}L z$saS5IzKqt*!cp@Bj*PJw$6)_^UILUO&A94i*){ z35mZQ{8}TPh4=K~%MpE+)|M)#T5xkzta7R~OC$QfTnBsl-jOIOw2!;kK8}K$n?}Xj zACZ>q+57>HF?*EQqk)|@LX6wR85nwmVwIJoIm0!TCFXVHJYVWG=N)fV>9$Z%LEk^) z|FQSp@o^OA|M+Q7+B=;j+b79)?lK06<%*4EFtQDnYD82g=^ae(JrJrXp~sX^LI^FC1VY5`{eEV2K8fz zhc_~tA&mu1FQ4%q6{%)LP_j8ShHojKKy>?$j$ZACFq*Lo);leDZk3+_OD z0$Ic_zy>7MNzal|vhSToN&HPQoKm0w`@lyEpOy|9Tb0AN3p~KR11Ie3%jA1pPdt2i zkhGRk#2a|Rcz@U~^=wr*XBN{Le9MsLx91Nz^0)t-{PGQhQw(cEQJ_9ck1b+dVflH2 zIbXVp&&qjd!mLwXa7v@iQSfR+Hdr>BuGZ4Nh@U+hMw}JSR|!`P>#e%Y%4Yrsjt=?U zC>eRiJ0bQ&e?1H`;Qn3lZ|(;_bsYte8>@`{VZmk{j_Pp7E(dg|{c?F5PPeb1$1x57 zM`1JRIdRM?8F(cA`e<9&%N7fMpIS_7$&6Ty$H-Tc@9#VE(0)|f3AdpLS+^tQlQMp@ z5{6Spj4`ObN$I(=sSb=fVzrr`s&utF2s_h+?*?uMYH@cZ(au4Mkhg`6F^?08Ci;Og zf4plbo7iCCKcCTXPcVlNO3Xw)iNnJ4aRh+_Suu@?sgKB^>YW4OpiNYwa@*paLKvKs zdduU!pC`c>4bdI>IXHm)&my4O2~Xgelp!$>cb#w-tT+mpV_StF9s7h!LB@A4O6nJ=9!Y<4l?tbdB&N>mvOG3c8tr9#%pN@l)@u`a& z7x%c9`A~IXxu4W!>o0R6q6Z}5;1k_ zR8S&f)+KrulLcvYF(cFr=dtSijuC9v{T3pHt~Vyl1Lmg>pder(@3900Xi_ad5d z(`2jlE{yRqbrRBfJJf#)l@-a~V(U0%M>~F@4fF;Qb@{<4z#K@_>(*FsBz-hE$jD)p zD%SqUK~vWX8V5oqcMNnutnFlXe1NkH5r>gXH*Zd_8BpZ2KavT4W?4pdk*U37jFsvj zu|e)BBwWtg0HWxbW&Sa}@&PB0L_(dZj_r)b2w!%mwaS}r*Z+oe{eNQDzYM)@Yd2jC zY+}e)-U{=)LY}!y&u+RHI6XRV48?=Jaz76Zy;zrdD&t3+?gjd2KBb+rA+aU&9v*RHo~5s(yzbPeL# zem<0yGwMZ~4r}LdsOb`@pYhn25N?#@AI8n9AB~#_u`J6l=@68!Vx3kx7!;e9W`4kX z3_NLNS`+3xxM2I!Tv*~#BUJuYCsX-7GIE~CXwC4jvA5QQ2Vqp69QJHOeu#SlNPyp* z5AOB{YKsHh@D2e%&Y;Ln=Q)KG!n8o^oQpWgtsSLj5R+CVj7_=F?UPM6OW@Ot=iw~v zHNVl`0a3w-4dvI9QHBSp{7Ap@b8_RHoSM?GcLmn^RYToM|0-%tsM0s*lFnE<9V<>& zb){YN+soX6TG@g?NLT|0jp#NlijdfFzy!8p^(P@ zJA~28d|H1XpA4*@E$T^OjB zOArKyWi{J0=%z|ZHLg7iI7=yBd(mx+w4GhLHLc_xxOVcU@ zZ@!Jkh%U})dh@Q8nYFEIU3d5OyOfmeECM2R%QYhc2sZK3B#+$NR({~fxN@c zYZ20X3imQ)%uOiEnJ}s>QhtmWpaZ}QH^TQuIPqHm#bREI=t(hAME{@*V*#R*?=NmD zSQ4Bt|A>IhVNhshN3R_a1E2q)`_M~|vJ4-DJ_HAXBx*AzJ_lnArSN2=n2my}@F7ue z1{G#LRVyEgIE!K^YmQ?Qi+X4YM5s@Kt?MD93xUwoWt5T0mG#JU8faKVslp}<-g-*B zt{HM^UL)?&^GMT;@!;0VhcU57CI%ZD(5k{r3^h7n6SeMin^HIt#4#+oVFNX5Jc(eU zVnN#{xr)6{d}qwhu%|)zMVXYKES+*qmPn<9riNIAR$)Nnt@0GdeCchg(5plTnmFth&4*XJr8{Uz z^=S6xRcsuDhdG-uMITJ3j%3Nr_R_Iogw7J#|cSc3d8 zw}Ry6V%W{YSZ)Hr%7ihGrBXFpTrC_mJxZ3|L`dSc_HRQ@38>{@z+AJ8j6c_QxO^!>oQq=<+B8OO) zA{mq}WGZq1`H+sEGDllt!%z7RJWiRzt8s7!a(qq8KzH-d9^H@?p3XJ;c_|9@kw;Pnc3_*lYU#lDsM<_yg?uu4E5*7qD zx=Sk`4P$*qt-oS_5Yf^#rxzOVi4Mn1)wn2U*>ZOoHV_6xeIc*K(H5$3DQ{yuX(03U z!jJ$_?rg3#_e9^-q_3)P#=||;CGG0NI$}rNqlzx|8SkMS=McYmvCg`>9fj-fC@PC< zV0+oK#pRkvkiI6V77h7g?rp%A=#T?ztHE=8I2Pn4ay<%{WTEQnJmsPZBg}psA0qbYhIGGWP5smTCGjUv`v5cV} z?r;2s9?~^UjhUvVjw|Tcm~L9u)SPZscY0>h17IZkxVm(+Vjr0AN)IsQV)Q}j=JWvL z2#Vhz#%g?B(KImM0)|2$_PumQSQ(gR5$ zLpp;b%cL{uG?MI85lehU+_EXq)Z_0&ee0H-ONe1UY3RjblJS_!G7{=w>(M zL$Z$R#6W>&*%!8BrYV~rSiM6!i!9DAGj&M5Je>tvHk}1``}-;fs&`OXfUmi6Oo*3@qxrbdUdt2tO|?PgR8K@;|3O*E|NE zy9pn#l208v#I~XI9nzE=$242Zed+x{455 z`6M`@{VSg=?{S#WD+;DY!FaxKoL(h^~CNst?>a2>@3@tH2WyI0jt-k_x&Rfv46-;3sP3)4?8BSqIM3 zT+eZrQ{^K*R+XRi4ZKx8N6*)zf6d;fstJ#8Q9HWNfLCkMc+dHpu=AO8wteSs!_H^X z`4->#yRh@waOQZLW$Hp#7IsUOe~2tUkiCYod`DT%AsTbqasE%(`CK|P0UYO^u=9Cz zX0PNp{}^^YpU%uX#~FvC2g6@iCUR&TtuS5Pi`~oM?_dF zlSQ;C0dJQnZAoU!rOjn+r%QrxEf@)>D;?P7hrNS7q0mGnA6^5kYjZPYB z*7k6gleVf!1iW{`Bs|eHp@9zqhg0GQ{yu&Rv)|c26v30#W?1L%93Ls z3^getu7Cn^UE-9&fP^E?a>O)_!I^W?iHP!I24^qCW7Pa(DF9;(y>c7aa&fHWYnf#^ zNib)i)TrU;lYvNlNwXx5mpB_i6q2~)?azpBta2-S;_$d`>}ams3^SEj<~iVD*F9WA z&kbpCmLLqJG;qvw;pX<+@%B~VJ`a?p8uv4-ADe0iHo#%8Z#HU4$&=EB zpxDfvTJs`C#Yst==5;ZwX(XgS7?gWp-8s#0ztCjrobH zz^xcu=bPg=K-tGh1Bgp=+-ds3pRu+*G*Lc+%_u2-lsUNfdLG?x`q3VrhE>gdxg-l~|#A+^;dlhz*NOSJ#DYih~AA^L2 z$~91@wb*W;k44@~w}aU!`#*20${x@BJwY$QqdwmsUC5;{HQ>-e_B60A$E*0)RRh_h z?B(|;-pQe=FIg)#tjq07nqrf-QzB45y*a|iW^JrXF=VH+M9bfR?i8OdLi@r_J7Ltb zlP!xtmm$c^SbQENw##AjdM{VE&=70y{C^I^yaG`Fw=mS%_2Z)PK!sUDizm!00W2|s zy4s0RQeq?(C~jT__x4x*o1mR_wuac2ySnkK;`YMW2szg;n1;P3kLSN(i0i*Pwh#QT z$NFEav)+Cp=FIscWr5=*+*%Z0uEb=Ad^N-_j&x77jxTS(^+k2aCnphcG2}Ji@H!b; zlThn~Lt`6F_rvEr#|?iDMte%f?BXBZm%h z?Wq8QQ|QfWk$m--{Uw)tg>Kx@WOY$R0AUyB92cPzMv+68#t!u zjftLtY^)m-$ubdajvN}XpUS>O8Fc$%F~sfP%UiQKY{Lnb9Gc+7&FW&K+L9yTnAd~a zemuulC9TZCH(KEv7&O%x=~@*?9H)9>B#w;>*sjpG47K*95@fpWCuJCx#%Yc2s7(cG z-iRPO%NXiN^-+ms-bCV~q9$N7=+4FNMn2*@0-U!aNyt$XQW-mo!Gje;wSu=*A~}7~ z?kK*J;!QQs4f*WtP;vyU>&7$rYTN)lkmJqF7#-FB{Rs}-*^kafBJ|P+ z5ViC%)C1;SKu|tQpGNFoM(m$N?4P^#Ui#T-d%JC>8cXyd15>0z<%@Z@$RKuVTY`3~ zSAurxQ^ej&m{Ye`VSZS;2Y}t2{3%@;=i8-bPT23I11H-m|4oEuv;da_Y84& zQSC38nT?-}Nsq>2`MMCWUB}<@mGjw)6PWiu!_Iv{7a>3R(`4^OtMz+$bhfWt;~Q^v zjrP-!P%E7WU7o{xF^p}kmM}YJ;TE&~jIe)%D$#1)4-kd_SFt}qyZBS~7ibs1wA;_p ztEe$l8(AfH=cQ3;jV+*{GoFVUgkMrTj<;IVUZ|pi8#-H3#s?VSR}yuO%0-8vM<2x` zzYj^?+D#W@IM$_0_rq?#z`#6j$*{LI>FojWMi&ERCtrGy-cZ*=GFHdBT^UMi!I%9~ z2zQ8!I~ax@y+GWD1eY!bz7)=v9wzR~A#X#&-iq}0hYv+ zPK+l4;eOg{xLM!#>f!p(y@Wf|_xY3IrYH6m-+=Gc!}a6a^^?%+{0wyW>d=FHsaJRG zJ>1q(B!_wz%6`Sq{jG2d7n0uovyh%ab;*G=s~#otU7zG12K_#W)Q(QW0vuGWv_jST zA*ntSYGpOfp(uZhH#XSfrZE`gMk1Re<=~EII9BGbG!~_+`wMdZ5fW7l6pJ2xeHP)T zU^mu4;jP@E!x_6D^2VC9DxUG=d73=v)m`ESBtAnT&Wp`={{y%cKFsGxdkO0h-Cx3* z8&Z)M_1rZv6LL(zm_)-!eN$wa8a;?VuB1E+kX*u0v|^pZ0G*LxSSvUbMnH^i~k2d zFVPRzl(_c)PslbA>0%Tx88UB2L!Rp3I264*%-C#+G)~DezUnMrqaA#eTsS2rFeP3F zY-=}Nj5cQD&PWaeL-v&VbR=OE8NvlXZOCti;~`(k+D7>0#n(Og(FFvxs^*MT*x(uPXB6t%5PHeq#jR+gJr098z6 zmhOk{8mn$o{YzDh^$=Z^|J<+3ybP7LHXIPV0a>t^{%;mnp70yTkBsUfA`AzRH8@aU#%FNPSSBKyE0Xfgu)`cwb(AG1b@?tk~FgI*OYShhRoE9tCV@ z^nJepVc@O13y+agj219B&a9x$_mx3P1(*Rz#9PoW6Z(`1#~?$EH-S)B`G)ep1*1yP ztR#fF79x~z$n?SwPCDg-6UByUMpX@>=%qa;(dOFlg=KJzK-Nb#nj7K)ssXBu@%eqq zy~@A24v6@$@dm`*5%+meoDGj&$s(ard=58zn8gg5rzJLMQ9mvKOmm8g8mgurHP-HwC0YKXIqFX*gXFgA6( zeCBzn7BA5Mapzyq*%p_Ws@phuEHCvt;rh! z{4d~hS)VfgkK&;pl(!YkUlAr3Y}uU8M|3ZR;jMsOFJOkh_o| zCf4&5r`g>L?YPxx8S`%dchU{JNZ6vthr)Si-`OIFrKv^&LKAr}ibIq8t-ezOu`P54 zke$3b4Mu-!?y%AIz9p}<)Eg(TXVA(uz|LljPY}BKcSe`ZNOtM_s9LQ!07MQUMb2I_ zWxDYxoR=G);c3$s9C=bH9JiPXotkhOJ*t>?cey)Mo$~@@2bYrGz=cjJ<0&v2C$bOY z9UA~~q?g(iuzpUNV+a(~l|BhcEJ_+CJ-jCF^iXwWgM*oZ^Xe}JpCn=XdIp(uuvd3&@I zDpvRB+c`hf(N?At#hBmw<@SwpBd1j6kyD&v@D+nRuo~z6Vj6*VVJx0OC(bXbWuL(m z^d*jqH19Rl=GXAt)|=OF;GkM$J$FD~47nFYoGx2JhGg$_*$iGAyc8b~Rkg01l0+1D zL0Z`B`w_x`as$|8Kq-dN)@Uz=oC~?_vu-%>{VSG;~YZfp|UvWN_ zHIKr^xYj}HHCVld$jkgUc z-n$JYRg;#ldThRGs3E$4=189Y4 zGv2_A2nSGGCxhAEk^ZgAX`Cj;*&lb%xgvLBFmb5V}EJEt4}ff*-Z958t%&%>BJUC8n_=03yaDY*ww<)V^F6hg^2W$0WxQJ!|6% zb~h=$*GgTK=S-4HKSIP-A($B9^!3rM&6(~f1W zynP|;x#zH-3~xURX_G9(=ChCkZ7Oe{(@Ik)=S846#*2O9?|tJXG^&!>W*m&>2W=yp z#i5YFzT0;kZS6#wPt(v`^A2!XMaHK7kKsu zVOKgEEw;alS0;)daoU`S6V7*_&2b>E??9X5zyN#)+Eh{@EY`_g-7u}^J((T?lO~Ok z{jhI*gvP;3r^qUaxI)40ya%bb{iv|-%~{1`FtQpF%nzS775Y3Jmk`8$nnsmD?bha-;K(ZD4V2?tMJwYhpX&IjH=$uG?}B2Vahm-q6vejO5E*H+ zJyiF=agV?83cBlzu^0UFNR`*&-#i+P9JSXk@f0}8UUYL9AS)O8ua0fwrj6TPP4(KV z7b)KA%|3=rdNVPgIh2b0 z5qXsHuRi-{TKRL>ob!FFa%x;qcc2cG)>1WKZ2G`HU}G;}3Iv-|VavY$P`XXm&Pxnwu`q!%@7 zz-Aydku-809JgaP(>UDe;wO7mW}xp0IGfPZV4uYJQCGJy#xKTbw4^DWw`{G8k$l2L zal;|8$PA}9%efu?7&f{1mQPw5zWtVlHr3J`<@di3kH2Kso{s5XojujLiow3Q7q=Nk zEpwfHVmn36+UxVBYBDOvhOkN6i2;O3Bn+u+#McO|+j*C9r47CT)#C9%d(N=M0^W^X z&te#2q!<)FCaU8b?T^}9vI%u0n}XG>2YuvU+LVAGPwtmU{m0h`oq1IV>a;`^Sxrn{{Pvjo6@o`ozE=Z5*8=H(0D8( zX={?K^*4tRXRW!e=(-0m%+jXlz|C}@Mtg?u2k~G#eG>B&Kdsa#-nJw{Q`l(Fq_>}9 z*!|}i_V_u5Jp+jdgs5U6iKpuS~D&@wd0HY^)p8=mnk_TC6IcbqnKXlW2a zvT+a)T9IL;!L;n-rwmFy4xCffMhtu5@I4T$S5P3d@^4_2MGFqSSFw!HQL|!Oz(_~G z_LX6i+9!rZT4^f|{g#lYv^9;k&yI4Eh#lwVN7g=)P8MfY_EF+t8+tfajN8(9oEW#G z@pm*1UV0CzS8JxU14ymXFW8Gw$y#v=2woTpc`lc9i3>IfcqGgn$-LY?o>*S{f$x%3 z48#B#Yhut0$VT@OaWwUDtI%hfyHX@&}7gvU0Wd`vD4K_`_ewjqSYM`PSW7)5s!P1ElJl}r5N}K9ex6(>`Ay)S3zW-5iHTZ)v z$Gzntn~R(6fKv#$7khEI1<6|&Ty1qA=(xK7Z9_`I!|U(?Ue+y>n@Wkq9h0kL3q&pi zahwN%9bV@^#?lBB*&})IJ~7cjy$lZfTwnSj#yAM7`rh#fYjgIIdn1ZChrm7_xu)Y& zf#}6pKBfV8P1Tcm!jgOrG=67(lAo^vbhg`!aUe9{{iM9 zj`>5FhdO3`tE&0K9P@@S4;Qn2iJvQ~kKfNp%a(PWy+y_bNQdrAnXgI;3%*Bkp~*q3 zh+XsSCyO1+PU7CZ96sF%T$ejY?Y<0DoCi}K!)^%qRc-^NP?gJe(@?-3&Sf zh8}$$)38l4h%QD41T!X3x?9M7Gasjgy_oc}ws@h7F_B&-(aQ>Ox1^S$0z!jr?1UP? zS@tgS9%LBsA}dP^$bcQ1#ySzo5F;0%3^no*$}po4p$zvw{CAK?7{v%rORX_FOzOTB z!lH7rtgnsKn#sBLhKL1jZP_2EE^4jC0d0X*d0uC4-iFx~7VC}OF(#=nfsBpd!zB>W zm>eK5J&aBgMptg4xr^qBl^bBj#TH{A(cIiLv6}0`64z!NG*dfh`rO=Jnqo4?QtEa- z#^E9IR(s!GmevEUn`ndG-6Q9rpdit$Yvn!2x{vQ}=DfE_^$myR9}dfAlemF)uqYOJ zewVg2A%pWp)p+PxJ#5RSzTe6O?4>{2f zASqO6)d}l08o3CXurA#OMlSs(ENfdB zxjvQP;Kf1NIfC-(_8v;z4j#&jG%A#vcJxsOxhT6wP%=AvDD5;VS$?EZp***XhhmOL zMD>-(W);tDB%T=DgyQ-3ZXWi3XjIsT&G4`<-8YJj7PNP4RJRcJta%>xc-Z$I_APPEt(y+^3O5Z0Me4(C5$sw0;Z^E=vxB>U6eaVm%^t3wesdxS zCl8AvTuq8XxP2`T!I2Cz1(mx|$*zpx{&jQ|chDFQcVMT7`#+Nm`t1~z ztc?^E<8P+-BH4ivgcY-*2rrVN5IXns5xnwtK?GsuoG8Naq$q?p5AqP4RL43=@2P%p z1b5{jQQW_gqHs4~;NkkI{(p^|BN_G{D#?aKO6uH*WDgt`mFz`Qlw|#n_#aA!nYh!x z&5OwJ?eC&83_9MEq2**>hQThvFU+^i-PDQJmV+Xay>oh0vd>6Ssq^Oxe964N+l(M+ z*SH8)jz-nWJbtZ*vdJwTij#Nv`m^^Mb4mnzpL<+vx0N}U6eZpAhdo@sRQ;b*-pjjR znDQ^Uaf_z>F_F0CpN__DcT!Z`7C-ktjGL3{pZ6sh_G*Rtq%&V~C9`g)QRV1CFMHB$ z{Aw@K&5xkG_NIrTz2%`SqEW^1$Woq$u2P#z%3d^_32XMsP=N5yjn#6ovbz zZKAjv^o5H<7((^GXId1uc_$C|{N19s7}EBh4u?l@|Fvfnw{0&Eci`Sp+%5aUT^zw( zv`-ZGYEo1>oWFk*7t_Yx?=KvjbQhC-Nkl$%aNow>HKyS zcaOeg#+KZW%(Fgrajj)EDwz|Xc-VV=8^zwUFYMn%upiW`BW>}Uq$ruUX@D`**J0C5 z@9BJe1oyguQQVhEQMeapqPWCsoQrF%k%v*039IN~U(g=KzP~S- zmqxG)8+zCW(5SG-PWG@L**JIS3H!ij-^B1HjnV;W3iuVG5 zs734Q3;Wy%_K!EZ*ls%4-sIul_lGDhR*ZU2kMkn9e|+D?wLYRz$^4rSJnVU&M6o~X zOXl+<*xP^QV!JXQN{UKnC{e`$V z-$%;tW+S8JcVALe`5m)PwESYrPVe$w62bjqeHYhCjfYXS z28VQb*d3chu{-;c`O*mXyVG23w=VxkijsM&oujzZ`@&rw!To&KC~m`U9`4RFqquMV zO1QiAg?m{<-gWkN<+Zk^QKj)EvpktU-Zv^Ub`|%Yf0swFA3MOqevL+jJ$|-_eeQ3g z*pvFgz9NFX-CPfQ7L5w~DH>HC*3FAzW9vola$g<6zUL4Z+btU(lA>@s7e;Z{|CMlY zI7ILAUK5e`sl`!w|4xdN4o61i-SAh!-KMW}xHcm1HYY^oJ&_b8@8(OR@^1Yr;bK9k z_w>CkB5&^OsJz>eqU3$|f~dSu+4qineFXP!mq&5+D?HpouZ!a1TO@@W-P>|Q1oxF& zU0myX8dcrM-tJ+KxYNV-=Rr3{P)@zqMR9Av?WCw!uXn$X;H^O25<%GKAs4|qmPRGV z%!fUctDf>uoG}xYBzjM~nMC2Xwp)0SoC5{}z))4z7H z-LzOnib{)5zK!By>8JO!xIKdV)b~-`FGx|ivwNbrTl9r{M+En|8a<+ad!H1A+mwbe zG+V`zQtx%@&IoR54Hws1i$;~k57Vfyt-Ocr*QvWAD4%zDC<7;WC@W}GD7Q@VQM`Kf zKm=t(r;Fm|NjoVDA-}bU;MA#&-8e?e{oN7VV`jRz)@d}VIBveDhu!ahC^nYPde85B zBiOSKaj{*Q7m}i6zGFcY7fW2dws5E|gnTNgQi4!)s`7(=((f znRmJ?in~!?GCv%_J?t?T*E)wrCG%B}d)Rxu9>qSaFYHGm*zf+s#dgcZkEAG>2P6`a z`uam(Y4KPDw`vV|4W&gLDGK+8Q4!qk+qt0>dvy8z!wa~KcPs8G-9YUr-QJCh^_#ZD zeCtR&GS*W@Vt%Ou4CaLJhD^o8y_Okk@;YHAZ=`750~c#09vN%Te3;4GAY{D+7wcU- zGFHE0n918GV|ByDx&)7mwdv?EQ^6Blm~Me{#u~J4m}$JnB(dX0&Wv?hgvr}NpkmiD zmPqHchmm&ikOqu{OhfRNfy^@{1Z4aoGLjxf^(UT~6_ z_5?B|Cxw}I^_WhAi**?u87sSCn8{nXwnXrA;heGlwo#bLTZOhtlYz7pkBoI!XP9Y* z7o0E^y2w>@b1Ad{zfQcRgG$aD*yK_+iCSrwJ>TaxLrt-?&+(y&VLwynvu z`wn3yZ=F|_g4f}kv1aTTX7Uzol}t~=Ib(e`EzC5{OQ%^oA@5GZBV%2&bC}6nrnQ8r zWfwACj%P4-IS)x{OMX`}J%?wIsUytPwHukf#52g`?YC0ZeD-uQeLEw}>XzERynPMW+9!4tO0+S&{=;UZi$xKP184d;yY;UQrrZ#7ae9chtiS}DxrZD3S|?h`m? zti2Y6nY^_}Ri0MCIb(ftXqd@cNK{O_9Y&_*hliQG6+x?UG0M{@JkV|68BB3+c~1#G zpiHLxk}%VBFP)@`z5>n}>nuCW?6r^@=;+VZ`n#Q^}sn})gBXO^45tI)3I6AHxOy-$kChxNd#q=qhGuF%J zhM79U!R>Y)nU1<3%;atIR7kN4$<+U%Fq5Z|R!MLwoHN!QmxP%-^|DILSKyqnHeViQ z^7O>2ay|&>jP=T8VJ1)MtB|H$E;3yiX7aQO3h5*`XRK?l3Nv}?SQWdrtI1TpCd}mN zf-Qb8)to6!^oN(8&Q*o-Z+OjE=Uo>D@RX;DDRn)WcDo_W^t?NQRwKtJ;GD5m+!$u^ zRHZ7Rr`$xQ_ihd|P4SRq05%%;ae#Rik^*9b~%V z&M=dwR#Tl*(_LhG@U1YDHziiB)Q51+Sck3(F?I6@^IUsr0lq5LjNjsk$u7U+MJ~us zD?bR1jEVE{aBRUtFq@Om`e+&ZVVJdeX+zj>n8QZuH5o7a0lFA-2r0hJ27JKk;NtG% z*w&asXHp%XSMhisGMk<7meO1LP5KLHddv3XHpUS};?e~dqeQ3x!7)yOTYx&Faxbuq z`C#tA-W}lVGH!Cv+kcB=972d4L_EeA(V#4)L-6&nIaLBBIb&`NbNO_9h}<%0TuyHp z+%=4TR5EExm_Wu{Nd+(6I=)A$>Mc8T-G#SeteowB<9rqjJ^CVk^N?4A3XVCdP~c=Y#*-3 z;;vd;+v1d@O%cn?*x^4Zjg*^sY)iyYm7DyUPM%AlQAn%h5CR%qLpfh^B{?{paDbKX zujk{vjg-gyzPM6~Ia;SB%4aaGSnLv#zaz#?Y{aG5ECq&z6vah+n}HKouO=&ZlW2l9 zUk}?ouB|#zJ`*52=My+Dejc3FE$AlW+2*?Op6&Kk0pN-UYNI0A_E@d>WCHyklaWTCm{9@X% zl!TCP#m#0E*N}x>?qlf|ml+Y4`#qP=h>O=K=Ua0sWBU|)3q+(1-n~M{vZYD-K}tlI z#lm_UU6@legivj434cL~HRkS^%MzDz?Rfpt^Xk_B?FfutAJ{cNja@BW#p>XvC{i$@ z)ut1>>giISaO9InA9n=T%Iq)VW;L?T;dl>c?2-8|!a)ajq@(HVI7t~~I1)FvlgKY3L0 z`eB`;ZhLaqPE-%)1io&ziEy}Z@~FM;*|KxgtCy`CbY&YkYU#N*P9F8eRc)Q4-d%jw znJ#l+$q=@Tq92^Qm94=Zytof>py^V19=-c95+K!32y->=8DdLV!3E&v< ziUarZ1EWEjUsvI{pBCbcrtshGfZJ>uqu3)y%lHD<%H z?b$XfF%FHU5e9Pmz#s2E=|O76&0TQ=N?m?Z!o*lNg_kNaEmkQdBg2zxIOg;U?k*LmE!%Ywoepbfub|@R@}G^M+G(2@KU&zKth>^ zAm`G&hN28M?OhGYAaY&+CllcQssFLdu+sfm39`VNR=Ga|#po_He&&WW8T zB4JU;=TE_@oXn&`GGXkC_jJcz8On3Wdi39bR@x5_Ig&kLoXQi^%kXUM4`SeK_u=E# zb8icoKSk~csc+O;4Ger4PIuRI<1G3*0KSp}o-v0Z2uGaL;HEXJES7^rYrVanNSSMjje^YH*P zBUqOJ@*EgS2jXGQ#Y6e8j-3eq(^yW7gFsF7uR@oGDP?NTTw^=D#LhUv&iIKPTli?l z9(83$?V|l`yi`UMn}Gs-ajFjIJVIlbGRE_ur?^vq4@O9H9rHYz<&;;`gt1M{hiYQi zXtCH%A{VQV!#p3xVuNEj1eSbN)+SLavksdU9<4>a&DaD|`)5U;xJ74OCsUGc$v`fPSvBljss*z%nBE8rM zvvF{!N5WW0Byr$6Y0CSW0UyOo5UUo9M}slnPqi>bJ!u}}dmQPsJA;zuqbL*RA92G{ z)*M+K)00^n-AT%!ze2i=jf~aC)({>wgkl!~%Fe(%7LSH}hXb~5fLb{YPJyKO9jv9} zN$aMIfd!F#L$cO90TvZj#$3g~i~$g$&56p1a4qDNd*vkh=23epw@-$(l!K@^=nO{l z9r#YF`cxHbMZp~dKSiA@V%{c}7r;}@Sn;DPONrW5DsC(HL za_tJac*5-A7%4Qy;^yy#^Ae(5ibpYP)iuO$>K`d`^q-_3Ze2;^z<4p+%i+|BR)zzN zVp6f@(X$fDz6=jtP63s!T;{@y5bkcw+l+BJoY7iyuyh5C?qKO)_PFUm1aI=8V9url&HY3&`?o@J4~-JadvaS}BKGG^vl_rUW+8 zLcyRYBf;m=)gogP;(7z{%hw@sij8SKY21RmFL->(v~Ju82H&T11v3-5b2pi7Go5N; zoVLwGJmb|0BB2g|%&Cf4U6-E|3~Fd1uGkuN?}orJxFL{LAHyWPq&VqvbR=@q6SDBr zKCeeSoO~#r+N|0fEjALeu^h!y`9{Q8qNrtax=D645=_S8hb-$gu_7kdyEDI}Foedd zjB|EuV2oO3sVTHoI6mcA=_XiLAF=8(e$8oRW<2ho%c3S{jfc^KtTq&j`=hY9I{>?x zpts<$+5l_?h`3;W&7`q2>TzMHDl17IGMHb;qICry=B@NAW1qK?x2q4+8XDuh57TP@ z+hLkY=Xeaunz22Yc09!z#Hxfr>CuSx=(oX8x*ZSm4m>y~!ijZA>pjVD+)1{$@9i$w zC-69EjFWm9w*B%^7;~<#Q5c4+&QZH++;um2+wyz-(m;D3@|pJ#T}Ro|W6vQy_Ck7; z?gb60X5WW5REZ*N{YvJhoD3MA(Xk0rGrIf9Ugpz3eHNoT-DyAV2gIGvL@}ut^Qo1X zd8~#_UI4eReA&u-i(-MZOqpv3hO30Xw6q1g@g3_kHOHRKThU9kk(BX z-dEyy0n!t6d=ig_=1gr8gg=ttbxWnEU}ZyPJ`IEEk8XG?pEQBt2Ge{7Yz}v5d=jEn zo&{Gx!slQu;cg2^NEc%Xk7<2A%(Id_YV<-E!vYTml_Hl4sq#YD$BVuXx_CZbf+fxK zHy{>G=t7n)p4oF%Vp}Ao0c_3qLp%I!Nw@IltBCwk=akR zqs%67Zf7Qyca;YxqhHj`C#h|?md5OK4re4dI+@SFrTrzMyrSeQzf5%n@6Z&(3Z12t#(Wh4 zrF7}?3eB3nfPJ4DeF$5ACw<}57+^q;tzSWdqHd%wcY7wh%H zVDzjEDL(-Bb-spRFcVZ1txP)FUy*Zi+&rFg-%kl3#=O^r9r(m|nd??lPa| zsjwHbxO;`99{p0}Q|Zq@Fu#R@!tuST7evwmh_4DFpHal+9^$`J5$LvWPuk`Z`Vo8N|UrCir;tc3K+Jzm}_hQLn;AqOu+|0yqY4|+LDp(u~d z@-xmOxSK6KilNY3QvK79nD6Yz`#U(ZQoW5N%UzsZx(Nf)S!l}YXVW7O4&GkXP;#maH{T9fmuc+eazxR>& zd<0oAZ2c=tWfGgLZm9;7eW~(O2E7*Z_%IGC7vy0GN-N3 z1Ab2P!rTc>bR-o9s?<<36}PgX7iAI`CZX@Rn_nK?W%oO)5=2uuYeMnreuDdbfU1jiax2~)>eWmMLn+a<|U(nlod_BQq(_y z0;lqAo!HEyeLejNNCP!)k}-#rN`L zpirSAt1!&k;l0HCI90MK>pmD|4s9F@w`TAjP2P08WxeLg-6Wac1G|74|0ry^xG^t| z7v$kwcmuR&`yp?P#b_%~Cye_L&$>XZD;RNV&hG(P)(Ap6dAH1Tyyq7+Z`_%gEbGOp zN-skJbW)5)^JJ`V#~ZO6@NdXwLbISJ!@(FoFhSg5k>|%)3r%@pXJb4X#_V(h_jaam z|97hc&9G}_ILvtl>QjkfT}NtmdP8l1OO1@5R5&vP$Ji7}kRSRJ(KX88C?J=(0>M(R z*8T7`hO9rR7N^fu2qvLu>mFiS9>{pl#Y4@LX8~h>=~wQBt6Ecl0`&j72BGs(w9pLK zL{KsZt%@p@Y{QjCyS8#mIEV`v#E%jLT?~8}@Kf6Bq>T6R z;Zkfi%k{sJWyQ^dl~r`m%~%6tBU@<1x{@;D5;OBlG~;c^Uvzp%{8U0O#rmOR$AW7W z-oDCOqmAQ`LlBPC>p1w$y<>&otZ)(zfW*qQ{UIE*kyx9H z*&opuU|BjEZJAA4bbs`1{nMxrq+nh9{Y;Znh%%QkUQP9xCM<#X%QOw>fI=La zeu?w|73nM3V5J+3I%Z}=8nZtEt~)C`eP&Y{ztp;;()E%yPD-a8pI6amPn8VuvQ1dw zQm{^#>3)SamlO!8$q%5Qr|Td(WK|)a%80gZm7TtGdI0DH(ugD>Pnje8$Fkj@!jeH` z8uNPuRJ56Mm+oqkg9X6OYdemvq_qYf3(9RuhSdf?y4fP^tde|SPe+6#M`(iCPnsosI=i%wC9 zWqeXmozcpa#n=Q6^(f}#76;=7taB6$MM>J^bz1ck(Oh7N@&|US9ITojkf6dDqTc3H zNC&DT2xqO(2#lVp zoDO^^sDTKUo1DVp85xj``F)Cku-5xP!rB$DsPF&Bu(EDgqDz%(nTw7A>oWBrZK|sG zqD^IGPbS*mW2S6~M9x{he%?>!o~mxxM9 z_HFi8QKkcs4$bC%04NV4!`A_Z{Xyk=DF!)SP+kw88QW4}Glv!UGJ|IE=es-@F!|~% zw>W$j@OTKyoBgE_%6yfe5l-3v3~&UX#|6?cV3eUnc81bOn*g+STLWvuYhvQT;65jq zy3_X$*lA#YLAwYw;T0yDFJEyqE+~d8RLBaxS?LXWK+89Jw6maMv;RXB$L|m((Z2$O zp(IFFDDYvh%a(!SFbBo)DGu1@rQ6@qdzl#_fC02nAL5D!IlbP+BA>%FNtis~7ksQ^sSf4u?CE?RkvFcYxkNm4Pz7 zU~^rW(anyVs+Aed;>4iutY&Nn-I?-W>`3D`U_vcup?Ff3jFB`7S?NmdK?`#b+y63C zmZL|$MGMRep2cz+HK}Fh2Hp8KuRz+-T`X6_qLrDFR69s1%7c*vk5MebXdo&n`+GQQ zWtL^AN6WP3Ybv{N;Z@HV!`aoSxny5;2dQ%f+Dy`90g8eU=`T>k(ebwOBs{VsHa6>;bpCtU82KsH3hBhR|%~OmIXmkX^xQ0=6m`0=B z%NLx4?QIgTxSNeNP>5t6Z+r|etcOSxL~+Zo??t!|a_vg>Ly@o{#mQ4;Lm^Dgt*F>X z(kiM;A#T0T+5>u!7N=6FIgRN*e5hlZw|{ z`M{7~iUo6%qgw2S?ky?S2Qh%Fk zA%*e-j8?n?l)h6@>dennK$XVT*sKtX&13#YMPQS~_7~eRMMpK^FDUU48AIY35Dja# zhh~t`(x)@be_#oS>&4wU%xpt6vd~XsQY3V=g(Lm8kO+YV z-~>B)VXKibPp=EYoh8h8g;%{1U;WkY4kD8Q^HvZ}zy(koX~7oLkYsEG z*6rJ=1Nj$dZL4${%DB2rqhx2KblE;phXfs!2r6}zW=icbrp(JFu@cZ@yyl>IRwH zw!S}bqMAfrJpsdFyfet!Rck;urY~+vU?IX`NH`1$#SlXSHDwzoVe#U=EB+6IIR#ya z>q6Q{{MUeR2g*i}jxDjmzZU4so5x^3gn6TKfECScdHGR<)0+Kvc~%b<;#}Y*YRw^t z5EX&Ny12O=mKG;qw`?qylsx5E5{dlU=^E(M{CrO*{9G|5W7F89$ka&JAWvRUIE99I zGqyvXi}nd$TGYp}0N~oVwu2FrGzpT;&Mc4FjIfeUK08`E1?pt<=zzC?akY$2>pzjx zZ$xvtHeKsxWUZ5twQf$Q(y7Hwb?G{nq0V8bb8=cQtbt-m{j{v~6q9ne0syx6vuc}6s0hmiw!_#i zoDzyhJ!39H**3et!ceC0y+Sjl;*IY<_>#5s-XOj8^o{9>X&8@9LCDe9UE_H?u?v@~%Tj9|=Ze~n1 z1}^>dkw3!ASoH!ned#ZnTN4x5+wkpRZ|h@k3$nQ@MzOtPkBoKy_~V$Qyi^$2DaJ7H zLKyU||JIxd{|sZhKo|k}w`UkT;L&>+zWj&)vGD>ned#ZlI}#Jv)A&X{?SwbdnlE$D zKIAs{as=9$o>Y2HMVudkehz+jq2FEcm=_gjHxMz8J#b7-=0IlDz;-I9C#r7lizkKs4c`!UKfECL<5E-ZDcN01dZ7?XowXH4i< zH|IO}2g63C>mW3%DxB&V^&kr+oOy6fMVc}sXA*1b8>3aLWAZuEqxz(5wwBRz+?ndg zECxHUxe*7P-JNPS%Wvl*B()#g_zOS_vwdx&fk6rSOrH?=xWK69HX?jzh2GADoE#}+ zXJpb?>oDevUHAQgOJ8QRK@NZ8xcXGDk1!Ly-_^pzqE|Yp!bE?Tot{Z!grvf(4ThOW z*G9vX$r(3Bbx)CpaT~j{JVpb?7Km!HHy2I~`5|4SKO5S;pu03C|_l)Vm`Q6k#{JTSFVmW8mS@^wl<`5!1KQ9T!dhN8`v1R)z+ z9sA)3(lO45(VQ*n*eZoqJ``RMk63Ipba)I*DEX9v|2N=u<1oTnPWMp(^LD+%OQ)Z@U{*x5Aj++sl>UH;B?-Kug(=pXq8wnXy@dN74Q8Smp@_BW$&V zXQ#+$?2f#&9zu|!OE&$r+Lr#)?K-lQFdR$S_;S1&=t-fRhuGOQVzd#2jq(k(pgdK; z6;hADBSh^c^+-~kVVZ0!VpMEM52>vu8F%?E6o>ugZB0?%0ySgcV9LB5SCm3F2Fih? zRFTq>Djh{|otDzkG&ay!mZy^G7*I3o)~mezEAp1QT1h6ln8)Jb@Rx~c4re5f^Qg+- zJMhPEJL%8-9Uf37n8$leTA2cxC(!joQq_Q#Nsr~P>ITdvmc7%^;s6$*#|{$#o|>MWqrmhQHsI`*%DGe zE+x<1x~n00W~zJ>VVsU|>;$ZC3X9V>*rRKnAtFe=N^Y5Ff?%E{RLNVRmYEUe2xN&d z65%;PuK^>{SR#Ek7_iGbZX}S(!L)UEi&6FErfpJqYVpi(=oZGv1}4{=H>=HzMVI7z z6s?Mpg9O19;?Y#1%|j-!c|<27TRMF$X;+u(SM+SwI2~TGNvTFe>4#?!hw0fL>E*N` z`=bpxT-p$Cf)w{BT-X{^m0Ni&8`dlegl-Q5AT0Lbb!bx-GfXKTXpDUMFr2L&jgf4s>ths*(APnm19rko zpf=YT=P(m{^hU%@ePe>@Wxmkn(wjW`G|-KM_*et0<8>X4@E<5X{)eN+ZD>LZ+Y5qm zFgyUhnK0)eCI)i^L1BdxL0yH|27_AVrlJHj z;dnSpXqCsqxYrVwAI`LP)5Vae?WqJigmU~L%zqvE&xe$)-E=WfqwT0}94O;*?BJ9LscA8nLp*1&p+858f52j_eq>r*R=@2{{5`E6g;PVQZ^u zS;A)|H0hkgH*lA6x@NgIRo5|9|3sw*Cd)i6!BwpA1cjT}7SzO$S+O$vXbG8LvyB*C zm5Zl3uooL2PCDVS+9<6j^$Im`O3KbAckiE8X8(a%GM6CDi&3#Byv3}*N0N&WS+)C! z<+9^(kZ~|WwkeTq!kUUy_KOfp?4$wnp=8E<95e1z`C^dKyJ38#%+Noi%D)$0=oix1 zc7*tcUaEB#RhLQy(M@#z4by&6|5kTCMhyV#ogRy$-Yr4;q6HE4G!}n) z*v|RsJ)DOH6w=1w%ypTFt5Y0QO`Uit{Bcrz*A)K%2uC^0Cg~jHSYr%Bv`K8c#sk9{ zUS3A2*TkbRO)ImpZg%pLgQjAO-@pXwi?lK_pva)nmBxvkoym=}=45;g%*BPv3H&62 zRf9&+{yV+S)&W5qAXVI#${A?;QuRld!afF&($^SQ09S3@cOco@ z60G<_Nqq;+Ef52$^rq^@YHumy5*&>olK_yYP)GW8Ij3bba*^5DvmYqkl82eG+h?-I zHJG9VyButNiyLnudGqT8gyBbYUN5h<*ESnhK``m?(IXHhmw;-~@vZt^+4vW3`z2_! z?V4Lgu2yBlu15lBOZW`TTc)dpIfv{-jwOLdWduqU*Ei_Z?VH3>xtf`G8v7~%kol4t zjF{KJiDzfXYLVlvmXLI3@kk(4sHgM*I zj}t=&P?ZU#(3dJMRl9QzKe=Wf`4QT+3i8G+1Hm!yjle97R0AFvz7(K&RJ% z;Q^AHNtuwOtWQdk&B1CE2O5Qb$ue8Df1SAG>?X>Vk*Jp+MntpY)(z4$85z&DS&Vw4 z-v_#?kDSjP5$gYjj~gR}7tQLD{ScSd?M6NO%rlc`?&?J90SLw&bc~TMC0vcMwAh}& z>JDR#uF5&yn69aOJHN-?0izN{)y)S%uGa_cSx6WU!I=O5n0pg2xr!=mxTlxf-LoY< zJ?Wn8Az|WWx_cm*5HmrN3>fxJ5J-Z^CQB0FhHiq$%^gNSWC@GxAR>lc5tKy*H&#Ib z2?!#JK?D>KWm6HC;d|e6>Mq?gA>#l2|MO3t^u1Me>eQ)Ib*oNQojNCF--|~JEC=x` z)#F6rxpalu_e9J3JjW4DRP2kQSVzv?1?LWo<})Lsp3doM`)9BiGoq~9w5()|8gQqe zEFYC5V#2)}eaQJK&L&}VacZ{H;jM?B z#2WHsxPZ&nanbgy9SLFRB<*XfG%{U)B_p{6cB0T8ZLuYE|0i^h=&H6J(J%~#e ztaZg!9Fb-$`+8_;u2ao9NOgbKDx~#>^RlVKwQoWU?T&kofvoO?_b59)$2!uojCNCTr|gT?P10ZF~x=|dui~e4AVl5!k`N^*B%iVrf~DV z)LeqeiZy((dgkMxgF{o?eiX?)XZaRVaNRRlS=O6L*#)NYf+XkPXr`W963*#hb9pm; zIyew7l{-x!*ni+wN&%ghdNAjqo~H@VA49Pf>JcE5#Yxoi7`1-DHvwRO3C#|+Gd+y8 zY)lCjwHCX>Nc)cv%Hl5bXPhtMusrQtj$G0V8tt5c*x8RYVuRu-z9iXZ`UC*}r&FIC zxQI5)#7;onKJ1y#&p~qCnGYkJ$MLh#;~thL$34z^fQ>lmfi)$Z^bDdUxUcmDKzjCG ze~iEIO87FRv_~p-Flgo<+Tlr-tXp~%r0~@v!hH%qgHPkfzL~m#zr-8v4dYkT*eWwM zu;v9^<684FeyYuXgx>0~MGJVfXPECwHer?xX?cAe7#r$o4;OeE_oK09g`Bk#46R20hBLqS|E zP=rZCtbWfQ%vMI+eilLZyBwxOU9yv3kq+V}?biU%v~hmlI4Y>SfV)gEm$JVL5^yaY zd9csQhh8{!38<=eaRE2)TKsc>Go}3&uV%|;19QvGRIVj=#ykOSkzDO=j5*DT!KXRq zaD;e@W1{sVE{OHU3RBc#8P24+#5leLHekUO($JQ4o@YU`T9P8?JHJB+cD;Bx*82tW zTP}a?%`jC|=9|C^fT`@0)yNJjYofD39ux6sDWF=aFy^imbBQK#0=Vko#L{gnUFaka6k9?jG zH1{hAx<3rMLV?YVaV{MT+naH!@(JNU0%2b_JMpgq3)-F!)Aoe(+gr+b4QaS+&Eo!q zAJg8iGe^+g*Py*mXM6ux+xuCxhqU*v@G@*Y5Vki{Ms4q~+)>*b>LPxVKLZq&%U^BX z#U>z4UWzukz(|uz9s?(h8$rU>0d`IGeks`bE7;5ZjopGtr5Vv~Au;R;l1q95-%MD# zC3=D+`aMAck}@^Y*6a!Q)b)hY*hsQ;1!!*oSy20OE?M2r?@8KMA`wJ*ZyiGRq(7tW z*jJLV%l)yz{tMgp4g8d+1YInM(-GxOq?TZsTo$|7Ly+XR5NU5gacnHceUC8p`2|3f z#or#0_6}l-b{jMPRT5o33J&hIK`k1uzTEjT=%lUy6!j3R<3E-%#Hh;A*hiNXReqLu z(UbPKtwY&rN*~q88_J2hEUmo8bne}u^WfjxfY1U3UEdr6_3pGN{YG%{f@UC{{F|+z^67o3GXH|l=RZhuhw&4)<@J5M+Mh?w z>{Ix~G>wUTY61{vjKU`H8i7rYfK3Ikjz!p0i84I`EW@-ce%$5&s$~RJE7L?GX~Ub; zClk8^bvcv$#uZ9kp~00RTtVRy7?OysVn{nea?)?PWAM7t9*f`En7Ac`b*f7zGWKbxWLAEuZkPj1KBdRMIQr{A5C{3UWA9&N z#-D)xvp~O8A8S^_**w5JlH|uYod{I&CV3nKiDId}z+*@@i&J2ZVl+qBs5!cV9OIc| z0)7lq^0%Dnh!q4)IF?QBn+Ym}rv+ysGflz|qsU+r#fFn*#$>!m+oWSVvZLWILUegb z0xPm9fDx^vV^b^IlPlU&?Up?iaZmQtr5>GXPfFS}No!9W&3R=rDS$G_M)6N4{>9+R zihBG<3jQFq4*!wFJ!8|jHz#gtJvHDyN^l3Mb-0fr?(R+Fo=Mz$f$j#rJR!J))H>Wx z5cfwmjoT(}YCSd3yX>|pxAoZ09?j1&Y4@xB1}l2Ldv zll-1T+*G}?x5isNW9+%iUk`OGKW5XHb<3~W&ruZm;HUO26Z-S5K3Llx7_Zxy@R*r{j>x`x6#2{8g0nlwL0@II z0EGM%5XLG9cuRP4jn9BW4Y0gnk!?(rFLF9`TNW)?#689)VrdLDn0Jf>j098BI90Y3NRbEGJN376oR z6~WDd{SnkXnEzfTTT5PU3DP#jO96yXZ+Q6Wjyj+U1W#PD~{yH_IS8`fQnT%e^K_6xA zOn4<{8Cm;b;;VUx-Oe0^PAYU0W0?t03Sl;mI{V1Fi)D zpSR3HC_V$IAW+ZSgUDMhzO55hrcYQYa@TV6PT^~mVPJY@1uiOaO##j_e@3n+Mc=tz zJD5yH{Xa|}K979f8f0&Z&jL6XfXZh$H;!E-d}ii=iRAOKbX8~cX zf`HG2CkOcqI2Z(cJ~IoU_za+eKs}!iC7-!T;4_y3uK&JKM(ffI<1Vvv+(o9k02zIl zGMf9~^yPXn`CxyB^9>+~R%xg6N>j)z}v3qil{_L5$9X(Y>wJ$#40-IeMf}g;DFR zKabpTifC7m!nTg2I=rCOxYWEO6A-LYu*p1;XB|z64yz;GkuftWEO<1}ge^lWmx1b9 zdq<`tshX#vcO;$_pkUmQQFX?+O9o-n_cSnTnGHktME!(nz^!(Utr8zgYumZ}{EuR>BA~Ys5-jqp#v_kOnyrz!hH&||jyC%Q1S{ z1=$dNBHj`8dvuF_Iv5T2ji)T4_YZqZFw0quADko&En1fE=pZ&`a}PmmE~k$Udpm^u zltVQ|9`z}QX^K4RQ>Z)#Z1T{Q8g8C93$@0&qEso@b}cJ~wi}aysl{zGFfF*WZ!TG2 zCx8Qo0G|VO`Sy-6fr2j;UPZxoOipgKEnFh{prt*Dp;NM+ggnUVO4ia`#X4D%)@YJv zu;Okwl}Sq-k~pY|CrhG!7e&Jcu^wX&Aw{jU&~PKam&_HpcG0!&KZhKq)eX~6CMf&G zCP#0Z2KGU6SKri#j*;IP?9T(4Tu&=)=f_oWf3>Xyy36g*QP)m$#6fNFiRgz8Zi}GG zhB$=BT7i_9T;T^mby(BYRUKBo$z03A8UK0z{agyS{GmvzJ>NMM-^ao){`>v+!#*^5 z5rxLMdkP4}M@C)YZJuO|33yD9Bg%Zfkni*nAyQupGC~zv=TR?9N3G0dfQNQ=9@eqt zgX_$9b?3U|>jXLDb6vUd4s?N9XH!hc#{R~=%%oXR(hvx3AtphCM zyOELKcpeyXU9gfyESe0*a>Uq)0y=Z!@_92H>L|MKFlq#29ykqj%lMZReL0XEoAzQF z1~=^QqvAsxGwn<9R+%{c`8{`E82Q1cwNQFHdf;A!Y~sZ6TB0IxL?rJU6{J%SGtQ+r>PUG*6KHoj;+dw6DzSU(<(YT z63%EuJX8A*nC)ED!-*-voW9I;w9vYXq%Z^wb;#Qf{aDf zR9NFvHF_{@NPr3tv@62`8n4jJM4$TBzyw-`Zl0MaxBBKFE+;IEOydh+y=Z@*PaBGa z{)XT~NG;m;3(OUSIXv!u8BgbO9J{Z53~f@q5VN^G9uSTB>?@g}9LZ3a1>r;L09E;* z4pfy-7fZxM??SAa{(Ti4xH{rR&o#Ey@4<1KGx^69BC4-i2$b@p&PpB3G>Jld2fwfo4OK&fIbb3ncY;>J9v>cnba zBOFMb5HtrNQ7kzuNNsd-8+q)v&bLbPwkmssND!+pwoR59zA!5 zlk=3mX>s@Kh=hT6c=*DL$B@Q}=Zl#=r^joTqStw(tzl@2+czVU?sZyJb@fFsHxz9n z`l%fKWL`|rCrs3y%QunoKiP9(#zuQCx3HMo;`Xh0;((5iP1|$%7BlG@c>uIwwx*qs zZ!<475HL7GLR)}0)z;bpZ=>3CVUCDBm)jJrti2b9cyA}(T{en0w12drJ+W#=fW%zdoDj9UJ&y`JV6W}o3`ijBW9Ae zJq)y{J(nLdC-)biTJwL;o(r*t_FV2^xghplJV7iUo3`h2pUHH;X5vH6d>c7-6lf1l zMIT@$)Qx*bJL9SLTpncJ|IwZc^M>|ZeiGnM#?qK=E~jkcs}DScL>CToe6`QLvAt8D z2wxUPmu#OAX>dYe(mp9^F0-pPDDF5CUIUOa2p|DU8L)r+31$edX;$CBh*l^#xcpIy z+d>t5C*b>E3~3DFATHG7e+T|g!2i-TT-)CZ7|PuYk+!%y6n*GKTG3WWOs zz4onmEYJaS8LLt&L|6%gdgwthnxZ;u#^$iEbSs8+LB^vbqgPi^`?917gZuL_B|aoi z?bCZGd!Y;U7~q|sF~7E^q=x)V^oK0i+CN93sU!w|H> z+5ueb8r=^=J$01ZCCvVW@}skYyE7b1@Vf^}`TpgMOT7U?yUt*uNuh zace7PzrY|zO!)b_5f6BqLrlfDf9$@95FBN?FX4&F6-Fz1&7eWz#f-BO>Ab3uuvEU3MZJb# zX`KBhJR$)0>k<|+w^Rd9KY)R!HhC>LKg7F%{x16Z2DKfPmH6j)tMLjUQR=M5oVBX` zTd^a$e+F{rd&meATpC!9)!1tGy8d=Rq^TPxAKza{9atcNHxS6D(q$Y^pjN8}mcUFw z%03TSvHm{`@4m5@B?2M|=%=99p%T1K&hR;XC~A zuxKk??xJf-UdHaQWWzR>T54`&TZs8GYK>Cg9Kg>>AGhH=r`hsW*qtX6=2@bOV@qAWz~$ateR2FsvX+fmP&84-vY|#dT3KOj)7}W z{LpvHk$ARpBr|_d!HeyHxW_P7(AMte;6LFRe<)sFMLY#K{_(EUQpA0Q<80Am%QlYh zrvI3s32N^&q*O6Olx3nT+HE>z*8pxT+_!{FM+8xB2N| zijt1cF}u^ORf+=7b0<_&KTtDf@2#_c&N7uUA8s78~29c{*Wf z+qsg{*KPRm_@Uy2TJcLrUspF_|B}WUO|}Vxe+OhaFAtb-T>A*pJDuBs!&Kp2rsFi4 z+_C$xi>S^<82Sf(q(f2eort?yhvUgVzn{qvp#@7vDdUWml$pY@$H|cWYiyKlNX*ij=f@LJ88+2LIxA9!V~4KsT4?1#77w&LlsL zWb=wUqRryS&K`pgz&nado%(#ZUF!og-_bUvpOSY30PEp?9l{Z*fjg22bzO5L==&#B4Snj?v-(uSxvyk-Cq#ViMnBF!G}}Bhl7Drsx}T0X5ud} zZ8g%!@FD`LU$P86_G*?b0w#LMH4rgjJ@ZajM`*1+hat*{o~scbdK9R0R}GUwe?=8C z*(+qwliPmlr@{ZXG?E0x#U1zg%Pscv=)Stf#L?+;)MeJx={%>a`-$nXox=GC6IpW> zQLI`pRf#hRzesVSjk5`c*WsQdylLf{;AlHlZT=gMGUS-T@SzJ;x968WCMo29FKhzO#Yhm6Q;p6pgjSI@hwio1Kf+n`qK6!yz>q! z<3vjHi6SAB5gEC~J_SK{DgovC;7Sq%EF8CfM0EJW`8i^B{{S6S0+Ia#TTn~`it+-# zprRZn36F&+{tVcg0Y>xdZipP^2t!3U?um%7QBl?3g`iNVh({pN>%S_UJp{0bu#GBD zN4fHy!F~=1Stosc1|ng8113u>XLG!p61(wQDu`;!hh+Z@izjVQGddRe`r6@enjifx(PkAn3V19Bl2!k!y%`i^Q#GoK$qd;Fd^2 zwYOrvXtie{!u>q}aY2i(FXC0JJ)58+1BUfxTu^Tbj8^XuiuLYe9#e0o)YUufSMcPZ z-h{Uz@pbi{gT#^bX5|{|Ej87-rDLOggVz{Nf4yxe{TV~bo! zO1rO11Wgv24)!t3Os%6|Te2cImOe`Aw9FdHyiUrT7b(+{jpo+O45T(*E@~|mg81m= zqE@|Nm078TDs_gg0nl}{xq_00-k5KFyk7|6-di6^x?bp*AEg78=N-O{pbT!YY-8}G zVszDUgW&mC1doztMXq#g1fzdV1}0W_1Jd4MyG_Z8~f z37bnBZ6^UYmik9rZ?Gaa8x~6S(8sOV)+qlbDSuIQIzBSv&}9_?~d?wb9bT zYk=YDSgRG$ir!Hx$TE2c@S9TRPLVRvJy0ZgN)FDYzXV*aNM!107};oT*}|6b0$3S1 zG1yrOVmbSxoLi)vUFyo=L6#|J#oS0s{kKJ_rYz^7U4yb9565nmvUbz5cE_W|s9uOQ zF5K{qm*J1lrgf&7JrQlsazO(y-alM`@I6ta9SBY@L&>K#QR&H~-93P=oVIs?+z&M> zSeP;!L*eP|o}@(qE1%AY_qIIT)e$rYvlOea_NF^QE1&L2%if2W%~5jGErN$k$`B%oEA?eGUw)i}j%t_{dVuIxohzEh!G*Bw?zXYGC^M#<}22MVD*>Nmd)0?Lay_B{B+vgCyIsvK_fd^BcR&0DI!*A2;m4^!hPLz95<-nwC_Sf@TFcdqC)GBdbo|DXAm5Kt7JXlP zpWS%UiAWOu(HJI_y&?0cRnmlTheSDJ)`-VYgTRB{KmqMZf0Va zLICp#!Xk?LuW%+$N|b^CJ;@=_3%4GLo@pb|GnVM3K7z+b&y={!7C~JOL?G*a8o!~- z^|;G6LE=G@cyL{!8UYQPNIKNQozzUS%sF4fzTIu?pDsHe9BRu`Wi@!nWTadO&^rJn z?7=chMf%PH&Z%~VR*U(>CSt}jeVSZXe!$g(^m4|CjU3s+VB)mxWaj`K>Gt^O9Z8JI zpMm4Teq8s((nMNn*4(&z0%#EQeOush^+1~h@*0;`9wKU{zg|fe>S`bmcPTmK=i4 zA?PV3SX8$U#S6EwD@Fa*W+$>Gg_ezcBq?VMX-kBh-p+ zEV?HgypdJfLmM!HFd8f1qkmZ+g)(>KoS^R`>gm3@1BT2|GK{SYe{$L0lxpJVvK|>` z$(IoMQk1jmd)=Oj?~2pPVczLr%H&O5`CAj^^`(^>RkcL&tFW78<=X{!j3Uz(am6YXW$s~43z2Yj-PUenNP`e=U)6ktb&ujnPDOJ zdoY=lH#dH0ir;}}CX7PRpv13nKe1lXRDX)n)c~61oC+{(A<1-2^np`@u=G~!b>S0r z&P9haphaW5*cTnTUDrJJJ5YodwxKIi6WtIz@Xr%gMzo%De`o&03ODXv=X{Ux-<;NEDxzcU628GY|h-dZfn#@71hp zaD9wJ;=*NeYb=+^*zg8!{4BJ@asLc=iB15xXjMQb85Y=!q8l;l-5c3{V4iRsDcYZ9 zY1&Eit?BZK;paNJZzai+6SG51Q{+)Zw)z#YCEr;p=dyA*Rvu?w*LFBfYiQ(KS4dUl1e-gkL&c=u>K(bHVKm1f9xk@|obQNd60*ym#pP)a#g)eTF)73h zA|@lIYb#?j)felE%OstXk*w>)w5-*!U!RL7lBwzz?;1^ZV`GhY+LO*#u?E2!r&O}i zSF{Qs`~ct+2pUpuzGTEK8?%T!K+i9alaE#mb5ratlu`RU5^+A`or0&;p7KtWr{$f- zXVUwE1e4zBe7gLVBBp-Kz8Vz3py(Nhs-1}+N)RPpyDGJ$>DA#@v=mM-^2yp+NTtMO zd1vDdk`=#T%m#4G;H{MyXIHddF6A;kETne=c+3>(nWDv?v!q_goYZf>J!e%1d=?Ss zuyqcQi0*zqok&G{Q*CG72(Br7dCpAL}D)uVlQK? z?9||@58gxD{9x17153QiBLD;*0dNHYT$WkcCtmw9p5B!b#a}xHH8Y$Jz6FQw< zamVD3tjKBjIUc)A6TPnxI9**?pY(+|lCDCMesfUs#r*qyeslE<#bVN0&8G3bN<5-6 zik}$!g~+b3TVGOwp$8UEwIMV&g9&HA4Gm@z$g(V zjGG_CO+y@S()tHx()q$%*@^Z%q{@14iE|_H=#kk56yrRPpUHjGwUGLv-W zqa1W@LiYaC@wFB@O)Yq9CeL-*!2_~1icXvd@KS3)zP$(L3hk)sEQT{)J;Wk>j&YYg zH3|Xb&_R0vY2qTJXv6Xc+871Z>8J8H&CEV3GM@hC&c=1=5<%91Qi=xXa8|MEDU%RSG<;zVxN#9h{XEiMpGG+<_hNPoGre;ao> z-qMTuck#sT>-X?z;C>=(c>vty12`|Us&buqgDxU}fp>BzmZ>Sc8F7dUmIMH^?c$b%rcw zgG30An?crSNms@I#{E0h#^JOQUcRH)#=Uk@mu>5NLR`Px^=P?AN+{C#7I$=-t@*#g#3kLIo2mjq_gpY+QU|UA4n$S#9Uc_m zdXTk|dqbjMX8(k^^^Wf>9kOZ00WB)Hy2Z6A7TReT7C4J*30xaxi3JG>YQZxVy)B?s z4x+@nQ4&ouwRzc+mAZ$B4~0Mm^g`gnHCPN=?AZ^I5G|y7u?TqqKD`t>o=~te<2MF7 zZGGJyCSj4f{gf!RZrgrf-Ii$Gy6VUit}8)UxQ)tOsk&*g*V$t8P1V>QFzoSl_Lr3X zvycwM*9aI07H_6|sbH;siObjn+?-BN;9HfHQRyv3ahTkjDP=F^r9WP5sC1g3iimf{!A+z{n^osSjmHmg9qfN zb|a$g(6<__BygrLs4QV)?rz4W!mkijdlo-7z)ReCDmlMK5cB+RnDi)-1Y(#7+WM*F z+br&I%EzQJX56?P!^^^Tuvufm9Qev}6SDg`sjpJESeRM;GG`$UoYAT1F19sgdR;Td zp;;Y^{Q>vLRa+=2qMitp%?bNC;BVoIIekzW?nqe2qW4?;ChQIPHMN$Q9;=*9SFk{M z9tl3~g}|K#?zlSG;N<{uL_hdD0F^&dz&)3^d?f0sPx7j#zVKvz_HVh@6OVEKBE$vF z^$5;|lzv)Gj0mV3D}iK>R)Xp_z;|J^jLs2d#EU(OxdhtB*U?U1m61LI`?Ce;<;3M) z@(l1o@>g;RT|{J))tk^vpMb*>iLhbn21;-$6w2V~&Y z-%~Ivcdk^-D|MJVnw-Dl(VD4zYVtW;FTpq1B&dSl0HK8m^JiaPH@g+xw4lGqfI=P&84xD zcrw_^!{bBU1rWAtymY@ z^&ZLlM*x_;m6k;R_4o!LY7h`!3@PYKCXJD6B>Jjz&T749x2b~usCeVe(a#}l5s;Lc4p_88WA_eq)D9F?9`2oIrFcR+%|)_DOoH6>m4Hz9Xo z=QKSt?z{tpZCUrPc<6y}K3U8qX`csz(cci8x3JBuZ*W$gEuCQS$iYVBI+hd!dx4b> zn4Hn9IZG}cU`^7RmT1M3OZ(9+I5G8s#kvhXLL7jY@-!x$!(KH{q9Wxw{pkG*YuLJu zyMG6baFh<=l5g(2`04A&L1{#S|3GjXXdK4kwfFGqF;bH(@1MbY&hnT~6LM*fxipaV z{uR8te0BegpK?i4RixJUFm>=h0I|OT7JI`%=8>T96H0UfVmZIKkx)%YQ>b_V#XT%K zWyqK#d@Q~soHk*|4G93(l0goaMfger!WgMb3bDAmH;g6*cp5)A^)uCBaU*kN{2bYl zIRs@h;_Vjvc&+#`xFW9t)W-DoFkK?YAl!cnKA=LrrF3j0r#luY#ih9xIHl(q@VrP` zt}WN<k(_QG@w4xMl|>k}%wbb3=r6NR&6Fz<$jGZ? zDlRQbk&y6K4S1bElPT|B$d4(_i9pgQqF`j*O${Qsgs3qn8V01IfI`&wOpLH)9P*b9 zd3FH-jJZJ-?II&2to>O}Tr=44=Etrn38yQ7a>E`eeZt^kV@EA;NCD#!$u0dLpp&bK zAR_EfXetAurB+!0;W?Kz!V_C^(oM-po8z7PTfYL#{T%n?n=dSQ1mU>LPq(n($MUY-j$d{W zPK}v@{R4KEW=q6;ct%5j-rgy_haqnGFSV;!aDjHHR2>iXnEm0v9l)j~GfSzNP=eVj zM&{tjUHTxFSvYh~)nn2Q2%SdiZ5b@m%=Z~{izICJ)tcf=0zOej5*=+=5Q{y4I@Ts5 zn(OE(cv>lMDjx}N8Xrk-Gd|jr-gG`){UwA{`C}Jgk!`sGx`t_L=IxspKji+8$s(jt3Ea=Z|3)>lr7?35g9ts!EK*?}w69r07%UyOgIZ751YBHKKG z*bj+Xo|5TxBdIQ8W)KnL^ge>fd5@wc>=i(mUUV;B4cSZzA#EGMR&1JWfhXGT;eolW z3Rv`d0!W^*jPGmJY$T~v(|0Bm`;I6G-Gx!du^wy;q93-nByI>IuwUZb96`eh-l_k5 z0I6+>GT8YnZ!5fEo7v@4TaM`JBAA=qe&Mnub3KU13M~DHI0xk1$D0KNx#Su?G?r&C zCL-7XiQyoO8z4da?uvV_0X19e<7Nl+-`PVw_JY!=h2x;O`M)iE>Hk!Caj6vV)5BH` zciwYQn4XOoS(3}v`-tzYxU_Gcc7`w;*7$vOxk}^oi>!A4!)ySL{w+SuP9Gc$&i_de z6jQp3Ff7JK{Q~>13?SLTMgN033DpY9Q$+yKG>0?=j(3r|YczH1#?_ zz6t0Wri~ci1oVF%--tN;7XO>^O^6pVy#+#XBw}F@5#rp)_$FlkH{%-ti{7Gu&i{3M zBc6ibv0N#m23a)?=sAcieIG#19v{D@$D<2Yu{f>K7lxIZ~R2TWm(V7w#=}#57NRGR9(0bsV<&f>V08vC>d*s z$6^nG#`a`N2h{&SW@t~PRC;_9ft0RoWsd-^PfPLkWOIF75^*W)F(h?ki_7z3@6k}L zEiKU~F6ptsAu7JIQ;@doPlC+6<)=e59~~kc7rp9z0bQX=Hw0|R(wNL5h0VTP*A24m zmU6kWHwCn%WXaS2Bw9jW*Sr9K%4=T6PxV3chs0XUMNRgVuq8br{c)scb-Q)c^v#yX zJ}~`xXl1?)o+^kaVK)n-v3pmNYNxp$xa&f&dkyijh1G(MB zDj68=Wkr&@s^s0MN#mOmG`FPJZx>kIz+rFm%=G$! z#)w4?5#F5ESaJ~VRg&(FN%Y8fPzj8tEkIjK@n+t8%{U4<1ZOcl)ui;~N`fV{KQ@UiUuyw$=M1wCVm#+y_Yd=4<>v)#u>tlR!d@7{el-Hy)d2etVV?+L zua3ZuZ-7k?1Gb1CL;u$zuoD_!4O+QMSLFoysK(anw}aZtBT}+PNTIPQQn(uLEIiC2RT( zyx~CHB>|zSX6G2B|QXX4;D0oa(*>C}MBy9G(A zu?$UI3EYYpjmG9B?r)ZGx5ThO)t&4wqAGD$I4}dkhaBZ|YyDfu**iwQL|muDbsI*A zVBD{cmWZEc7JQ1w9`W5#o}#qzemW+HiMS$jJ9NEZBaD16?JwkOrcUP;&?L8@p?)Uh zzUoKd=!p?j+0o^r18& zGKQ|$wvh~%p~tp~=ccT>XQ9~L7J6>ViX4tE#U{wA`=)yXQbrUd=oDDcWgG8$spF>m z1j9w(X?Zh+*7N0zdT+WP$=tsxc@OZ7J1kV*A_>qx;vZZ%J&2ITIX?+rO){K0NwTKP z?IiCZ0phP-Q;NHMuilDbS?(%%4nA!?U(^9naGoTmQ?I<*!$GJ!1A>kO>_!X!XH%>>Ml={RV!7sgL5PcM6opIFT+xpC~{-;4wsoQVmth{M0~f8_jD@a5W}es1LE%LDNhK zD>^@CNY_&I8@@U9#|qv}&?&+Z_Txx&*W<_gdL-frM%>H@`(#{Ta-fT64IY5$TE>KB zc)`gAXY3~d*geD)`>GO<5kjDAwS z1=4~sngsf`l4!^Um$;jtG&dt5rkgPR4lPja}_Afz!vz`%ho9uUbo6Mkm28lD%(l+HW z+6;T38RX6kaQdDe6rzH&b7@gwW-)TDidNP3+5s&wpzT}OKjsywx0YKP31b{PyTH!GRHX7*Q+Y-pPjb|UoimDu2^ z{e~d8n^kHnO{z;hx;`~q@$U;!Pug%}pK8ndynxEKRrMJeiw%*ySXACBL|WScTD4-Wf*q{+B^qXKcNw=RP zN4qcws__(l@5$IsO|jT7(B}(~w4_fIoIZlM%<)^~XlcjC)zPHxYTMHZXFE{oY(UD& zW$o#uOQqkor=Y&U&6H^J0pbsHY$_b(u{dkR?eO%HDA+PsI_HIBdk#d*Hc8GWvoKhc zYEKDr+~1mq5jWPsJ2KYFW%AXe$_1E56JlVv;dxf=clarF*TwNB0J*f#6VIS&z< zGBf3Q9fq#pG^5;|tjqg(3~9K>Q?yTox`Wn%r?|dVkw_I59*S*z`vnv)i;v&qrRRu* z^bsAp^xL{ZjnW+Ir$jm@1?V2=5vF3DXpg5j2D#rxH*)vFqNU73mn+5iT^=Q(Q3YKbhGBanlK_(S!E6zmZYlJTq$Pa|9z0S&!$C1P|G_#TB z{29@eJ>#{lL9)k~xXa(PRM}&#G(x3|wEGvp+YkUPk1VP~C>fnM0MN5R8yRk%q>+hH zSn8aIoV*wo#+;9sz>p!9yKgeT?t{^v7XOT7L$f;&CsmALpw7T@(Y^+Yk#J^w3wYeO zNv&u^-UbqY7JN>`4il_CUW4!~AZ)OM#5{qeGzo-OZA-X@$0#!*zk`Czh`cBEilY_! zD=QRu9psAsZ;ZJ>w2I^Q-w|-%#gE!e@^c0Tk^Vto?H}iW?#tOfl;pVm9`oLdp{8iJ zv0vN)g6b3RL!vU^PDyhKVtiiR&KSjUKfsK)F7hUW|LC9MC<4OMcK}FVJNoQ0&++;M z7FJw*(E7Kx&)%>xN+b!p~sN-Pt=oFOs8=)50qD?^wEh| zV})E+tBiYfMC_}ZlJcVcFQAEHG~P%erjPzjW{0l1{zLxG;_M-P=)1rYui*(>itU@T(vsFoUwv^xtNXnUwa>_Vk?86gGVhNU*+tGLU z9X8fJ(SwFbr;HhAq5NlL%y=Jhs2;p@VA}@Q6YQ~Arls8`gjX&zeUr90v2WV#pAWc)yU$}UM+1MtHdeuq_mh+z3f8+|3coNzim&9FG7rjL1D^4$UJb4-soD8}EWxf^i zlz#z_#v{$0fFB#n=92di+5+}yzCk$z*_-VZjD1*QT_%bpPwz((p~Z^*6)Xwj7!bUB zA_+2?PB6sPPo@B+=nqbyv|;NKu2J^DP~hEfVlHLOK8(4KG4@)7*^eipUwjSELuEW9 z84&k6F_w|Gg7XY=z%NfOy&4DpO+39U*>`XqY_0Zi{*Ged3hm&yOQcQ}z-{qD?Q)j& zJ8oS61kqXNUBp9AVLA?@{=rw+OJG7Swf1ws0TW2;5bLC|j0eO5h+37WH_(<>8bOh~ z;1GrxNUzFZpN?&Lj=Dm+B0hLHgc@1(ABvY@Yas=>CBWD{#1wlw(5!p$KSKUrvz`g> z$3SNo$s5Me>B|)+z^E#p4V^3QvOUWC!<_`18BS!HBPN{(-$Nq5h%b==JSrGsO!&1v zz|0tvBemoyIMmhT-jh19@88?b;1%(q#ms)e_QE#BN_{wUim@OS`xkii9C(Fptqh)miuFHB zmPvcg|2baGY|GU$R&1*VF!->O;4DQpTb7uxoSmSFFJKdY2E9zyj%nG2(M9Xwh>S=) zll$iQZa7w%bC`}qpgcIV$lMM;0=e{Hrr=D1$YjW&ZB#?_R1l4i&38d(JYr|y2qm=p zAzK9hk-l&d2&6Gf=~2^=cm4wsFO3d)NR2HO7T~)E8)QI|Uvq(+b?<GW6 zaV$SVu#w#hja4u$~EGRBXQ^FNd^GfqRo$q3H+HpYPOpNGU!}IRO zZ-qwYFx;16VHdP@8RlCA(+niiv6%!mM?hS*6+OmBMs(h`v_B4R!p+-aJg|wu z-;@~*qbT6)M24+?=~iJm{a1l+wZ#~k#VDS=0}y#Dxf+#Eeej6-F?(_+KJEWw1na@=TWvl z0{Ex!+$18nVIcgZ6$);Hht=0>Th=Q9gxy0-p#_}M;AiS#77#{-DW<3})hTz6DYxL@ z*|s>0CA^<9sI;62TAl$diPed!h+_goeC(L7}@Pesp``XCN&Q{UvRyAng%yg!0GNLCZ9r!^v1@ntsII6?b8X zF4$#}K)4^lT^OPa(j^d0x8VOvQ21LYgfQ>65H}0N#r1V|_}WL3ccmG?$hOKHL`K|{ zZH=Himw>XZ@+j-}cA~sh+~up%gw7{{kS18NV~o<^K-8=&;-mFN%wrM#K@pFIMesE! zLIQO~FlHk~%x4k&J|O$bU$_#jp87R7E}Y}wt7#tE25^J?scc^TKGtgM7ebXyY*(w6 z?Aceq8V`@_)s4M?+IL|gH1si+p#A=vC}D%lyCP(rjyVgKx>S~BAhP!vZkG)bL8beH zOEm^91U9~ATjYq_FGE^c%d=JI50qP6#)@XWvjA_HH6r^*7+iwnw6l=;{ifa}ZetBw z@)YR?pz66T=+TP+=?>thyV8oGQi7os`zP2!s5AM?1Cr-icbBnp@=bADa%=|#We5gL z(RP9;k>@$7B{sLI=OlpJ1JF?2gyDK7v?!+={;dW7d}k&RUjeE?sVpXlSP-54i2VYl zcaD%B2S(ZR!ZL)m0XX7i+64a$(lTBbqKiX+wy*?`xXvj^jOw+9#V_2K zM@YU?gT>^Uwkz$)^DpQUJ0LCM$>0~DC2lj)*%3czW^Ifs&=@9uCnjPaT=pAy=JzMy z`+dkW1w$7luHZA5K=_%PZXtHL?45xTTWkS5ye#@8e(fVs$B}&?n zui`a6qgG2)A7mFGHZ@gM5_D@zO_$7uzxQd{CRts>UgSHj_ygJd1bd?hu8ZR8Cly6K;E->l{eZfn>U}5cG$yFq^zK54j=bv zg3ZsaMYn^kh&dQvv&@HFWI64?-G4b#(qdM6{cYUGDS|1BPDN~OXH4*7I40#Bhe~)3 zX8Bx3%L6h8ae-RVjITJAs)z#}e!=0_QoR<@&}IlS830)EvhZ;*IxR(kQWl>H zi-gJ;W3o;c%EzYdGYCX6e}|Y2{Ov5Ypddx>*MKzVnx{6+xE|sq{y3gbLLa>`kXg_Y z`=A=|&ov$;l)VU*#jPA@q<>0dGRh0~2WJ8x#XiDEN2H+-Pedx0g2sld*rp3UCBNyi zvmY?J=>bz_Ujl)UmBl6vjQvgmnghJa_|@37I|c9FR7Tk3+{{s|PBVKk?M?>})eKXz zh2v~4d4j<~nj=zA=MFHAssJy7Lt2=oVjWuF0r=h3C&{C8(I}66w`w`?U8$SDG28_;U_$|UF3KtFYw+$gK@&TBXu# z9CU>3ijOJ?6ybMk)I56c>STJ^ z+++-_f&>hh{b+XFqAvjNME~m6Q$UIvS{WKeOE&S{-zDXExvqOc_4HzsxrZe(YLud& zLE1LL2&FI^66i#D($k14D_xS})&67)#*1X^WDpCn!=KY+E{NMpknS$UkMlSNa_=`_ zmx)}4$nstW^TntF+)G)GyjW#;YLR(u0piQAS{1W$QmfEF0{vy9V9^U!bUNPyv%Tkl zTxoe7{o`fnA1ts^j?hv46f&4n$++sbr$VsD?vZaZF77gq?kt^%h57nNuymFAvbPS; zXYY#D;W-_6H-?7`{OgDZy;?XTm4_8bl3dJp@0xB9dUZ zBKoZ$<*zTt#$5?fkQG#MTe2Jq4F7k#|L;(!$n41&cG9Rzit&-e!}z&8%^EUF0JCNkWe}ddt@L1 z)9^YQ5M2_IL}X6$2h=c+_R70U)9gP%!$Py^ZfJ^9L>ZZn|B1$O(92O=)^{wcVr~)8Zg;`6EVv>DiS+{So;7a6ThFmSg67%^LX8wqB%`|dYiLx-V52-xgU@6!rCfiqfv+B@XVy0 z2N3I3`R+1Ci(N%RxCIE!!x~~E7t1Jrr$rb175RqA?f$Q$Ys6i?y6wPM7>+~#XRi2K z2_jdjEoJ+7K*e3M5)Qk}F`?Ce83cMUAKjC%#{dPka|k#pipI=1V=Q3*d)kYT^v2uY z$FNv#h5T(4%u75l^%a4~0(DPqH8A4{%{u|l&JOrX>4=*JJe>vSQ;G7i(0@G?dpvR~ zh8vbCJ?h#T$#EP8e-;@{9ePby;mm+9zG32k(a{@FqZjmLc;zHWYu|C z#(;O^huC|wQ&9FRZ_|+i)#t0)dj#po66C};QcCH7Xx4ht1vh-u*<+|s7?Qeathu!0 zkxOuDz7N|cVycs$!Gu1XSI{J08Y7UzQl>Dk?1FKZA27~2>=W_yK8GJz%x4ZY39*@h z4fgQ>k9py8yN3MG!+eMFh<1U9L7(tV#gUiqm z#a1ckj3dr;W!_4~Xs_>8>GQ732^D2X7#u3?j{~LW;mvaS8-dVCuc9%U>M^Hb3qN37gB?Vs zkdc%@Q?WBZ{A(N+PevjuFob8=x|kD3Hm={GqqeR2em)O0-YNJ=e^Bd!s8azGA&NRt zcY`MW#l_c^jD!91aX9Qk&Z*duoqw66GaNdy*@ins#>n*NQ03KBPO2Oi*KCWCt@4?; zUiSV}WZDr2oigK~A1EwtdNr5lX<$9BX{lsw-+`&2vRPa%dWqXXds~bHl`*EwyLFDj z$qvWHl=yM`6M1_Y>WDkLGO4b{3D`vM3y9HhSjTd&=dpk7bRglt{zW`98J7=19C?*8WIpiDXn<1tN)WUy?@T7G34iU2_@Q3RpG)wg zN$k7>q9l;4-jmFjYgm{s&O+``Qytf^f>gbR1sV z1?r>HBAZ1TySFoJLX{VAWDM3rz!v*2CncQUU@=nZOoWW<#kC9=h;HsF_UxU|RT@qQ zEoVP8cX2qbvO*&E88Gp6e&5pfK?H}k@qLR6a>YRhIDeA0^I$}I22KD9YVR7WL%IhQ zYu9G?`eBc7$_)0jA2lbMee(T|OdMsnL{iPJ%{~cOC&;{^FEao^tUU zS9tG)Z?=3gSl<5%4UFYIqy-e1arOt}j>nR^N&HoE&Hu#BVhBB#K%scuysBP3VViZohe3XiG?4hwI{zFQ4j9(QDvO_H)`t>5|d>=f^9RAM_)qPU%Y7mhoZvhm-+5465p#OkrV#*aO2YeMz8BjCZyG^0(gxlG8<6%WuOt+-+-*Vb$a88(G;%9^*XO2C7ry|03n2oVLGVKHjh`fOc`MCb}ZPHX@PNDVIaT~>Zh0g!gv=1%V_wvSe-v5|uPg?vjP-&)!n zE|XiYfP-!rXkUFAOr!aEi2@DR3PXRbxz=0@^o^eaN=C!Wx4t-8Tmh(bB&zlNFHMQW zfbe1K3w1OnszLjN)$-~)8xj{s6Ki#etZ7go?ekW7VPw>USIC3P=!9Mr$MJPIaGn&T3JR5zGqGJ!DgLd; zA(D2B>cv1abshu@3q7T~u>MxR!$4?^2D;W$&XBIOuG78*g2xaAlO9O_TnA8;r`#8h z9SQtzVT?B`*&m^ALo69&)_n)Ud`0?KL>AktqTJYRVM!i5n&v`6X!i~_fj2w z6_3c8$D+*7vrMCVWMs}zW}DJS5lMC&q{NL~998vbI2lw}uBlp#pIwQ;jXVmmq8J|t zyzAC`KGPB+(pMrY9gWeI&I-^s51(OqOu~^(&mV(1nshy`@;r#9DCjkw%TPssBUK>p z0i<_1VrBht6~_Fxg~wd$*KLR%qKltm-!2eogH0LBITjzYid0t+x65Dn+pPWug=%W` zUA*ei#Fvo>f1912ytJDaJTxz3ans7>)9h^uzWyfArKnY_Xn8YgB-fE!;G;$Ed{w#*wX8LbN!eTp`b=s^Yx*R-Z|z@RU9HZ$_coH8T+glH+NuVxPBjE!XjSh zRCmGH7vZdmc~7n{he*{AneJ&#+IU-+c9*nP?FY11$gK-e&V&*uFq?1Q9KM)O>l#qF zdH}mv*YQWJj~RQ$yxgddkQv^;h3Pw8_S ze*%Mprz?HHwS*RmRE`=2*#aMJ5kPYVSYx4n@Dt`1yMX0W3D%PYt_8Iz^Lhed< z`4_x6E)FD>-Hn2ezkZ7(qfbGs-rZz(q;Ct-H_~){8Z<|AC5v!u!dRZfddXPtc8szs zryP`;jQS(FsR+itr6%?>M09Ovd+ri={J~dFVFD5^a&)SH5ZaF+YW;}jD5valkv*hG!>K6fZl`4x1NM=T9;gjGl zDcXl&|M#QkY7Y!@UvlKE%p3#GIP^5C_f+WrE6>DwH$dSgdf)KNkPVmNjh6FMVsq|7wGSlt6_=pO#bN)y>B$O|C1vJ*(p1#; za9k$$IC+`4f%LRKa3kMhtY2I6-$>$a47zka%TfmaDuEZhjHm9eR$$|6csWkHMd0rh zQ@J#Z@arPH?i>7uH}TW8we^Mk_}{6&uDf6m|4s0kO+{#EX zPjxl6cHBMrhgG(|3()FDIk!9d-)wc`djP3FxASqoW^_n52FH&?v=JRyQt#~Kc4pw1 z!T0qcwcQnturb_XxNAEa29{!FU$>#J4IDjE(_U6j##~mxr_&(=ca;O?n%>+rc!9ewt({etTZ=I{MRSl z{mEK2UmN!tF!Qn4j@7pLu!reFbiT%t_hN=H^Zdg0cxkN0jP=Q&xcy`vj8o=( zaO;LL?`0O>t%U*^5HMTAewzEA4?rYy(ex0Vn?0R1eVg6{%r<>fz--f-$F}L8sn;WR zazbPg)h-*bg33YS3AAccuH@;6tfcSQa#vsd&_X1d%WJH?(b@_+($gseUI%vpi_X+E zh-&eDRf{A}o5i_1iE~Ob&JPslR3GP_B#!FQ$8`SG?JYXv%s=KrX01ONfA@z!R8(2@ zWecZhyUq5bfM@1M3O$EGo0w_7b&=1}isb_1=f|LEEO1nl9XA$On45a?$;D;+xG@1s zdKwe(VNCFf=oruNPsH#gLHJX?TYVhF%{~BHb)^Qf+&Kzke#v-adga@kDtPXW5${~5w>E{I; z(4}iH@Re#uWwchS6~<4eH};_4K|20DKh4dd=03>C{KELxvV)>OfY=;PVXYd3Uu6;g zI31x_+a+W14`cN`nc>%;rr~mOL58etlPH7emO@qLFDL))l&O4k+eZ&8O!$)wnv0ff zpM9NTaPlWqn>jjOd2Mfk65LX+3+Rc9z=pLLpMTDfPo$9JLjjPux&_zQ^;Ap0yV z-Lf6Vc)!A94OW5vN}$Y+r=EQD5l#gUXVvmI;hg9pf5+o0O}ZA(U3?e+QH5FY{+F7w zR;aD#>jbqW)qQe)I-x$R?Aoug-=Hj1cpAH_KRJ=FQ@_@J&Fk+i*pc5J8KHU%iBH^zuA_gFR5^Ma zKMHmW;Og(o(GyaN?pX#Cn{f_R8c*soyOEn^zBcy>^eH!_{Gn1KFJDQc>VmoI9Bksr zA@)tHjbaKZc}Q6hmuSaC2cCw?Mngrw6$I;d8=ZtWzr$^)c$A|qz_tEz)Xi50%@nO- z>1NfXrne>3l`$)>J)&`7mbi1rX=wH0&#;F$R2d(l>B&3=bt@Z%A5u_wIj+Wxlt&kJ zyQd_q(5Fdw=5)eQuLv*N2FDiatf}=)j~CBUypy&O&q4>1x3^kydO6L?hq~GjLUnwJ zgpkh1n-;jko3vHY-;(BRrCIZ7W~44SCrv1M!MY0Wu*y$kfS;`N)v4Iq-45s@SP^YS z3qP(45o!{Bh@9@u#Iqg56^Sk4nHf`!MSO^yso^^nsQxTfD-?5J(>?v*YKzrdD`mR} zv2sH_a*pv6yW5<(*oNQ<^ts5;ovashcw77_ou^qw<~HfL(l-x4jq4azleUnULQ~2o z&(KzobTQFVq_-DU-&S4Bc&x0pDk^B=wfFCU2bJg?JcBD&-iL2uKIq&QjoN{ARg;~? zpM&T24|}S~<+JDR$PA8M=Tarl5#v5K2iIVmr?CJ6<=TS6VYL~B!eLF}9geST0y~@r zH5OWQBwc0n0)BLoW#hfcCgmu*%Jp!o6vkgmMoZ&2^J^EYpfxcFDfJS?#zI`Z#Q~d- zHg+)2=HiZgCwAgzcw%RM)q&@O!F6Whp)n++QmjvH*gK+?+(q@j(H3^DD|Kyhtbbq8x*~SQg@Sx9f?K^n4Nhl*7 zomvr&!Ryc6iky9Urf3r&aa=rrmSKk1+S#ynn)N-uQU}*h6iIG9i3uDu7ys z-_6B(>idt0-tbh3u9}%il#I@!ADzu6cE?loqpnucL#VzbTbHUDai)>XGyU<~ zBR7^1&jn}u=mTgZ8XARd8Kj1_G1iRblGiXHS_-tG@uiQ|5~M-MZlG*=V>{d(@FEUR zimYoL!v{DWauGNEwz1|>vn3msP*XC|-7El|w#HwSd8QJpFlw~rxgcC7ziu}BXv)QM z4xcAOV~wLK`*4CG^BVX3m1p7i5mXMBUxXAhe%Cpj=hz;96V<^7ikiLYIsP?(c6hN8 zy^oPxCi1$uWnL*=z>ke)T4RPA8OdbOBUwuIdb$!y_u18CCuUWQUe z#rvieo^rD+#S&T6!Srm?d>81(wjR;S*m6+rwL{0te%#FL3ZToi%b6+mD|v@2QIr^~ zz0%W3B~w3!yRfS=&{iop$%=T#`qq4QSU$}th|g6spVy|DYu2GyWTJo5ttXl5ZwR#Y z%z5aZAS}PNnGgBx8rpJmuDf9+t=94!3WyZPMgPe zHr-A{Sg)&&yu#K!COk&^xPZwCF=r+;u^-Ue&Vjv$gIKFYHSDSC%QeksDO3HnhBWMx zkQ4}coXl(dvT8RJ!}m6R#;JaLG4Gm>U;hMu9e(YX%;B7B0@ogjYz%g)Uvaro!KpK) z+ae#b?B#0S^^eG&j>*8XX(v>4j5x!X4YjJ_-cXy?YR(S#k=SMwqm_JFD%tw2cZQo2LoqTWP?vPs@vkN@6=Np;ubYhXl!J>r)&Cc))0F%$fYv(2p z!LhmcJcZr_2SZZ|QO7tEM*2CEpPpscqDr5wW_p{ZrMLXe;8>EAhfXK{d=XdnhNcwa zGI^Zi?kq8L*mV5Eg^$r<@D&nL=0+xun2vL#aMl}+Lc$60dbWPn^1~`espFE08DX}` z``*>?y~?|(L3bHkW~!z<=l0o?HXASC2W>7bg;x-(W4JVbX=UqJ{Z@V$a#DV}TgrM{ zQq-*^ybzkpOXzLlC|oLHNAvXsdo|A4OR>qNvhQKdK3bvuQ;%wuxLG--{?YVX0&BqP zO4|QzwGxeEz@jtZB&%HI(gwFjV?Nr4U;7k{;;~?GhUy@#iEb{w2%l|>xQ2vurk5 z@yMAjL98b0TxkZvA27Uf2}WIX7t5TjU*****NSG786F3Lo({Y4<*EN?*>u=rgCnud z#ID!VMa>puYYk;dJ1RXaCYF1P8UWbqH>sV!U~w#6vgKNiZlwz+vW+_e=s$mlRM*sWwhZ03Sw6kFt9^1e|)ZSZ(_L zBl;fkV+32Xh+YcL@`cS>+0=>d)os7@*ty9yD95Ho{?_ekrh3Ouw1J!yLu=#zPWSJ_ z=ZwFdp4n|0hc}}tzeV>QH3XkP^cgWmFN2TTaZf)n<1^g>+FFX=)Hbm@qp1`}l07gh z=9p^nTUw#fY*t>iSOIG)#6qhGNIf8XKN+{M!By*+ST0=P|2K%NT3_4w|m6;d)82w|mr=ZmyaXjP*(cJ-N2o&}IbXVHZ29 zKjMp!)2PGE#4zM?E$XNzGc~IRzgImtCWB|&vWxff5G#(Q@HnfU;i;tO)%1*M2?$N& zb$y#9OFoC@#tm<1Ha$gx>gQ%@_yp7Os=EfR*;ZgLLo`mq*>5jBgtx#>#T9h6jb!cJ zcGDe+vWzICRk62lT-|K4abM4DcWbuh!~1aZgo{I#$E`LbGay0SLogxZUcWY6%#Bd# zX4u$K9O?XxzHYnU)6(J^&s;dd%{6u`s~BH`_@`)GJwILZ!*u3far=LqeQ4_}_J^yP zP%Xz;E(>6vWzT)s6KVDrc2af@*c_@1DztmrNZn9Q7Q|!8us<8?<&3#GjF8X5EcJA2 z4_!tdq8uN@CKWYYvlENKQD!>=B3zcCylL4OG|!Ms&kJEnRjl7++6+s zITB?SHY4NfTTFMzoa~-t{Zd3FdNq+MQ|F1=Q|7g5I7T#z!R~Fht-OTbc75AzsS`lTL*I6$ zboY`;AJ*$lq)kOF1YxgqS+%LC-FEKntgbFCoxi27O0Ij5kORudIx$4uWduzOU7;=Q z^VKJwe3DYLn~&^Lb-&Fd`byz}oF=w%v1^_i9VIIT9NSCPZp+fL8D)@WqvQs$^-8}l z!7RmgE*gKY#&@zQ9A*ZIUm|niLanM-`QZ#(KDR3+Wv1GS2CTDpszRstx0{Jbt8DB~ z63|qtoqxj~H-}zW8+wh!#dZu|&QhJvC&PF#7Qo6Zt52oo`6`EFJytzGK-~>r3u5DS zq7v)ZBWNF?@%j`Ry#Z%!S$}q-uX>S5$JPWK4JPPs1b^a9{6ud~i7?S)eXEo^fwr=b zJmjNSkx#B_nf>Y~SznI6N#osB95}94m{AyMYp44$q4X>DGcq3A4z6SIG!0(&K%V9B zhxoDOa5q~BuV`-Ch(-oUo8M(S6WxkbiRLl<=uR3)ZJm_)H+cb$@IroivekZGbCQ!M zY(*FT(z>_c?91D+t;R*TF>_^ATutA~)p%4l@O)quZdJw!Ssk< zts=i>U|UVKK}RCC1TG^qdYh86M|0nft5OX=M!D}#dlc)=-a&{SNH^^nHAbgIJ_@ytGtXt<$Q9>!&O+{d1oB`(i& z;)47~;zIHR#%s`#r)*_Dv#q59Qh$vv6mP{74zr6K-o&7y_6i?o3~;TlSQ+z!$fBJ> z8hMV_UOM8_n4ml|UyEZtNLxpoJC^;N>5FAQbEGkzpnVZ*Z#&YXx@S<9dBpruq+e}5 zhCZeGJp4xAkJ_C74o0A!M>THIyM*x>8^hFgw(ie|TK{E3n|CX@kf%DM_Xye6?{`-_ zNBb6p>w)P^@cv}qcNJfRa93$?YH|DERM!aW^siZxAAAjs^vk0I!4lK&HA-qL3%OmO z)o-+}5G|eUeHqdxM~pu9CW3od>`DTolL=7#_oeaMb1T7{ZSmjl;@9Rt!ru9O1zdZk zK0ug^DYe3{5?OmT6tWvcR{fXmKUIw82SpQlhqdOfdH?B2ch;E?dAut++~@H_A_g7N z+k4I{F{SNSN5CJJx z1Gn43zC>xis4o|BcpmdQE3h4uTlfIhl&a1~V)K!YjjK5MV5e%rZ_)eJ*9~?gXKR+w z!muEg!C)_>Q&%cJXCbX-o`-kQ!Wqvj*s;R&RDo{L7T%*Eo_?}TRPnZ9XuTbQ)j3M_}0Gi;C63I!X@owZrKx2HK2 z?e6mZHn%%9^-O*N+{Co1RV;NQ6+7$Dq2~iS$3F=3HYaf1v8#TGPOXu*hruzUXMu$T$?dn$YXr~Lb^+_(|cM;U#IV&;(y=Af5IZ_H;H)n z^oW$`ufY@%Ri^*Etup;}aH4Z1_-`l+)6291%i&EzY5X^3+K8UXpv&$CK4rn4j`|d( zI|!$v4rD9BpU_0Jx@0PX>cNkw2MZ;;ADHZd#*>m=zOmUvsNYOI;85$+sR!RgCe!M{ zJ(B(})o4A$kFN)RZ5EJkNxD}ubV9{HY{9j9Fw&nE=v#Cp+vEPI1-G>xyrdcJ3aBU1 ze%unx>cM-PxbMs0{-g!h>cKrt-1ld2f7*g;^`K{V%K8T~xIb&bEp4XG9N5IYDua7( z3+{2ky{w75A%lD0G~8zW+Ce(rM4;+duE**ZZ+_9%$&*x*pDXrO>(`Eof4`3(SVa9M z5g(Wyk^1#*bn5FDYT0_9akDDVlqyfAYH@=@@N)Eq|E5+Msi#+~rlUS(t(uPd6t&9n z>?{kZCz_M3fcK%QtyVzV9o0cLVskr5z7LvwgGNE}%{THUX8mUBAPZejrw)Dx5l*Xv zzmSGn>)->;LUaoe!dv;F4*s$Q*XrP4B`wIeWpE#A!ELRB$2Fs=tqijj@!^)Zt|GQX z$kxVRwM4Mm__LM>*(&+#mIziQ=Ty_27)#lD`J0vqRxj7IM95ao-?l`s%K5RD2-zC? zyJ-=UK1_Y!&ME`HCs=i~UCJ*sidF{XNvhf(6o0FAbV%|4=;N0xqJEQzf0`bVI{IA{ zVs*5Tt5XK`kC`%OUV`v@1epPy_;y?kOmkp_I|Z)g)L2^$;~}ls77*P*lH>7}F?@!d&E zOa^{{o97R+Ja+#0GhLmF3jL(61!O{}ry)qVgwoH12?MD-8EOABa$@*3V94l+J zb{zv?S3@ebH#CaTo0wTtmrl=*VznHt)zQw(Y@|r$rh>@Sn~#LQY`nD$SrnFoQY89@Rw7K{S=ns zpYh|abd@-`jjr^GF43hk=}OnD4Wh%^nuOmAKI;sDt!q33z8ptEc%P_kN~p1kV8^?8 z`6wkt?4K*PbXmyh4!r)Q?A$K`5Afp)f7$V)Pp0tuI%CKWf^3y*_`$3MV~ZIY$}d1M zH9Oq}7S<%E9Q_g$E|xb{P>n7`iwb&3K}~@@j5q!jKTcpBjzN7gxjZL`4Px2%?rAdk zwTPaaNiY0JkKOHdN+;Rh2;(yujOYRtt2qvFi5IzPzLN6#TSY>iT62CYwoIWGO~ZKkh~ZKVH)G<|NKJnj51O!Gf? zbVg|oipa>JXPbN|WE*_^QGASNbd(e{9XC)@rXv0)A^k7Q%nY%5Y9`en7ATwMpOZBI zzstvVTP7w@HnB%c8?Ijb-_pyJhnZWZCr~!Mzhu(;zv;i~^*=y4oa@SA@0RHbluh@q zO82X2Yx+05@!$FJt!W?VwC?(3n!i6z)05$Z7V}YJTDz$v)EsUZm%{T8rFmV3hHIz> z!qaI{bTV`+&BH$xXIk?o`0-_^;yBT#$w^D!YdE3B%oEe~y}kgoL?pq2666ugRAyFkQYp177#*s8x|;7U zejL;uy^NtubxrrkM0+`UIc~G&*weA`guvhOs6@AG{J6ZM5*4B1&cN^F&%pN<*RsIg zR`1~=(AraRMb7~_dscnyo{mY5M--N7P}SKnIUsjX?JARKxw80zVr^cjK2TW8Q!8z? znL0p}yK`bEb^(pj@Z`n=87|u%%9O}#+y^}86(vShw!0b6muK&c2ZMXVM+M=f44OFV z7HZ(&H$vty*X7xg+~YcKQ5hS^`&ipUqG|49tT=&Ts?PIVpk2mu&U|<$w1Sw&z6%}_ z{X~!^Befy#;brYYZNPc@8{*NqD-DI*Crc;pvPi8`3~y$5%)O%UJABV8MsrBLv$z(M zuWj{5T(soY@AzX(?ASeWP#G^ZV_dro2#PVTJ!~s!u3gP$(};aV#_(=4D8oe6m~b>= zj%izUE&c(4uR1rRd ze|Sd>OMXg@MM1t0ep)UoiygUHeDx1_`;5Yj_8G+)rT*|;hM}^0PTsv!GC2qSD$%}h z7jQt)Mv1lO8#F4jieFi>#CZ;9aeq;(bG(ZS{?TDu3v#5Q{UE$3UptxuE2RBDq3lRG z%7xm|Ze;sEq3lRG%I&qI+y8ewJ5rAFj6!YA4A1pp{{u;TTAp}2#69Ex6XMf2FGAeS zmumkL;*OT*yae%*6Z!vyxTEEXmoduMIr8!u<>LC9JM3<7xEW1m2Q`mS$~~T z=1lC{n#5~e&aKld7z|Q>v8_7F7m&FL16}Ee-!bW6C)D{W0nb{!-OGllktZ!ch*7WpHkyMV-xSJ?-@b( z0nln)<3Fd?PyCLooQLr;3j+u1uvwhrdonl{2F{RhXtWyUU=iYj5Oj;5+Ics*1i3TG zx4nHFWA>Y;DS~(hzCo;par8(A8gew6F!#*y^!JWaV?uS_J09?H+%%I1iHi+U9w`OR z5m-VD*E0Mx?Jf=ybCr||5t<;O`u#;hlwk;KS|yf7mbXEnSEY9_0E?s=p;%$TDuw|Vxp7~|=~T7bmU zm&=D&g4UO-Hq-?bYCF)8RQqz4ZlUx+v)sc*wd+(06j#n|haUz|9KLR{%(~*{;$O6) zcmtp*Wx@mhngYeAWFY%of8aX;AFkYlgen%-OtFx!BvrZlo@9-A` zUH2Q^2;F_2>ur`{4U>N-=5~60?jYBn=W`zhQbQJ#$~!say5`G@tj>Og@IRmpr)OdNRKE$^NZC(=1h&YFW!zPm(ehJ>oRl4Hz~-D8Ts**h(>M{=F8Q{ zNHHVP?s9DhEDT=@=Ukuewv;QU6EMS0uR&wsL^4d&=o7&CTUeV-h+|Ezr(*5jDQhb8 zFJ~UHRAs>I{CDz_pY%!lQ(AJ=4Eg}wLc(_3ErBojr*p4Zhw*-DfH@%AZ9v&I?#l~j zUdaQtA75sG`FSgY?(*v4mEqF;)t_wMuDjB+?EZj`qhq}c1Vl$WQ&#^s}Ed($$?y+8xeQFw(dd1HOdrk9&2l7`OyRdstZ&M zS0llCG@~%snVdCDa%Ck|xjM%nR_SY`hk^MT_evb z_jav5u)b@)x65gScgno@m(C*|_j6hZc0q82Yni%y)Z0}W`zoYP@6EoydVFP8&&UhQ zy*&^aDCB05L__gEp890I8(tk$_Ga{Z+Z>fG0cTQ&0 z3c!U_l_{Q@vfG$v72k(s7d>CF2W~ny4J?{b9RGG(+nM?C9y&FvE{FGbZQ7n|_%n+A zGTG=?;H+{;Xw(4FbK?yT`FG_8cBAz;hl#P8ODu}3^l*E2)O{B78Ey@2f67oFx4mI; z$Aehk+AJo*a=`qJWY8#Re!oHq(6;1r7s8kR<@d+%NsbOS*TJ7AIaU4^@HfO?jlZS* zjVue|C5juwnBLQ8sr&5aKD)cm9`5r@_gUsX%lXu{&o5XL#BwrM;HINofNXX;?AD1@ z)(g3Lu(FKu7_3uzR=Y5)>O7XUh0c=!WivU_HXN)Ii)l>rBr)aj;jQAan95Ze(>zH` zd4hE*Xp1x@h%}~ol9=)Y>r&7bF(tb+rg@T>@&xNr&=xTz?lh)(l9=)Y>r&7bF{Pn2 zrg@T>@&xNr&=xVJ)HJ4fl9=)Y>rzl_Oj9|QR`e>;9?WO7F5w8Vx9EJL#O$Wu`^#Ap z>D1<1uKd1`c58XFoTxhG-8r2eS2PN)(0gr94_7fr!%e5t!v#viO>@)31xmwBKhwhn zO2bVH)58Ty!%f!H!v#viO`_Ao1xmsbx$cf!HBU6T3f<<3UM4eqfRB_4^Um>)F$mzX zTz;)Vo4`t7Cs)XAKWTmf(_(@ zTg6MTfqZbQbO|<)4{jAM!3J`{iEMX6w!V@1~1ZZSUdR zlkR(1 zxU`7BG5&P;<6!=d9oofGi1*oD2*!yt9$3KoTWi-`@+frsuFqzv zP=e&nx%`}ybYQn+Sk4glF&Te|c6D{b4LKN71-ZAt_+Cx*!A9L~g{o{XV0t$p(y2|blVH7x>D+E^HTLnctt`!I-^9aj zEJ8nvW&L}5+lT#o1wFa5ChbXz96R1eFh4?kT771OruAmFN$#V7Og%^Llk?FR;JD5! zwI@HJ`p632~&e>n|bord=kPlx1T6$R&E=Qy$_xq)|ng2EY+~HkhoZU9xWB?!R+Dc zaIwB~-sF_ZyfEDxVWNeHD(Sf%tKDq|VC)4Y!E5uQ|M z$|g?TwhB61rVSLoiYQJND`tiN3pNfITui_{C zCj~QzoBl_%+=gY>EYO+*k2FCf?>xKdTq{yV>@`jcI@b_h&2Mxvm3$fng+*@xy2yh? zB8ao#^MKTz7sUET7lGP2!d_x{F)pqp7|UXTi>;Rc;&UkF;eMlshSi z?;$9E)+*%9EeYJ=Ox3=VvjODNLV6W4I?=~x>V8q=Wq~hI|2F=Dr4-viuG#@R6%i<7 z+&86+LD$Z3mZ#hdfU<@3JIb>~8Jjzuiq5&dG&=k3Y!UnD%>bfXNYzCjP;|BfVX}Ge zUMJ_!v&Io~2xlBISJ*0FK@KzBxqYmBSy-%~^_|7KS$vgDST!nMEl1a;o<&-RmAl-v zDOd96%C^sS4CQ*X=YmbM43Xg@vfhGS{Mn$V=$bf%4G43dcs@})ZwlfM@pZpp1GPo3 zMc29kP9eRTAhRf9+ywE5<=6nubwZB6wC20csct~&sXFd#>X38 zBYcMEG45Sdz_z{Rrvwe3A35WeOhDhjVzs!Q#;*)g$>nHQ7v^*HG-5N1Q*_HycfLG5 zPs~Ov2h2V6ZJ+!XNis=^{>@j%RaP+6XT!1J1u+U%4SPkFu9Jj__mwu!rhA*$$0)iX zA!ux3*)K(l@h+p$Vwuch-G|B56)U0YGh%ghlDb;s(N|%Fe?|I{EICf@kEt&m*Jlf3 zi!`HMA-t%sYx8X000{cJwr_AZpwQP=`94oiPy(Vss@Lgzc7E{0`TZ+`%6WvNQ8A_~1 zp98R{cZL}pi0+n6oww2k&DxH4B({q#m2+nA%mi&a_e|hJ_uYbgdbi_&!0nRGT}i}G zSqdxDO5q!!Fu5Dj?%=hF-TBsE^}kd%3nt>Iw|5J5_oiYbQ0gwkdr0ZU<7=2_Zpnr# z*ffG}yfG)gg#I0(Tn7vimwrJbfSFc1QW}^Yuw0?D419-=U3&lp#d%Ts+qas)YpJ$E#P33 ztAzq>--hcrGdKLHUdgxCKY0_?E+0KtWiuI1SH$hjM9W8)dfva&^c|d!_9F2hz7?3QbPgY!kH3T` zh;K_lFHS(;1r%QgnH2TQhWfn})vYO?NEY^`Eq9D}^|ci&BjE~!!|p&JE4Q~3$MHnC z^A?Q73|2-?Jllc16RCxJ8l_=g4)O!AJH$x17vShwQo%<2^eaJb9=zDO+gK=_#la^= z3rM>&w+R#QYtYTT$@)+)ClZB91IGGojtab=^+$@=Rid>uLb;Hy7P%^&_if@6%x+lP zL3|f@jXU{a*+rmg=Y2P35Gswk0WMQR=5S*xCb6K==MZXlP!8WLrSD6TZ2Ulk2A?oW zBecTuM_lXZ>1O~)j79*dR7&id^xckDYFB};~LSvm%3j06VBa1wnU9`-qr zqmY$O$>wOurf6ePy5`(J{^4YEMv`IUs7C*5oIOj`h|NdkpEcGXw-<4qoyu=;^HQv_ zODRnqE$w0*!DQEoajJ=B7q9$v}s1b_={g{Bse| z!d`v*1av>3n77yp(d}uYSslJD34V}}IpN&|$;A9Ggq+66hj&9N{1!7bR#wQH_LLaI z**~TRAUiU1!o75Qqdy_45C;>{hn|Ay!NJ6@I2Y9T6*#`PYPP4pF<`Sj{T+U5PqlaA z+EbxW&mLb>-9s(ve5~L-K3Xgej0T%}bDL%a;aX`d2+!7MxDCApxxrkpgHu<)t)|(b zb8GxRi5?F$oro@~`#qoTX0!Vq(wz+s)lu8RXj*uTeE+~Fi2uZI^nF^-&B+@)5SH6n&>ZhUpmCZ0WDa8>Yw ztB%HRm1@;^pniXoG(AUd7pFD3#v{U~8j0x zlFlT(n?D<1@lER8S`?taY`s&)T((s2EPGb(#*vfBWA2bUC@ll7 zUaH`=)Jsc>D=(Fav*23wQe~x~AKZVITZ+W}N4Zr7tiHY)YzAcO_)Ps3;P8&rq0g|q zJG=r_9*w?zHBem>FDx^27WPO2YCBCnMhrF?qrDkk)OVja2WY1Q7NdQDjqEV_?<`86 zM=_v7Ddrbk?9tqTYjfJ+q#X)!D(=SzlFjQGk=5Chb*@M^UN&mQ%9iYwT7cbv?hhh;Gnbz& z>}GCJ*UV+73J(wpm9Nvm(rZ7A8TWUu`c5bAU}=nehKumEXt~ydY1Y4Kl~O+1(Je5v z-dwN~Pz%xZ{gi9|7aA)1${^3(IcZuk&;l}8ZTUCt{;*_F61_QXw{fZR5?kr?}ab@puZ*J=!ag@|T?`)Zv-Qwj;cLkS%|CvP0oX0fSD>Knh?%rb?l zlGpae0r^Pzs;p-vtV0VknNjN@B$OSsJ`cZZ^YUgl;1Fx`gvENoTcFZaARfdUbMvy`9%nf?h!+a7 z3qRHH2+=+?s9e066Ag_Wf%&$b*PkwaQm~x`8)yvaGr5pMv{niR?KEvLn^Lfdo?&Q8 zA&o`N_@bH16MwV`YwiOq7O>C|S8)9ialJ(D$??9qY%~6bf;IknT)eyeAHgf$;9B`#8G_0(|CL=U7g#f8ni2c5+{oV)~YL zHW$C7T7NVg4oxW}yiGX!O~?7Na8?_RLP9P9jZ8j!I?h*wv&L`~5@PvnWRep?*|csD z&M}6g5WU|xvPk<~*D{XhavUOMk2E?K46X8LTQzzS9#&?eYj}#R5*>#xx&niX1cfhF z5IIwSw3097hu?HbZ)*VZe*ZtXi6dB4jK-PPJA8k)Ik8) z!L>T5CT_=kHF}o>3P+cip3~)*LqN^8aEB_Y$^BY*dcJEbfT@k)(Xu?q%bsr(^9dEbrKhqFR*S3(mQWR%LnQd0?xt z^)<2lb6IqIitPkL8n@XN?ffDzoNU*YlyPFdpJHpfRH?H;%@Ea0O-Nb6Ezb9IYh- zlP@5|>X!1kxwsKtCf;CesY1fnGBS;@g5BA85njy>L~3MF5X&DOO^BAbESUkH%%*yR z=do-a!xEP=$~;Cf-8_aj%-uXj<5taA?zzWJQ?xeVaw23+LoB&u8lvP(-&*$JaF~~m z)3>DFRD!Kr87b5E_eoLumK+=U!F`O}l9=iKCtzfBdK~bqPLIdms#D>#=ya2Ewzaj& zLhgQeb~;r&vUU=mj84g9PKrXOU*LlzjEDFH(CWOs^m^3Bi(x_h5&*}WmS2nuEej7V zpWlq-uxl@8u~N}kp;x5nV%$!vFH=mks;JVc{Ha!r?0_fhwCY$ftVFBIDq0oHY4u*^ zy}1_oqaQVO+Keup8kt0=O3ZYsxg6)}(5bMUP9^mgof;|A>CZ?{I+Yw7`oVpo+>#jX zm&&btn|>bzJEPx|foJvm3j9vL^Wnp-oe0PD%P?=v!0v7}`d7+jbIvsjMY()x9ea1? z+b^&@C@xt&g%3Jb8P_~~g1=AkcNc%?xePjb7H&DzAZjfaz1wIX%N@}aRjghD=@;Mz z9npTOjIRV!YEz758x#=4f<>zoda6QW{qjz2f8*uyRt=ZZafPsbRALFMK~GNv{We?a z9a(+0X4=Ic@bNbtpF|!RB)Z}_ggFVq-U$Lp8{vM>kTIxIv*J)&Uz7yF5!e-+ha^(F z51d^$tRWozCF>XJJEfZ!O1@5LF7s<&iqM#S7K=7h)`(bHPx{-vi1Rb85yX<3D_7EX zOSw{@>l=OvJ1SSwT|+-setriuQ+~LtH?90c_*>ft;k2|5e^yqv);p1Tb`^Ag?Pq(Un4@52m_0M^JR7Q0YqkR98l1AR%J9GAa%$(UtOo zt`yVh>L1G7Hg(mcAYEB{iLR7hsw?h*Q?G>WbS25Q=*mc$t{x>x=}NL{=*M*R1kjAG zUIjd>t5@T1)s=9(uBv{IFzDTeuJUFx!PP6pBRl8u$>>Vw7=6EMZRG5R@X9gAoC~!R z(S{t==tHSG8U#xnLX$e=Pt|d*0;?8=P7h7+JXWF(v5Pv4QXCV7lOyGZ#T`iE_EBe) zgwt0}8JwoC8*XUUE#bK&q%UJA(U*v(W2V)nFJU`vEHm$+RF`cY@6oR zz#n#!M)SoF-cO^>m4uUs7LT)@v-TPQH4dbwknk>ML}o%Mj}3?KZOSj&l*_yN3aQ+R z6}h}SmzQimUto#p?CLrp@Gpo3lf5H-x#ji}aT&xH3c4b1L*-~shQ*a7+ZCEVo$k$e z3Cy7C&Q%iLO*UEVICR^;+%d}Z`*{0^lRS`A+YQ<~SP zpVjs`_6B+p z3R1RsK`cykKArz}0yO^Lh2uZ)FO+TbKRU5UCF|Wvr8CddY4OP_LoertbIknO#MF)p zMyKE%W-;(oVVq_dubhr?I^OVPn3rkt4bY4~z)uig#cy;5ff&<`uNM4+2LF)YQ5xwS zPHGxlzjjzQh(CfeyjCO+cPh2PRCUwNHSfc1!^yBf&cP!{-yi4A5lR zxJDSfNXCaoZ!AIfsE2`Cza%>^x6)~-F16x9zY?+yJ}Tede)TBTKdrmh2s`%Kh0 zb*B`?sh(%h*x2H#TSspC!mDfD(5)P`+Dqpg=dqeuU(t z1LeP=AJf5F!iUexJ7y%-ApRR+mX3*;=4o`|9I&RUEX)qC*sjf=Br_XH<9WlZ&1eDZ z?h6*%<3+^bLVi5NH=fB4PrE{E(eO0Tqcok1tZWr>h$i=9%h#CVwhhy=)sxs<5XD)E z0v+XIwYjsg6n_?~#s1xZVPXuCwL~m6BX+a7thl3P^r#4KFUgUL3XmTAI_+{kcPjIt zYvl$PL%js_?nEI{R`%>6@f|^YLVVer0BWG*R49v z+6rdo!qO+tc+rS4zg1SBMHG!0<%wQHsH1cgU{&*12>cCp zKZgGj#1S4=7UGxljoAk7tj)}LoSx&;fQP)8Oi?&pPR>QUw;^;^LH`(llZ+9`IHNtm zi&pT%OBseyZ74mivVg7YWfm*t$NQUkfEB|?GveCZLhf^<$pwqvyq$p#;wk7QqB$S; z#A^lUY6xD6UdL~O`FaI-A-(~3f+=_@dSi+ip8=!k+X)93C*NcdtBWSzjAL{00)GAS zy+Wc*Z0}I^E;KBsqqn3e-3`IZhBSOqe(F4ESEtsQC@vyoic29}PpD4Cd|fbO%QOH% zH9eyf7b`$q3@?~H#q~!D@uVo~^gwtgTMrcQSE^RMd-oviT z@K^H|H2%A8ztdz$^@<07dm5MvdI#jk-+y+pDRs7rIWv~csr#ffibdyB*R)72A?+_2PpB3&- z{1w!4^cqgEMVABiO`@RD1+X=C?|8FE01yR=6>pz$_ z?^~(=4ag#j*F_iFn z5VdC8*$H#9RBR3aT?xP(0J;-^IRNw|0CNDCkpRr`(_rG=h`Uh&8ce)L&ayez%h@4k zGW9OXQwcwaD9F0y{cyeSA5#8|kA#gS}4GH4TOG>0Z_?3Vn*hoDFu z6|5LtLG+Zq&h6Pg1J;E>V%cMMf~RDn4+FH-4F`1;?{oXL+=p;BVJqQ#U0m!#C~w8+ zO0l>j=OOAlxb|}f?dP<>9SF=vgX)B;t2GE$#ArYaf0@iyvU$o!AA!D|Y|65s#!BN+ zwMS-~HsxdIr${tfu(dSrAWffhC*bI#TT7ChyEL^{_W{`h3)h1u6KR@0RfidKB0YXD9I@RS`!!-J}o zzAZHVO~k_xSUM_Yl*>%Pl~%8trVj7+y7>ung;%J}@w(|s`0!Hxc*=(dm^j6UiqsY= z|7Jh4TA|o`)O0Og$mI-ETa-8-s1j#FPCB0^w_nE2$bK$+9T`fs)?(xXQ%c3r4$tXG zpIH{k6oRo&dQN{rQOOkB%HFpC=$Adg;)re`B2#RZT5U5W_@bY{q;8HNW1o&IXWS&r zkQ)0&COuAo$VzsN(Q=Zx~B;hp+6H$X^@QBKIG3JB zeGYu8y`w_x?l|y`m96M+CZ|!CEUJ~uNZw0FUM=PsGK+2d3)tw_dZT_<(zja zi^z<(Y|)jq@6EO?+{kFx3sCv#8X0Baq5N>7vk+ZJoN~m=n64^{QaR#f%_0U`Dn=1( z%kQn^mt}`$e)Be7W&?8fLVb+nGh9%((Th0gU)SjsY`|Qc?ZmRoTb9wUa=T=#J6$!l3 z>YDh;+(Vjz&`bi^ob?wUEL*&-1)eK}JiyS|=*O$&QH72i6ReXz#MD18yW3<(opm`* zTRDyb?B1~v%d_tA?r6w%lma^@FfmkY%oMe%5o3q{UU*1od&;~Q&{=$vH>n}MUp!H%C zx(Ri2Mfr5=#mx}qDpPe?yXQ`ZMY4QoA;j{NY@SKLS_aYgqV1dZ$sgyGfrW0~%`00;wU<+j{4hfoAr9u2x%jFxv@y^U;U-we?KxJhXtW)&+4f zCU`W7^ivO}K$;$kWz%zh*7I6<_DBf7PQD}=TPLw)tcVA(n(@M=v+Y(u63ZL$-$fC+X@G77raUH&GMdntU&P_>wj{zeL0nUWIZ1>RH-mO{ zH)}XbxW3JV-5hjRsfG(0-_eoC>O|JQk!eD0;BF-{tV=;NZtH1IiWWPn;)-_6)m1`TUV zi-Wc3dhUnzbX3MVij|J&BjDIuiJy)&9g5?UQ|xS#W0d1Mq~xL^4pfvnYXh|&cbqY zeGzB69E3gyNg@%)5)fP8>)3qpjMFRdVblGn-A;m#TF$GL`fNn&=3dk7Bwz$A$G#nN5yhkF-iuG>43zFHzm-3R zulGwFvm3@lrLi}7%RVg-t))ESE!@j(JPQ|6(5JCN?y5y#5PDT6xl_zZ!S z!U+9?{C3G!2g;4ufG4);=mgJWCC8_fQv_|4`W-XITw*#wj5>D9;rHNopS{xy>g^H| zBT4SivR+!?YyXgsN_{ex)OkgdfN`f`p>dfE3&myHXP=YG)%Dp@S5td-_P|J4pN+v= z8wX1M4gFZ3-364kAz6%EDe|_yraiM)8GXTMQ}*TK#~5`RV+c+q+K&%=%v1}xoRU^4 zsM-*Q4LJ73^UJ`SL2B$F9N~K0eq(MA~?Jp$j9*_m*ZuB z1yviuFkTEbR=DFuE-u9IJB=4b<0;sD;~<3>8qd+Ey>YO>YKwM3KAIm6_EHxHj|pPo zv8HKmAt!Fdz&-rp{MrMk{TO)7UoA(ty+mIb{=AEtHv(FVP~^P*F2zW`qUY_G69^UQ zrjVN=ZCm@yH=au{+#RA%d*gZf%qTPt_=*Q~v7jR@G^hLZ`34KYy zCLd-zx$`VN;lS*d`FQypVDhoJmBv?qOD>OCS0dk2$mIrtk&B|5T#QDnNKP(tVUCYq zM=&cF#g$z2oi3L+<qr zLvd!<*e)u9@+_eoFO)s(uS`yUWGzN^H^WboUb|) znLojwiPxya-vDvB%4#XnGnKBlQm0|}+%mvQbeFomo4_AAG>E^+mzTX``J?rU$$YoS zwHya(d^W|wP5SWj+ucLW{j9C6(Z}1X9(DcZEVV_jB-Q8Rz1-@okl8SS01E*mhxcvwek?4 z1C{0=5Z z&MW!1DqWOt9OEx$wl3rMBz}s1IgiXZBbV#R4GiV-pSMv4?l3p7Gj5IPXwp1CAsD&GR~WuN!$gw@t)4!yy3FyBDh7ttGAD12(dXw6cJB3~A z-9ji8g!TZ~Qx7T%S;z8_J3mRlFBI@g1st4r=3mW9Z}gCXIQ?Tg`0 zuPz;$JfCvLQLs-k51o81?jRQR=vM@9DiuT8rj*{?Twl%68=ZKq3d#B61Eq09+&YXm zD5j42sSIlFIs_Awv=NhEv0T1U3ESG!j#_&XaPkHVc~cs)lR^ZXywO75oQCYI5C^;f z;Mpuza@{L>5yPtZIL(4*W;}K-$NOKL4U{KZZ=^+K;?wxUUz1zT{^R#+UG4XsP8VWl z;ObrDCvmR9J*>$LQCQ(OnZ0eAJ*zN&_yUeUya5^<%&73$lwjm&54uW~=vFGfJ4^R- z76;~IfxlcY&JQnOO@&c9+Al5y`-5C3lCuZO=M@yD8SPHm*h^AePzb9@i+?dF^O z`w)(`z<7Ar_I-q}=>pYC_2nXc+8Y=1(U@y1^93O$a|B^0Zbk9)1L`GOqbC6s?R zUr^M1tY6I+6gh9dnlC7N-hOSq@V0z>Ayuqkzu|)v!W#Y7r3TWkA=zPO1}A}aR&I>A zf&6hBq<8YI5Uh=ak8=d5(>%`PRWW?K_%V2K4JY+-D<3%T?0v@Wb)ZRFmV$u^`SU(| ztTDtXLBo|;d58|;$GHy0wPg9$ple!z&jIz=W3`GDzC*2ncpLt(V{wOm^G;qOemm_G z{f0``On7)jWul9%=Aoc5!cG<~B=iTr zLoofewite2M>S7!Ao{smiJb{xIQj?Sx)oK2Y;z2)pG{GId=x6A@QN8cmNxzfsKy?6 zF}w}3CDljWks765(Mj}j)MI6S-9s=ItoswF<#0V{@tpv|D{-+^|7U@DUN{rHQNfP@ z-{8+13WxQ^>p8E8tKQ*R8foKPN&Htpj0A;ai@%lySQ9FW;Tiyr*Z;d!Yd%s+yQqv+vi*wLkUl^W8E}Ir>e7Ksq7ww!%~av7{&iX;Bv4o6PzZr z!LQW{$I0%WxLllQgl!9x6K5Vx8uW`f4jh~v#Qy@TfyQz-%9U@k(y}MNLy5CUkEcT4d zEp<4~I*MzYc9uIcIN zNz1YUW?{hvmNaYv7DR$Xl`JAENd-k05ru(WiNoLm3W`WnWC0P7tRgC+A|PNwBuEgH zq@bc8CQwly#s5C1s%vJ4_3?eL@B6NQFPN^r`_!pZr%s)!uC8FZ1M}I4J#Y-Kkz?3K zjsasBUw|bBf8?%A+(-^bBWd#9@6^v4gE4co8}E>NF(dC%EP9`O8+mw$>QDDvx3ee} zL^nFS)4+EP2Mv51k?PoS3)kRaJd%g5()PCzY=RPn=Ku+W($PtX)QrWs!Nq=W9G7Jp z0hv%CBAKydm_@JJbrLziB1dY00v{Fe>+GHuN#iSC;2?J-Aa5jFO!>AV=|G^6OVCpB zLhN5d3mJGTHWPte2SV8XH;CO3eBn$)a^|%jPcg4LO6GcoM2R9+FRkl$T2UEBx45NXNfw5nNGesY&Fa=|G1L%V;CkJrVSfxM|{x>ZQKB)v5tOHQ`f0?kuBPbN+ng zvjX+2l@TMf22v^7=wl;b@pmryR5Hh>X(>=%5`Cr)xsV7y$MIdX{!1}|?34!@!=OLx zWD7ZR1BF|lDC``Io5CekFk`tFee|qiAN5U7@x4$|)2ZVtL4$9MG6tQbPLY-d=@e<` z>mcdt2zX&FTjATaaR3^9tfOPfC_8+#7xgwUu;L8v18vsi!U+vggsV`}>IAX(k^cBU zL7f)tgp!u!ZwMMQtd4hq;B9!$HWD5KYcawnky@iPiHv0gy-f5gkxsS)ZZ=5AgcZJn ze5eH80`Ht=96`p85F>R@aU;Zr?|Ged@O8WpvMmOOQQDc{mom~eiW)eh(Ox`OzKXBoj`l-X3Q_IMrs z=v7>E-Q&Lot8CZ!Z*U1Bj-{SNz69WI_8~Ol4&Mt|tI^x9 z7-qGylMFr`D~fn>MjBPr=itK6Wf6OGt7PupwX0?3z<~o>%Mf}{t&45|uk6Ya9XRlG zt4!bFnpbD)N5M{5eL{v&{|z<_DG?cluR2U8m`5i66$Ea&j;yY*I#9khf(cL;3)u8Y zJo4m>GJ;v~(NQrWBRl2pd6+ z7@{zP^GJ`bV0TCZpd0|InFyq*~DhN9%<36WWY2uG0apAQ! z;P5CVxq|5XqW6(h?P|dY-sH{N;JS5dB!plw8IpR~SU+sDO+F;^Le<5nA66exxN{KR z+X{|>((pFRPI&+L^2qA=vv|xiY>DoY^#!67twRQC7t@nqbXo>cV=F{>PWte~1Kr%W z$5yyR$ZPw_AIUx8wxV96e~u@-Xg4?k%W^TP6zf&L2WH8Y*4Pi$%tqITpb8PXli{?; zNQASd;>dcnzb5SpN;|ZgMJJFx&gY7N0O#4`e6zFry|O2Jh5XY z+RAjfhbQ{Ka=TNL=Hc2sU-=A8`w<>1w{IV(X&3%Lsw=w^h6NM@mt?Sz_I0DV($uj# z8M7@Y&NkDVm+}^!<;)@!I-N(3Z3l`Wda`9jCh*lAnJDjh_t3~BzVS@ISKdyRw~>eV ziWNE%o+57}5Azjz;6CbLM)C7BBaNu;7~h8^vGipP`k0x{-O~~ z1tA&*(RQQ}%yuC4%l3!XFqB7mbGk$|9p`dO4PXW+j}EA~bSvdy{a^!FpWNoOf@ZI= zcsfegXO*TSjK1udMc>NoOeayT2+p05;;~)yf_!dUK2F$H11(dL94%R-lqgw+N{2e^ zW)aMjR5g=$$Es?UOeL@A0@br0V8n7Y3v;3zwp5-$-9ESp?p580gMe zbo?8jrJXtON@*7UEFY1YIUf^orF=l@;iaX_vHjp=}8Bab6h)rHvBM;f-ewQHxRt)3ZK+ciexfk1ouq?cmqqkxuq{X30kx%!2$Y7f)~w!8qC7G>Uf4(vS=n(Qk^su4Ni|FjjTcDv7X(o zAk8q>)4rz!Q?Wf5U)?cMU>Fi>@sgp3MhP5(TBJI>$=;l9fmC01+hi-*Cv%(ZwnI`O zRbn1_NhiZ{(n>2RUQ1ibDBC0nm@3Kos2Wn&1LvgVzSf0O}! z_toj|_E07~(05)N54V9nR8y+pH6;zzVRkX)FqVb)?^F|~D$HMMS7Xg+U$$ZTlv_!0 zSixkfk7xr}#nha*IUlLkiKZtSr@9MotOqw(AGjp>?@?UI?y;DGNH4hb?MjHbqV8tV z*g_YAY;6ya9PD*~T(B{q_+q_aPMVYwh04vQN4kP&=|$Z^P7O_}T|`c~7=IBTiE>st z3L%ZIP#I??geVpiWFu$uQcl-hs=TG1vMMOM&sVnOG#inV&vEk3y4cE!iVTe^Y%I}f z%||7oJ6SJLdCu8w$yJDt4StiI)B>l`{LorXObzwqcs%?C0q=d~)T|?~SI#=(;Y8Xj z>yU+AkDQTff?81HEi6|Fsbls_=)_=Ri5koZAgpeIyu9?0W|rSq;iIT z=X?6)T!jBX2-98p%DM1oSC>@o&@9v}lViv*J!g@u{9`=Rh?w&jLmQ-rvFl{WNUSj= zM|?Sx)txdj=P^NL(Bp~8pqYORbEBA7hQXr3iB(F46Z;SG$4mFaC@f5L3DV)Ea!L0!x_0mmq3-^oe9FaH}W?z%qyxv%q>5{ z?F)yOj)&xmsu5@IkJ$Yjqwq11MZAb&RQF$r2^BsH7S#r2?ZOY}Svdd^e++s-qX~ra zWI?QhPpjq&enlT~>*H$*H>i0CT(TDK6R6`9#8W5rkI37 zZW>c=f)vK~(80sdZ&tV92y{Af;W!RJ(=^D#c3lw(A*($6gKPL(R4*{Nniw=72Gfh0 zBV5}VYJ=#JJU|Gep|wH*M2*xZn*72mvOL4mf;f-Lmo*-z+X3Y5TXL zXraFx%?P7i(>WV*7!IGkB;7l-g$2<$iz<;u^NQ{w5gz5dID>DZ7GM^LGx!OaI#V>k zhr?-j%mZ+kh@tLi!xA1L#8e>(IitJe%b1;=ECD{{BD#E4&np^2$xWx^@}0rT5TVGV zT}Pzt;@h*p$K2$i!JxwHP=sS*6?Qf@^0^OKQ95D-kC2_9-pv6UeAUEnpR9?fFth01 z47CBn2%!kKr7+P!%uom1NO~hU4BU7G6thOgQN&Auad1>TxC5<>ATghyczMn+J+4N@ zFQRF_YSx5o3^6j@!AMu363z zIOWrkQ(0co9A1G~Rwx6%Qj--_X~FNJfyqWGgqMORzI9Sk7)yt>I!CNU2S7e2KLFn^ zFpiR3R1It}OdhFDOr4P$xESFF5RtYYq$FzMCsYeRb!gr{k%dPQ_h}>?77o$l`H8UC z`Iy&;2f-Kc6Ml|PP4vGEOXacnZp* z&r0xgw0;UpLe$Lm`y!h_Y&h?Wyh&FxvY9TJD!q}fuE;jJx*}U}fddK?6*o#806@{{ z0mY*$6Xq4IB01h>VrKLb_z4n5r;?`cQg9OJg*N^94#jd?DMQe<8W9}2i_9z~{g6_s8X6*&O8u52V zti1?;6knBC3Y@wKx~9kR)ChlwAkR!S!i0us5e6$9(`xu&(!55PcUl%zueMbE}+U%Ho*ljxL6$-I(cE|0im;U%5D z+Lx4rsjbY5<+l%bpuET&#R$UFPFs8QijB3TTJ#Xw#;n(90!7h(^iTMY)@wu)ru7;u zXiH>)%!G8nJ`9tY1iE*sEaco(D&x4htIUe$uD*c8=`$UbS%iKN-bG>38#j{cL4m3e zq{>~7>OLy>tr)jJOUQGmsUl#V?E%mSv+%qQh&Lln@j)OoX^`tpYkY~Nsn>^yY%6S& z<^vw4n~%_{)sdUzJGk8bJ=I( z3P(?C#AxjjNXfd1))Sr&(wq#~T|RD60|-S8z_LA?CL0?BH3AxGOcb8*OvK1_R>-a| zgX6CR%spyS-6g9DZi}uWteBnzkHL2YkK-rO6t|x60#NY`Lr-`PajNVIE~k3RpZ4j{ zwF<#zAS{>NB>q9+bLhXxSh4%s()MbyU&8T>qUMMmX@MUjOuwP4Dd-KgB)AoYQBx_K zO>yQ59SuNOs5L!pLr-O-wg~d~@OB7z!cRfeCVephg-F8J;3u*OkPTc*z|#PN9U+aa z%}Ta5@ePCb9H3Mc|LdYbmQONn50p-Uk?y$}x+`#Nq<5@u?0`!%+S)SN96{}^q{*#< zTWWV@^O%cM>G?Lhe1&Z6w8E6!jM6s(O=EGlEt^h(q>gZ^+Y_7u>BHFW!Ix7hIrdiW zGTaPP?t~{i8$>ycgZSnsd!d*>L`?+uK!abPlT!2-YFDa9QeyHV<|X=?ZR5CPH#y~O zA(}tW;Iz^p+C)s@lsU_(>Iw7X3i67nmK~u2nk|~0Gdz}xIb)MxGB8keA}UNL&CcoK z3D2bjvgDPI9OIczg@ zf6)oBR3lN;1bfmVRFO)Req~kqCotQCgP`RqRDo*(?#Mcuj`@>#bwQ99+{OCuH&6-b zf2{wOCPZnH|7MYF|4lU*9`6Wwzl-Gk;A20B8h~}hqvCK9o>RZEGqjBJc`!fXW{d+H zVH^y|Upt(kTX0YNt{LHnfT&Q;A#7*a4Po0^60V%3d`Cc=DsVUx_)H@f-MC<)Tl=D<2@l?YcsQyu`aq?N zBLR`AC<(@Vs>h1-Gi=gr$*mi5&_z|#$D%Ud4=UMu*wC$eo9doP5GasXqK zRl==cE^e}3#?}eA2K(VBjAJQ$x#gfBY@F^3enDBbZ@!G?pXLZ%o>t$Ov~G<_i|~I> z3-hL&h>y3sY*aX&P#TXXYi_G~YmE}~D;7rKDwV^rjXoVjm z%)!fA5JY=Rq;$On9`MDMnmfX-N=Q59ot$xZ=qCM{O!Lt$SnA8XS`r;s2f% zR}VWat~mcKt@~oqx<4i@!v8%jt{!$;Tyg$eT0>&e8XA)p;s2f%R}VWat~fHSXkEFE zRE;z6O4SttW9kaM(3h$!SaONSvaZbKu-w4}2-TG*7&5}wf{nC3vN&B=t|m_$BKiNN zt}HUbHxP^KDK@opI2aH?BisYO(H2j&Az!1mVL-OjcOxrw9iruUtx$VhaR54P9Emwm zSg66DvWBCzqmMxNOpLw)Ho2<=(Q_KerysS$X{7SJ3SUQdn9USS5);ChEUkjVt5MSN;kSH+Vv|~5S_B)m zf|Di-O@f?tXy9cm$Z5e(7*{O#8ArDpqpRXF8ln3d0f?gnjNo_#B6KG)Ug1=SY}P6M zgM46pA?$7oiQ57rdOWz2>&SBYvOCL!tk8pqj8}e6R^Ek+0r56rYJs1}2u=V*=0(Cu zsz78Sh2?Iz1c!DZnfz5T$zg80I%;AlY%i^kKO3(SS{OWatH2#cYHhTXL6M_NdD7_m=xt;arU>GzIp~ra7F$I=V7`AX&?2N3B+l^x8cGRS13t~i(X1hX80p#;hs+gWMfa}RK^Ov^Wvqyry@Pv6*X#`rk{%K~yhrUnW;oCw0rUJT(jI!rCT&I< ztC*NO8YPL*Q(B*YEMm+AC(Q-VK}H&m$iciKHa%?#^m!pCLE1&|QP3uMDg?g+xy+rF z|P!_8C6-F>BkyA3_5Das@~mYi=uTN#~?Hfg5?HO;Wv(D zkzMCsBU_Xqt}}tFdtnG!MhJdSP^ePR$NjG|eH6rqAJie^)gO3Nsk zLqV$lMoprlRhf}@QEKY#*S*Q&);kUX~CyJUMCBEt>U))lNQ`TJ+LrpRB$wU`u-Fw*a+e~oe!5exI{^Vs|aO2G>hBFb7%-sX%NI+ML>#Gb@U#&LkS2I z;7JmKoxbrD7b6DD&KwY?5Lq+1+^m$9gLvy~!Gi z599N3hcS}{xD>xml{K%ZQ3YWY_eD!hV^eML<({?_>Q7BMjR6~Be2vH64)_U#7NJ>H z!0iA+7QIdo3XgDcR_kL^H4skrB~L+aMaXIM~Q z6z5-3v}O>-PG?N%bV@%*I`sUqbfQ!$ozv*&5Me4@I61s=bi-c^Xgis-(BrToiH7f{ z1oxu*z~iv8PZZSy_JAlYA2w--)kEp$;7QLflP^l8h{(QnO z05|}V7{_$}%b*Gsqx|!?WEFmdP4DC$CWS_}XIQnyA?$+TE1m>%V8ZO2Bm|y!Gd}Dle7_&*W*bWnF=0-m0Va~#q}Faat-YAK#WNb zynBMY#|lmtnibXPK1LL*?|rf4+Yl!QJ8wrB5E7aSXU6?MbTV02lA`eJ|0LbC|DNtN zN?;HBs?w?cFXRY7&;OeLO8*b!_{9)nDf|zuHJ$;LhNqEUORt;_R>w<^di*%ia5l@J z3I0SKfEu8teKMzmG`I-X8hi#n&Gta^moZ@z4WVv?+Fs#u&E75%Rn$!c;LBi>Wx ze|MZM~L2wmH8U2Dm)GwF`L(S^zl>4|O$ZLoc z$#Y*!5gqrLLzROJ2M4qwXuIbj)IRTmkHjYo!u7aMsc{*|#POqUIk*&-6zi3v&)Ku> zk&RXp9107rm4fF{y=Y1V-33bBrO7+lrj#k~+!%RB#K=o{jJ!0@Nwp<-EsDy+%}9m+ zBI|xBE468u$tkcM2ipI6U>?VWTNz$EN)xX$EjWrYsAN5nyExDikWY;8Q{WX#i<9y! z9vG01u(H{YX5MaJ9{B%528-W&_W;S!ckcL z9KpH?bswL<$doc4O{T1KvqRhMrS*wS)@0}{7Tcv8p_V$9C0Q;ACfEdWHVXGcp8KEc ztL}d-GwvNl3+_N{`c!0CZ5~tLrE`*x9Z{&5l^)A3^R(V}Nt3OOhTN0rOh>9pXv4~| zrKrVWcPVRWT0(YRY#UM*rH8$<%mHt{f`u;m$U#}A=a%L+vh1f$+Zapt@uJd6Co&(I zwVlX#yHwyr2v?P|uL)5B6P5v>l@irm}~}`AcKp^BXZbPBcJ&IiFH7*%luRS>_F?3#8w_*^> ztCURRoQn=KHZY9aJJSx}97`ax($VK>nlPk(6R<2cX za+N_9BbP%|Ls>-leRVa`<1upjLKA3wg9jN4d+6b?Oo$1%>7wP7**K0zIwIS)A=Ospcg6nE@l&0>bW!^lLoUk#TKLBQ8^KA1^~ES3l} zs)!r9DVk|$KROyT%1%+-p(Kc!jmbXz{97cNbBkNH&Igbqo(-Iko##G;+q1vkhpJ!;{KtD{HDE&P2C)9`ct}W0>F_ut~slZSE)A|DG<7j+~ z{)})hO6(*O3+E#gd*2)Pfmnd;wh_?aLCga;!dP?V)BOcQP&KDN1A~-A^cDn)P{Y@D6PQpWNX1i*UU;UHPJ3NsIARYUdX! z59*QRWwSluD<>k^t-;#}+pPiN7S|!#87#^{>URRAM;~7+6#t6k=zy1hB%vX|mp~s3 z(CB7oY+Z*20{(*9=T{^$X8x zzwe^#{sUoS=1pM#JOI=3$X~^bokpqDcrSR6FX@Zx8u$_nVYV~Ef5r2P1GrnfoOsjJ zw|7tumn9U9!3jM_TKyYrjqoM>23slZ#X#>+?pj`s@4#%mvT&Z{Q3m}Yd_O6Ro+o*f zLC=#s%D{P&M;SOz@?ab$g^g>a){U?O!D(ni9dbbg>D3Ul2g7sRz8g_W9ps_)~9RS&M%XojxQ`lvRY%qzl{rB*Rkyz;&p zF7X3odtTN%>=~MYIL5dHJhg&*P^RG=0Kt6-p(|I8V0Wp>BE3_&1is9O7bx$%U#iS|5~Om+3x6M#FXlv|AmQFS0MD zcroX=qAxCR>?kcJn}ZA1HV^^tUY%eB_d;6C)}y0@eUU6Yz?`fcT$;X&XuMx_7+=Am zQUXI)VhIlKxPo~n*h|Bgo5}lOqkl(_6pamD?~1$zEM z;A9VHQgr zKeED0mJha6v=^e)E~Y0zyd`9ZKEiz@7q_(TjuNErWpp3fhbO7Ns70js*oZ@zL_jNH zS;k6A#uK@AbQPJG&2BJgUqvD&hVm5L1Ttv;HW0g(>Ur2H{YSgTf3y~sgpu56EftGI zFW)pJlhQ{0O$D!F+9?F#{gAf!0DfXB*+IIETlY*@TpjxuP?>eiEy`n&<~pup6c1vI z!zFI*=4jNLZCD3}>UIhjNKUjKIq{FyZXUudN|R8O=9VapUb}giBhW;v&?g+E*;S!W zIY^TMb5lQ}iGDnH+g^a#APT9amqhvBmR@?on~9fP97@6QN00&=2r2H8brip9aVR~B zSsZ!{w`%F;aSDd%x75b-OS6}N z{6AT`8OAx$zMNF7+T@U0u!$81Sg^T`9{u}*O|PU(_R0mDDIAvyFlNE#U#K^p@W#^M zHvsig%xda!n!LgTcSOc{!Dcg@uUd+bnPabDDt8ceB0^fT*=#N+L*@x(kxeeApU~$3 zawDGbJCr`wbJF#n)^pM`wVty}EE5k;{VX~OREGWo1je5R|MJQOGcGVXLnYAzN>n!wW&b zL@<6GzXcyb|6_d@^I`iZ-^GI2zKgs;R=b-zx5LaHC{qYJ3uI(|UW2?V8(fut6(KI3 zlk?k$rl>hyh`V>0qA_N1*1YL~!h46_Q$!T=FhX0L?GZI^xk*&|Ig!uOsoCL{PS@gD z5chXu`>X8I(X*~Xr-%Ub%=A#(j@3TWi?+J18 z3c}KM+MxsBEU|A6*rEFoLt?M!(B>UBb|tucLqmsR&^vZ$zT%Q7I)lq@OfF3nQ$Z&~ z5j>@kCH|=D5cii*=rv$6R1wne`Gv4l@RK>3`?^C(KXRMQnQBg>&=PHAFe;(eKOEarn$DMKA7$lHcEME@6YC+^)ZF-t71X{WXh%d@1`zI#>1 z4T#S8R7)`e;`!w=lp-p>ZS&i=Uh?ya%IKkWmgzb-^dNG)AV zts-NjV_mllSz^~(+t%KOq@>9d(R`;J_x2C%&_in_mlWaASO)Sd(^!EDKp{)CP+WZC z)Rj_00kOT%)@hXiG6Y#r9;DM0F;3+&T`Yq&No>1LqrDD2f_|b*?LjTyyE>O0v|gqT zlXWutYi7 z#><~ls1A-oSd9`3h&*UR+WjEJpmY<(W3V-8S0yTBi6*Ei#Lp)Vf}fOXmM#SY-a|ee ztnAb$KJ947=ns3APj_qVCXKytqs{O5Ry!o1N%Ay_;uqwcWC;kW`y^?m*i%v3c)IvA zVB1=&mt?7CiZql3l?UiH*d=pb%iL6Ha+I!(mWV)q(p#+jLF&a48}5;z77n}CT4LHc zDOHAOjhX4B=S;f+cE6{{lZL^U(ti5jsses0EqH5>v!TRc7>m-3y#WIzg8;`m-^5hK>`#V{HJ48<@vW|TClQjhHV-vV+M0oSL^hr%W}tkfXZ>0EwM=mz zB#s-~Y7JC>d#|F=mFH zMisPb(*GT6YKO+WVE0PTYHXVh?NOn0arJSTn%~@l9MPZOT&6-(%#H;T%M|acGRhRU zb+CQdR`?C+&GxB!o+%bJvdi*b^VgYRK7h$e5-41 zCYE-{l6e`{K-#c`Yo=W?^Hmw8h;=&dXdUwCP*};5B3dfH77&s5r2deaw)?p{Mi1Qw zeo*`3Gw>j?XH-pjy?}THb}H+_Bo#^#VMP}Z8#mi&?9pkwrn!8qd!;$L2YNvDeNsdP zja|^#1{Dg3-rz^+;scqkzpZr)@&{7VSu1UsD=HnNiy1DdNvyQiap&o{-DlZx2R?0w z7OFa!B09mtNzUzc8!%pDUuiB?RSBku`ugcW9a;nLBe_h_oExjU9}w@M-I6-32|Ja! zOwzi#SI4ChP01xuV>z1c5sm$<>4FLih&H;eKG)VxqtypCzlK`+ZrVDZ)i(5z&SfWE zmKT)t@ZQRIrikBl8`@VtEkW%jnJrPlFMSF6toPtR=mO#;XpMA` zE{eaD{vbotZe;uW)-CN&*EV)&ylSU2#EW0a)*wS{87H5nSySM{=+6?jsQ!4mNLX)s znvavDHWI}xD1GwO+17=}q!*}bc2u4!;ahK8C%lnI@IDt`7~Xuzs(^Qa-Zvcw9WzGmKc?7_gR1W z*7nbjz+PmFb1%41C{euql-=T_&XXaG6@ZR>d%74mSxS{C)+;(otUhR$%*VG$sS?E= z6*nLryWP(Dy@)|M4~W*&B^D4>Kau*&5bvrUMFu7e$#i{U!9w{a91t_oBwawXP`#0W z7=K=3cw;#ty<@t#YKD|AT?D|H{9lIn`eB{!CYuY5!b?4m1{b1B7snvIY(L)o!j|vv z(ULAv{0IF5*%G%#%S54cu>hWxV!)5XUg)hYLpZ>hdVQJVD6oCphx_<~EsFyove-;f z(oD*nC@w&=#Lp5h!#`6g1jJq6NeL`5JKOHVJ^7;@YTiWBC5n1TL(1|eN}6P`M82}q z4ABX7l{9W)sL3w#iYg6DG=0P_)yI_%GQ}3iC)=o073$)?SR$=6QCw81C5qOnd@V5- zeG8H~T}0~Hx!i)fMLNJp%>DAIB_7b}Zi1w;r?6c2vp++vkd{~%8vn8i#r2M{Tj!r1 zx8Gg98X~wKYl+^9UyA6We3&I_pf*Y?-mN92bE9OrSy^_-fwvurjZ#=Zd|wrMf01-Q zElbv!fGB8fhYohMLw&o+P^K6%R_ZDs1{B$L^&*~#AkwDfAg+=+oD5PUMW?gsG{sDAU2_vk))ZT?NO<}bg>&XnK-A2>-NgFF61B_^rz4TwZ={SV%e(#1l&FQmOgUinvL#r@q!RBzJ~7r|9p z`%w6HvgZsjMf+G&_193(bsEpiuuH$2u7kHif3so97*mBc$$s&$$85S^QK}MaqOtZW zlqtHPB_?l?DEvwu(Qtu%{^n^`P4ag7+kYCvf-KI(v zZ`LS%Dx-9pRbkWmLgmj5hi{CF-6&UhB%Irk(OA$fgN|6vM|^Se7*EE zmryb?^tdX^4B^64ikl(cMoG)iS-i2x&|3I93Z;mx%9<>3`fJq7Pf2S*^4 zgd~cZq5~355>u=Tu>~$8(`)B1mtu9+Im6?M13(_OhBxqs0R|s7b6+T#2A*1jAs4JQ#4&g zBQchdMW};B(;cgGB4P>B&pF3Ba^XcT-ay+%X_bif;sx*#q89qCghU)&#EZ`iXJ_SJDU_J)Cmqcz6KXO`!?v}`6F+li`c#_x)FHbb{#6Xec zpj`Z*kOFa!sKChkDy?}ysxWd~@gbV3%*VRR=5vpz#z>bIq+_R5j*+o3sV5p_3CER$Js?kcgKX?KZBdIv1x8N6uM(fW;#pCfk)?x`J0raml7~9k%OD-ztaZ2!UyqA{JOlqMwYpB+!?8Y4sTYWs#UPH=OtpFi zVguI1kme33+jzjSL(Jh=M|Vj+s~vmAe1mFb+v{ZB3&cLLfRU-_Ur<_i<5TexMv7Eg zW5vhfSw@y>nnU-7?-?FwY`5}JCE{zbgJU&rZ*x8) zb~3VgyNz7Hssk$1b~|kS{34FBJl|>W_p3O@Iqk0GDZoi=rx@9%bMdSAlKI@)K=Nto zyeQ5v;>X(x-4Mw)2r$)$Xqq3tO$LgtC;mXd+*kg|*yybIAa|MtbM(Qa(>y7G;<{ax2 zj8;o|ava@Q<|YSinOiw-;(V1?8Y{rb7}%v7GJCYf+Bo_#O2hx<0-Wu8N=x&m2jM08$mt!E)jK(`UaXuoB zJ03SFUs<}h^QB|HN!GGPdy+353rw=8jTl{%62kK`pFJw4Ctw|$7&)boQzFA~yC|nG zuas#;95s!~E=LU^uG9LdM+kh>zCM!Xv}kD5b$M$fiAX<*l!%tbRjwtV$;pt25N(Xs zjI2`nA>=xwl_b7tDY2=`N8vKz1{db(=)8 zfb39AzZ% zx#WC>vxjklOQ%;SnXmSaA|uJ7d^OZ{d6W^bs03>(nr@DVjCxivko&Z4Of~9*CP^%7 zDLMCaEHRofpLcXCv&3l0$cr&ZD~oJw=3O#Y0os_>7HR$$Ri*`KW3FM&TNLMhj%7wS zMjleg03bIY7QPE9e>f0GccwX^Xa+l$8@E_XK=YJBux8%q%gAYMKP!xWEMcu2Tb>oh zoscj|OuIXZ3}6XYXs^D)kVuL008O1Mje9Jzx)s03SS4r$2Q%mH+OxfAjDv(i?1hIR ztBW|+8O6+bR-r^%IyNZe5mj@OoEwaXnC1cPdp8)5GO|O_R07T8TsjxF+A?o2W;4>U zmW{k-Ji)0ywn3JA#POOj7kn^(sJ=v+IyW+sB%W*|k&%u~#zI-92PCrEvDsL{so!&} z&3Uu2lr=U|w_jV0wH#}1O-VCLY&AA;th!o67Fz*X#B=V zSLG85#6hEyn=HJqYA*`J$3|5*SybRjTf)OeBRAEZLEU8P1>&&Lm}7mbE$S2FYDOmf zZp(AlxZh2huQA7tRnEDUX^z&DNU^h~GtooVat}uPq_te-Y{|&`+iau-5UM-f)w@iA zxQ1weTzpv4%yf2eUdPCx8030JUW!3(VI)bv6Loa<^H5H+bXjzC4rJtls&Sar=)8wh zzf<|u0w9AJ>92J7yz_SFJjk3R>MJk0$T7(I3a2$id!)h6%^s?8l_Iu&20OPi&DDxV z7(<*p8M&>EO*6!~&qFnC%(oIL5h3Sipb?^LTbcJ2jw0t*;4H-NDi;M}wDVgJ^{5}! zwmQlAGpGKj?jucd{>Hi3jj=x2>P>R~&bg?p@^#GlkW+X`KVK;tAtpP$Udm}BZ9kKp z<-C-y(Yg;g)fr#}FG7m*RA-tu2{dPPE~YxOz0@Cj>j#@=ma`$ce?nBpHzX;~lg>6? z%Ee2X^HS%n9BXa19c!ucPOm_;l$jEVp!ahRBRyu=$a+GMR&~{DGL1KYko|nB`)r$? zgPF!T*C8&gqj7)_ouj;Db&Cc%#EfMQajm)6`4Go?Fa~*yky{l~6*My#*&Kt+hRTw} z>W^_EBKVZRGd{^k*T*I25^=zZuY#aCkNQqDs~snt&vNR!yGoh@@wsyu)6~e3G)>J@ z&NrFQWR#BN{Dt!^#1i5|m3o0V@7#x2LcCv3#>zGSbe>@ex89EfZYxnv|8#x_M2Kq( zY~*j}Ph9Tn6b(k)%s&~)S2TqD#Tsi-Q^uMF#0d>2i6(o{T>|IT4wq>%av1rt5f=@e zh}CyWB;s(J7SnvLsN*BcQiKJGO|c7|fU zj<)7ajNG7*(~fJ*UX1Ki$XQ1R^EO6WDCBz}{TZ>8#?CuBns+fWNYVTXq=2>Ymy)?a zbTtPvvP98*VqR~K^-(?j2(4A--!$Ud-F%e!{9er=);;VHKbw8b8H|*x9!2Ic(g<%` zL{lL8n2Q-1fKgeA+-5H0w60LG3PeA171NB?Gy~1;jQo7ijy1^K;iLDRDphRcK64ja zRLfZsi8zLsyAex>pYZNLY5n0C#t1B`g+mPg4*tv)F^@6l>KYku(g=T&SgVn#=4nQ* z)5vu53?qXyGSfWAx!9%QOw(V}JWB{H({ak?yu$p8V-0{ema$$nQ~Xqdik4sA zawue@naVVaif!aQvjQWdbgU1|ij0f_56S04Gr&lF9czz?vy+k5Va<83na;=yOYPM6 znN=AX_pFT^Ft1>wKqH6D3`VBu)DN50{8T!p&=;lDR~w(2)fsUo*vL_{1|wH&u#ppH zCL=3#tk2AvjNGbePMWnCxmqJ%n6(+{^PZG&wc|^(4kPD3u#s=fAR~vfY;Bw|>-nk0 z|0!%EKbqN0(+i$lYV3k}CFg7TaU1#5Y{5vo- z1zP6%uHlRv(P=es6)}>x%r507uF;H`8foep$H-5bPcv79kv2ZfYMKJqbU%$F_0Y&L*9@j9)||(;9Yat_VYHiGLJX zXvA;rXXI*~uW}YnX9b_5T8GIN4q^rJuFh$yg=1HNJgL(PSf4U-gSM7*>j--!|D)2v z*Bj~9d8Rp}`CMV8BoLqDT0ga{R7Q4aKJ~2%j6A00X<(%>awe1gIux?GDcfHklHu9=fz{m-_cS{es!5YYX)?Q~LuUYq? zMNSff-^P17dW@?b+pUoa)JvI&(VlOXVGan!O-3=zDTVlq-PRPQIf9W%qDeINS#y}C zPfv-Y0C|#;tTqzCmm}*bM!vXNA_3!LYXS4Ar;v0Y&oI(eAsHBdS;?^;P@FT3Bi0&5 zhV_zs>Hv8j2-eN2SXn^UGM}D`CeJuwy~MFTRDAM{udHp1Eb1-!G%?OvZ!>Z~#_K3w z!gwwHc|dVof*F-1QjgsAy&zRopp@oL8Ek z3nZ`H1f8-3~1CY*)j8e!(AlEZ;jf%AeNOwlMs`Abr+Ba=qen)@bM+&dAk@&-WNPeSnc3iqCoDO7|$Xgtt`b z{Ayg~9?Qt<81W!G{KIJLevo5LQhC2*+~A(fNI>PnaNgj4gpo~39t+4+MlzIsd_bl# z@}!b55y*5#8YmCogb7yb& zYL3-h(X?_7bgyTcxvHkLbKdKIjcIOHwX(f)u=@>0!iuJ|^FBA`K_acAicdG^{qDCI zc}4kz9zeD+QlgNa&XD^(M%pUP_jMM!KV;;*%6mT`yBSGRmN@{(UPg8+Z43mmkC8W2 z=?n&PfRRjI*_k8R%?aKc81+&7-^>Ld8{MiKF7!gWgByy5%&+w zr@l&yXntbk+D^8oEq4FLeypOVnddH-NM3Zg(&2pPJa_p-Dz7`0o)-a0Vwx$+lPm?2 z!pKuf&nuiI?uv=zAk0? z@)FyDv}R<6qInNUTSodRnw>zdVWftl*#qP{Mh+@uKadWL%v1e@LqIw)@}@$L0O`WW z35A>hay=t0Ra&Qj+`vehLQVs@kxS>IYCX>axru3Rz$hQ(0<#F*y_lv@*~a(I#qQo* zUYQG~+bQ zSvS6Kg61pD=dAlFgRtNS-b zS}U5tK>lE)o0j=k_n(ZI%8v~N&EJe%Q1TQ4ag--*c$HTl3B*~RbofL)+gg5gyULT- z`s|=xzy5Gr0d7^#1a zMAiVgk&!=CthJ`sb2B5aw39S11L?`ghHE9V!Ss3hFfvsk8-d))$Y+Z479h7X;#R3| zH~pSF7-^(py=NwP?qXz)inY@$=NZVzor-3UndrHfkvA00ejxWT@|mJJWR~{~WyGV9 zBW99kI3vSUtP^Ik=K;2aB!!$ZQ#_*>X{~a4+D!F~Wn`K{&H@?7d7w|Y z2U5()Aw~16S-V#zGay%a}LSJts(!jHuC9Jz!(yVs0@Eqo}dRDd5YU%l; zyg=%SYUM(KXz4jt-iKWL+ypTGO2joloHZ~%^KJ%^(@um`$IRFtB@MoadA=;~M9qB} zK9l}@qL=4%T&!C?XUaRld5vN78RWTG-av#0pO&#Aj=`Qkn9q@IHqB5%5Noy1Mv6TD zVPsNu8yW5SlaVydd7S4`TyC zm{smcildq8sg&eLTK%4qG$mr1rwVf(;*v;#n68jdEgPBTxq@k;Ii2IF#z;T6O*7Y1 zgAp1zr@sPG;;G5VVa@qzPi;o}du^H}p1O=g^S;beFHYtao*b6BBuAD-iCE>S&#|_r z*nHL~q)6-ec~3*832U0Qo<@vd2S)xY5HEU~#HF>)(~M~fHOa>g?}PCpksVUAVx znAB>4_}Mc)X%cMp2A7Ro^gPI#PyfZ%JRuW7^Th?5<_{pHHGj$TFsB~Xv*De_NPSuk zguepe^iEHr`o49&L?RBacP`UJZM8fhrOGtPJ1@x(k6ic^)}VKi#V+}wVtbc7bh98D0^3y0#U=el#yyzNX`YKruSJ!9FIzw3q)P-GDcp6 z7o|U}UGgrEOTD3Y1*g?pd#w)M&2cmxy>BrMx?_q@SMNJf^nhdn+ZAr;V2B3~v=iqF!sJH-nM=)tL?W%<B3?@);+p*zvAt{NYs8_ z^WG2_>vivqO!HW>oz`34K8#dKwUKS!TjOGV;O)mW(R#YudzVZLzSo6S%=A|xI{GT7kbWk0 zvym>oD^kcOoYo$oyDuZ9wBP9NtHGSdX=}O3SDTTiHPYLc8yD+#-<2s;%HFLqtz69L zY8pq=-*+|3vs1MNCE`wBYvw#r*QUFGkj#&MYinbOuLH|m3vW{NS0F+_D6Q1342WDa z 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 z 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
  • 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 z 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

    ?k^!5ccmGX`>p)G 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¥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
    +hEE^tMvN_98p~1FYSae$MMg{ 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%0ASW4C{Ao_7RL-8gFQg#FmoS%|>T7Cg!QsQZWYH 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¥ypWRO-Pd7XpH@bocj9+g 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 egZ$Tj{^J_~__K`BdkFRTg-J|P|!2b`psH!Re literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.dll.mdb b/Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.dll.mdb new file mode 100644 index 0000000000000000000000000000000000000000..ddfa4aaa8c53163e0b200e21f903723875e00aba GIT binary patch literal 363782 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⩔fAJHh>XHDei;v;5d6|1CtCO?*#a-6Ko^` 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 e#EopqO>Du + + + Sirenix.OdinInspector.Editor + + + +

    + An ActionResolver resolves a string to an action, given an InspectorProperty instance to use as context. Call to get an instance of an ActionResolver. + Action resolvers are a globally extendable system that can be hooked into and modified or changed by creating and registering an . + See Odin's tutorials for details and examples of how to use ActionResolvers. + + + + + The context of this ActionResolver, containing all of its configurations and values it needs to function. For performance and simplicity reasons, this is a single very large struct that is passed around by ref to anything that needs it. + + + + + The delegate that executes the actual action. You should not call this manually, but instead call . + + + + + The current error message that the resolver has, or null if there is no error message. This is a shortcut for writing "resolver.Context.ErrorMessage". + + + + + Whether there is an error message at the moment. This is a shortcut for writing "resolver.Context.ErrorMessage != null". + + + + + Draws an error message box if there is an error, and does nothing if there is no error. + + + + + Executes the resolved action for a given selection index. + + The selection index to execute the action on. Defaults to 0. + + + + Executes the action for all selection indices. + + + + + Creates a new action resolver instance from a pre-built context struct. This is a more advanced use that requires you to + know how the context needs to be set up before action resolution happens. However, this allows you to do more advanced + things like adjust various context values before string resolution happens. + + The pre-built context that should be used to get a resolver. + + + + Creates a new action resolver instance for a given string. + + The property that is the context for the resolution to happen in. + The string that should be resolved to an action. + + + + Creates a new action resolver instance for a given string. + + The property that is the context for the resolution to happen in. + The string that should be resolved to an action. + The extra named args that this resolver has access to. Passing in a named arg that already exists will silently override the pre-existing named arg. + + + + Gets a nicely formatted string that lists all the errors in the given set of action resolvers. The returned value is null if there are no errors. + + + + + Gets a nicely formatted string that lists all the errors in the given set of action resolvers. The returned value is null if there are no errors. + + + + + Draws error boxes for all errors in the given action resolvers, or does nothing if there are no errors. This is equivalent to calling DrawError() on all resolvers passed to this method. + + + + + Draws error boxes for all errors in the given action resolvers, or does nothing if there are no errors. This is equivalent to calling DrawError() on all resolvers passed to this method. + + + + + This struct contains all of an ActionResolver's configurations and values it needs to function. For performance and simplicity reasons, this is a single very large struct that lives on an ActionResolver instance and is passed around by ref to anything that needs it. + + + + + The property that *provides* the context for the action resolution. This is the instance that was passed to the resolver when it was created. Note that this is different from , which is based on this value, but almost always isn't the same InspectorProperty instance. + + + + + The error message, if a valid action resolution wasn't found, or if creation of the action resolver failed because was invalid, or if the action was executed but threw an exception. (In this last case, will be true.) + + + + + The named values that are available to the action resolver. Use this field only to get and set named values - once the ValueResolver has been created, new named values will have no effect. + + + + + This will be true if is not null and the message was caused by an exception thrown by code invoked during execution of the resolved action. + + + + + Whether exceptions thrown during action execution should be logged to the console. + + + + + The string that is resolved to perform an action. + + + + + Whether the action resolver should sync ref parameters of invoked methods with named values. If this is true, then if a ref or out parameter value is changed during action execution, the named value associated with that parameter will also be changed to the same value. + + + + + Whether this context has been resolved. + + + + + The type that is the parent of the action resolution, ie, the type that is the context. This is the same as .ValueEntry.TypeOfValue. + + + + + The property that *is* the context for the action resolution. This is not the instance that was passed to the resolver when it was created, but this value is based on that instance. This is the property that provides the actual context - for example, if is for a member of a type - or for an element in a collection contained by a member - this value will be the parent property for the type that contains that member. Only if is the tree's root property is the same as . + + + + + Gets the parent value which provides the context of the resolver. + + The selection index of the parent value to get. + + + + Sets the parent value which provides the context of the resolver. + + The selection index of the parent value to set. + The value to set. + + + + Adds the default named values of "property" and "value" to the context's named values. + This method is usually automatically invoked when a resolver is created, so there + is no need to invoke it manually. + + + + + A color palette. + + + + + Name of the color palette. + + + + + The colors. + + + + + Whether to show the alpha channel. + + + + + Add, Edit or remove custom color palettes used by the . + + You can modify the configuration in the Odin Preferences window found in 'Tools -> Odin Inspector -> Preferences -> Drawers -> Color Palettes', + or by locating the configuration file stored as a serialized object in the Sirenix folder under 'Odin Inspector/Config/Editor/ColorPaletteManager'. + + + + + + Specify the amount of spacing between each color in a color palette. + + + + + Specify the width of each color in a color palette. If StretchPalette is set to true, this will become the min-width. + + + + + If true, all color in a color palette is stretch so that the entire color-palette area is filled. + + + + + If true, a toolbar with the name of the color palette is shown above each color palette. + + + + + Gives you the list of all custom color palettes. + Remember to call UnityEditor.EditorUtility.SetDirty(ColorPaletteManager.Instance) after modifying the list. + + + + + Configurations for Odin DLLs import settings. + + + + + Gets or sets a value indicating whether or not Odin should automatically configure the import settings of its DLLs in a preprocess build step. + Keep in mind that this feature is only supported by Unity version 5.6 and up. + + + + + Gets a value indicating whether or not automatic configuration of Odin's DLL import settings is supported by the current Unity version. + + + + + Installed Odin Inspector Version Info. + + + + + Gets the name of the current running version of Odin Inspector. + + + + + Gets the current running version of Odin Inspector. + + + + + Whether the current version of Odin is an enterprise version. + + + + + This is a class for creating, getting and modifying a property's various states. An instance of this class always comes attached to an InspectorProperty. + See Odin's tutorials for more information about usage of the state system. + + + + + If set to true, all state changes for this property will be logged to the console. + + + + + Whether the property is visible in the inspector. + + + + + Whether the Visible state was true or not during the last layout event. + + + + + Whether the property is enabled in the inspector. + + + + + Whether the Enabled state was true or not during the last layout event. + + + + + Whether the property is expanded in the inspector. + + + + + Whether the Expanded state was true or not during the last layout event. + + + + + Creates a custom state with a given name. + + + + + + + + + Determines whether a state with the given key exists. + + The key to check. + True if the state exists, otherwise, false. + + + + Determines whether a state with the given key exists. + + The key to check. + If the state exists, this out parameter will be true if the state is persistent. + True if the state exists, otherwise, false. + + + + Determines whether a state with the given key exists. + + The key to check. + If the state exists, this out parameter will contain the type of value that the state contains. + True if the state exists, otherwise, false. + + + + Determines whether a state with the given key exists. + + The key to check. + If the state exists, this out parameter will be true if the state is persistent. + If the state exists, this out parameter will contain the type of value that the state contains. + True if the state exists, otherwise, false. + + + + Gets the value of a given state as an instance of type T. + + The type to get the state value as. An will be thrown if the state's value type cannot be assigned to T. + The key of the state to get. An will be thrown if a state with the given key does not exist. + The value of the state. + + + + Gets the value that a given state contained last layout as an instance of type T. + + The type to get the state value as. An will be thrown if the state's value type cannot be assigned to T. + The key of the state to get. An will be thrown if a state with the given key does not exist. + The value of the state during the last layout event. + + + + Sets the value of a given state to a given value. + + The type to set the state value as. An will be thrown if T cannot be assigned to the state's value type. + The key of the state to set the value of. An will be thrown if a state with the given key does not exist. + The value to set. + + + + Cleans the property state and prepares it for cached reuse of its containing PropertyTree. This will also reset the state. + + + + + Resets all states to their default values. Persistent states will be updated to their persistent cached value if one exists. + + + + + Contains information about a change that is going to occur/has occurred to a collection. + + + + + + Specifies the kinds of changes that can occur to collections. + + + + + Unknown collection change, the change was not specified by the invoking code. + + + + + The change is adding a value to the collection. Value and SelectionIndex will be set. + + + + + The change is inserting a value into the collection. Index, Value and SelectionIndex will be set. + + + + + The change is removing a value from the collection. Value and SelectionIndex will be set. + + + + + The change is removing a value at an index from the collection. Index and SelectionIndex will be set. + + + + + The change is clearing the collection. SelectionIndex will be set. + + + + + The change is removing a key from the collection. Key and SelectionIndex will be set. + + + + + The change is setting the value of a key in the collection. Key, Value and SelectionIndex will be set. + + + + + Handles all prefab modifications that apply to the targets of a property tree, if any. This class determines which properties have modifications, what the modifications are, auto-applies modifications if the current instance values do not correspond to the prefab values, and also provides an API for modifying those modifications. + NOTE: This class is liable to see a lot of changes, as the prefab modification system is slated to be redesigned for increased extendability in the future. Do not depend overly on the current API. + + + + + The prefabs for each prefab instance represented by the property tree, if any. + + + + + Whether any of the values the property tree represents are prefab instances. + + + + + A prefab tree for the prefabs of this property tree's prefab instances, if any exist. + + + + + Gets the Unity PropertyModification for the property at this path, if there are any. + + The property path to get the modification for. + The index of the tree target to get the modification for. + Whether any children of the path have modifications registered. + + + + + Gets the Odin prefab modification type of a given property, if any. + + The property to check. + + + The prefab modification type of the property if it has one, otherwise null. + + + + + Registers a modification of type for a given property. + + The property to register a modification for. + Selection index of the target to register a modification for. + The modified list length. + + Property " + property.Path + " does not have a value entry; cannot register prefab modification to this property. + or + newLength cannot be negative! + + + + + Registers a modification of type for a given property. + + The property to register a modification for. + Selection index of the target to register a modification for. + Whether to force the change to be registered immediately, rather than at the end of frame. + Property " + property.Path + " does not have a value entry; cannot register prefab modification to this property. + + + + Calculates a delta between the current dictionary property and its prefab counterpart, and registers that delta as a modification. + + The property to register a modification for. + Selection index of the target. + Property " + property.Path + " does not have a value entry; cannot register prefab modification to this property. + + + + Adds a remove key modification to the dictionary modifications of a given property. + + The property to register a modification for. + Selection index of the target. + The key to be removed. + Property " + property.Path + " does not have a value entry; cannot register prefab modification to this property. + + + + Adds an add key modification to the dictionary modifications of a given property. + + The property to register a modification for. + Selection index of the target. + The key to be added. + Property " + property.Path + " does not have a value entry; cannot register prefab modification to this property. + + + + Removes all dictionary modifications on a property for a given dictionary key value. + + The property to remove a key modification for. + Selection index of the target. + The key to remove modifications for. + key + + + + Removes all prefab modifications of a given type on a given property. + + The property to remove modifications for. + Selection index of the target. + Type of the modification to remove. + + + + Gets all prefab modifications in this property tree for a given selection index. + + + + + + + Default implementation and the version that will be used when no other OdinAttributeProcessorLocator instance have been given to a PropertyTree. + This implementation will find all AttributeProcessor definitions not marked with the . + + + + + Singleton instance of the DefaultOdinAttributeProcessorLocator class. + + + + + Type search index used for matching to properties. + + + + + Gets a list of to process attributes for the specified child member of the parent property. + + The parent of the member. + Child member of the parent property. + List of to process attributes for the specified member. + + + + Gets a list of to process attributes for the specified property. + + The property to find attribute porcessors for. + List of to process attributes for the speicied member. + + + + This attribute processor will take any attribute already applied to the property with the applied to, + and take all attributes applied to the attribute (except any ) and add to them to the property. + This allows for adding attributes to attributes in the property system. + + + + + Looks for attributes in the attributes list with a applied, and adds the attribute from those attributes to the property. + + The parent of the member. + The member that is being processed. + The list of attributes currently applied to the property. + + + + Finds all attributes attached to the specified member and adds to them to attribute list. + + + + + This attribute processor can only process for members. + + The property to process. + false. + + + + Finds all attributes attached to the specified member and adds to them to the attributes list. + + The parent property of the specified member. + The member to process attributes for. + The current attributes applied to the property. + + + + Attribute processor that can add, change and remove attributes from a property. + + + + + Instanciates an OdinAttributeProcessor instance of the specified type. + + The type of processor to instanciate. The type must inherit from . + A new instance of the specified type. + + + + Checks if the processor can process attributes for the specified member. + + The parent property of the member. + The member to be processed. + true if the processor can process for the specified member. Otherwise false. + + + + Checks if the processor can process attributes for the specified property. + + The property to process. + true if the processor can process attributes for the specified property. Otherwise false. + + + + Processes attributes for the specified member. + + The parent property of the specified member. + The member to process attributes for. + The current attributes applied to the property. + + + + Processes attributes for the specified property. + + The property to process attributes for. + The current attributes applied to the property. + + + + Attribute processor that can add, change and remove attributes from a property. + + + + + Base class definition for OdinAttributeProcessorLocator. Responsible for finding and creating instances to process attributes for properties. + Default OdinAttributeProcessorLocator have been implemented as . + + + + + Gets a list of to process attributes for the specified child member of the parent property. + + The parent of the member. + Child member of the parent property. + List of to process attributes for the specified member. + + + + Gets a list of to process attributes for the specified property. + + The property to find attribute porcessors for. + List of to process attributes for the speicied member. + + + + Find attributes attached to the type definition of a property and adds to them to attribute list. + + + + + This attribute processor can only process for properties. + + The parent of the specified member. + The member to process. + false. + + + + This attribute processor can only process for properties with an attached value entry. + + The property to process. + true if the specified property has a value entry. Otherwise false. + + + + Finds all attributes attached to the type and base types of the specified property value and adds them to the attribute list. + + The property to process. + The list of attributes for the property. + + + + Default implementation and the version that will be used by if no other instance have been specified. + + + + + Singleton instance of . + + + + + Gets an instance for the specified property. + + The property to get an instance for. + An instance of to resolver the specified property. + + + + Base class for locator of . Use for default implementation. + + + + + Gets an instance for the specified property. + + The property to get an instance for. + An instance of to resolver the specified property. + + + + Note: this interface may be temporary, and may eventually be substituted for a public-facing way of extending the prefab modification system. + + For now, it only exists to denote which internally defined resolvers support prefab modifications being set. + + + + + Responsible for getting and setting values on properties. + + The type of the owner. + The type of the value. + + + + + Whether the value is readonly. + + + + + Gets the type of the owner. + + + + + Gets the type of the value. + + + + + Initializes a new instance of the class. + + The field member to represent. + if set to true [is readonly]. + + + + Initializes a new instance of the class. + + The getter. + The setter. + getter + + + + Initializes a new instance of the class. + + The getter. + The setter. + getter + + + + Gets the value from a given owner. + + The owner. + The found value. + owner is null + + + + Gets the value from a given weakly typed owner. + + The weakly typed owner. + The found value. + + + + Sets the weakly typed value on a given weakly typed owner. + + The owner. + The value. + + + + Sets the value on a given owner. + + The owner. + The value. + + + + Gets all s for a given type. + + The parent property. + The type to get infos for. + if set to true members that are serialized by Odin will be included. + + + + Gets an aliased version of a member, with the declaring type name included in the member name, so that there are no conflicts with private fields and properties with the same name in different classes in the same inheritance hierarchy. + + + + + Gets the attribute that the OdinAttributeStateUpdater applies to. + + + + + Gets the strongly typed ValueEntry of the OdinAttributeStateUpdater's property. + + + + + Gets the strongly typed ValueEntry of the OdinValueStateUpdater's property. + + + + + Initializes this instance. + + + + + Draws the property with GUILayout support. This method is called by DrawPropertyImplementation if the GUICallType is set to GUILayout, which is the default. + + + + + Draws members marked with . + + + + + Draws a warning message for non-serialized properties that sports both the SerializeField and the ShowInInspector attribute. + + + + + Determines if the drawer can draw the property. + + The property to test. + true if the drawer can draw the property; otherwise false. + + + + Initializes the drawer. + + + + + Draws the warning message and calls the next drawer. + + The label for the property. + + + + Draws properties marked with . + + + + + + + + + + Draws a space for properties marked with the PropertySpace attribute. + + + + + Initializes this instance. + + + + + Draws the property. + + + + + Drawer for the ShowPropertyResolver attribute. + + + + + + TextArea attribute drawer. + + + + + Draws the property in the Rect provided. This method does not support the GUILayout, and is only called by DrawPropertyImplementation if the GUICallType is set to Rect, which is not the default. + If the GUICallType is set to Rect, both GetRectHeight and DrawPropertyRect needs to be implemented. + If the GUICallType is set to GUILayout, implementing DrawPropertyLayout will suffice. + + The label. This can be null, so make sure your drawer supports that. + + + + Draws properties marked with . + + + + + Initializes this instance. + + + + + Draws the property with GUILayout support. This method is called by DrawPropertyImplementation if the GUICallType is set to GUILayout, which is the default. + + + + + Drawer for the ResponsiveButtonGroupAttribute. + + + + + Draws the property with GUILayout support. + + + + + Drawer for the attribute. + + + + + Draws the property. + + + + + The default method drawer that draws most buttons. + + + + + Initializes this instance. + + + + + Draws the property layout. + + + + + Draws Color properties marked with . + + + + + Draws the property. + + + + + Draws char properties marked with . + + + + + Draws the property. + + + + + Draws string properties marked with . + + + + + Draws the property. + + + + + Draws sbyte properties marked with . + + + + + Draws the property. + + + + + Draws byte properties marked with . + + + + + Draws the property. + + + + + Draws short properties marked with . + + + + + Draws the property. + + + + + Draws ushort properties marked with . + + + + + Draws the property. + + + + + Draws int properties marked with . + + + + + Draws the property. + + + + + Draws uint properties marked with . + + + + + Draws the property. + + + + + Draws long properties marked with . + + + + + Draws the property. + + + + + Draws ulong properties marked with . + + + + + Draws the property. + + + + + Draws float properties marked with . + + + + + Draws the property. + + + + + Draws double properties marked with . + + + + + Draws the property. + + + + + Draws decimal properties marked with . + + + + + Draws the property. + + + + + Odin drawer for the . + + + + + Returns true if the drawer can draw the type. + + + + + Draws the property. + + + + + Draws properties marked with as a square ObjectField which renders a preview for UnityEngine.Object types. + This object field also adds support for drag and drop, dragging an object to another square object field, swaps the values. + If you hold down control while letting go it will replace the value, And you can control + click the object field to quickly delete the value it holds. + + + + + Draws the property. + + + + + The TableList attirbute drawer. + + + + + + Determines whether this instance [can draw attribute property] the specified property. + + + + + Initializes this instance. + + + + + Draws the property layout. + + + + + Draws Color properties marked with . + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + Not yet documented. + + + + + Initializes the drawer. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Initializes the drawer. + + + + + Not yet documented. + + + + + Adds customs generic menu options. + + + + + Draws properties marked with + + + + + Draws the property. + + + + + Draws properties marked with the . + + + + + + + + + + + + Draws the attribute. + + + + + + When first learning to use the Odin Inspector, it is common for people to misunderstand the OdinSerialize attribute, + and use it in places where it does not achive the deceired goal. + + + This drawer will display a warning message if the OdinSerialize attribute is potentially used in such cases. + + + + + + + Draws The Property. + + + + + Common base implementation for progress bar attribute drawers. + + + + + + Initialized the drawer. + + + + + Draws the property. + + + + + Generic implementation of progress bar field drawing. + + + + + Converts the generic value to a double. + + The generic value to convert. + The generic value as a double. + + + + Draws values decorated with . + + + + + + + Draws a progress bar for a byte property. + + + + + Converts the generic value to a double. + + The generic value to convert. + The generic value as a double. + + + + Draws values decorated with . + + + + + + + Draws a progress bar for a sbyte property. + + + + + Converts the generic value to a double. + + The generic value to convert. + The generic value as a double. + + + + Draws values decorated with . + + + + + + + Draws a progress bar for a short property. + + + + + Converts the generic value to a double. + + The generic value to convert. + The generic value as a double. + + + + Draws values decorated with . + + + + + + + Draws a progress bar for a ushort property. + + + + + Converts the generic value to a double. + + The generic value to convert. + The generic value as a double. + + + + Draws values decorated with . + + + + + + + Draws a progress bar for an int property. + + + + + Converts the generic value to a double. + + The generic value to convert. + The generic value as a double. + + + + Draws values decorated with . + + + + + + + Draws a progress bar for a uint property. + + + + + Converts the generic value to a double. + + The generic value to convert. + The generic value as a double. + + + + Draws values decorated with . + + + + + + + Draws a progress bar for a long property. + + + + + Converts the generic value to a double. + + The generic value to convert. + The generic value as a double. + + + + Draws values decorated with . + + + + + + + Draws a progress bar for a ulong property. + + + + + Converts the generic value to a double. + + The generic value to convert. + The generic value as a double. + + + + Draws values decorated with . + + + + + + + Draws a progress bar for a float property. + + + + + Converts the generic value to a double. + + The generic value to convert. + The generic value as a double. + + + + Draws values decorated with . + + + + + + + Draws a progress bar for a double property. + + + + + Converts the generic value to a double. + + The generic value to convert. + The generic value as a double. + + + + Draws values decorated with . + + + + + + + Draws a progress bar for a decimal property. + + + + + Converts the generic value to a double. + + The generic value to convert. + The generic value as a double. + + + + Draws byte properties marked with . + + + + + + + + + + + Initialized the drawer. + + + + + Draws the property. + + + + + Draws double properties marked with . + + + + + + + + + + + Initialized the drawer. + + + + + Draws the property. + + + + + Draws float properties marked with . + + + + + + + + + + + Initialized the drawer. + + + + + Draws the property. + + + + + Draws decimal properties marked with . + + + + + Initialized the drawer. + + + + + Draws the property. + + + + + Draws short properties marked with . + + + + + + + + + + + Initialized the drawer. + + + + + Draws the property. + + + + + Draws int properties marked with . + + + + + + + + + + + Initialized the drawer. + + + + + Draws the property. + + + + + Draws long properties marked with . + + + + + + + + + + + Initialized the drawer. + + + + + Draws the property. + + + + + Draws sbyte properties marked with . + + + + + + + + + + + Initialized the drawer. + + + + + Draws the property. + + + + + Draws ushort properties marked with . + + + + + + + + + + + Initialized the drawer. + + + + + Draws the property. + + + + + Draws uint properties marked with . + + + + + + + + + + + Initialized the drawer. + + + + + Draws the property. + + + + + Draws ulong properties marked with . + + + + + + + + + + + Initialized the drawer. + + + + + Draws the property. + + + + + Draws an enum in a horizontal button group instead of a dropdown. + + + + + Returns true if the drawer can draw the type. + + + + + Draws the property. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Draws char properties marked with . + + + + + Draws the property. + + + + + Draws string properties marked with . + + + + + Draws the property. + + + + + Draws sbyte properties marked with . + + + + + Draws the property. + + + + + Draws byte properties marked with . + + + + + Draws the property. + + + + + Draws short properties marked with . + + + + + Draws the property. + + + + + Draws ushort properties marked with . + + + + + Draws the property. + + + + + Draws int properties marked with . + + + + + Draws the property. + + + + + Draws uint properties marked with . + + + + + Draws the property. + + + + + Draws long properties marked with . + + + + + Draws the property. + + + + + Draws ulong properties marked with . + + + + + Draws the property. + + + + + Draws float properties marked with . + + + + + Draws the property. + + + + + Draws double properties marked with . + + + + + Draws the property. + + + + + Draws decimal properties marked with . + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + + + + Initializes this instance. + + + + + Draws the property. + + + + + Draws properties marked with . + This drawer sets the current GUI color, before calling the next drawer in the chain. + + + + + + + + + + Draws the property. + + + + + Static GUI information reguarding the InlineEditor attribute. + + + + + Gets a value indicating how many InlineEditors we are currently in. + + + + + Draws properties marked with . + + + + + + + Initializes this instance. + + + + + Draws the property layout. + + The label. + + + + Draws Vector2 properties marked with . + + + + + + + + + + + Show drawer chain attribute drawer. + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + Initializes this instance. + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + Draws the property. + + + + + Draws byte properties marked with . + + + + + + + + + + + Draws the property. + + + + + Draws double properties marked with . + + + + + + + + + + + Draws the property. + + + + + Draws float properties marked with . + + + + + + + + + + + Draws the property. + + + + + Draws decimal properties marked with . + + + + + Draws the property. + + + + + Draws short properties marked with . + + + + + + + + + + + Draws the property. + + + + + Draws int properties marked with . + + + + + + + + + + + Draws the property. + + + + + Draws long properties marked with . + + + + + + + + + + + Draws the property. + + + + + Draws sbyte properties marked with . + + + + + + + + + + + Draws the property. + + + + + Draws ushort properties marked with . + + + + + + + + + + + Draws the property. + + + + + Draws uint properties marked with . + + + + + + + + + + + Draws the property. + + + + + Draws ulong properties marked with . + + + + + + + + + + + Draws the property. + + + + + Draws properties marked with . + Calls the properties ToString method to get the string to draw. + + + + + + + + + + + Draws the property. + + + + + Drawer for the + + + + + + Draws the property. + + + + + Drawer for the + + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + + Draws the property. + + + + + Char property drawer. + + + + + Draws the property. + + + + + Delegate property drawer. This drawer is rather simplistic for now, and will receive significant upgrades in the future. + + + + + See . + + + + + Draws the property. + + + + + Property drawer for . + + + + + Draws the property. + + + + + Base class to derive from for value drawers that merely wish to cause a value to be drawn by Unity. + + + + + Draws the property. + + + + + Gradient property drawer. + + + + + Int property drawer. + + + + + Draws the property. + + + + + The GUIStyleState Drawer + + + + + + Initializes this instance. + + + + + Draws the property with GUILayout support. + + + + + LayerMask property drawer. + + + + + Draws the property. + + + + + Base class for two-dimensional array drawers. + + + + + Override this method in order to define custom type constraints to specify whether or not a type should be drawn by the drawer. + Note that Odin's has full support for generic class constraints, so most often you can get away with not overriding CanDrawTypeFilter. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Draws the property. + + + + + This method gets called from DrawPropertyLayout right before the table and error message is drawn. + + + + + Compares the element. + + + + + Draws a table cell element. + + The rect. + The input value. + The output value. + + + + Draws the element. + + + + + Property drawer for nullables. + + + + + Draws the property. + + + + + Quaternion property drawer. + + + + + Draws the property. + + + + + Populates the generic menu for the property. + + + + + Type property drawer + + + + + + Draws the property. + + + + + Draws properties marked with . + Displays a configurable list of assets, where each item can be enabled or disabled. + + + + + + + + + + Draws the property. + + + + + Populates the generic menu for the property. + + + + + Odin drawer for . + + + + + Initializes the drawer. + + + + + Not yet documented. + + + + + Adds a generic menu option to properties marked with . + + + + + + + + Populates the generic menu for the property. + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + Draws the property. + + + + + Draws properties marked with . + Draws an info box above the property. Error and warning info boxes can be tracked by Odin Scene Validator. + + + + + + + + + Draws the property. + + + + + Draws properties marked with . + Creates a new GUIContent, with the provided label text, before calling further down in the drawer chain. + + + + + + + + + + + + Draws the attribute. + + + + + Draws string properties marked with . + This drawer only works for string fields, unlike . + + + + + + + + + + Draws the property. + + + + + Draws string properties marked with . + This drawer works for both string field and properties, unlike . + + + + + + + + + + Draws the property. + + + + + Draws properties marked with . + Calls the method, the attribute is either attached to, or the method that has been specified in the attribute, to allow for custom GUI drawing. + + + + + + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + + + + + Draws properties marked with . + + + + + Draws the property. + + + + + Initializes this instance. + + + + + Draws the property with GUILayout support. This method is called by DrawPropertyImplementation if the GUICallType is set to GUILayout, which is the default. + + + + + Draws properties marked with . + + + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + Draws the property. + + + + + Draws all Unity DecoratorDrawers within prepend attribute drawers within Odin. + + + + + Initializes the class. + + + + + Draws the property. + + + + + Draws all properties grouped together with the + + + + + + Initializes this instance. + + + + + Draws the property. + + + + + Draws all properties grouped together with the + + + + + + Draws the property. + + + + + Draws all properties grouped together with the + + + + + + Initializes this instance. + + + + + Draws the property. + + + + + Draws all properties grouped together with the + + + + + + Draws the property. + + + + + Draws properties marked with . + + + + + + Draws the property. + + + + + Draws all properties grouped together with the + + + + + + Draws the property. + + + + + Draws all nullable reference types, with an object field. + + + + + Draws the property. + + + + + Returns a value that indicates if this drawer can be used for the given property. + + + + + Evaluates all strings, enums and primitive types and ensures EditorGUI.showMixedValue is true if there are any value conflicts in the current selection. + + + + + Sets the drawer to only be evaluated on primitive types, strings and enums. + + + + + Draws the property. + + + + + Adds the right click area. + + + + + Adds the right click area. + + + + + Opens a context menu for any given property on right click. The context menu is populated by all relevant drawers that implements . + + + + + + Initializes the drawer. + + + + + Draws the property. + + + + + Draws all reference type properties, which has already been drawn elsewhere. This drawer adds an additional foldout to prevent infinite draw depth. + + + + + Prevents the drawer from being applied to UnityEngine.Object references since they are shown as an object field, and is not drawn in-line. + + + + + Draws the property. + + + + + Draws properties with a set. + + + + + Draws the property. + + + + + + When multiple objects are selected and inspected, this his drawer ensures UnityEditor.EditorGUI.showMixedValue + gets set to true if there are any conflicts in the selection for any given property. + Otherwise the next drawer is called. + + This drawer also implements and provides a right-click context menu item for resolving conflicts if any. + + + + + Draws the property. + + + + + Animation curve property drawer. + + + + + Bool property drawer. + + + + + Draws the property. + + + + + Byte property drawer. + + + + + Draws the property. + + + + + Color32 property drawer. + + + + + Draws the property. + + + + + Color property drawer. + + + + + Draws the property. + + + + + Color palette property drawer. + + + + + Draws the property. + + + + + Drawer for composite properties. + + + + + Draws the property. + + + + + Decimal property drawer. + + + + + Draws the property. + + + + + Double property drawer. + + + + + Draws the property. + + + + + Enum property drawer. + + + + + Returns true if the drawer can draw the type. + + + + + Draws the property. + + + + + Short property drawer. + + + + + Draws the property. + + + + + Int property drawer. + + + + + Draws the property. + + + + + Long property drawer. + + + + + Draws the property. + + + + + Property drawer for anything that has a . + + + + + Initializes the drawer. + + + + + Draws the property. + + + + + SByte property drawer. + + + + + Draws the property. + + + + + Float property drawer. + + + + + Draws the property. + + + + + String property drawer. + + + + + Draws the property. + + + + + Ushort property drawer. + + + + + Draws the property. + + + + + Uint property drawer. + + + + + Draws the property. + + + + + Ulong property drawer. + + + + + Draws the property. + + + + + Unity event drawer. + + + + + Draws the property. + + + + + Unity object drawer. + + + + + Initializes this instance. + + + + + Draws the property. + + + + + Vector2 proprety drawer. + + + + + Draws the property. + + + + + Populates the generic menu for the property. + + + + + Vector3 property drawer. + + + + + Draws the property. + + + + + Populates the generic menu for the property. + + + + + Vector4 property drawer. + + + + + Draws the property. + + + + + Populates the generic menu for the property. + + + + + Draws the property. + + + + + Descripes an attribute example. + + + + + The type of the example object. + + + + + The name of the example. + + + + + The description of the example. + + + + + Raw code of the example. + + + + + The example declared as a Unity component. + + + + + Sorting value of the example. Examples with lower order values should come before examples with higher order values. + + + + + Preview object of the example. + + + + + Extension method for List<Attribute> + + + + + Determines whether the list contains a specific attribute. + + The type of attribute. + The attribute list. + + true if the specified attribute list has attribute; otherwise, false. + + + + + Adds the attribute if not exist. + + The type of attribute. + The attribute list. + + + + + Adds the attribute if not exist. + + The type of attribute. + The attribute list. + + + + + Adds the attribute if not exist. + + The type of attribute. + The attribute list. + + + + + Adds the attribute if not exist. + + The type of attribute. + The attribute list. + The attribute. + + + + + Removes the type of the attribute of. + + The type of attribute. + The attribute list. + + + + + Odin has its own implementations for these attribute drawers; never use Unity's. + + + + + Gets the priority of a given drawer type. + + + + + Helper class to get values from InspectorProperties. This class is deprecated and fully replaced by . + + + + + If any error occurred while looking for members, it will be stored here. + + + + + Gets the referenced member information. + + + + + Gets the value. + + + + + Gets all values from all targets. + + + + + The content padding + + + + + Draws the menu tree. + + + + + Gets the value selected value. + + + + + Invokes BuildMenuTree. + + + + + Use this attribute to prevent a type from being included in Odin systems. + The attribute can be applied to Odin drawers, Odin property resolvers and Odin attribute processor types. + + + + + To safely change anything in the type cache, you must be holding this lock. + + + + + Put this attribute on a validator class to prevent the ValidatorDrawer from running that validator in the inspector. + Typically you would use this for a validation-related attribute that has its own, complex custom drawer that should + handle the validation and error/warning drawing while the inspector is being drawn, but still needs a validator to + run for the project validation scans. + + + + + Apply this to an assembly to register validators for the validation system. + This enables locating of all relevant validator types very quickly. + + + + + This attribute can be placed on an assembly to register a value resolver creator that should be queried when a value resolver is being created. + + + + + This attribute can be placed on an assembly to register a value resolver creator that should be queried when a value resolver is being created. + + The resolver + + + + + A ValueResolver resolves a string to a value of a given type, given an InspectorProperty instance to use as context. Call to get an instance of a ValueResolver. + Value resolvers are a globally extendable system that can be hooked into and modified or changed by creating and registering a . + See Odin's tutorials for details and examples of how to use ValueResolvers. + + + + + The context of this ValueResolver, containing all of its configurations and values it needs to function. For performance and simplicity reasons, this is a single very large struct that is passed around by ref to anything that needs it. + + + + + The current error message that the resolver has, or null if there is no error message. This is a shortcut for writing "resolver.Context.ErrorMessage". + + + + + Whether there is an error message at the moment. This is a shortcut for writing "resolver.Context.ErrorMessage != null". + + + + + The type of value that this resolver instance is supposed to get. + + + + + Gets a value from the value resolver in a weakly typed manner. + + The selection index at which to get the value, in the case of multi-selection. Defaults to 0. + The value that was gotten. + + + + Draws an error message box if there is an error, and does nothing if there is no error. + + + + + Creates a new value resolver instance from a pre-built context struct, in a weakly typed fashion, though the result + is the same as using a strongly typed generic overload. This is a more advanced use that requires you to + know how the context needs to be set up before value resolution happens. However, this allows you to do more advanced + things like adjust various context values before string resolution happens. + + The pre-built context that should be used to get a resolver. + + + + Creates a new value resolver instance from a pre-built context struct. This is a more advanced use that requires you to + know how the context needs to be set up before value resolution happens. However, this allows you to do more advanced + things like adjust various context values before string resolution happens. + + The pre-built context that should be used to get a resolver. + + + + Creates a new value resolver instance in a weakly typed fashion, though the result is the same as using a strongly typed generic overload. + This is useful when you don't know at compile time which type you want to resolve. + + The type of value that the new resolver should resolve. + The property that is the context for the resolution to happen in. + The string that should be resolved to a value. + + + + Creates a new value resolver instance in a weakly typed fashion, though the result is the same as using a strongly typed generic overload. + This is useful when you don't know at compile time which type you want to resolve. + + The type of value that the new resolver should resolve. + The property that is the context for the resolution to happen in. + The string that should be resolved to a value. + The extra named args that this resolver has access to. Passing in a named arg that already exists will silently override the pre-existing named arg. + + + + Creates a new value resolver instance. + + The type of value that the new resolver should resolve. + The property that is the context for the resolution to happen in. + The string that should be resolved to a value. + + + + Creates a new value resolver instance. + + The type of value that the new resolver should resolve. + The property that is the context for the resolution to happen in. + The string that should be resolved to a value. + The extra named args that this resolver has access to. Passing in a named arg that already exists will silently override the pre-existing named arg. + + + + Creates a new value resolver instance in a weakly typed fashion, though the result is the same as using a strongly typed generic overload. + This is useful when you don't know at compile time which type you want to resolve. + + The type of value that the new resolver should resolve. + The property that is the context for the resolution to happen in. + The string that should be resolved to a value. + The value that the resolver should return if the string cannot be resolved to anything, or if there is an error in creating a resolver, or if resolution itself throws an exception. + + + + Creates a new value resolver instance in a weakly typed fashion, though the result is the same as using a strongly typed generic overload. + This is useful when you don't know at compile time which type you want to resolve. + + The type of value that the new resolver should resolve. + The property that is the context for the resolution to happen in. + The string that should be resolved to a value. + The value that the resolver should return if the string cannot be resolved to anything, or if there is an error in creating a resolver, or if resolution itself throws an exception. + The extra named args that this resolver has access to. Passing in a named arg that already exists will silently override the pre-existing named arg. + + + + Creates a new value resolver instance meant to resolve a string value in particular. This is a shorthand for creating a string resolver that has the resolved string as a fallback value. + This special case will get you the behaviour where, if you pass in a string that is not meant to be resolved in a special way, the value resolver will just pass you that string back as the result value. + + The property that is the context for the resolution to happen in. + The string that should be resolved to a value. + + + + Creates a new value resolver instance meant to resolve a string value in particular. This is a shorthand for creating a string resolver that has the resolved string as a fallback value. + This special case will get you the behaviour where, if you pass in a string that is not meant to be resolved in a special way, the value resolver will just pass you that string back as the result value. + + The property that is the context for the resolution to happen in. + The string that should be resolved to a value. + The extra named args that this resolver has access to. Passing in a named arg that already exists will silently override the pre-existing named arg. + + + + Creates a new value resolver instance. + + The type of value that the new resolver should resolve. + The property that is the context for the resolution to happen in. + The string that should be resolved to a value. + The value that the resolver should return if the string cannot be resolved to anything, or if there is an error in creating a resolver, or if resolution itself throws an exception. + + + + Creates a new value resolver instance. + + The type of value that the new resolver should resolve. + The property that is the context for the resolution to happen in. + The string that should be resolved to a value. + The value that the resolver should return if the string cannot be resolved to anything, or if there is an error in creating a resolver, or if resolution itself throws an exception. + The extra named args that this resolver has access to. Passing in a named arg that already exists will silently override the pre-existing named arg. + + + + Gets a nicely formatted string that lists all the errors in the given set of value resolvers. The returned value is null if there are no errors. + + + + + Gets a nicely formatted string that lists all the errors in the given set of value resolvers. The returned value is null if there are no errors. + + + + + Draws error boxes for all errors in the given value resolvers, or does nothing if there are no errors. This is equivalent to calling DrawError() on all resolvers passed to this method. + + + + + Draws error boxes for all errors in the given value resolvers, or does nothing if there are no errors. This is equivalent to calling DrawError() on all resolvers passed to this method. + + + + + A ValueResolver resolves a string to a value of a given type, given an InspectorProperty instance to use as context. Call to get an instance of a ValueResolver. + Value resolvers are a globally extendable system that can be hooked into and modified or changed by creating and registering a . + See Odin's tutorials for details and examples of how to use ValueResolvers. + + + + + The delegate that does the actual value resolution. You should not call this manually, but instead call . + + + + + The type of value that this resolver instance is supposed to get. Always equal to typeof(). + + + + + Gets a value from the value resolver. + + The selection index at which to get the value, in the case of multi-selection. Defaults to 0. + The value that was gotten. + + + + Gets a value from the value resolver in a weakly typed manner. + + The selection index at which to get the value, in the case of multi-selection. Defaults to 0. + The value that was gotten. + + + + This struct contains all of a ValueResolver's configurations and values it needs to function. For performance and simplicity reasons, this is a single very large struct that lives on a ValueResolver instance and is passed around by ref to anything that needs it. + + + + + The property that *provides* the context for the value resolution. This is the instance that was passed to the resolver when it was created. Note that this is different from , which is based on this value, but almost always isn't the same InspectorProperty instance. + + + + + The error message, if a valid value resolution wasn't found, or if creation of the value resolver failed because was invalid, or if value resolution was run but threw an exception. (In this last case, will be true.) + + + + + The named values that are available to the value resolver. Use this field only to get and set named values - once the ValueResolver has been created, new named values will have no effect. + + + + + This is the fallback value that the value resolver will return if there is an error or failed resolution for any reason. + + + + + Whether there is a fallback value. This boolean exists because then null is also a valid fallback value. This boolean will always be true if an overload is used that takes a fallback value parameter. + + + + + This will be true if is not null and the message was caused by an exception thrown by code invoked during an actual value resolution. + + + + + Whether exceptions thrown during value resolution should be logged to the console. + + + + + The type of value that the resolver is resolving. + + + + + The string that is resolved to get a value. + + + + + Whether the value resolver should sync ref parameters of invoked methods with named values. If this is true, then if a ref or out parameter value is changed during value resolution, the named value associated with that parameter will also be changed to the same value. + + + + + Whether this context has been resolved. + + + + + The type that is the parent of the value resolution, ie, the type that is the context. This is the same as .ValueEntry.TypeOfValue. + + + + + The property that *is* the context for the value resolution. This is not the instance that was passed to the resolver when it was created, but this value is based on that instance. This is the property that provides the actual context - for example, if is for a member of a type - or for an element in a collection contained by a member - this value will be the parent property for the type that contains that member. Only if is the tree's root property is the same as . + + + + + Gets the parent value which provides the context of the resolver. + + The selection index of the parent value to get. + + + + Sets the parent value which provides the context of the resolver. + + The selection index of the parent value to set. + The value to set. + + + + Adds the default named values of "property" and "value" to the context's named values. + This method is usually automatically invoked when a resolver is created, so there + is no need to invoke it manually. + + + + + The Odin Getting Started Window + + + + + + Shows the window. + + + + + Initialize get called by OnEnable and by OnGUI after assembly reloads + which often happens when you recompile or enter and exit play mode. + + + + + Gets a value indicating whether the window should draw a scroll view. + + + + + Draws the Odin Editor Window. + + + + + Priority for and types. + + + + + Priority of the resolver. + + + + + Initializes a new instance of the class. + + The higher the priority, the earlier it will be processed. + + + + Draws an editor window with a menu tree. + + + + public class OdinMenuEditorWindowExample : OdinMenuEditorWindow + { + [SerializeField, HideLabel] + private SomeData someData = new SomeData(); + + protected override OdinMenuTree BuildMenuTree() + { + OdinMenuTree tree = new OdinMenuTree(supportsMultiSelect: true) + { + { "Home", this, EditorIcons.House }, // draws the someDataField in this case. + { "Odin Settings", null, EditorIcons.SettingsCog }, + { "Odin Settings/Color Palettes", ColorPaletteManager.Instance, EditorIcons.EyeDropper }, + { "Odin Settings/AOT Generation", AOTGenerationConfig.Instance, EditorIcons.SmartPhone }, + { "Camera current", Camera.current }, + { "Some Class", this.someData } + }; + + tree.AddAllAssetsAtPath("More Odin Settings", SirenixAssetPaths.OdinEditorConfigsPath, typeof(ScriptableObject), true) + .AddThumbnailIcons(); + + tree.AddAssetAtPath("Odin Getting Started", SirenixAssetPaths.SirenixPluginPath + "Getting Started With Odin.asset"); + + var customMenuItem = new OdinMenuItem(tree, "Menu Style", tree.DefaultMenuStyle); + tree.MenuItems.Insert(2, customMenuItem); + + tree.Add("Menu/Items/Are/Created/As/Needed", new GUIContent()); + tree.Add("Menu/Items/Are/Created", new GUIContent("And can be overridden")); + + // As you can see, Odin provides a few ways to quickly add editors / objects to your menu tree. + // The API also gives you full control over the selection, etc.. + // Make sure to check out the API Documentation for OdinMenuEditorWindow, OdinMenuTree and OdinMenuItem for more information on what you can do! + + return tree; + } + } + + + + + + + + + + + + + Called when the window is destroyed. Remember to call base.OnDestroy(); + + + + + Builds the menu tree. + + + + + Gets or sets the width of the menu. + + + + + Gets a value indicating whether the menu is resizable. + + + + + Gets the menu tree. + + + + + Gets or sets a value indicating whether to draw the menu search bar. + + + + + Gets or sets the custom search function. + + + + + Forces the menu tree rebuild. + + + + + Tries to select the menu item with the specified object. + + + + + Draws the menu tree selection. + + + + + Draws the Odin Editor Window. + + + + + The method that draws the menu. + + + + + A menu item that represents one or more objects. + + + + + + + + + + The default toggled state + + + + + Initializes a new instance of the class. + + The Odin menu tree instance the menu item belongs to. + The name of the menu item. + The instance the value item represents. + + + + Occurs right after the menu item is done drawing, and right before mouse input is handles so you can take control of that. + + + + + Occurs when the user has right-clicked the menu item. + + + + + Gets the child menu items. + + + The child menu items. + + + + + Gets the index location of the menu item. + + + + + Gets or sets a value indicating whether the menu item is visible. + Not that setting this to false will not hide its children as well. For that see use Toggled. + + + + + Gets or sets the icon that is used when the menu item is not selected. + + + + + Gets or sets the icon that is used when the menu item is selected. + + + + + Gets a value indicating whether this instance is selected. + + + + + Gets the menu tree instance. + + + + + Gets or sets the raw menu item name. + + + + + Gets or sets the search string used when searching for menu items. + + + + + Gets the next visual menu item. + + + + + Gets the parent menu item. + + + + + Gets the previous visual menu item. + + + + + Gets the drawn rect. + + + + + Gets the drawn label rect. + + + + + Gets or sets the style. If null is specified, then the menu trees DefaultMenuStyle is used. + + + + + Deselects this instance. + + + + + Selects the specified add to selection. + + + + + Gets the child menu items recursive in a DFS. + + Whether to include it self in the collection. + + + + Gets the child menu items recursive in a DFS. + + Whether to include it self in the collection. + Whether to include the root. + + + + Gets the full menu item path. + + + + + Gets the first object of the + + + + + Gets the object instances the menu item represents + + + + + Sets the object instance + + + + + Sets the object instances + + + + + Gets or sets the value the menu item represents. + + + + + Gets a nice menu item name. If the raw name value is null or a dollar sign, then the name is retrieved from the object itself via ToString(). + + + + + Gets or sets a value indicating whether this is toggled / expanded. This value tries it best to be persistent. + + + + + Gets or sets the icon getter. + + + + + Draws this menu item followed by all of its child menu items + + The indent level. + + + + Draws the menu item with the specified indent level. + + + + + Override this to add custom GUI to the menu items. + This is called right after the menu item is done drawing, and right before mouse input is handles so you can take control of that. + + + + + Handles the mouse events. + + The rect. + The triangle rect. + + + + The style settings used by . + + A nice trick to style your menu is to add the tree.DefaultMenuStyle to the tree itself, + and style it live. Once you are happy, you can hit the Copy CSharp Snippet button, + remove the style from the menu tree, and paste the style directly into your code. + + + + + + + + + + + Gets or sets the default selected style. + + + + + Gets or sets the selected label style. + + + + + The height of the menu item. + + + + + The global offset of the menu item content + + + + + The vertical offset of the menu item label + + + + + The number of pixels to indent per level indent level. + + + + + The size of the icon. + + + + + The size of the icon. + + + + + The transparency of icons when the menu item is not selected. + + + + + The padding between the icon and other content. + + + + + Whether to draw the a foldout triangle for menu items with children. + + + + + The size of the foldout triangle icon. + + + + + The padding between the foldout triangle icon and other content. + + + + + Whether or not to align the triangle left or right of the content. + If right, then the icon is pushed all the way to the right at a fixed position ignoring the indent level. + + + + + Whether to draw borders between menu items. + + + + + The horizontal border padding. + + + + + The border alpha. + + + + + The background color for when a menu item is selected. + + + + + The background color for when a menu item is selected. + + + + + The background color for when a menu item is selected. + + + + + The background color for when a menu item is selected. + + + + + Sets the height of the menu item. + + + + + Sets the global offset of the menu item content + + + + + Sets the number of pixels to indent per level indent level. + + + + + Sets the size of the icon. + + + + + Sets the size of the icon. + + + + + Sets the transparency of icons when the menu item is not selected. + + + + + Sets the padding between the icon and other content. + + + + + Sets whether to draw the a foldout triangle for menu items with children. + + + + + Sets the size of the foldout triangle icon. + + + + + Sets the padding between the foldout triangle icon and other content. + + + + + Sets whether or not to align the triangle left or right of the content. + If right, then the icon is pushed all the way to the right at a fixed position ignoring the indent level. + + + + + Sets whether to draw borders between menu items. + + + + + Sets the border alpha. + + + + + Sets the border alpha. + + + + + Sets the background color for when a menu item is selected. + + + + + Sets the background color for when a menu item is selected. + + + + + Creates and returns an instance of a menu style that makes it look like Unity's project window. + + + + + OdinMenuTree provides a tree of s, and helps with selection, inserting menu items into the tree, and can handle keyboard navigation for you. + + + + OdinMenuTree tree = new OdinMenuTree(supportsMultiSelect: true) + { + { "Home", this, EditorIcons.House }, + { "Odin Settings", null, EditorIcons.SettingsCog }, + { "Odin Settings/Color Palettes", ColorPaletteManager.Instance, EditorIcons.EyeDropper }, + { "Odin Settings/AOT Generation", AOTGenerationConfig.Instance, EditorIcons.SmartPhone }, + { "Camera current", Camera.current }, + { "Some Class", this.someData } + }; + + tree.AddAllAssetsAtPath("Some Menu Item", "Some Asset Path", typeof(ScriptableObject), true) + .AddThumbnailIcons(); + + tree.AddAssetAtPath("Some Second Menu Item", "SomeAssetPath/SomeAssetFile.asset"); + + var customMenuItem = new OdinMenuItem(tree, "Menu Style", tree.DefaultMenuStyle); + tree.MenuItems.Insert(2, customMenuItem); + + tree.Add("Menu/Items/Are/Created/As/Needed", new GUIContent()); + tree.Add("Menu/Items/Are/Created", new GUIContent("And can be overridden")); + + OdinMenuTrees are typically used with s but is made to work perfectly fine on its own for other use cases. + OdinMenuItems can be inherited and and customized to fit your needs. + + // Draw stuff + someTree.DrawMenuTree(); + // Draw stuff + someTree.HandleKeybaordMenuNavigation(); + + + + + + + + + + + Gets the currently active menu tree. + + + + + Gets the selection. + + + + + Gets the root menu items. + + + + + Gets the root menu item. + + + + + If true, all indent levels will be ignored, and all menu items with IsVisible == true will be drawn. + + + + + Adds a menu item with the specified object instance at the the specified path. + + + + + Adds a menu item with the specified object instance and icon at the the specified path. + + + + + Adds a menu item with the specified object instance and icon at the the specified path. + + + + + Adds a menu item with the specified object instance and icon at the the specified path. + + + + + Adds a collection of objects to the menu tree and returns all menu items created in random order. + + + + + Adds a collection of objects to the menu tree and returns all menu items created in random order. + + + + + Gets or sets the default menu item style from Config.DefaultStyle. + + + + + Gets or sets the default drawing configuration. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + if set to true [supports multi select]. + + + + Initializes a new instance of the class. + + if set to true [supports multi select]. + The default menu item style. + + + + Initializes a new instance of the class. + + + + + Scrolls to the specified menu item. + + + + + Enumerates the tree with a DFS. + + if set to true then the invisible root menu item is included. + + + + Enumerates the tree with a DFS. + + The predicate. + if set to true then the invisible root menu item is included. + + + + Enumerates the tree with a DFS. + + + + + Draws the menu tree recursively. + + + + + Marks the dirty. This will cause a tree.UpdateTree() in the beginning of the next Layout frame. + + + + + Draws the search toolbar. + + + + + Updates the menu tree. This method is usually called automatically when needed. + + + + + Handles the keyboard menu navigation. Call this at the end of your GUI scope, to prevent the menu tree from stealing input events from other text fields. + + Returns true, if anything was changed via the keyboard. + + + + Handles the keyboard menu navigation. Call this at the end of your GUI scope, to prevent the menu tree from stealing input events from other text fields. + + Returns true, if anything was changed via the keyboard. + + + + This class fixes a bug where Unity's Undo.RecordObject does not mark ScriptableObjects dirty when + a change is recorded for them. It does this by subscribing to the Undo.postprocessModifications + event, and marking all modified ScriptableObjects dirty manually. + + + + + The config used by OdinMenuTree to specify which features of the Menu Tree should be used when drawing. + + + + + Gets or sets the default menu item style. + + + + + The automatic scroll on selection changed. True by default. + + + + + Whether to draw the tree in a scrollable view. True by default. + + + + + Whether to handle keyboard navigation after it's done drawing. True by default. + + + + + Whether to draw a searchbar above the menu tree. True by default. + + + + + Whether to the menu items expanded state should be cached. True by default. + + + + + Whether to automatically set focus on the search bar when the tree is drawn for the first time. True by default. + + + + + The scroll-view position. + + + + + The search term. + + + + + The height of the search toolbar. + + + + + Gets or sets the search function. Null by default. + + + + + By default, the MenuTree.Selection is confirmed when menu items are double clicked, + Set this to false if you don't want that behaviour. + + + + + By default, the MenuTree.Selection is confirmed when menu items are double clicked, + Set this to false if you don't want that behaviour. + + + + + Class with utility methods for s and s. + + + + OdinMenuTree tree = new OdinMenuTree(); + tree.AddAllAssetsAtPath("Some Menu Item", "Some Asset Path", typeof(ScriptableObject), true) + .AddThumbnailIcons(); + tree.AddAssetAtPath("Some Second Menu Item", "SomeAssetPath/SomeAssetFile.asset"); + // etc... + + + + + + + + + + + Adds the menu item at the specified menu item path and populates the result list with all menu items created in order to add the menuItem at the specified path. + + The tree instance. + The result list. + The menu item path. + The menu item. + + + + Adds the menu item at specified menu item path, and returns all menu items created in order to add the menuItem at the specified path. + + The tree. + The menu item path. + The menu item. + Returns all menu items created in order to add the menu item at the specified menu item path. + + + + Gets the menu item at the specified path, returns null non was found. + + + + + Adds all asset instances from the specified path and type into a single at the specified menu item path, and returns all menu items created in order to add the menuItem at the specified path.. + + The tree. + The menu item path. + The asset folder path. + The type of objects. + Whether to search for assets in subdirectories as well. + Returns all menu items created in order to add the menu item at the specified menu item path. + + + + Adds all assets at the specified path. Each asset found gets its own menu item inside the specified menu item path. + + The tree. + The menu item path. + The asset folder path. + The type. + Whether to search for assets in subdirectories as well. + If true, sub-directories in the assetFolderPath will no longer get its own sub-menu item at the specified menu item path. + Returns all menu items created in order to add the menu item at the specified menu item path. + + + + Adds all assets at the specified path. Each asset found gets its own menu item inside the specified menu item path. + + The tree. + The menu item path. + The asset folder path. + Whether to search for assets in subdirectories as well. + If true, sub-directories in the assetFolderPath will no longer get its own sub-menu item at the specified menu item path. + Returns all menu items created in order to add the menu item at the specified menu item path. + + + + Adds the asset at the specified menu item path and returns all menu items created in order to end up at the specified menu path. + + The tree. + The menu item path. + The asset path. + Returns all menu items created in order to add the menu item at the specified menu item path. + + + + Adds the asset at the specified menu item path and returns all menu items created in order to end up at the specified menu path. + + The tree. + The menu item path. + The asset path. + The type. + Returns all menu items created in order to add the menu item at the specified menu item path. + + + + Sorts the entire tree of menu items recursively by name with respects to numbers. + + + + + Sorts the collection of menu items recursively by name with respects to numbers. This is a stable sort, meaning that equivalently ordered items will remain in the same order as they start. + + + + + Sorts the collection of menu items recursively using a given custom comparison. This is a stable sort, meaning that equivalently ordered items will remain in the same order as they start. + + + + + Adds the specified object at the specified menu item path and returns all menu items created in order to end up at the specified menu path. + + The tree. + The menu path. + The object instance. + Set this to true if you want Odin serialzied members such as dictionaries and generics to be shown as well. + Returns all menu items created in order to add the menu item at the specified menu item path. + + + + Assigns the specified icon to all menu items in the collection with the specified ObjectInstanceType. + + + + + Assigns the specified icon to all menu items in the collection with the specified ObjectInstanceType. + + + + + Assigns the specified icon to all menu items in the collection. + + + + + Assigns the specified icon to all menu items in the collection. + + + + + Assigns the specified icon to the last menu item in the collection. + + + + + Assigns the specified icon to the last menu item in the collection. + + + + + Assigns the specified icon to the last menu item in the collection. + + + + + Assigns the specified icon to the last menu item in the collection. + + + + + Assigns the specified icon to all menu items in the collection. + + + + + Assigns the specified icon to all menu items in the collection. + + + + + Assigns the specified icon to all menu items in the collection. + + + + + Assigns the asset mini thumbnail as an icon to all menu items in the collection. If the menu items object is null then a Unity folder icon is assigned. + + + + + Assigns the asset mini thumbnail as an icon to all menu items in the collection. If the menu items object is null then a Unity folder icon is assigned. + + + + + Constants which describe the type of change that was made to the OdinMenuTrees's Selection + + + + + + A menu item was removed. + + + + + A menu item was selected. + + + + + The selection was cleared. + + + + + Handles the selection of a Odin Menu Tree with support for multi selection. + + + + + + + + + + Initializes a new instance of the class. + + if set to true [supports multi select]. + + + + Occurs whenever the selection has changed. + + + + + Occurs whenever the selection has changed. + + + + + Usually occurs whenever the user hits return, or double click a menu item. + + + + + Gets the count. + + + + + Gets the first selected value, returns null if non is selected. + + + + + Gets all selected values. + + + + + Gets or sets a value indicating whether multi selection is supported. + + + + + Gets the at the specified index. + + + + + Adds a menu item to the selection. If the menu item is already selected, then the item is pushed to the bottom of the selection list. + If multi selection is off, then the previous selected menu item is removed first. + Adding a item to the selection triggers . + + The item. + + + + Clears the selection and triggers . + + + + + Determines whether an OdinMenuItem is selected. + + + + + Copies all the elements of the current array to the specified array starting at the specified destination array index. + + + + + Gets the enumerator. + + + + + Searches for the specified menu item and returns the index location. + + + + + Removes the specified menu item and triggers . + + + + + Removes the menu item at the specified index and triggers . + + + + + Triggers OnSelectionConfirmed. + + + + + Used in to associate name to a value in the GenericSelector. + + + + + + The value. + + + + + The name. + + + + + Initializes a new instance of the struct. + + + + + If the + + + + + Opens a window which displays a list of all icons available from . + + + + + Opens a window which displays a list of all icons available from . + + + + + Builds the selection tree. + + + + + A feature-rich enum selector with support for flag enums. + + + + KeyCode someEnumValue; + + [OnInspectorGUI] + void OnInspectorGUI() + { + // Use the selector manually. See the documentation for OdinSelector for more information. + if (GUILayout.Button("Open Enum Selector")) + { + EnumSelector<KeyCode> selector = new EnumSelector<KeyCode>(); + selector.SetSelection(this.someEnumValue); + selector.SelectionConfirmed += selection => this.someEnumValue = selection.FirstOrDefault(); + selector.ShowInPopup(); // Returns the Odin Editor Window instance, in case you want to mess around with that as well. + } + + // Draw an enum dropdown field which uses the EnumSelector popup: + this.someEnumValue = EnumSelector<KeyCode>.DrawEnumField(new GUIContent("My Label"), this.someEnumValue); + } + + // All Odin Selectors can be rendered anywhere with Odin. This includes the EnumSelector. + EnumSelector<KeyCode> inlineSelector; + + [ShowInInspector] + EnumSelector<KeyCode> InlineSelector + { + get { return this.inlineSelector ?? (this.inlineSelector = new EnumSelector<KeyCode>()); } + set { } + } + + + + + + + + + + + By default, the enum type will be drawn as the title for the selector. No title will be drawn if the string is null or empty. + + + + + Gets a value indicating whether this instance is flag enum. + + + + + Initializes a new instance of the class. + + + + + Populates the tree with all enum values. + + + + + When ShowInPopup is called, without a specified window width, this method gets called. + Here you can calculate and give a good default width for the popup. + The default implementation returns 0, which will let the popup window determine the width itself. This is usually a fixed value. + + + + + Gets the currently selected enum value. + + + + + Selects an enum. + + + + + Draws an enum selector field using the enum selector. + + + + + Draws an enum selector field using the enum selector. + + + + + Draws an enum selector field using the enum selector. + + + + + Draws an enum selector field using the enum selector. + + + + + In simple one-off use cases, making a custom OdinSelector might not be needed, as the GenericSelecor + can be populated with anything and customized a great deal. + + + + SomeType someValue; + + [OnInspectorGUI] + void OnInspectorGUI() + { + if (GUILayout.Button("Open Generic Selector Popup")) + { + List<SomeType> source = ...; + GenericSelector<SomeType> selector = new GenericSelector<SomeType>("Title", false, x => x.Path, source); + selector.SetSelection(this.someValue); + selector.SelectionTree.Config.DrawSearchToolbar = false; + selector.SelectionTree.DefaultMenuStyle.Height = 22; + selector.SelectionConfirmed += selection => this.someValue = selection.FirstOrDefault() + var window = selector.ShowInPopup(); + window.OnEndGUI += () => { EditorGUILayout.HelpBox("A quick way of injecting custom GUI to the editor window popup instance.", MessageType.Info); }; + window.OnClose += selector.SelectionTree.Selection.ConfirmSelection; // Confirm selection when window clses. + } + } + + + + + + + + + + + Gets or sets a value indicating whether [flattened tree]. + + + + + Gets or sets a value indicating whether [checkbox toggle]. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Gets the title. No title will be drawn if the string is null or empty. + + + + + Draws the selection tree. This gets drawn using the OnInspectorGUI attribute. + + + + + Builds the selection tree. + + + + + OdinSelectors is an abstract base class that combines OdinMenuTrees and OdinEditorWindows to help making feature-rich selectors and popup selectors. + + + + public class MySelector : OdinSelector<SomeType> + { + private readonly List<SomeType> source; + private readonly bool supportsMultiSelect; + + public MySelector(List<SomeType> source, bool supportsMultiSelect) + { + this.source = source; + this.supportsMultiSelect = supportsMultiSelect; + } + + protected override void BuildSelectionTree(OdinMenuTree tree) + { + tree.Config.DrawSearchToolbar = true; + tree.Selection.SupportsMultiSelect = this.supportsMultiSelect; + + tree.Add("Defaults/None", null); + tree.Add("Defaults/A", new SomeType()); + tree.Add("Defaults/B", new SomeType()); + + tree.AddRange(this.source, x => x.Path, x => x.SomeTexture); + } + + [OnInspectorGUI] + private void DrawInfoAboutSelectedItem() + { + SomeType selected = this.GetCurrentSelection().FirstOrDefault(); + + if (selected != null) + { + GUILayout.Label("Name: " + selected.Name); + GUILayout.Label("Data: " + selected.Data); + } + } + } + + Usage: + + void OnGUI() + { + if (GUILayout.Button("Open My Selector")) + { + List<SomeType> source = this.GetListOfThingsToSelectFrom(); + MySelector selector = new MySelector(source, false); + + selector.SetSelection(this.someValue); + + selector.SelectionCancelled += () => { }; // Occurs when the popup window is closed, and no slection was confirmed. + selector.SelectionChanged += col => { }; + selector.SelectionConfirmed += col => this.someValue = col.FirstOrDefault(); + + selector.ShowInPopup(); // Returns the Odin Editor Window instance, in case you want to mess around with that as well. + } + } + + // All Odin Selectors can be rendered anywhere with Odin. + [ShowInInspector] + MySelector inlineSelector; + + + + + + + + + + + If true, a confirm selection button will be drawn in the title-bar. + + + + + Enables the single click to select. + + + + + Occurs when the window is closed, and no slection was confirmed. + + + + + Occurs when the menuTrees selection is changed and IsValidSelection returns true. + + + + + Occurs when the menuTrees selection is confirmed and IsValidSelection returns true. + + + + + Gets the selection menu tree. + + + + + Gets the title. No title will be drawn if the string is null or empty. + + + + + Gets the current selection from the menu tree whether it's valid or not. + + + + + Determines whether the specified collection is a valid collection. + If false, the SlectionChanged and SelectionConfirm events will not be called. + By default, this returns true if the collection contains one or more items. + + + + + Sets the selection. + + + + + Sets the selection. + + + + + Opens up the selector instance in a popup at the specified rect position. + The width of the popup is determined by DefaultWindowWidth, and the height is automatically calculated. + + + + + Opens up the selector instance in a popup at the specified rect position. + + + + + Opens up the selector instance in a popup at the specified rect position. + + + + + The mouse position is used as the position for the window. + Opens up the selector instance in a popup at the specified position. + + + + + Opens up the selector instance in a popup at the specified position. + + + + + Opens up the selector instance in a popup at the specified rect position. + + + + + Opens up the selector instance in a popup at the specified position. + The width of the popup is determined by DefaultWindowWidth, and the height is automatically calculated. + + + + + Opens up the selector instance in a popup with the specified width and height. + The mouse position is used as the position for the window. + + + + + Builds the selection tree. + + + + + When ShowInPopup is called, without a specifed window width, this methods gets called. + Here you can calculate and give a good default width for the popup. + The default implementation returns 0, which will let the popup window determain the width itself. This is usually a fixed value. + + + + + Triggers the selection changed event, but only if the current selection is valid. + + + + + Draw the selecotr manually. + + + + + Draws the selection tree. This gets drawn using the OnInspectorGUI attribute. + + + + + Draws dropwdown field, that creates and binds the selector to the dropdown field. + + + + + Draws dropwdown field, that creates and binds the selector to the dropdown field. + + + + + Draws dropwdown field, that creates and binds the selector to the dropdown field. + + + + + Draws dropwdown field, that creates and binds the selector to the dropdown field. + + + + + A feature-rich type selector. + + + + Type[] selectedTypes; + + void OnGUI() + { + // Use the selector manually. See the documentation for OdinSelector for more information. + if (GUILayout.Button("Open My Selector")) + { + TypeSelector selector = new TypeSelector(customListOfTypes); + TypeSelector selector = new TypeSelector(AssemblyTypeFlags.CustomTypes, supportsMultiSelect: true); + selector.SetSelection(this.selectedTypes); + selector.SelectionConfirmed += selection => this.selectedTypes = selection.ToArray(); + selector.ShowInPopup(); // Returns the Odin Editor Window instance, in case you want to mess around with that as well. + } + } + + + + + private static Type currentSelectedType; + private static IEnumerable<Type> currentSource; + private static Func<Rect, OdinSelector<Type>> createTypeSelector = (rect) => + { + TypeSelector selector = new TypeSelector(currentSource, false); + selector.SetSelection(currentSelectedType); + selector.ShowInPopup(rect); + return selector; + }; + + public static Type DrawTypeSelectorDropdown(GUIContent label, Type selectedType, IEnumerable<Type> source) + { + currentSource = source; + currentSelectedType = selectedType; + + var dropdownText = selectedType == null ? "None" : selectedType.GetNiceName(); + var selected = TypeSelector.DrawSelectorDropdown(label, dropdownText, createTypeSelector); + if (selected != null && selected.Any()) + { + selectedType = selected.FirstOrDefault(); + } + return selectedType; + } + + + + + + Builds the selection tree. + + + + + 450 + + + + + Sets the selected types. + + + + + Editor Only Mode Utility. + + + + + Gaither all necessary information about the editor only state. + + + + + Disables Editor Only Mode. + + + + + Enables editor only mode. + + + + + Checks to see whether Editor Only Mode is enabled. + + + + + Checks to see whether Odin Inspector is installed in Source Code mode. + + + + + Contains general configuration for all Odin drawers. + + You can modify the configuration in the Odin Preferences window found in 'Tools -> Odin Inspector -> Preferences -> Drawers -> General', + or by locating the configuration file stored as a serialized object in the Sirenix folder under 'Odin Inspector/Config/Editor/GeneralDrawerConfig'. + + + + + + Specify whether or not the script selector above components should be drawn. + + + + + Specify whether or not the warning for properties that do not support prefab modifications should be shown in the inspector. + + + + + Specify whether or not the warning for properties that do not support prefab modifications should be shown in the inspector. + + + + + Specifies the maximum depth to which a property can draw itself recursively before the system refuses to draw it any deeper. + + + + + If set to true, most foldouts throughout the inspector will be expanded by default. + + + + + If set to true, buttons will show the result values from invoking them in the inspector by default. + + + + + If set to true, type matching for things such as drawers will be precomputed in a separate thread based on a cache from the previously loaded AppDomain that is stored on disk in the Project's Temp folder, resulting in some overall speedups in some cases when doing first-time type matching. Requires a recompile/project reload before it takes any effect. + + + + + Specify the animation speed for most foldouts throughout the inspector. + + + + + Specify the shaking duration for most shaking animations throughout the inspector. + + + + + Specify the animation speed for + + + + + When true the component labels, for vector fields, will be hidden when the field is too narrow. + + + + + Specify how the Quaternion struct should be shown in the inspector. + + + + + Gets or sets a value indicating whether [use improved enum drop down]. + + + + + Gets or sets a value indicating whether [use improved enum drop down]. + + + + + Specify whether or not a list should hide the foldout triangle when the list is empty. + + + + + Specifies whether a list should hide the foldout triangle when the list is empty. + + + + + Specify whether or not lists should hide the paging buttons when the list is collapsed. + + + + + Specify whether or not lists should hide the paging buttons when there is only one page. + + + + + Specify the number of elements drawn per page. + + + + + Specify whether or not lists should be expanded or collapsed by default. + + + + + Specify whether or not to include a button which expands the list, showing all pages at once. + + + + + Specify whether or not lists should show item count. + + + + + Specify whether or not lists should show item count. + + + + + Specify the color of even list elements when in the dark skin. + + + + + Specify the color of odd list elements when in the dark skin. + + + + + Specify the color of even list elements when in the light skin. + + + + + Specify the color of odd list elements when in the light skin. + + + + + Gets or sets the default size of the preview object field. + + + + + Gets or sets the default alignment of the preview object field. + + + + + Gets or sets which types should be drawn by default by the preview object field. + + + + + Resets all settings to default. + + + + + + Tell Odin which types should be drawn or should not be drawn by Odin. + + + You can modify which types should be drawn by Odin in the Preferences window found in 'Tools -> Odin Inspector -> Preferences -> Editor Types', + or by locating the configuration file stored as a serialized object in the Sirenix folder under 'Odin Inspector/Config/Editor/InspectorConfig'. + + + + + + Whether Odin is enabled in the inspector or not. + + + + + InspectorDefaultEditors is a bitmask used to tell which types should have an Odin Editor generated. + + + + + The config which contains configuration data for which types Odin should draw in the inspector. + + + + + Updates Unity with the current Odin editor configuration. + + + + + InspectorDefaultEditors is a bitmask used to tell which types should have an Odin Editor generated. + + + + + + Excludes all types. + + + + + UserTypes includes all custom user scripts that are not located in an editor or plugin folder. + + + + + PluginTypes includes all types located in the plugins folder and are not located in an editor folder. + + + + + UnityTypes includes all types depended on UnityEngine and from UnityEngine, except editor, plugin and user types. + + + + + OtherTypes include all other types that are not depended on UnityEngine or UnityEditor. + + + + + Contains configuration data for which types Odin should draw in the inspector. + + + Note that this class supports assigning arbitrary editor types to inspect any Unity object type. The Editor Types GUI in preferences simply does not, as of now, support assigning editors of any other type than . However, the API is open to further customization. + When an editor is generated for a type, a new editor type is added to the GeneratedOdinEditors assembly, which is derived from the assigned editor type - in most cases, . + You can check if an editor is compatible using . + + . + . + + + + The type binder that the uses to bind types to names, and names to types. + This is usually an instance of . + + + + + Resets the drawing configuration to the default values. + + + + + Gets a list of all drawn types that have entries in the drawing config. + + + + + Forces the config's internal drawer type to value type lookup cache to rebuild itself. + + + + + Clears the editor type entry for the given drawer, so it will be set to Unity's default. + + The drawn type to clear the editor for. + drawnType is null + + + + Assigns a given editor to draw a given type. + + The drawn type to assign an editor type for. + The editor type to assign. When generating editors, a type derived from this editor will be created and set to draw the given drawn type. + drawnType + The type " + editorType.GetNiceName() + " is not a valid base editor for type " + drawnType.GetNiceName() + ". Check criteria using . + + + + Determines whether an editor value has been assigned for a given drawn type. + + The drawn type to check. + drawnType is null + + + + Gets which editor type would draw the given type. If the type has not been assigned a custom editor type in the config, the default editor type is returned using . + + The drawn type to get an editor type for. + The editor that would draw the given type. + drawnType is null + + + + Gets the default editor that this type would have, if no custom editor was set for this type in particular. This is calculated using the value of . + + The drawn type to get the default editor for. + The editor that would draw this type by default, or null, if there is no default Odin-defined editor for the drawn type. + drawnType is null + + + + Checks whether the given editor can be assigned to draw any type using the class. + + Type of the editor to check. + True if the editor is valid, otherwise false + + + + Checks whether the given editor can be assigned to draw a given type using the class. + This method checks the attribute on the type for whether the given type is compatible. + + Type of the editor to check. + Type of the drawn value to check. If this parameter is null, the drawn type is not checked for compatibility with the editor type; only the editor type itself is checked for validity. + True if the editor is valid, otherwise false + editorType + + + + Gets the type that an editor draws, by extracting it from the editor's attribute, if it is declared. + This method returns null for abstract editor types, as those can never draw anything. + + Type of the editor. + Whether the editor in question is also an editor for types derived from the given type. + + editorType + + + + A type that indicates that a drawer is missing. + + + + + Draws an instance, and contains methods getting all types that should be drawn by Odin. + Note that this class keeps a lot of static state, and is only intended to draw the instance of that exists in the singleton asset. If used to draw other instances, odd behaviour may occur. + + . + . + + + + Determines whether Odin is capable of creating a custom editor for a given type. + + + + + Gets an array of all assigned editor types, and the types they have to draw. + + + + + Draws the property. + + + + + Contains information about an editor type which is assigned to draw a certain type in the inspector. + This class uses the instance to bind types to names, and names to types. + + . + . + . + + + + A default, empty value. + + + + + The name of the type to be drawn. + + + + + The name of the editor type. + + + + + Initializes a new instance of the struct. + + The drawn type. + drawnType is null + + + + Initializes a new instance of the struct. + + The drawn type. + The editor type. + drawnType is null + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Determines whether the specified , is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Implements the operator ==. + + The x. + The y. + + The result of the operator. + + + + + Implements the operator !=. + + The x. + The y. + + The result of the operator. + + + + + Represents a weakly typed collection of values for a - one value per selected inspector target. + + + + + Whether the values have been changed since was last called. + + + + + Marks the value collection as being clean again. This is typically called at the end of the current GUI frame, during . + + + + + Marks the value collection as being dirty, regardless of any value changes. + + + + + Reverts the value collection to its origin values (found in ) from the last call, and marks the value collection as being clean again. + + + + + Force sets the value, ignoring whether it is editable or not. + Note that this will fail on list element value entries where is true on the parent value entry. + + The selection index of the value. + The value to be set. + + + + The original values of the value collection, such as they were immediately after the last call. + + + + + Represents a strongly typed collection of values for a - one value per selected inspector target. + + + + + Gets the value at the given selection index. + + + + + The number of values in the collection. + + + + + The original values of the value collection, such as they were immediately after the last call. + + + + + Force sets the value, ignoring whether it is editable or not. + Note that this will fail on list element value entries where is true on the parent value entry. + + The selection index of the value. + The value to be set. + + + + Represents an alias for a strongly typed collection of values for a - one value per selected inspector target. + This class ensures that polymorphism works in the inspector, and can be strongly typed in applicable cases. + + The type of the aliased collection. + The polymorphic type of this collection, which is assignable to . + + + + + + Initializes a new instance of the class. + + The property. + The aliased collection. + Not yet documented. + Not yet documented. + aliasedCollection + + + + Whether the values have been changed since was last called. + + + + + The number of values in the collection. + + + + + Gets a value indicating whether this instance is synchronized. + + + true if this instance is synchronized; otherwise, false. + + + + + Gets the synchronization root object. + + + The synchronization root object. + + + + + The original values of the (loosely typed) value collection, such as they were immediately after the last call. + + + + + The original values of the value collection, such as they were immediately after the last call. + + + + + Gets or sets the at the specified index. + + + The . + + The index. + + + + + Gets an enumerator for the collection. + + + + + + Marks the value collection as being clean again. This is typically called at the end of the current GUI frame, during . + + + + + Reverts the value collection to its origin values (found in ) from the last call, and marks the value collection as being clean again. + + + + + Determines whether the collection contains the specified value. + + The value. + + true if the collection contains the specified value; otherwise, false. + + + + + Gets the index of the given value, or -1 if the value was not found. + + The value to get the index of. + + The index of the given value, or -1 if the value was not found. + + + + + Copies the collection to an array. + + The array to copy to. + The index to copy from. + + + + Gets the weakly typed value at the given index. + + The index of the value to get. + + The weakly typed value at the given index + + + + + Sets the weakly typed value at the given index. + + The index to set the value of. + The value to set. + + + + Force sets the value, ignoring whether it is editable or not. + Note that this will fail on list element value entries where is true on the parent value entry. + + The selection index of the value. + The value to be set. + + + + Force sets the value, ignoring whether it is editable or not. + Note that this will fail on list element value entries where is true on the parent value entry. + + The selection index of the value. + The value to be set. + + + + Marks the value collection as being dirty, regardless of any value changes. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Represents the values of an , and contains utilities for querying the values' type and getting and setting them. + + + + + The number of parallel values this entry represents. This will always be exactly equal to the count of . + + + + + Whether this value entry is editable or not. + + + + + If this value entry has the override type , this is the path of the property it references. + + + + + The actual serialization backend for this value entry, possibly inherited from the serialization backend of the root property this entry is a child of. + Note that this is *not* always equal to . + + + + + The property whose values this value entry represents. + + + + + Provides access to the weakly typed values of this value entry. + + + + + Whether this value entry has been changed from its prefab counterpart. + + + + + Whether this value entry has had its list length changed from its prefab counterpart. + + + + + Whether this value entry has had its dictionary values changes from its prefab counterpart. + + + + + A weakly typed smart value that represents the first element of the value entry's value collection, but has "smart logic" for setting the value that detects relevant changes and applies them in parallel. + This lets you often just use the smart value instead of having to deal with the tedium of multiple parallel values. + + + + + The type from which this value entry comes. If this value entry represents a member value, this is the declaring type of the member. If the value entry represents a collection element, this is the type of the collection. + + + + + The most precise known contained type of the value entry. If polymorphism is in effect, this will be some type derived from . + + + + + The base type of the value entry. If this is value entry represents a member value, this is the type of the member. If the value entry represents a collection element, this is the element type of the collection. + + + + + The special state of the value entry. + + + + + Whether this value entry is an alias, or not. Value entry aliases are used to provide strongly typed value entries in the case of polymorphism. + + + + + The context container of this property. + + + + + Whether this type is marked as an atomic type using a . + + + + + An event that is invoked during , when any values have changed. + + + + + An event that is invoked during , when any child values have changed. + + + + + Updates the values contained in this value entry to the actual values in the target objects, and updates its state (override, type of value, etc.) accordingly. + + + + + Applies the changes made to this value entry to the target objects, and registers prefab modifications as necessary. + + True if any changes were made, otherwise, false. + + + + Checks whether the values in this value entry are equal to the values in another value entry. + Note, both value entries must have the same value type, and must represent values that are .NET value types. + + + + + Determines whether the value at the given selection index is different from the given prefab value, as is relevant for prefab modification checks. + If the value is a reference type, null and type difference is checked. If value is a value type, a comparer from is used. + This method is best ignored unless you know what you are doing. + + The value to check differences against. + The selection index to compare against. + + + + Represents the strongly typed values of an , and contains utilities for querying the values' type and getting and setting them. + + + + + Provides access to the strongly typed values of this value entry. + + + + + A strongly typed smart value that represents the first element of the value entry's value collection, but has "smart logic" for setting the value that detects relevant changes and applies them in parallel. + This lets you often just use the smart value instead of having to deal with the tedium of multiple parallel values. + + + + + Determines whether the value at the given selection index is different from the given prefab value, as is relevant for prefab modification checks. + If the value is a reference type, null and type difference is checked. If value is a value type, a comparer from is used. + This method is best ignored unless you know what you are doing. + + The value to check differences against. + The selection index to compare against. + + + + A polymorphic alias for a instance, used to implement strongly typed polymorphism in Odin. + + + + + The number of parallel values this entry represents. This will always be exactly equal to the count of . + + + + + Whether this value entry is editable or not. + + + + + If this value entry has the override type , this is the path of the property it references. + + + + + The actual serialization backend for this value entry, possibly inherited from the serialization backend of the root property this entry is a child of. + Note that this is *not* always equal to . + + + + + The property whose values this value entry represents. + + + + + Provides access to the weakly typed values of this value entry. + + + + + Whether this value entry has been changed from its prefab counterpart. + + + + + Whether this value entry has had its list length changed from its prefab counterpart. + + + + + Whether this value entry has had its dictionary values changes from its prefab counterpart. + + + + + A weakly typed smart value that represents the first element of the value entry's value collection, but has "smart logic" for setting the value that detects relevant changes and applies them in parallel. + This lets you often just use the smart value instead of having to deal with the tedium of multiple parallel values. + + + + + The type from which this value entry comes. If this value entry represents a member value, this is the declaring type of the member. If the value entry represents a collection element, this is the type of the collection. + + + + + The most precise known contained type of the value entry. If polymorphism is in effect, this will be some type derived from . + + + + + The base type of the value entry. If this is value entry represents a member value, this is the type of the member. If the value entry represents a collection element, this is the element type of the collection. + + + + + The special state of the value entry. + + + + + Whether this value entry is an alias, or not. Value entry aliases are used to provide strongly typed value entries in the case of polymorphism. + + + + + The context container of this property. + + + + + Whether this type is marked as an atomic type using a . + + + + + An event that is invoked during , when any values have changed. + + + + + An event that is invoked during , when any child values have changed. + + + + + Applies the changes made to this value entry to the target objects, and registers prefab modifications as necessary. + + + True if any changes were made, otherwise, false. + + + + + Updates the values contained in this value entry to the actual values in the target objects, and updates its state (override, type of value, etc.) accordingly. + + + + + Checks whether the values in this value entry are equal to the values in another value entry. + Note, both value entries must have the same value type, and must represent values that are .NET value types. + + + + + Sets the actual value of a value entry, for a given selection index. + + + + + Determines whether the value at the given selection index is different from the given prefab value, as is relevant for prefab modification checks. + If the value is a reference type, null and type difference is checked. If value is a value type, a comparer from is used. + This method is best ignored unless you know what you are doing. + + The value to check differences against. + The selection index to compare against. + + + + A polymorphic alias for a instance, used to implement strongly typed polymorphism in Odin. + + + + + Initializes a new instance of the class. + + The value entry to alias. + valueEntry is null + + + + Provides access to the strongly typed values of this value entry. + + + + + A strongly typed smart value that represents the first element of the value entry's value collection, but has "smart logic" for setting the value that detects relevant changes and applies them in parallel. + This lets you often just use the smart value instead of having to deal with the tedium of multiple parallel values. + + + + + A weakly typed smart value that represents the first element of the value entry's value collection, but has "smart logic" for setting the value that detects relevant changes and applies them in parallel. + This lets you often just use the smart value instead of having to deal with the tedium of multiple parallel values. + + + + + The number of parallel values this entry represents. This will always be exactly equal to the count of . + + + + + Whether this value entry is editable or not. + + + + + If this value entry has the override type , this is the path of the property it references. + + + + + The actual serialization backend for this value entry, possibly inherited from the serialization backend of the root property this entry is a child of. + Note that this is *not* always equal to . + + + + + The property whose values this value entry represents. + + + + + Provides access to the weakly typed values of this value entry. + + + + + Whether this value entry has been changed from its prefab counterpart. + + + + + Whether this value entry has had its list length changed from its prefab counterpart. + + + + + Whether this value entry has had its dictionary values changes from its prefab counterpart. + + + + + The type from which this value entry comes. If this value entry represents a member value, this is the declaring type of the member. If the value entry represents a collection element, this is the type of the collection. + + + + + The most precise known contained type of the value entry. If polymorphism is in effect, this will be some type derived from . + + + + + The base type of the value entry. If this is value entry represents a member value, this is the type of the member. If the value entry represents a collection element, this is the element type of the collection. + + + + + The special state of the value entry. + + + + + Whether this type is marked as an atomic type using a . + + + + + An event that is invoked during , when any values have changed. + + + + + An event that is invoked during , when any child values have changed. + + + + + Applies the changes made to this value entry to the target objects, and registers prefab modifications as necessary. + + + True if any changes were made, otherwise, false. + + + + + Updates the values contained in this value entry to the actual values in the target objects, and updates its state (override, type of value, etc.) accordingly. + + + + + Checks whether the values in this value entry are equal to the values in another value entry. + Note, both value entries must have the same value type, and must represent values that are .NET value types. + + + + + Sets the actual value of a value entry, for a given selection index. + + + + + Determines whether the value at the given selection index is different from the given prefab value, as is relevant for prefab modification checks. + If the value is a reference type, null and type difference is checked. If value is a value type, a comparer from is used. + This method is best ignored unless you know what you are doing. + + The value to check differences against. + The selection index to compare against. + + + + Determines whether the value at the given selection index is different from the given prefab value, as is relevant for prefab modification checks. + If the value is a reference type, null and type difference is checked. If value is a value type, a comparer from is used. + This method is best ignored unless you know what you are doing. + + The value to check differences against. + The selection index to compare against. + + + + Draws short properties marked with . + + + + + + Not yet documented. + + + + + Draws int properties marked with . + + + + + + Not yet documented. + + + + + Draws long properties marked with . + + + + + + Not yet documented. + + + + + Draws float properties marked with . + + + + + + Not yet documented. + + + + + Draws double properties marked with . + + + + + + Not yet documented. + + + + + Draws decimal properties marked with . + + + + + + Not yet documented. + + + + + Draws Vector2 properties marked with . + + + + + + Not yet documented. + + + + + Draws Vector3 properties marked with . + + + + + + Not yet documented. + + + + + Draws Vector4 properties marked with . + + + + + + Not yet documented. + + + + + Draws properties marked with . + + + + + + + + + Draws the property. + + + + + Base class for creating editor windows using Odin. + + + + public class SomeWindow : OdinEditorWindow + { + [MenuItem("My Game/Some Window")] + private static void OpenWindow() + { + GetWindow<SomeWindow>().Show(); + } + + [Button(ButtonSizes.Large)] + public void SomeButton() { } + + [TableList] + public SomeType[] SomeTableData; + } + + + + + public class DrawSomeSingletonInAnEditorWindow : OdinEditorWindow + { + [MenuItem("My Game/Some Window")] + private static void OpenWindow() + { + GetWindow<DrawSomeSingletonInAnEditorWindow>().Show(); + } + + protected override object GetTarget() + { + return MySingleton.Instance; + } + } + + + + + private void InspectObjectInWindow() + { + OdinEditorWindow.InspectObject(someObject); + } + + private void InspectObjectInDropDownWithAutoHeight() + { + var btnRect = GUIHelper.GetCurrentLayoutRect(); + OdinEditorWindow.InspectObjectInDropDown(someObject, btnRect, btnRect.width); + } + + private void InspectObjectInDropDown() + { + var btnRect = GUIHelper.GetCurrentLayoutRect(); + OdinEditorWindow.InspectObjectInDropDown(someObject, btnRect, new Vector2(btnRect.width, 100)); + } + + private void InspectObjectInACenteredWindow() + { + var window = OdinEditorWindow.InspectObject(someObject); + window.position = GUIHelper.GetEditorWindowRect().AlignCenter(270, 200); + } + + private void OtherStuffYouCanDo() + { + var window = OdinEditorWindow.InspectObject(this.someObject); + + window.position = GUIHelper.GetEditorWindowRect().AlignCenter(270, 200); + window.titleContent = new GUIContent("Custom title", EditorIcons.RulerRect.Active); + window.OnClose += () => Debug.Log("Window Closed"); + window.OnBeginGUI += () => GUILayout.Label("-----------"); + window.OnEndGUI += () => GUILayout.Label("-----------"); + } + + + + + + + Occurs when the window is closed. + + + + + Occurs at the beginning the OnGUI method. + + + + + Occurs at the end the OnGUI method. + + + + + Gets the label width to be used. Values between 0 and 1 are treated as percentages, and values above as pixels. + + + + + Gets or sets the window padding. x = left, y = right, z = top, w = bottom. + + + + + Gets a value indicating whether the window should draw a scroll view. + + + + + Gets a value indicating whether the window should draw a Unity editor preview, if possible. + + + + + Gets the default preview height for Unity editors. + + + + + Gets the target which which the window is supposed to draw. By default it simply returns the editor window instance itself. By default, this method is called by (). + + + + + Gets the targets to be drawn by the editor window. By default this simply yield returns the method. + + + + + At the start of each OnGUI event when in the Layout event, the GetTargets() method is called and cached into a list which you can access from here. + + + + + + Pops up an editor window for the given object in a drop-down window which closes when it loses its focus. + This particular overload uses a few frames to calculate the height of the content before showing the window with a height that matches its content. + + Protip: You can subscribe to OnClose if you want to know when that occurs. + + + + + Measures the GUILayout content height and adjusts the window height accordingly. + Note that this feature becomes pointless if any layout group expands vertically. + + The max height of the window. + When the window height expands below the screen bounds, it will move the window + upwards when needed, enabling this will move it back down when the window height is decreased. + + + + + Pops up an editor window for the given object in a drop-down window which closes when it loses its focus. + + Protip: You can subscribe to OnClose if you want to know when that occurs. + + + + + + Pops up an editor window for the given object in a drop-down window which closes when it loses its focus. + + Protip: You can subscribe to OnClose if you want to know when that occurs. + + + + + + Pops up an editor window for the given object in a drop-down window which closes when it loses its focus. + + Protip: You can subscribe to OnClose if you want to know when that occurs. + + + + + + Pops up an editor window for the given object in a drop-down window which closes when it loses its focus. + + Protip: You can subscribe to OnClose if you want to know when that occurs. + + + + + + Pops up an editor window for the given object in a drop-down window which closes when it loses its focus. + + Protip: You can subscribe to OnClose if you want to know when that occurs. + + + + + + Pops up an editor window for the given object in a drop-down window which closes when it loses its focus. + + Protip: You can subscribe to OnClose if you want to know when that occurs. + + + + + Pops up an editor window for the given object. + + + + + Inspects the object using an existing OdinEditorWindow. + + + + + Creates an editor window instance for the specified object, without opening the window. + + + + + The Odin property tree drawn. + + + + + Draws the Odin Editor Window. + + + + + Calls DrawEditor(index) for each of the currently drawing targets. + + + + + Initialize get called by OnEnable and by OnGUI after assembly reloads + which often happens when you recompile or enter and exit play mode. + + + + + Called when the window is enabled. Remember to call base.OnEnable(); + + + + + Draws the editor for the this.CurrentDrawingTargets[index]. + + + + + Uses the method to draw a preview for the this.CurrentDrawingTargets[index]. + + + + + Called when the window is destroyed. Remember to call base.OnDestroy(); + + + + + Called before starting to draw all editors for the . + + + + + Called after all editors for the has been drawn. + + + + + See ISerializationCallbackReceiver.OnBeforeSerialize for documentation on how to use this method. + + + + + Implement this method to receive a callback after unity serialized your object. + + + + + Unity property drawer for abstract types. + + + + + Initializes the property drawer. + + + + + Draws the property. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Draws the default Odin inspector. + + + + + Draws the default Unity inspector. + + + + + Not yet documented. + + + + + Draws the property tree. + + + + + Called by Unity. + + + + + Called by Unity. + + + + + Unity property attribute drawer. + + + + + Initializes the drawer. + + + + + Draws the proprety. + + + + + Not yet documented. + + + + + Utility class for locating and sorting property drawers for the inspector. + See Odin manual section 'Drawers in Depth' for details on how the DrawerLocator determines which drawers to use. + + + + + + Base class for all group drawers. Use this class to create your own custom group drawers. OdinGroupDrawer are used to group multiple properties together using an attribute. + + + + Note that all box group attributes needs to inherit from the + + + + Remember to provide your custom drawer with an + in order for it to be located by the . + + + + + + Checkout the manual for more information. + + + + + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public class MyBoxGroupAttribute : PropertyGroupAttribute + { + public MyBoxGroupAttribute(string group, float order = 0) : base(group, order) + { + } + } + + // Remember to wrap your custom group drawer within a #if UNITY_EDITOR condition, or locate the file inside an Editor folder. + + public class BoxGroupAttributeDrawer : OdinGroupDrawer<MyBoxGroupAttribute> + { + protected override void DrawPropertyGroupLayout(InspectorProperty property, MyBoxGroupAttribute attribute, GUIContent label) + { + GUILayout.BeginVertical("box"); + for (int i = 0; i < property.Children.Count; i++) + { + InspectorUtilities.DrawProperty(property.Children[i]); + } + GUILayout.EndVertical(); + } + } + + // Usage: + public class MyComponent : MonoBehaviour + { + [MyBoxGroup("MyGroup")] + public int A; + + [MyBoxGroup("MyGroup")] + public int B; + + [MyBoxGroup("MyGroup")] + public int C; + } + + + + + + + + + + + + + + + + + + Draws the property with GUILayout support. + + The label. This can be null, so make sure your drawer supports that. + + + + Base drawer to inherit from to draw methods. + + + + + + DrawerPriority is used in conjunction with + to specify the priority of any given drawer. It consists of 3 components: + Super, Wrapper, Value, where Super is the most significant component, + and Standard is the least significant component. + + + + + + + + Auto priority is defined by setting all of the components to zero. + If no is defined on a drawer, it will default to AutoPriority. + + + + + The standard priority. Mostly used by s. + + + + + The attribute priority. Mostly used by s. + + + + + The wrapper priority. Mostly used by drawers used to decorate properties. + + + + + The super priority. Mostly used by drawers that wants to wrap the entire property but don't draw the actual property. + These drawers typically don't draw the property itself, and calls CallNextDrawer. + + + + + The value priority. Mostly used by s and s. + + + + + The wrapper priority. Mostly used by drawers used to decorate properties. + + + + + The super priority. Mostly used by drawers that wants to wrap the entire property but don't draw the actual property. + These drawers typically don't draw the property itself, and calls CallNextDrawer. + + + + + Initializes a new instance of the struct. + + The priority. + + + + Initializes a new instance of the struct. + + + The super priority. Mostly used by drawers that wants to wrap the entire property but don't draw the actual property. + These drawers typically don't draw the property itself, and calls CallNextDrawer. + The wrapper priority. Mostly used by drawers used to decorate properties. + The value priority. Mostly used by s and s. + + + + Implements the operator >. + + The LHS. + The RHS. + + The result of the operator. + + + + + Implements the operator <. + + The LHS. + The RHS. + + The result of the operator. + + + + + Implements the operator <=. + + The LHS. + The RHS. + + The result of the operator. + + + + + Implements the operator >=. + + The LHS. + The RHS. + + The result of the operator. + + + + + Implements the operator +. + + The LHS. + The RHS. + + The result of the operator. + + + + + Implements the operator -. + + The LHS. + The RHS. + + The result of the operator. + + + + + Implements the operator ==. + + The LHS. + The RHS. + + The result of the operator. + + + + + Implements the operator !=. + + The LHS. + The RHS. + + The result of the operator. + + + + + Gets the priority level. + + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + + A that represents this instance. + + + + + Determines whether the specified , is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Equals the specified other. + + The other. + + + + + Compares to. + + The other. + + + + + DrawerPriority is used on inspector drawers and indicates the priority of the drawer. + Use this to make your custom drawer to come before or after other drawers, and potentially hide other drawers. + + + The following example shows how DrawerPriority could be apply to a value drawer. + + [DrawerPriority(DrawerPriorityLevel.ValuePriority)] + + public sealed class MyIntDrawer : InspectorValuePropertyDrawer<int> + { + // ... + } + + + + The following example shows how DrawerPriority is used to mark a custom int drawer as a high priority drawer. + + [DrawerPriority(1, 0, 0)] + + public sealed class MySpecialIntDrawer : InspectorValuePropertyDrawer<int> + { + // ... + } + + + + + + + + The priority of the drawer. + + + + + Indicates the priority of an inspector drawer. + + Option for priority for the inspector drawer. + + + + Indicates the priority of an inspector drawer. + + + The super priority. Mostly used by drawers that wants to wrap the entire property but don't draw the actual property. + These drawers typically don't draw the property itself, and calls CallNextDrawer. + The wrapper priority. Mostly used by drawers used to decorate properties. + The value priority. Mostly used by s and s. + + + + + DrawerPriorityLevel is used in conjunction with . + + + + + + + + Auto priority is defined by setting all of the components to zero. + If no is defined on a drawer, it will default to AutoPriority. + + + + + The value priority. Mostly used by s. + + + + + The attribute priority. Mostly used by s. + + + + + The wrapper priority. Mostly used by drawers used to decorate properties. + + + + + The super priority. Mostly used by drawers that wants to wrap the entire property but don't draw the actual property. + These drawers typically don't draw the property itself, and calls CallNextDrawer. + + + + + Base class for emitted MonoBehaviour-derived types that have been created by the . + + + + + The field that backs the value of this MonoBehaviour. + + + + + Sets the value contained in this scriptable object. + + + + + Gets the value contained in this scriptable object. + + + + + Strongly typed base class for emitted MonoBehaviour-derived types that have been created by the . + + + + + Sets the value contained in this scriptable object. + + + + + Gets the value contained in this scriptable object. + + + + + Sets the value contained in this scriptable object. + + + + + Gets the value contained in this scriptable object. + + + + + Base class for emitted ScriptableObject-derived types that have been created by the . + + + + + The field that backs the value of this scriptable object. + + + + + Sets the value contained in this scriptable object. + + + + + Gets the value contained in this scriptable object. + + + + + Strongly typed base class for emitted scriptable object types that have been created by the . + + + + + Sets the value contained in this scriptable object. + + + + + Gets the value contained in this scriptable object. + + + + + Sets the value contained in this scriptable object. + + + + + Gets the value contained in this scriptable object. + + + + + This class fixes Unity's about window, by invoking "UnityEditor.VisualStudioIntegration.UnityVSSupport.GetAboutWindowLabel" before any dynamic assemblies have been defined. + This is because dynamic assemblies in the current AppDomain break that method, and Unity's about window depends on it. + + + + + + If you mark any of Unity's assemblies with the [AssemblyVersion] attribute to get a rolling assembly + version that changes sometimes (or all the time), Odin's hardcoded assembly references to user types + will break. + + + To fix this case, and all other cases of references to wrongly versioned Unity types not being resolved, + we overload the app domain's type resolution and resolve Unity user assemblies properly regardless of + version. + + + + + + Specifies hows any given drawer should drawer the property. + Changing this behavior, also changes which methods should be overridden in the drawer. + + + + + + + + + GUILayout enabled the use of GUILayout, EditorGUILayout and + + + + + Draws the property using Unity's GUI, and EditorGUI. + + + + + + Base class for attribute drawers. Use this class to create your own custom attribute drawers that will work for all types. + Alternatively you can derive from if you want to only support specific types. + + + + Odin supports the use of GUILayout and takes care of undo for you. It also takes care of multi-selection + in many simple cases. Check the manual for more information on handling multi-selection. + + + + Also note that Odin does not require that your custom attribute inherits from Unity's PropertyAttribute. + + + + The attribute that this drawer should be applied to. + + + Checkout the manual for more information. + + + + Example using the . + + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)] + public class CustomRangeAttribute : System.Attribute + { + public float Min; + public float Max; + + public CustomRangeAttribute(float min, float max) + { + this.Min = min; + this.Max = max; + } + } + + // Remember to wrap your custom attribute drawer within a #if UNITY_EDITOR condition, or locate the file inside an Editor folder. + + public sealed class CustomRangeAttributeDrawer : OdinAttributeDrawer<CustomRangeAttribute, float> + { + protected override void DrawPropertyLayout(GUIContent label) + { + this.ValueEntry.SmartValue = EditorGUILayout.Slider(label, this.ValueEntry.SmartValue, this.Attribute.Min, this.Attribute.Max); + } + } + + // Usage: + public class MyComponent : MonoBehaviour + { + [CustomRangeAttribute(0, 1)] + public float MyFloat; + } + + + + + Example using the . + + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)] + public class GUITintColorAttribute : System.Attribute + { + public Color Color; + + public GUITintColorAttribute(float r, float g, float b, float a = 1) + { + this.Color = new Color(r, g, b, a); + } + } + + // Remember to wrap your custom attribute drawer within a #if UNITY_EDITOR condition, or locate the file inside an Editor folder. + + public sealed class GUITintColorAttributeDrawer : OdinAttributeDrawer<GUITintColorAttribute> + { + protected override void DrawPropertyLayout(GUIContent label) + { + Color prevColor = GUI.color; + GUI.color *= this.Attribute.Color; + this.CallNextDrawer(label); + GUI.color = prevColor; + } + } + + // Usage: + public class MyComponent : MonoBehaviour + { + [GUITintColor(0, 1, 0)] + public float MyFloat; + } + + + + + + Odin uses multiple drawers to draw any given property, and the order in which these drawers are + called are defined using the . + Your custom drawer injects itself into this chain of drawers based on its . + If no is defined, a priority is generated automatically based on the type of the drawer. + Each drawer can ether choose to draw the property or not, or pass on the responsibility to the + next drawer by calling CallNextDrawer(), as the f attribute does in the example above. + + + + This means that there is no guarantee that your drawer will be called, sins other drawers + could have a higher priority than yours and choose not to call CallNextDrawer(). + + + + Note that Odin's has full support for generic class constraints, + and if that is not enough, you can also add additional type constraints by overriding CanDrawTypeFilter + + + + Also note that all custom property drawers needs to handle cases where the label provided by the DrawPropertyLayout is null, + otherwise exceptions will be thrown when in cases where the label is hidden. For instance when [HideLabel] is used, or the property is drawn within a list where labels are also not shown. + + + + [DrawerPriority(DrawerPriorityLevel.AttributePriority)] + public sealed class MyCustomAttributeDrawer<T> : OdinAttributeDrawer<MyCustomAttribute, T> where T : class + { + public override bool CanDrawTypeFilter(Type type) + { + return type != typeof(string); + } + + protected override void DrawPropertyLayout(GUIContent label) + { + // Draw property here. + } + } + + + + + + + + + + + + + + + + + + Gets the attribute that the OdinAttributeDrawer draws for. + + + + + Tells whether or not multiple attributes are allowed. + + + + + Draws the property with the given label. + Override this to implement your custom OdinAttributeDrawer. + + Optional label for the property. + + + + Tests if the drawer can draw for the specified property. + + The property to test. + true if the drawer can drawn the property. Otherwise false. + + + + Tests if the attribute drawer can draw for the specified property. + + The property to test. + true if the drawer can drawn the property. Otherwise false. + + + + + Base class for all type specific attribute drawers. For non-type specific attribute drawers see . + + + + Odin supports the use of GUILayout and takes care of undo for you. It also takes care of multi-selection + in many simple cases. Checkout the manual for more information on handling multi-selection. + + + + Also note that Odin does not require that your custom attribute inherits from Unity's PropertyAttribute. + + + + The attribute that this drawer should be applied to. + The type of the value the drawer should be drawing. Note that Odin's has full support for generic constraints. + + + Checkout the manual for more information. + + + + Example using the . + + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)] + public class CustomRangeAttribute : System.Attribute + { + public float Min; + public float Max; + + public CustomRangeAttribute(float min, float max) + { + this.Min = min; + this.Max = max; + } + } + + // Remember to wrap your custom attribute drawer within a #if UNITY_EDITOR condition, or locate the file inside an Editor folder. + + public sealed class CustomRangeAttributeDrawer : OdinAttributeDrawer<CustomRangeAttribute, float> + { + protected override void DrawPropertyLayout(GUIContent label) + { + this.ValueEntry.SmartValue = EditorGUILayout.Slider(label, this.ValueEntry.SmartValue, this.Attribute.Min, this.Attribute.Max); + } + } + + // Usage: + public class MyComponent : MonoBehaviour + { + [CustomRangeAttribute(0, 1)] + public float MyFloat; + } + + + + + Example using the . + + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)] + public class GUITintColorAttribute : System.Attribute + { + public Color Color; + + public GUITintColorAttribute(float r, float g, float b, float a = 1) + { + this.Color = new Color(r, g, b, a); + } + } + + // Remember to wrap your custom attribute drawer within a #if UNITY_EDITOR condition, or locate the file inside an Editor folder. + + public sealed class GUITintColorAttributeDrawer : OdinAttributeDrawer<GUITintColorAttribute> + { + protected override void DrawPropertyLayout(GUIContent label) + { + Color prevColor = GUI.color; + GUI.color *= this.Attribute.Color; + this.CallNextDrawer(label); + GUI.color = prevColor; + } + } + + // Usage: + public class MyComponent : MonoBehaviour + { + [GUITintColor(0, 1, 0)] + public float MyFloat; + } + + + + + + Odin uses multiple drawers to draw any given property, and the order in which these drawers are + called is defined using the . + Your custom drawer injects itself into this chain of drawers based on its . + If no is defined, a priority is generated automatically based on the type of the drawer. + Each drawer can ether choose to draw the property or not, or pass on the responsibility to the + next drawer by calling CallNextDrawer(), as the GUITintColor attribute does in the example above. + + + + This means that there is no guarantee that your drawer will be called, since other drawers + could have a higher priority than yours and choose not to call CallNextDrawer(). + + + + Note that Odin's has full support for generic class constraints, + and if that is not enough, you can also add additional type constraints by overriding CanDrawTypeFilter + + + + Also note that all custom property drawers needs to handle cases where the label provided by the DrawPropertyLayout is null, + otherwise exceptions will be thrown when in cases where the label is hidden. For instance when [HideLabel] is used, or the property is drawn within a list where labels are also not shown. + + + + [DrawerPriority(DrawerPriorityLevel.AttributePriority)] + public class MyCustomAttributeDrawer<T> : OdinAttributeDrawer<MyCustomAttribute, T> where T : class + { + public override bool CanDrawTypeFilter(Type type) + { + return type != typeof(string); + } + + protected override void DrawPropertyLayout(GUIContent label) + { + // Draw property here. + } + } + + + + + + + + + + + + + + + + + + Gets the strongly typed ValueEntry of the OdinAttributeDrawer's property. + + + + + Draws the property with the given label. + Override this to implement your custom OdinAttributeDrawer. + + Optional label for the property. + + + + Tests if the drawer can draw for the specified property. + + The property to test. + true if the drawer can drawn the property. Otherwise false. + + + + Tests if the attribute drawer can draw for the specified property. + + The property to test. + true if the drawer can drawn the property. Otherwise false. + + + + Some drawers don't want to have its GUI disabled, even if the property is read-only or a ReadOnly attribute is defined on the property. + Use this attribute on any drawer to force GUI being enabled in these cases. + + + + + [AllowGUIEnabledForReadonly] + public sealed class SomeDrawerDrawer<T> : OdinValueDrawer<T> where T : class + { + } + + + + + + + Base class for all Odin drawers. In order to create your own custom drawers you need to derive from one of the following drawers: + + + + + + + + Remember to provide your custom drawer with an in order for it to be located by the . + Drawers require a context, and are instantiated automatically by the . + Odin supports the use of GUILayout and takes care of undo for you. It also takes care of multi-selection in many simple cases. Checkout the manual for more information. + + + + + + + + + + + + + + + + + If true then this drawer will be skipped in the draw chain. Otherwise the drawer will be called as normal in the draw chain. + + + + + Gets a value indicating if the drawer has been initialized yet. + + + + + Gets the property this drawer draws for. + + + + + Override this method in order to define custom type constraints to specify whether or not a type should be drawn by the drawer. + Note that Odin's has full support for generic class constraints, so most often you can get away with not overriding CanDrawTypeFilter. + + The type. + + Returns true by default, unless overridden. + + + + + Initializes the drawer instance. + + + + + + Initializes the drawer instance. Override this to implement your own initialization logic. + + + + + Draws the property with a custom label. + + The label. Null is allow if you wish no label should be drawn. + + + + Draws the property with GUILayout support. + + The label. This can be null, so make sure your drawer supports that. + + + + Calls the next drawer in the draw chain. + + The label to pass on to the next drawer. + + + + Gets a value indicating if the drawer can draw for the specified property. + Override this to implement a custom property filter for your drawer. + + The property to test. + true if the drawer can draw for the property. Otherwise false. + + + + Provides a variety of miscellaneous utilities widely used in the inspector. + + + + + Converts an Odin property path to a deep reflection path. + + + + + Converts an Odin property path (without groups included) into a Unity property path. + + + + + Prepares a property tree for drawing, and handles management of undo, as well as marking scenes and drawn assets dirty. + + The tree to be drawn. + Whether to register undo commands for the changes made to the tree. This can only be set to true if the tree has a to represent. + tree is null + + + + Ends drawing a property tree, and handles management of undo, as well as marking scenes and drawn assets dirty. + + The tree. + + + + Draws all properties in a given property tree; must be wrapped by a and . + + The tree to be drawn. + + + + Draws a property in the inspector using a given label. + + + + + Odin property system exception. + + + + + Initializes a new instance of OdinPropertyException. + + The message for the exception. + An inner exception. + + + + + Base class for all value drawers. Use this class to create your own custom drawers for any specific type. + + + + Remember to provide your custom drawer with an + in order for it to be located by the . + + + + Odin supports the use of GUILayout and takes care of undo for you. It also takes care of multi-selection + in many simple cases. Checkout the manual for more information on handling multi-selection. + + + + + Checkout the manual for more information. + + + + + public class MyCustomBaseType + { + + } + + public class MyCustomType : MyCustomBaseType + { + + } + + // Remember to wrap your custom attribute drawer within a #if UNITY_EDITOR condition, or locate the file inside an Editor folder. + + public sealed class MyCustomBaseTypeDrawer<T> : OdinValueDrawer<T> where T : MyCustomBaseType + { + protected override void DrawPropertyLayout(IPropertyValueEntry<T> entry, GUIContent label) + { + T value = entry.SmartValue; + // Draw your custom drawer here using GUILayout and EditorGUILAyout. + } + } + + // Usage: + // Both values will be drawn using the MyCustomBaseTypeDrawer + public class MyComponent : SerializedMonoBehaviour + { + public MyCustomBaseType A; + + public MyCustomType B; + } + + + + + + Odin uses multiple drawers to draw any given property, and the order in which these drawers are + called are defined using the . + Your custom drawer injects itself into this chain of drawers based on its . + If no is defined, a priority is generated automatically based on the type of the drawer. + Each drawer can ether choose to draw the property or not, or pass on the responsibility to the + next drawer by calling CallNextDrawer(). An example of this is provided in the documentation for . + + + + This means that there is no guarantee that your drawer will be called, sins other drawers + could have a higher priority than yours and choose not to call CallNextDrawer(). + + + + To avoid this, you can tell Odin, that your drawer is a PrependDecorator or an AppendDecorator drawer (see ) as shown in the example shows below. + Prepend and append decorators are always drawn and are also ordered by the . + + + + Note that Odin's have full support for generic class constraints, + and if that is not enough, you can also add additional type constraints by overriding CanDrawTypeFilter(Type type). + + + + Also note that all custom property drawers needs to handle cases where the label provided by the DrawPropertyLayout is null, + otherwise exceptions will be thrown when in cases where the label is hidden. For instance when [HideLabel] is used, or the property is drawn within a list where labels are also not shown. + + + + // [OdinDrawer(OdinDrawerBehaviour.DrawProperty)] // default + // [OdinDrawer(OdinDrawerBehaviour.AppendDecorator)] + [OdinDrawer(OdinDrawerBehaviour.PrependDecorator)] + [DrawerPriority(DrawerPriorityLevel.AttributePriority)] + public sealed class MyCustomTypeDrawer<T> : OdinValueDrawer<T> where T : MyCustomType + { + public override bool CanDrawTypeFilter(Type type) + { + return type != typeof(SomeType); + } + + protected override void DrawPropertyLayout(IPropertyValueEntry<T> entry, GUIContent label) + { + T value = entry.SmartValue; + // Draw property here. + } + } + + + + + + + + + + + + + + + + + + + The value entry of the property. + + + + + Draws the property with GUILayout support. + + The label. This can be null, so make sure your drawer supports that. + + + + Gets a value indicating if the drawer can draw for the specified property. + + The property to test. + true if the drawer can draw for the property. Otherwise false. + + + + Gets a value indicating if the drawer can draw for the specified property. + Override this to implement a custom property filter for your drawer. + + The property to test. + true if the drawer can draw for the property. Otherwise false. + + + + Custom types used by the can choose to implement the ITemporaryContext + interface in order to be notified when the context gets reset. + + + + + Called by when the context gets reset. + + + + + Used by all InspectorProperty to tell Odin how to set or get a value on any given property. + + + + + Whether the value is readonly. + + + + + Gets the type of the owner. + + + + + Gets the type of the value. + + + + + Sets the weakly typed value on a given weakly typed owner. + + The owner. + The value. + + + + Gets the value from a given weakly typed owner. + + The weakly typed owner. + The found value. + + + + Used by all to tell Odin how to set or get a value on any given property. + + + + + Sets the value on a given owner. + + The owner. + The value. + + + + Gets the value from a given owner. + + The owner. + + + + When creating custom property drawers with or etc, + an OdinDrawerAttribute must be defined on the custom drawer class itself in order to specify that the drawer is meant to be included in the inspector. + If no OdinDrawerAttribute is defined, the will ignore your drawer. + + + Checkout the manual for more information. + + + + // Specify that this drawer must be included in the inspector; without this, it will not be drawn + public class MyCustomTypeDrawer<T> : OdinValueDrawer<T> where T : MyCustomBaseType + { + protected override void DrawPropertyLayout(IPropertyValueEntry<T> entry, GUIContent label) + { + T value = entry.SmartValue; + // Draw property here. + + // Optionally, call the next drawer in line. + this.CallNextDrawer(entry, label); + } + } + + + + + + + + + + + + Initializes a new instance of the class. + + + + + Property drawer for primitive composite properties. + + + + + Draws the property. + + + + + Draws the property field. + + + + + Represents the children of an . + + + + + The that this instance handles children for. + + + + + Gets a child by index. This is an alias for . + + The index of the child to get. + The child at the given index. + + + + Gets a child by name. This is an alias for . + + The name of the child to get. + The child, if a child was found; otherwise, null. + + + + Gets a child by name. This is an alias for . + + The name of the child to get. + The child, if a child was found; otherwise, null. + + + + Initializes a new instance of the class. + + The property to handle children for. + property is null + + + + The number of children on the property. + + + + + Updates this instance of . + + + + + Gets a child by name. + + The name of the child to get. + The child, if a child was found; otherwise, null. + name + + + + Gets a child by name. + + The name of the child to get. + The child, if a child was found; otherwise, null. + name + + + + Gets a child by index. + + The index of the child to get. + + The child at the given index. + + The given index was out of range. + + + + Gets the path of the child at a given index. + + The index to get the path of. + The path of the child at the given index. + The given index was out of range. + + + + Returns an IEnumerable that recursively yields all children of the property, depth first. + + + + + Gets the property's already created children. If the child count is less than or equal to 10000, children are returned in order. If the count is larger than 10000, they are returned in no particular order. + + + + + Gets the enumerator. + + + + + Gets the enumerator. + + + + + Represents a weakly typed collection of values for a - one value per selected inspector target. + + + + + The property whose values are represented. + + + + + Initializes a new instance of the class. + + The property to represent. + property is null + + + + Whether the values have been changed since was last called. + + + + + The number of values in the collection. + + + + + Gets a value indicating whether this instance is synchronized. + + + true if this instance is synchronized; otherwise, false. + + + + + Gets the synchronization root object. + + + The synchronization root object. + + + + + The original values of the (loosely typed) value collection, such as they were immediately after the last call. + + + + + Gets or sets the weakly typed at the specified index. + + + The value. + + The index to set. + + + + Gets an enumerator for the collection. + + + + + Marks the value collection as being clean again. This is typically called at the end of the current GUI frame, during . + + + + + Reverts the value collection to its origin values (found in ) from the last call, and marks the value collection as being clean again. + + + + + Determines whether the collection contains the specified value. + + The value. + + true if the collection contains the specified value; otherwise, false. + + + + + Copies the collection to an array. + + The array to copy to. + The index to copy from. + + + + Gets the index of the given value, or -1 if the value was not found. + + The value to get the index of. + The index of the given value, or -1 if the value was not found. + + + + Gets the weakly typed value at the given index. + + The index of the value to get. + The weakly typed value at the given index + + + + Sets the weakly typed value at the given index. + + The index to set the value of. + The value to set. + + + + Force sets the value, ignoring whether it is editable or not. + Note that this will fail on list element value entries where is true on the parent value entry. + + The selection index of the value. + The value to be set. + + + + Marks the value collection as being dirty, regardless of any value changes. + + + + + Represents a strongly typed collection of values for a - one value per selected inspector target. + + The element type of the collection. + + + + + Initializes a new instance of the class. + + The property. + The internal array. + The original array. + The internal atom array. + The original atom array. + + + + Whether the values have been changed since was last called. + + + + + The number of values in the collection. + + + + + Gets a value indicating whether this instance is synchronized. + + + true if this instance is synchronized; otherwise, false. + + + + + Gets the synchronization root object. + + + The synchronization root object. + + + + + The original values of the (loosely typed) value collection, such as they were immediately after the last call. + + + + + Gets or sets the at the specified index. + + + The . + + The index. + + + + + Gets an enumerator for the collection. + + + + + Marks the value collection as being clean again. This is typically called at the end of the current GUI frame, during . + + + + + Reverts the value collection to its origin values (found in ) from the last call, and marks the value collection as being clean again. + + + + + Copies the collection to an array. + + The array to copy to. + The index to copy from. + + + + Gets the weakly typed value at the given index. + + The index of the value to get. + + The weakly typed value at the given index + + + + + Sets the weakly typed value at the given index. + + The index to set the value of. + The value to set. + + + + Determines whether the collection contains the specified value. + + The value. + + true if the collection contains the specified value; otherwise, false. + + + + + Gets the index of the given value, or -1 if the value was not found. + + The value to get the index of. + + The index of the given value, or -1 if the value was not found. + + + + + Force sets the value, ignoring whether it is editable or not. + Note that this will fail on list element value entries where is true on the parent value entry. + + The selection index of the value. + The value to be set. + + + + Force sets the value, ignoring whether it is editable or not. + Note that this will fail on list element value entries where is true on the parent value entry. + + The selection index of the value. + The value to be set. + + + + + Marks the value collection as being dirty, regardless of any value changes. + + + + + A contextual value attached to an , mapped to a key, contained in a . + + + + + The contained value. + + + + + Creates a new PropertyContext. + + + + + Performs an explicit conversion from to . + + The context. + + The result of the conversion. + + + + + Returns a that represents this instance, of the format ": Value.ToString()". + + + A that represents this instance. + + + + + Contains a context for an , which offers the ability to address persistent values by key across several editor GUI frames. + Use this in drawers to store contextual editor-only values such as the state of a foldout. + + + + + Initializes a new instance of the class. + + The property. + property + + + + Gets a global context value for a given key, using a given delegate to generate a default value if the context doesn't already exist. + Global contexts are not associated with any one specific drawer, and so are shared across all drawers for this property. + + The type of the context value to get. + The key of the context value to get. + A delegate for generating a default value. + The found context. + + + + Gets a global context value for a given key, using a given default value if the context doesn't already exist. + Global contexts are not associated with any one specific drawer, and so are shared across all drawers for this property. + + The type of the context value to get. + The key of the context value to get. + The default value to set if the context value doesn't exist yet. + The found context. + + + + Gets a global context value for a given key, and creates a new instance of as a default value if the context doesn't already exist. + Global contexts are not associated with any one specific drawer, and so are shared across all drawers for this property. + + The type of the context value to get. + The key of the context value to get. + The found context. + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Local property contexts are obsolete. Use local drawer fields instead. + + + + + Gets a object and creates a object for it. + + The type of the value of the context. + The instance of the drawer. + The key for the context. + The default value for the context. + + + + Gets a object and creates a object for it. + Returns true when the is first created. Otherwise false. + + The type of the value of the context. + The instance of the drawer. + The key for the context. + The object. + Returns true when the is first created. Otherwise false. + + + + Swaps context values with a given . + + The context to swap with. + + + + An can implement this interface to indicate that it defines right-click context menu items for properties that it draws. + + + + + Method that is invoked when a user has right-clicked a property, and the context menu is being built. The method is invoked in order of drawer priority. + + The property that has been right-clicked on. + The generic menu instance that is being built. Add items to this. + + + + A polymorphic alias for getting and setting the values of an . + + The type of the owner. + The type of the value. + The type of the property owner. + The type of the property value. + + + + Gets the type of the owner. + + + + + Gets the type of the value. + + + + + Whether the value is readonly. + + + + + Initializes a new instance of the class. + + The information. + info + + + + Gets the value from a given weakly typed owner. + + The weakly typed owner. + The found value. + + + + Gets the value from a given owner. + + The owner. + owner is null + + + + Sets the weakly typed value on a given weakly typed owner. + + The owner. + The value. + + + + Sets the value on a given owner. + + The owner. + The value. + + + + Contains meta-data information about a property in the inspector, that can be used to create an actual property instance. + + + + + The name of the property. + + + + + Gets a value indicating whether this InspectorPropertyInfo has any backing members. + + + + + Gets a value indicating whether this InspectorPropertyInfo has only a single backing member. + + + + + The member info of the property. If the property has many member infos, such as if it is a group property, the first member info of is returned. + + + + + Indicates which type of property it is. + + + + + The serialization backend for this property. + + + + + The type on which this property is declared. + + + + + The base type of the value which this property represents. If there is no value, this will be null. + + + + + Whether this property is editable or not. + + + + + All member infos of the property. There will only be more than one member if it is an . + + + + + The order value of this property. Properties are (by convention) ordered by ascending order, IE, lower order values are shown first in the inspector. The final actual ordering of properties is decided upon by the property resolver. + + + + + The attributes associated with this property. + + + + + Whether this property only exists as a Unity , and has no associated managed member to represent it. + This case requires some special one-off custom behaviour in a few places. + + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Gets the first attribute of a given type on this property. + + + + + Gets the first attribute of a given type on this property, which is not contained in a given hashset. + + The attributes to exclude. + + + + Gets all attributes of a given type on the property. + + + + + The s of all the individual properties in this group. + + + + + Gets the property's method delegate, if there is one. Note that this is null if a method property is backed by an actual method member. + + + + + Represents a property in the inspector, and provides the hub for all functionality related to that property. + + + + + Gets the property which is the ultimate root of this property's serialization. + + + + + The name of the property. + + + + + The nice name of the property, usually as converted by . + + + + + The cached label of the property, usually containing . + + + + + The full Odin path of the property. To get the Unity property path, see . + + + + + The child index of this property. + + + + + Gets the resolver for this property's children. + + + + + The current recursive draw depth, incremented for each time that the property has caused itself to be drawn recursively. + Note that this is the current recursion level, not the total amount of recursions so far this frame. + + + + + The amount of times that the property has been drawn so far this frame. + + + + + How deep in the drawer chain the property currently is, in the current drawing session as determined by . + + + + + Whether this property supports having prefab modifications applied or not. + + + + + Gets an immutable list of the components attached to the property. + + + + + Gets an immutable list of processed attributes for the property. + + + + + Gets an array of the state updaters of the property. Don't change the contents of this array! + + + + + The value entry that represents the base value of this property. + + + + + The value entry that represents the strongly typed value of the property; this is possibly an alias entry in case of polymorphism. + + + + + The parent of the property. If null, this property is a root-level property in the . + + + + + The of this property. + + + + + The that this property exists in. + + + + + The children of this property. + + + + + The context container of this property. + + + + + The last rect that this property was drawn within. + + + + + The type on which this property is declared. This is the same as . + + + + + The parent values of this property, by selection index; this represents the values that 'own' this property, on which it is declared. + + + + + The full Unity property path of this property; note that this is merely a converted version of , and not necessarily a path to an actual Unity property. + In the case of Odin-serialized data, for example, no Unity properties will exist at this path. + + + + + The full path of this property as used by deep reflection, containing all the necessary information to find this property through reflection only. This is used as the path for prefab modifications. + + + + + The full path of this property as used by prefab modifications and the deep reflection system, containing all the necessary information to find this property through reflection only. + + + + + The PropertyState of the property at the current draw count index. + + + + + Gets the component of a given type on the property, or null if the property does not have a component of the given type. + + + + + Marks the property's serialization root values dirty if they are derived from UnityEngine.Object. + + + + + Records the property's serialization root for undo to prepare for undoable changes, with a custom string that includes the property path and Unity object name. If a message is specified, it is included in the custom undo string. + + + + + Gets the first attribute of a given type on this property. + + + + + Gets the first attribute of a given type on this property, which is not contained in a given hashset. + + The attributes to exclude. + + + + Gets all attributes of a given type on the property. + + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Draws this property in the inspector. + + + + + Draws this property in the inspector with a given default label. This default label may be overridden by attributes on the drawn property. + + + + + Push a draw session. This is used by and . + + + + + Increments the current drawer chain index. This is used by . + + + + + Pop a draw session. This is used by and . + + + + + Gets the next property in the , or null if none is found. + + Whether to include children or not. + Whether to only include visible properties. + + + + Finds the first parent property that matches a given predicate. + + + + + Finds the first child recursively, that matches a given predicate. + + + + + Updates the property. This method resets the temporary context, and updates the value entry and the property children. + + If true, the property will update regardless of whether it has already updated for the current . + + + + Populates a generic menu with items from all drawers for this property that implement . + + + + + Determines whether this property is the child of another property in the hierarchy. + + The property to check whether this property is the child of. + other is null + + + + Determines whether this property is a parent of another property in the hierarchy. + + The property to check whether this property is the parent of. + other is null + + + + Represents a set of values of the same type as a tree of properties that can be drawn in the inspector, and provides an array of utilities for querying the tree of properties. + + + + + Delegate for on property value changed callback. + + + + + The component providers that create components for each property in the tree. If you change this list after the tree has been used, you should call tree.RootProperty.RefreshSetup() to make the changes update properly throughout the tree. + + + + + The that this tree represents, if the tree was created for a . + + + + + The current update ID of the tree. This is incremented once, each update, and is used by to avoid updating multiple times in the same update round. + + + + + The type of the values that the property tree represents. + + + + + The actual values that the property tree represents. + + + + + The number of root properties in the tree. + + + + + The prefab modification handler of the tree. + + + + + Whether this property tree also represents members that are specially serialized by Odin. + + + + + Gets a value indicating whether or not to draw the mono script object field at the top of the property tree. + + + + + Gets a value indicating whether or not the PropertyTree is inspecting a static type. + + + + + Gets or sets the for the PropertyTree. + + + + + Gets or sets the for the PropertyTree. + + + + + Gets or sets the for the PropertyTree. + + + + + Gets or sets the for the PropertyTree. + + + + + An event that is invoked whenever an undo or a redo is performed in the inspector. + The advantage of using this event on a property tree instance instead of + is that this event will be desubscribed from + when the selection changes and the property + tree is no longer being used, allowing the GC to collect the property tree. + + + + + This event is invoked whenever the value of any property in the entire property tree is changed through the property system. + + + + + Creates a new for all target values of a . + + + + + Gets the root property of the tree. + + + + + Gets the secret root property of the tree, which hosts the property resolver used to resolve the "actual" root properties of the tree. + + + + + Registers that a given property is dirty and needs its changes to be applied at the end of the current frame. + + + + + Schedules a delegate to be invoked at the end of the current GUI frame. + + The action delegate to be delayed. + + + + Schedules a delegate to be invoked at the end of the next Repaint GUI frame. + + The action to be delayed. + + + + Enumerates over the properties of the tree. + + Whether to include children of the root properties or not. If set to true, every property in the entire tree will be enumerated. + Whether to only include visible properties. Properties whose parents are invisible are considered invisible. + + + + Gets the property at the given path. Note that this is the path found in , not the Unity path. + + The path of the property to get. + + + + Gets the property at the given path. Note that this is the path found in , not the Unity path. + + The path of the property to get. + + + + + Gets the property at the given Unity path. + + The Unity path of the property to get. + + + + Gets the property at the given Unity path. + + The Unity path of the property to get. + + + + + Gets the property at the given deep reflection path. + + The deep reflection path of the property to get. + + + + Gets the property at the given Odin prefab modification path. + + The prefab modification path of the property to get. + + + + Gets the property at the given Odin prefab modification path. + + The prefab modification path of the property to get. + + + + + Draw the property tree, and handles management of undo, as well as marking scenes and drawn assets dirty. + + This is a shorthand for calling + , + and . + . + + + + + + Draws a search bar for the property tree, and draws the search results if the search bar is used. + If this method returns true, the property tree should generally not be drawn normally afterwards. + Note that this method will throw exceptions if the property tree is not set up to be searchable; for that, see . + + True if the property tree is being searched and is currently drawing its search results, otherwise false. + + + + Gets a Unity property for the given Odin or Unity path. If there is no for this property tree, or no such property is found in the , a property will be emitted using . + + The Odin or Unity path to the property to get. + + + + Gets a Unity property for the given Odin or Unity path. If there is no for this property tree, or no such property is found in the , a property will be emitted using . + + The Odin or Unity path to the property to get. + The backing field of the Unity property. + + + + Checks whether a given object instance is referenced anywhere in the tree, and if it is, gives the path of the first time the object reference was encountered as an out parameter. + + The reference value to check. + The first found path of the object. + + + + Gets the number of references to a given object instance in this tree. + + + + + Updates all properties in the entire tree, and validates the prefab state of the tree, if applicable. + + + + + Replaces all occurrences of a value with another value, in the entire tree. + + The value to find all instances of. + The value to replace the found values with. + + + + Gets the root tree property at a given index. + + The index of the property to get. + + + + Invokes the actions that have been delayed using and . + + + + + Applies all changes made with properties to the inspected target tree values, and marks all changed Unity objects dirty. + + true if any values were changed, otherwise false + + + + Invokes the OnValidate method on the property tree's targets if they are derived from and have the method defined. + + + + + Registers an object reference to a given path; this is used to ensure that objects are always registered after having been encountered once. + + The referenced object. + The property that contains the reference. + + + + Creates a PropertyTree to inspect the static values of the given type. + + The type to inspect. + A PropertyTree instance for inspecting the type. + + + + Creates a new for a given target value. + + The target to create a tree for. + target is null + + + + Creates a new for a set of given target values. + Note that the targets all need to be of the same type. + + The targets to create a tree for. + targets is null + + + + Creates a new for all target values of a . + + The serialized object to create a tree for. + serializedObject is null + + + + Creates a new for a set of given target values. + Note that the targets all need to be of the same type. + + The targets to create a tree for. + + + + Creates a new for a set of given target values, represented by a given . + Note that the targets all need to be of the same type. + + The targets to create a tree for. + The serialized object to create a tree for. Note that the target values of the given must be the same values given in the targets parameter. + + + + Sets whether the property tree should be searchable or not, and allows the passing in of a custom SearchableAttribute instance to configure the search. + + Whether the tree should be set to be searchable or not. + If the tree is set to be searchable, then if this parameter is not null, it will be used to configure the property tree search. If the parameter is null, the SearchableAttribute on the tree's will be used. If that property has no such attribute, then default search settings will be applied. + + + + Represents a set of strongly typed values as a tree of properties that can be drawn in the inspector, and provides an array of utilities for querying the tree of properties. + This class also handles management of prefab modifications. + + + + + Gets the root property of the tree. + + + + + Gets the secret root property of the PropertyTree. + + + + + Gets the for the PropertyTree. + + + + + The current update ID of the tree. This is incremented once, each update, and is used by to avoid updating multiple times in the same update round. + + + + + The that this tree represents, if the tree was created for a . + + + + + The type of the values that the property tree represents. + + + + + The strongly types actual values that the property tree represents. + + + + + The weakly types actual values that the property tree represents. + + + + + The number of root properties in the tree. + + + + + Whether this property tree also represents members that are specially serialized by Odin. + + + + + Initializes a new instance of the class, inspecting only the target () type's static members. + + + + + Initializes a new instance of the class. + + The serialized object to represent. + + + + Initializes a new instance of the class. + + The targets to represent. + + + + Initializes a new instance of the class. + + The targets to represent. + The serialized object to represent. Note that the target values of the given must be the same values given in the targets parameter. + targets is null + + There must be at least one target. + or + A given target is a null value. + + + + + Applies all changes made with properties to the inspected target tree values. + + + true if any values were changed, otherwise false + + + + + Registers that a given property is dirty and needs its changes to be applied at the end of the current frame. + + + + + + + Updates all properties in the entire tree, and validates the prefab state of the tree, if applicable. + + + + + Checks whether a given object instance is referenced anywhere in the tree, and if it is, gives the path of the first time the object reference was encountered as an out parameter. + + The reference value to check. + The first found path of the object. + + + + Gets the number of references to a given object instance in this tree. + + + + + + Gets the property at the given path. Note that this is the path found in , not the Unity path. + + The path of the property to get. + + + + Gets the property at the given path. Note that this is the path found in , not the Unity path. + + The path of the property to get. + + + + + Finds the property at the specified unity path. + + The unity path for the property. + The property found at the path. + + + + Finds the property at the specified unity path. + + The unity path for the property. + + The property found at the path. + + + + Finds the property at the specified modification path. + + The prefab modification path for the property. + The property found at the path. + + + + Finds the property at the specified modification path. + + The prefab modification path for the property. + + The property found at the path. + + + + Gets a Unity property for the given Odin or Unity path. If there is no for this property tree, or no such property is found in the , a property will be emitted using . + + The Odin or Unity path to the property to get. + The backing field of the Unity property. + + + + Enumerates over the properties of the tree. WARNING: For tree that have large targets with lots of data, this may involve massive amounts of work as the full tree structure is resolved. USE THIS METHOD SPARINGLY AND ONLY WHEN ABSOLUTELY NECESSARY! + + Whether to include children of the root properties or not. If set to true, every property in the entire tree will be enumerated. + /// Whether to only include visible properties. Properties whose parents are invisible are considered invisible. + + + + Replaces all occurrences of a value with another value, in the entire tree. + + The value to find all instances of. + The value to replace the found values with. + + The value to replace with must either be null or be the same type as the value to replace (" + from.GetType().Name + "). + + + + Gets the root tree property at a given index. + + The index of the property to get. + + + + Schedules a delegate to be invoked at the end of the current GUI frame. + + The action delegate to be delayed. + action + + + + Schedules a delegate to be invoked at the end of the next Repaint GUI frame. + + The action to be delayed. + action + + + + Invokes the actions that have been delayed using and . + + + + + Enumeration describing the different types of properties that exist. + + + + + Property represents a value. + + + + + Property represents a method. + + + + + Property represents a named group of properties. + + + + + Enumeration for designating whether a has a special state,. + + + + + The value entry has no special state. + + + + + The property is a reference to another property. Get the path of the referenced property from . + + + + + The value entry is a null value. + + + + + The value entry has a primitive value conflict across selected indices. + A primitive value conflict is when primitive values, such a strings or floats, differ. + + + + + The value entry has a reference value conflict across selected indices. + A reference value conflict is when the types of reference type values differ, or when some values are null while others are not. + + + + + The value entry has a reference path conflict across selected indices. + A reference path conflict is when the property consists of references to many conflicting paths. Use to get paths to all referenced objects. + + + + + The value entry has a collection length conflict across selected indices. + A collection length conflict is when the property represents multiple parallel collections, and their lengths differ. + + + + + Class that describes the different possible serialization backends that a property can have, + and specifies the capabilities of each backend. + + + + + The property is serialized by Unity's polymorphic serialization backend via the [SerializeReference] attribute. Polymorphism, null values and cyclical references are supported. + + + + + The property is serialized by Unity's classic serialization backend. Polymorphism, null values and types such as are not supported. + + + + + The property is serialized by Odin. Polymorphism, null values and types such as are supported. + + + + + The property is not serialized by anything - possibly because it is a method, possibly because it is a field or property shown in the inspector without being serialized. + In the case of fields or properties, polymorphism, null values and types such as are supported, but will not be saved. + + + + + The property is not serialized by anything - possibly because it is a method, possibly because it is a field or property shown in the inspector without being serialized. + In the case of fields or properties, polymorphism, null values and types such as are supported, but will not be saved. + + + + + The property is serialized by Unity's classic serialization backend. Polymorphism, null values and types such as are not supported. + + + + + The property is serialized by Unity's polymorphic serialization backend via the [SerializeReference] attribute. Polymorphism, null values and cyclical references are supported. + + + + + The property is serialized by Odin. Polymorphism, null values and types such as are supported. + + + + + An internally used interface that is used by value entries during , that lets value entries force each other to set values directly to their target objects. + This interface should not be used by people who do not know what they are doing. + + + + + Sets the actual value of a value entry, for a given selection index. + + + + + An internally used interface that is used by value entries during , that lets value entries force each other to set values directly to their target objects. + This interface should not be used by people who do not know what they are doing. + + + + + Sets the actual value of a value entry, for a given selection index. + + + + + Represents the values of an , and contains utilities for querying the values' type and getting and setting them. + + + + + + Delegate type used for the events and . + + + + + The nearest parent property that has a value. + That is, the property from which this value + entry will fetch its parentvalues from in order + to extract its own values. + + If is null, this is a root property. + + + + + Whether this value entry represents a boxed value type. + + + + + The number of parallel values this entry represents. This will always be exactly equal to the count of . + + + + + Whether this value entry is editable or not. + + + + + If this value entry has the override type , this is the path of the property it references. + + + + + The actual serialization backend for this value entry, possibly inherited from the serialization backend of the root property this entry is a child of. + Note that this is *not* always equal to . + + + + + The property whose values this value entry represents. + + + + + Provides access to the weakly typed values of this value entry. + + + + + Whether this value entry has been changed from its prefab counterpart. + + + + + Whether this value entry has had its list length changed from its prefab counterpart. + + + + + Whether this value entry has had its dictionary values changes from its prefab counterpart. + + + + + A weakly typed smart value that represents the first element of the value entry's value collection, but has "smart logic" for setting the value that detects relevant changes and applies them in parallel. + This lets you often just use the smart value instead of having to deal with the tedium of multiple parallel values. + + + + + The type from which this value entry comes. If this value entry represents a member value, this is the declaring type of the member. If the value entry represents a collection element, this is the type of the collection. + + + + + The most precise known contained type of the value entry. If polymorphism is in effect, this will be some type derived from . + + + + + The base type of the value entry. If this is value entry represents a member value, this is the type of the member. If the value entry represents a collection element, this is the element type of the collection. + + + + + The special state of the value entry. + + + + + Whether this value entry is an alias, or not. Value entry aliases are used to provide strongly typed value entries in the case of polymorphism. + + + + + The context container of this property. + + + + + Whether this type is marked as an atomic type using a . + + + + + An event that is invoked during , when any values have changed. + + + + + An event that is invoked during , when any child values have changed. + + + + + Updates the values contained in this value entry to the actual values in the target objects, and updates its state (override, type of value, etc.) accordingly. + + + + + Checks whether the values in this value entry are equal to the values in another value entry. + Note, both value entries must have the same value type, and must represent values that are .NET value types. + + + + + + + Applies the changes made to this value entry to the target objects, and registers prefab modifications as necessary. + + + True if any changes were made, otherwise, false. + + + + + Determines the value state of this value entry. + + + + + Determines what the most precise contained type is on this value entry. + + + + + Updates all values in this value entry from the target tree values. + + + + + Initializes this value entry. + + + + + Creates an alias value entry of a given type, for a given value entry. This is used to implement polymorphism in Odin. + + + + + Creates a value entry for a given property, of a given value type. Note that the created value entry is returned un-updated, and needs to have called on it before it can be used. + + + + + Determines whether the value at the given selection index is different from the given prefab value, as is relevant for prefab modification checks. + If the value is a reference type, null and type difference is checked. If value is a value type, a comparer from is used. + This method is best ignored unless you know what you are doing. + + The value to check differences against. + The selection index to compare against. + + + + Represents the values of an , and contains utilities for querying the values' type and getting and setting them. + + The type of the value. + + + + + An equality comparer for comparing values of type . This is gotten using . + + + + + Whether .is a primitive type; that is, the type is primitive, a string, or an enum. + + + + + Whether is a value type. + + + + + Whether is derived from . + + + + + Whether the type of the value is marked atomic. + + + + + If the type of the value is marked atomic, this an instance of an atom handler for the value type. + + + + + Initializes a new instance of the class. + + + + + Provides access to the weakly typed values of this value entry. + + + + + Provides access to the strongly typed values of this value entry. + + + + + Whether this type is marked as an atomic type using a . + + + + + A weakly typed smart value that represents the first element of the value entry's value collection, but has "smart logic" for setting the value that detects relevant changes and applies them in parallel. + This lets you often just use the smart value instead of having to deal with the tedium of multiple parallel values. + + + + + A strongly typed smart value that represents the first element of the value entry's value collection, but has "smart logic" for setting the value that detects relevant changes and applies them in parallel. + This lets you often just use the smart value instead of having to deal with the tedium of multiple parallel values. + + + + + An array containing the original values as they were at the beginning of frame. + + + + + An array containing the current modified set of values. + + + + + An array containing the current modified set of atomic values. + + + + + An array containing the original set of atomic values. + + + + + Initializes this value entry. + + + + + Sets the actual target tree value. + + + + + Checks whether the values in this value entry are equal to the values in another value entry. + Note, both value entries must have the same value type, and must represent values that are .NET value types. + + + + + Determines whether the value at the given selection index is different from the given prefab value, as is relevant for prefab modification checks. + If the value is a reference type, null and type difference is checked. If value is a value type, a comparer from is used. + This method is best ignored unless you know what you are doing. + + The value to check differences against. + The selection index to compare against. + + + + Determines whether the value at the given selection index is different from the given prefab value, as is relevant for prefab modification checks. + If the value is a reference type, null and type difference is checked. If value is a value type, a comparer from is used. + This method is best ignored unless you know what you are doing. + + The value to check differences against. + The selection index to compare against. + + + + Represents the values of an , and contains utilities for querying the values' type and getting and setting them. + + The type of the parent. + The type of the value. + + + + + The type from which this value entry comes. If this value entry represents a member value, this is the declaring type of the member. If the value entry represents a collection element, this is the type of the collection. + + + + + Determines what the most precise contained type is on this value entry. + + + + + Initializes this value entry. + + + + + Updates all values in this value entry from the target tree values. + + + + + Determines the value state of this value entry. + + + + + Applies the changes made to this value entry to the target objects, and registers prefab modifications as necessary. + + + True if any changes were made, otherwise, false. + + + + + Gets the parent value at the given index. + + + + + Adds menu items to the Unity Editor, draws the About window, and the preference window found under Edit > Preferences > Odin Inspector. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Sirenix preferences window. + + + + + Open preferences page for configuration object. + + + + + Opens the Odin inspector preferences window. + + + + + Opens the Odin inspector preferences window. + + + + + This class has been made fully obsolete, and has been replaced by . + It was a helper class to handle strings for labels and other similar purposes. + + + + + If any error occurred while looking for members, it will be stored here. + + + + + Obsolete. Use other constructor. + + + + + Obsolete. Use other constructor. + + + + + Creates a StringMemberHelper to get a display string. + + Inspector property to get string from. + The input string. If the first character is a '$', then StringMemberHelper will look for a member string field, property or method, and will try to parse it as an expression if it starts with '@'. + + + + Creates a StringMemberHelper to get a display string. + + Inspector property to get string from. + The input string. If the first character is a '$', then StringMemberHelper will look for a member string field, property or method, and will try to parse it as an expression if it starts with '@'./// The input string. If the first character is a '$', then StringMemberHelper will look for a member string field, property or method. + + + + Gets a value indicating whether or not the string is retrived from a from a member. + + + + + Gets the type of the object. + + + + + Gets the string from the StringMemberHelper. + Only updates the string buffer in Layout events. + + The property entry, to get the instance reference from. + The current display string. + + + + Gets the string from the StringMemberHelper. + Only updates the string buffer in Layout events. + + The property, to get the instance reference from. + The current string. + + + + Gets the string from the StringMemberHelper. + Only updates the string buffer in Layout events. + + The instance, for evt. member references. + The current string. + + + + Gets the string from the StringMemberHelper. + + The property entry, to get the instance reference from. + The current string. + + + + Gets the string from the StringMemberHelper. + + The property, to get the instance reference from. + The current string. + + + + Gets the string from the StringMemberHelper. + + The instance, for evt. member references. + The current string. + + + + Gets a unique key for any given property within a drawer. + + + + + public class MyCustomTypeDrawer<T> : OdinValueDrawer<T> where T : MyCustomBaseType + { + protected override void DrawPropertyLayout(IPropertyValueEntry<T> entry, GUIContent label) + { + var isToggled = entry.Context(this, "toggled", false); + isToggled.Value = SirenixEditorGUI.Label(isToggled.Value, label); + if (SirenixEditorGUI.BeginFadeGroup(UniqueDrawerKey.Create(entry, this), isToggled.Value)) + { + EditorGUI.indentLevel++; + this.CallNextDrawer(entry.Property, null); + EditorGUI.indentLevel--; + } + SirenixEditorGUI.EndFadeGroup(); + } + } + + + + + + Gets a unique key for any given property within a drawer. + + The property entry. + The drawer. + + + + + Gets a unique key for any given property within a drawer. + + The property. + The drawer. + + + + + Checks if two keys are identical. + + The other key. + + + + Checks if two keys are identical. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Unity property drawer. + + + + + Initializes the property drawer. + + + + + Draws the property. + + + + + Provides utilities for emitting ScriptableObject and MonoBehaviour-derived types with specific property names and types, and providing instances of with those names and types. + + + + + A handle for a set of emitted Unity objects. When disposed (or collected by the GC) this handle will queue the emitted object instances for destruction. + + + + + The unity property to represent. + + + + + The Unity objects to represent. + + + + + Initializes a new instance of the class. + + The unity property to represent. + The objects to represent. + + + + Finalizes an instance of the class. + + + + + Creates an emitted MonoBehaviour-based . + + Name of the field to emit. + Type of the value to create a property for. + The target count of the tree to create a property for. + The game object that the MonoBehaviour of the property is located on. + + fieldName is null + or + valueType is null + + Target count must be equal to or higher than 1. + + + + Creates an emitted ScriptableObject-based . + + Name of the field to emit. + Type of the value to create a property for. + The target count of the tree to create a property for. + + fieldName is null + or + valueType is null + + Target count must be equal to or higher than 1. + + + + Context that persists across reloading and restarting Unity. + + + + + Time stamp for when the persistent context value was last used. + Used for purging unused context. + + + + + Instatiates a persistent context. + + + + + Updates the time stamp to now. + + + + + Context that persists across reloading and restarting Unity. + + The type of the context value. + + + + The value of the context. + + + + + Creates a new persistent context object. + + + + + Formats a string with the time stamp, and the value. + + + + + Helper class that provides a local copy of a . + When the local value is changed, it also changed the global value, but the global value does not change the local value. + + The type of the context value. + + + + The value of the context. + Changing this value, also changes the global context value, but the global value does not change the local value. + + + + + Creates a local context object for the provided global context. + + The global context object. + + + + Updates the local value to the current global value. + + + + + OdinDrawer extensions. + + + + + Gets a persistent value that will survive past multiple Unity Editor Application sessions. + The value is stored in the PersistentContextCache, which has a customizable max cache size. + + + + + Provides context objects that still persist when Unity reloads or is restarted. + + + + + Gets a GlobalPersistentContext object for the specified key. + + The type of the first key. + The type of the value stored in the context object. + The first key. + The default value, used for when the context object is first created. + + + + Gets a GlobalPersistentContext object for the specified keys. + + The type of the first key. + The type of the second key. + The type of the value stored in the context object. + The first key. + The second key. + The default value, used for when the context object is first created. + + + + Gets a GlobalPersistentContext object for the specified keys. + + The type of the first key. + The type of the second key. + The type of the third key. + The type of the value stored in the context object. + The first key. + The second key. + The third key. + The default value, used for when the context object is first created. + + + + Gets a GlobalPersistentContext object for the specified keys. + + The type of the first key. + The type of the second key. + The type of the third key. + The type of the fourth key. + The type of the value stored in the context object. + The first key. + The second key. + The third key. + The fourth key. + The default value, used for when the context object is first created. + + + + Gets a GlobalPersistentContext object for the specified keys. + + The type of the first key. + The type of the second key. + The type of the third key. + The type of the fourth key. + The type of the fifth key. + The type of the value stored in the context object. + The first key. + The second key. + The third key. + The fourth key. + The fifth key. + The default value, used for when the context object is first created. + + + + Gets a GlobalPersistentContext object for the specified key. + Returns true when the context is first created. Otherwise false. + + The type of the first key. + The type of the value stored in the context object. + The first key. + The persistent context object. + Returns true when the context is first created. Otherwise false. + + + + Gets a GlobalPersistentContext object for the specified keys. + Returns true when the context is first created. Otherwise false. + + The type of the first key. + The type of the second key. + The type of the value stored in the context object. + The first key. + The second key. + The persistent context object. + Returns true when the context is first created. Otherwise false. + + + + Gets a GlobalPersistentContext object for the specified keys. + Returns true when the context is first created. Otherwise false. + + The type of the first key. + The type of the second key. + The type of the third key. + The type of the value stored in the context object. + The first key. + The second key. + The third key. + The persistent context object. + Returns true when the context is first created. Otherwise false. + + + + Gets a GlobalPersistentContext object for the specified keys. + Returns true when the context is first created. Otherwise false. + + The type of the first key. + The type of the second key. + The type of the third key. + The type of the fourth key. + The type of the value stored in the context object. + The first key. + The second key. + The third key. + The fourth key. + The persistent context object. + Returns true when the context is first created. Otherwise false. + + + + Gets a GlobalPersistentContext object for the specified keys. + Returns true when the context is first created. Otherwise false. + + The type of the first key. + The type of the second key. + The type of the third key. + The type of the fourth key. + The type of the fifth key. + The type of the value stored in the context object. + The first key. + The second key. + The third key. + The fourth key. + The fifth key. + The persistent context object. + Returns true when the context is first created. Otherwise false. + + + + Gets a LocalPersistentContext object for the specified key. + + The type of the first key. + The type of the value stored in the context object. + The first key. + The default value, used for when the context object is first created. + + + + Gets a LocalPersistentContext object for the specified keys. + + The type of the first key. + The type of the second key. + The type of the value stored in the context object. + The first key. + The second key. + The default value, used for when the context object is first created. + + + + Gets a LocalPersistentContext object for the specified keys. + + The type of the first key. + The type of the second key. + The type of the third key. + The type of the value stored in the context object. + The first key. + The second key. + The third key. + The default value, used for when the context object is first created. + + + + Gets a LocalPersistentContext object for the specified keys. + + The type of the first key. + The type of the second key. + The type of the third key. + The type of the fourth key. + The type of the value stored in the context object. + The first key. + The second key. + The third key. + The fourth key. + The default value, used for when the context object is first created. + + + + Gets a LocalPersistentContext object for the specified keys. + + The type of the first key. + The type of the second key. + The type of the third key. + The type of the fourth key. + The type of the fifth key. + The type of the value stored in the context object. + The first key. + The second key. + The third key. + The fourth key. + The fifth key. + The default value, used for when the context object is first created. + + + + Gets a LocalPersistentContext object for the specified key. + Returns true when the context is first created. Otherwise false. + + The type of the first key. + The type of the value stored in the context object. + The first key. + The persistent context object. + Returns true when the context is first created. Otherwise false. + + + + Gets a LocalPersistentContext object for the specified keys. + Returns true when the context is first created. Otherwise false. + + The type of the first key. + The type of the second key. + The type of the value stored in the context object. + The first key. + The second key. + The persistent context object. + Returns true when the context is first created. Otherwise false. + + + + Gets a LocalPersistentContext object for the specified keys. + Returns true when the context is first created. Otherwise false. + + The type of the first key. + The type of the second key. + The type of the third key. + The type of the value stored in the context object. + The first key. + The second key. + The third key. + The persistent context object. + Returns true when the context is first created. Otherwise false. + + + + Gets a LocalPersistentContext object for the specified keys. + Returns true when the context is first created. Otherwise false. + + The type of the first key. + The type of the second key. + The type of the third key. + The type of the fourth key. + The type of the value stored in the context object. + The first key. + The second key. + The third key. + The fourth key. + The persistent context object. + Returns true when the context is first created. Otherwise false. + + + + Gets a LocalPersistentContext object for the specified keys. + Returns true when the context is first created. Otherwise false. + + The type of the first key. + The type of the second key. + The type of the third key. + The type of the fourth key. + The type of the fifth key. + The type of the value stored in the context object. + The first key. + The second key. + The third key. + The fourth key. + The fifth key. + The persistent context object. + Returns true when the context is first created. Otherwise false. + + + + Persistent Context cache object. + + + + + Estimated cache size in bytes. + + + + + The current number of context entries in the cache. + + + + + If true then persistent context is disabled entirely. + + + + + If true the context will be saved to a file in the temp directory. + + + + + The max size of the cache in bytes. + + + + + Delete the persistent cache file. + + + + + Access the StaticInspectorWindow from Tools > Odin Inspector > Static Inspector. + + + + + Member filter for access modifiers. + + + + + include public members. + + + + + Include Non-public members. + + + + + Include both public and non-public members. + + + + + Member filter for member types. + + + + + No members included. + + + + + Include field members. + + + + + Include property members. + + + + + Include method members. + + + + + Include group members. + + + + + Include members from the base types. + + + + + Include members marked with the Obsolete attribute. + + + + + Include all members except members marked with the Obsolete attribute. + + + + + Shows the window. + + + + + Opens a new static inspector window for the given type. + + + + + Draws the Odin Editor Window. + + + + + Draws the editor for the this.CurrentDrawingTargets[index]. + + + + + Contains references to UnityEngine.Networking types. These types have been removed in Unity 2019+, and thus may be null. + + + + + Contains configuration for generating an assembly that provides increased AOT support in Odin. + + + + + + Whether to automatically scan the project and generate an AOT dll, right before builds. This will only affect platforms that are in the list. + + + **This will only work on Unity 5.6 and higher!** + + + + + + Whether to automatically delete the generated AOT dll after a build has completed. + + + + + A list of platforms to automatically scan the project and generate an AOT dll for, right before builds. This will do nothing unless is true. + + + + + The path to the AOT folder that the AOT .dll and linker file is created in, relative to the current project folder. + + + + + Scans the entire project for types to support AOT serialization for. + + + + + Generates an AOT DLL, using the current configuration of the AOTGenerationConfig instance. + + + + + The Odin Inspector Serialization Debugger Window. + + + + + + Opens the Serialization Debugger Window with the last debugged type. + + + + + Opens the Serialization Debugger Window and debugs the given type. + + The type to debug serialization of. + + + + Initializes the Serialization Debugger Window. + + + + diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.xml.meta b/Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.xml.meta new file mode 100644 index 0000000..e3bec9d --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.xml.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a4865f1ab4504ed8a368670db22f096f +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll new file mode 100644 index 0000000000000000000000000000000000000000..e4bf76042e3066a05c41fa3a1fff6c5198936f78 GIT binary patch literal 17408 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 U0tlrBnA~3kllx2Y;Qli3Ut85aRsaA1 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll.mdb.meta b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll.mdb.meta new file mode 100644 index 0000000..d46f601 --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll.mdb.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 74721b9f0af448f5ae2e91102a1a086f +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll.meta b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll.meta new file mode 100644 index 0000000..c30d538 --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 74721b9f0af448f5ae2e91102a1a5edd +timeCreated: 1488828285 +licenseType: Store +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + Any: + enabled: 1 + settings: + Exclude Android: 0 + Exclude Editor: 0 + Exclude Linux: 0 + Exclude Linux64: 0 + Exclude LinuxUniversal: 0 + Exclude N3DS: 0 + Exclude OSXIntel: 0 + Exclude OSXIntel64: 0 + Exclude OSXUniversal: 0 + Exclude PS4: 0 + Exclude PSM: 0 + Exclude PSP2: 0 + Exclude SamsungTV: 0 + Exclude Tizen: 0 + Exclude WebGL: 0 + Exclude WiiU: 0 + Exclude Win: 0 + Exclude Win64: 0 + Exclude WindowsStoreApps: 0 + Exclude XboxOne: 0 + Exclude iOS: 0 + Exclude tvOS: 0 + Editor: + enabled: 0 + settings: + DefaultValueInitialized: true + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.xml b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.xml new file mode 100644 index 0000000..f9e16ab --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.xml @@ -0,0 +1,202 @@ + + + + Sirenix.Serialization.Config + + + + + A helper class for quickly and easily defining custom loggers. + + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Specifies a data format to read and write in. + + + + + A custom packed binary format. This format is most efficient and almost allocation-free, + but its serialized data is not human-readable. + + + + + A JSON format compliant with the json specification found at "http://www.json.org/". + + This format has rather sluggish performance and allocates frightening amounts of string garbage. + + + + + A format that does not serialize to a byte stream, but to a list of data nodes in memory + which can then be serialized by Unity. + + This format is highly inefficient, and is primarily used for ensuring that Unity assets + are mergeable by individual values when saved in Unity's text format. This makes + serialized values more robust and data recovery easier in case of issues. + + This format is *not* recommended for use in builds. + + + + + Defines default loggers for serialization and deserialization. This class and all of its loggers are thread safe. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + The policy for handling errors during serialization and deserialization. + + + + + Attempts will be made to recover from errors and continue serialization. Data may become invalid. + + + + + Exceptions will be thrown when errors are logged. + + + + + Exceptions will be thrown when warnings or errors are logged. + + + + + Not yet documented. + + + + + Text for the cautionary serialization warning shown in the inspector. + + + + + Text for the hide button for the cautionary serialization warning shown in the inspector. + + + + + Text for the hide button for the cautionary prefab warning shown in the inspector. + + + + + Whether the user has chosen to hide the cautionary serialization warning. + + + + + Whether the user has chosen to hide the warning messages related to the OdinSerialize attribute. + + + + + Whether the user has chosen to hide the warning messages related to the SerializeField and ShowInInspector attributes on non-serialized members. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Implements methods for logging warnings, errors and exceptions during serialization and deserialization. + + + + + Logs a warning. + + The warning to log. + + + + Logs an error. + + The error to log. + + + + Logs an exception. + + The exception to log. + + + + The policy for which level of logging to do during serialization and deserialization. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.xml.meta b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.xml.meta new file mode 100644 index 0000000..0dff2fd --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.xml.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 74721b9f0af448f5ae2e91102a1a096f +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.dll b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.dll new file mode 100644 index 0000000000000000000000000000000000000000..fd13c99e082677e658c1b2c6841a8381bf2e2e2b GIT binary patch literal 369152 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 a`0<6G@Ala2@Q)qKzi_nw5BPtB1OExe9voW$ literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.dll.mdb b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.dll.mdb new file mode 100644 index 0000000000000000000000000000000000000000..1c8a28b423666259ed30fe4803fe636293d1b92b GIT binary patch literal 133720 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 + + + Sirenix.Serialization + + + + + Custom formatter for MethodInfo, since Unity Mono's MethodInfo ISerializable implementation will often crash if the method no longer exists upon deserialization. + + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Get an uninitialized object of type . WARNING: If you override this and return null, the object's ID will not be automatically registered and its OnDeserializing callbacks will not be automatically called, before deserialization begins. + You will have to call and immediately after creating the object yourself during deserialization. + + + An uninitialized object of type . + + + + + Custom generic formatter for the generic type definition . + + The element type of the formatted queue. + + + + + Returns null. + + + A null value. + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Custom generic formatter for the generic type definition and types derived from it. + + The element type of the formatted stack. + + + + + Returns null. + + + A null value. + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + + Applying this attribute to a type indicates that in the case where, when expecting to deserialize an instance of the type + or any of its derived types, but encountering an incompatible, uncastable type in the data being read, the serializer + should attempt to deserialize an instance of the expected type using the stored, possibly invalid data. + + + This is equivalent to the option, expect type-specific instead + of global. + + + + + + This class gathers info about the current architecture for the purpose of determinining + the unaligned read/write capabilities that we have to work with. + + + + + This will be false on some ARM architectures, such as ARMv7. + In these cases, we will have to perform slower but safer int-by-int read/writes of data. + + Since this value will never change at runtime, performance hits from checking this + everywhere should hopefully be negligible, since branch prediction from speculative + execution will always predict it correctly. + + + + + Scans the project's build scenes and resources, plus their dependencies, for serialized types to support. Progress bars are shown during the scan. + + The serialized types to support. + Whether to scan the project's build scenes. + Whether to scan all the project's asset bundles. + Whether to scan the project's preloaded assets. + Whether to scan the project's resources. + An optional list of the resource paths to scan. Only has an effect if the scanResources argument is true. All the resources will be scanned if null. + true if the scan succeeded, false if the scan failed or was cancelled + + + + Generates an AOT DLL, using the given parameters. + + + + + Indicates that an Odin-serialized Unity object provides its own serialization policy rather than using the default policy. + + Note that THE VALUES RETURNED BY THIS INTERFACE WILL OVERRIDE THE PARAMETERS PASSED TO and . + + + + + Defines how an assembly's import settings should be configured. + + + + + Include the assembly in the build, but not in the editor. + + + + + Include the assembly in the editor, but not in the build. + + + + + Include the assembly in both the build and in the editor. + + + + + Exclude the assembly from both the build and from the editor. + + + + + Utility for correctly setting import on OdinSerializer assemblies based on platform and scripting backend. + + + + + All valid Unity BuildTarget platforms. + + + + + All valid Unity BuildTarget platforms that support Just In Time compilation. + + + + + All scripting backends that support JIT. + + + + + All API compatibility levels that support JIT. + + + + + Set the import settings on the assembly. + + The path to the assembly to configure import settings from. + The import settings to configure for the assembly at the path. + + + + Set the import settings on the assembly. + + The path to the assembly to configure import settings from. + Indicates if the assembly should be included in the build. + Indicates if the assembly should be included in the Unity editor. + + + + Gets the current scripting backend for the build from the Unity editor. This method is Unity version independent. + + + + + + Gets the current API compatibility level from the Unity Editor. This method is Unity version independent. + + + + + + Gets a value that indicates if the specified platform supports JIT. + + The platform to test. + true if the platform supports JIT; otherwise false. + + + + Gets a value that indicates if the specified scripting backend supports JIT. + + The backend to test. + true if the backend supports JIT; otherwise false. + + + + Gets a value that indicates if the specified api level supports JIT. + + The api level to test. + true if the api level supports JIT; otherwise false. + + + + Gets a value that indicates if the specified build settings supports JIT. + + The platform build setting. + The scripting backend build settting. + The api level build setting. + true if the build settings supports JIT; otherwise false. + + + + FieldInfo method extensions. + + + + + Determines whether the specified field is an alias. + + The field to check. + + true if the specified field is an alias; otherwise, false. + + + + + Returns the original, backing field of an alias field if the field is an alias. + + The field to check. + /// if set to true an exception will be thrown if the field is not aliased. + + The field was not aliased; this only occurs if throwOnNotAliased is true. + + + + Garbage free enumerator methods. + + + + + Garbage free enumerator for lists. + + + + + Garbage free enumerator for dictionaries. + + + + + Garbage free enumator for dictionary values. + + + + + Garbage free enumerator for hashsets. + + + + + List iterator. + + + + + Creates a list iterator. + + + + + Gets the enumerator. + + + + + Gets the current value. + + + + + Moves to the next value. + + + + + Disposes the iterator. + + + + + Hashset iterator. + + + + + Creates a hashset iterator. + + + + + Gets the enumerator. + + + + + Gets the current value. + + + + + Moves to the next value. + + + + + Disposes the iterator. + + + + + Dictionary iterator. + + + + + Creates a dictionary iterator. + + + + + Gets the enumerator. + + + + + Gets the current value. + + + + + Moves to the next value. + + + + + Disposes the iterator. + + + + + Dictionary value iterator. + + + + + Creates a dictionary value iterator. + + + + + Gets the enumerator. + + + + + Gets the current value. + + + + + Moves to the next value. + + + + + Disposes the iterator. + + + + + Various LinQ extensions. + + + + + Perform an action on each item. + + The source. + The action to perform. + + + + Perform an action on each item. + + The source. + The action to perform. + + + + Add a collection to the end of another collection. + + The collection. + The collection to append. + + + + MemberInfo method extensions. + + + + + Returns true if the attribute whose type is specified by the generic argument is defined on this member + + + + + Returns true if the attribute whose type is specified by the generic argument is defined on this member + + + + + Returns the first found custom attribute of type T on this member + Returns null if none was found + + + + + Returns the first found non-inherited custom attribute of type T on this member + Returns null if none was found + + + + + Gets all attributes of the specified generic type. + + The member. + + + + Gets all attributes of the specified generic type. + + The member. + If true, specifies to also search the ancestors of element for custom attributes. + + + + Gets all attribute instances defined on a MemeberInfo. + + The member. + + + + Gets all attribute instances on a MemberInfo. + + The member. + If true, specifies to also search the ancestors of element for custom attributes. + + + + If this member is a method, returns the full method name (name + params) otherwise the member name paskal splitted + + + + + Determines whether a FieldInfo, PropertyInfo or MethodInfo is static. + + The member. + + true if the specified member is static; otherwise, false. + + + + + + Determines whether the specified member is an alias. + + The member to check. + + true if the specified member is an alias; otherwise, false. + + + + + Returns the original, backing member of an alias member if the member is an alias. + + The member to check. + /// if set to true an exception will be thrown if the member is not aliased. + + The member was not aliased; this only occurs if throwOnNotAliased is true. + + + + Various extensions for MethodInfo. + + + + + Returns the specified method's full name "methodName(argType1 arg1, argType2 arg2, etc)" + Uses the specified gauntlet to replaces type names, ex: "int" instead of "Int32" + + + + + Returns a string representing the passed method parameters names. Ex "int num, float damage, Transform target" + + + + + Returns the specified method's full name. + + + + + Tests if a method is an extension method. + + + + + Determines whether the specified method is an alias. + + The method to check. + + true if the specified method is an alias; otherwise, false. + + + + + Returns the original, backing method of an alias method if the method is an alias. + + The method to check. + /// if set to true an exception will be thrown if the method is not aliased. + + The method was not aliased; this only occurs if throwOnNotAliased is true. + + + + Determines the type of operator. + + + + + + The == operator. + + + + + The != operator. + + + + + The + operator. + + + + + The - operator. + + + + + The * operator. + + + + + The / operator. + + + + + The < operator. + + + + + The > operator. + + + + + The <= operator. + + + + + The >= operator. + + + + + The % operator. + + + + + The >> operator. + + + + + The << operator. + + + + + The & operator. + + + + + The | operator. + + + + + The ^ operator. + + + + + The ~ operator. + + + + + The && operator. + + + + + The || operator. + + + + + The ! operator. + + + + + DirectoryInfo method extensions. + + + + + Determines whether the directory has a given directory in its hierarchy of children. + + The parent directory. + The sub directory. + + + + PropertyInfo method extensions. + + + + + Determines whether a property is an auto property with a usable getter and setter. + + + + + Determines whether the specified property is an alias. + + The property to check. + + true if the specified property is an alias; otherwise, false. + + + + + Returns the original, backing property of an alias property if the property is an alias. + + The property to check. + /// if set to true an exception will be thrown if the property is not aliased. + + The property was not aliased; this only occurs if throwOnNotAliased is true. + + + + String method extensions. + + + + + Eg MY_INT_VALUE => MyIntValue + + + + + Returns true if this string is null, empty, or contains only whitespace. + + The string to check. + true if this string is null, empty, or contains only whitespace; otherwise, false. + + + + Type method extensions. + + + + + Type name alias lookup. + TypeNameAlternatives["Single"] will give you "float", "UInt16" will give you "ushort", "Boolean[]" will give you "bool[]" etc.. + + + + + Checks whether a given string is a valid CSharp identifier name. This also checks full type names including namespaces. + + The identifier to check. + + + + Determines whether a type can be casted to another type. + + From. + To. + if set to true an implicit or explicit operator must be defined on the given type. + + + + If a type can be casted to another type, this provides a function to manually convert the type. + + From. + To. + if set to true an implicit or explicit operator must be defined on the given type. + + + + If a type can be casted to another type, this provides a function to manually convert the type. + + if set to true an implicit or explicit operator must be defined on the given type. + + + + If a type can be casted to another type, this provides the method info of the method in charge of converting the type. + + From. + To. + if set to true an implicit or explicit operator must be defined on the given type. + + + + Gets an equality comparer delegate used to compare the equality of values of a given type. In order, this will be: + + 1. The == operator, if one is defined on the type. + 2. A delegate that uses , if the type implements that interface. + 3. .NET's own + + + Note that in the special case of the type , a special equality comparer is returned that only checks whether all the Quaternion components are equal. + This is because, by default, Quaternion's equality operator is broken when operating on invalid quaternions; "default(Quaternion) == default(Quaternion)" evaluates to false, and this causes a multitude of problems. + Special delegates are also returned for float and double, that consider float.NaN to be equal to float.NaN, and double.NaN to be equal to double.NaN. + + + + + Gets the first attribute of type T. Returns null in the no attribute of type T was found. + + The type. + If true, specifies to also search the ancestors of element for custom attributes. + + + + Determines whether a type implements or inherits from another type. + + The type. + To. + + + + Determines whether a type implements an open generic interface or class such as IList<> or List<>. + + Type of the candidate. + Type of the open generic type. + + + + + Determines whether a type implements an open generic interface such as IList<>. + + Type of the candidate. + Type of the open generic interface. + + Type " + openGenericInterfaceType.Name + " is not a generic type definition and an interface. + + + + Determines whether a type implements an open generic class such as List<>. + + Type of the candidate. + Type of the open generic interface. + + + + Gets the generic arguments of an inherited open generic class or interface. + + Type of the candidate. + The open generic type to get the arguments of. + + + + Gets the generic arguments of an inherited open generic class. + + Type of the candidate. + Type of the open generic class. + + + + Gets the generic arguments of an inherited open generic interface. + + Type of the candidate. + Type of the open generic interface. + + + + Gets the MethodInfo of a specific operator kind, with the given left and right operands. This overload is *far* faster than any of the other GetOperatorMethod implementations, and should be used whenever possible. + + + + + Gets the MethodInfo of a specific operator type. + + + + + Gets the MethodInfo of a specific operator type. + + + + + Gets all members from a given type, including members from all base types if the flag isn't set. + + + + + Gets all members from a given type, including members from all base types. + + + + + Gets all members of a specific type from a type, including members from all base types, if the flag isn't set. + + + + + Gets the generic type definition of an open generic base type. + + + + + Gets the generic type definition of an open generic base type. + + + + + Returns a lazy enumerable of all the base types of this type including interfaces and classes + + + + + Returns a lazy enumerable of all the base classes of this type + + + + + Used to filter out unwanted type names. Ex "int" instead of "Int32" + + + + + Returns a nicely formatted name of a type. + + + + + Returns a nicely formatted full name of a type. + + + + + Gets the name of the compilable nice. + + The type. + + + + Gets the full name of the compilable nice. + + The type. + + + + Returns the first found custom attribute of type T on this type + Returns null if none was found + + + + + Returns the first found non-inherited custom attribute of type T on this type + Returns null if none was found + + + + + Gets all attributes of type T. + + The type. + + + + Gets all attributes of type T. + + The type + If true, specifies to also search the ancestors of element for custom attributes. + + + + Returns true if the attribute whose type is specified by the generic argument is defined on this type + + + + + Returns true if the attribute whose type is specified by the generic argument is defined on this type + + + + + Determines whether a type inherits or implements another type. Also include support for open generic base types such as List<>. + + + + + + Determines whether a type inherits or implements another type. Also include support for open generic base types such as List<>. + + + + + + + Gets the number of base types between given type and baseType. + + + + + Determines whether a method has the specified parameter types. + + + + + FieldInfo will return the fieldType, propertyInfo the PropertyType, MethodInfo the return type and EventInfo will return the EventHandlerType. + + The MemberInfo. + + + + Gets the value contained in a given . Currently only and is supported. + + The to get the value of. + The instance to get the value from. + The value contained in the given . + Can't get the value of the given type. + + + + Sets the value of a given MemberInfo. Currently only and is supported. + + The to set the value of. + The object to set the value on. + The value to set. + + Property has no setter + or + Can't set the value of the given type. + + + + + Tries to infer a set of valid generic parameters for a generic type definition, given a subset of known parameters. + + The generic type definition to attempt to infer parameters for. + The inferred parameters, if inferral was successful. + The known parameters to infer from. + True if the parameters could be inferred, otherwise, false. + + genericTypeDefinition is null + or + knownParameters is null + + The genericTypeDefinition parameter must be a generic type definition. + + + + Checks whether an array of types satisfy the constraints of a given generic type definition. + If this method returns true, the given parameters can be safely used with with the given generic type definition. + + The generic type definition to check. + The parameters to check validity for. + + genericType is null + or + types is null + + The genericType parameter must be a generic type definition. + + + + Checks whether an array of types satisfy the constraints of a given generic method definition. + If this method returns true, the given parameters can be safely used with with the given generic method definition. + + The generic method definition to check. + The parameters to check validity for. + + genericType is null + or + types is null + + The genericMethod parameter must be a generic method definition. + + + + Before calling this method we must ALWAYS hold a lock on the GenericConstraintsSatisfaction_LOCK object, as that is an implicit assumption it works with. + + + + + Not yet documented. + + + + + Formats a string with the specified generic parameter constraints on any given type. Example output: where T : class + + + + + Determines whether a generic type contains the specified generic argument constraints. + + The type. + The generic argument types. + + + + Determines whether a type is a fully constructed generic type. + + + + + Determines whether a type is nullable by ensuring the type is neither a PrimitiveType, ValueType or an Enum. + + + + + Gets the enum bitmask in a ulong. + + enumType + + + + Extends various Unity classes. + + + + + Determines whether a Unity object is null or "fake null", + without ever calling Unity's own equality operators. + This method is useful for checking if a Unity object is + null, destroyed or missing at times when it is not allowed + to call Unity's own equality operators, for example when + not running on the main thread. + + The Unity object to check. + True if the object is null, missing or destroyed; otherwise false. + + + + Provides an easy way of claiming and freeing cached values of any non-abstract reference type with a public parameterless constructor. + + Cached types which implement the interface will receive notifications when they are claimed and freed. + + Only one thread should be holding a given cache instance at a time if is implemented, since the invocation of + is not thread safe, IE, weird stuff might happen if multiple different threads are trying to free + the same cache instance at the same time. This will practically never happen unless you're doing really strange stuff, but the case is documented here. + + The type which is cached. + + + + + Gets or sets the maximum size of the cache. This value can never go beneath 1. + + + The maximum size of the cache. + + + + + The cached value. + + + + + Gets a value indicating whether this cached value is free. + + + true if this cached value is free; otherwise, false. + + + + + Claims a cached value of type . + + A cached value of type . + + + + Releases a cached value. + + The cached value to release. + The cached value to release is null. + + + + Performs an implicit conversion from to . + + The cache to convert. + + The result of the conversion. + + + + + Releases this cached value. + + + + + Releases this cached value. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Provides utilities for using the namespace. + + This class is due for refactoring. Use at your own peril. + + + + + Gets a value indicating whether emitting is supported on the current platform. + + + true if the current platform can emit; otherwise, false. + + + + + Creates a delegate which gets the value of a field. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The type of the field to get a value from. + The instance describing the field to create a getter for. + A delegate which gets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which gets the value of a field. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The instance describing the field to create a getter for. + A delegate which gets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which sets the value of a field. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + The type of the field to set a value to. + The instance describing the field to create a setter for. + A delegate which sets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which sets the value of a field. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + The instance describing the field to create a setter for. + A delegate which sets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which gets the value of a field. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The type of the instance to get a value from. + The type of the field to get a value from. + The instance describing the field to create a getter for. + A delegate which gets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which gets the value of a field from a weakly typed instance of a given type. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The type of the field to get a value from. + The of the instance to get a value from. + The instance describing the field to create a getter for. + A delegate which gets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which gets the weakly typed value of a field from a weakly typed instance of a given type. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The of the instance to get a value from. + The instance describing the field to create a getter for. + A delegate which gets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which sets the value of a field. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + The type of the instance to set a value on. + The type of the field to set a value to. + The instance describing the field to create a setter for. + A delegate which sets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which sets the value of a field on a weakly typed instance of a given type. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + The type of the field to set a value to. + Type of the instance. + The instance describing the field to create a setter for. + + A delegate which sets the value of the given field. + + The fieldInfo parameter is null. + Field cannot be static. + + + + Creates a delegate which sets the weakly typed value of a field on a weakly typed instance of a given type. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + Type of the instance. + The instance describing the field to create a setter for. + + A delegate which sets the value of the given field. + + The fieldInfo parameter is null. + Field cannot be static. + + + + Creates a delegate which gets the weakly typed value of a field from a weakly typed instance of a given type. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The of the instance to get a value from. + The instance describing the field to create a getter for. + A delegate which gets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which sets the weakly typed value of a property on a weakly typed instance of a given type. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + Type of the instance. + The instance describing the property to create a setter for. + + A delegate which sets the value of the given field. + + The fieldInfo parameter is null. + Property cannot be static. + + + + Creates a delegate which sets the value of a property. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + The type of the property to set a value to. + The instance describing the property to create a setter for. + A delegate which sets the value of the given property. + The propertyInfo parameter is null. + + + + Creates a delegate which gets the value of a property. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The type of the property to get a value from. + The instance describing the property to create a getter for. + A delegate which gets the value of the given property. + The propertyInfo parameter is null. + + + + Creates a delegate which sets the value of a property. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + The type of the instance to set a value on. + The type of the property to set a value to. + The instance describing the property to create a setter for. + A delegate which sets the value of the given property. + The propertyInfo parameter is null. + + + + Creates a delegate which gets the value of a property. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The type of the instance to get a value from. + The type of the property to get a value from. + The instance describing the property to create a getter for. + A delegate which gets the value of the given property. + The propertyInfo parameter is null. + + + + Creates a fast delegate method which calls a given parameterless instance method and returns the result. + + The type of the class which the method is on. + The type which is returned by the given method info. + The method info instance which is used. + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + + + Creates a fast delegate method which calls a given parameterless static method. + + The method info instance which is used. + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + + + Creates a fast delegate method which calls a given parameterless weakly typed instance method. + + The method info instance which is used. + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + + + Not yet documented. + + + + + Creates a fast delegate method which calls a given weakly typed instance method with one argument and returns a value. + + The type of the result. + The type of the first argument. + The method info instance which is used. + + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + methodInfo + + Given method ' + methodInfo.Name + ' is static when it has to be an instance method. + or + Given method ' + methodInfo.Name + ' must return type + typeof(TResult) + . + or + Given method ' + methodInfo.Name + ' must have exactly one parameter. + or + The first parameter of the method ' + methodInfo.Name + ' must be of type + typeof(TArg1) + . + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Creates a fast delegate method which calls a given parameterless instance method on a reference type. + + The type of the class which the method is on. + The method info instance which is used. + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + + + Creates a fast delegate method which calls a given instance method with a given argument on a reference type. + + The type of the class which the method is on. + The type of the argument with which to call the method. + The method info instance which is used. + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + + + Creates a fast delegate method which calls a given parameterless instance method. + + The type of the class which the method is on. + The method info instance which is used. + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + + + Creates a fast delegate method which calls a given instance method with a given argument on a struct type. + + The type of the class which the method is on. + The type of the argument with which to call the method. + The method info instance which is used. + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + + + Compares types by reference before comparing them using the default type equality operator. + This can constitute a *significant* speedup when used as the comparer for dictionaries. + + + + + + This class encapsulates common combinations. + + + + + Search criteria encompassing all public and non-public members, including base members. + Note that you also need to specify either the Instance or Static flag. + + + + + Search criteria encompassing all public instance members, including base members. + + + + + Search criteria encompassing all non-public instance members, including base members. + + + + + Search criteria encompassing all public and non-public instance members, including base members. + + + + + Search criteria encompassing all public static members, including base members. + + + + + Search criteria encompassing all non-public static members, including base members. + + + + + Search criteria encompassing all public and non-public static members, including base members. + + + + + Search criteria encompassing all public instance members, excluding base members. + + + + + Search criteria encompassing all non-public instance members, excluding base members. + + + + + Search criteria encompassing all public and non-public instance members, excluding base members. + + + + + Search criteria encompassing all public static members, excluding base members. + + + + + Search criteria encompassing all non-public static members, excluding base members. + + + + + Search criteria encompassing all public and non-public static members, excluding base members. + + + + + Search criteria encompassing all members, including base and static members. + + + + + Search criteria encompassing all members (public and non-public, instance and static), including base members. + + + + + Provides notification callbacks for values that are cached using the class. + + + + + Called when the cached value is freed. + + + + + Called when the cached value is claimed. + + + + + Interface for immutable list. + + + + + Interface for generic immutable list. + + + + + Index accessor. + + + + + Immutable list wraps another list, and allows for reading the inner list, without the ability to change it. + + + + + Creates an immutable list around another list. + + + + + Number of items in the list. + + + + + Immutable list cannot be changed directly, so it's size is always fixed. + + + + + Immutable list are always readonly. + + + + + Returns true if the inner list is synchronized. + + + + + Gets the sync root object. + + + + + Index accessor. + + Index. + + + + Returns true if the item is contained in the list. + + The item's value. + + + + Copy the list to an array, + + Target array. + Index. + + + + Copy the list to an array, + + Target array. + Index. + + + + Gets an enumerator. + + + + + Get the index of a value. + + The item's value. + + + + Immutable list cannot be edited. + + Index. + + + + Immutable list cannot be edited. + + Index. + Item. + + + + Immutable list cannot be edited. + + Item. + + + + Immutable list cannot be edited. + + + + + Immutable list cannot be edited. + + Item. + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Immutable list wraps another list, and allows for reading the inner list, without the ability to change it. + + + + + Creates an immutable list around another list. + + + + + Number of items in the list. + + + + + Immutable list are always readonly. + + + + + Index accessor. + + Index. + + + + Returns true if the item is contained in the list. + + + + + Copies the list to an array. + + + + + Gets an enumerator. + + + + + Gets the index of an item. + + + + + Provides a methods of representing imaginary fields which are unique to serialization. + + We aggregate the FieldInfo associated with this member and return a mangled form of the name. + + + + + + The default fake name separator string. + + + + + Initializes a new instance of the class. + + The field to alias. + The name prefix to use. + + + + Initializes a new instance of the class. + + The field to alias. + The name prefix to use. + The separator string to use. + + + + Gets the aliased field. + + + The aliased field. + + + + + Gets the module in which the type that declares the member represented by the current is defined. + + + + + Gets a value that identifies a metadata element. + + + + + Gets the name of the current member. + + + + + Gets the class that declares this member. + + + + + Gets the class object that was used to obtain this instance of MemberInfo. + + + + + Gets the type of the field. + + + The type of the field. + + + + + Gets a RuntimeFieldHandle, which is a handle to the internal metadata representation of a field. + + + + + Gets the attributes. + + + The attributes. + + + + + When overridden in a derived class, returns an array of all custom attributes applied to this member. + + True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + An array that contains all the custom attributes applied to this member, or an array with zero elements if no attributes are defined. + + + + + When overridden in a derived class, returns an array of custom attributes applied to this member and identified by . + + The type of attribute to search for. Only attributes that are assignable to this type are returned. + True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + An array of custom attributes applied to this member, or an array with zero elements if no attributes assignable to have been applied. + + + + + When overridden in a derived class, indicates whether one or more attributes of the specified type or of its derived types is applied to this member. + + The type of custom attribute to search for. The search includes derived types. + True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + True if one or more instances of or any of its derived types is applied to this member; otherwise, false. + + + + + Gets the value of the field. + + The object instance to get the value from. + The value of the field. + + + + When overridden in a derived class, sets the value of the field supported by the given object. + + The object whose field value will be set. + The value to assign to the field. + A field of Binder that specifies the type of binding that is desired (for example, Binder.CreateInstance or Binder.ExactBinding). + A set of properties that enables the binding, coercion of argument types, and invocation of members through reflection. If is null, then Binder.DefaultBinding is used. + The software preferences of a particular culture. + + + + Provides a methods of representing aliased methods. + + In this case, what we're representing is a method on a parent class with the same name. + + We aggregate the MethodInfo associated with this member and return a mangled form of the name. + The name that we return is "parentname+methodName". + + + + + + The default fake name separator string. + + + + + Initializes a new instance of the class. + + The method to alias. + The name prefix to use. + + + + Initializes a new instance of the class. + + The method to alias. + The name prefix to use. + The separator string to use. + + + + Gets the aliased method. + + + The aliased method. + + + + + Gets the custom attributes for the return type. + + + + + Gets a handle to the internal metadata representation of a method. + + + + + Gets the attributes associated with this method. + + + + + Gets the class that declares this member. + + + + + Gets the name of the current member. + + + + + Gets the class object that was used to obtain this instance of MemberInfo. + + + + + When overridden in a derived class, returns the MethodInfo object for the method on the direct or indirect base class in which the method represented by this instance was first declared. + + + A MethodInfo object for the first implementation of this method. + + + + + When overridden in a derived class, returns an array of all custom attributes applied to this member. + + true to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + An array that contains all the custom attributes applied to this member, or an array with zero elements if no attributes are defined. + + + + + When overridden in a derived class, returns an array of custom attributes applied to this member and identified by . + + The type of attribute to search for. Only attributes that are assignable to this type are returned. + true to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + An array of custom attributes applied to this member, or an array with zero elements if no attributes assignable to have been applied. + + + + + When overridden in a derived class, returns the flags. + + + The MethodImplAttributes flags. + + + + + When overridden in a derived class, gets the parameters of the specified method or constructor. + + + An array of type ParameterInfo containing information that matches the signature of the method (or constructor) reflected by this MethodBase instance. + + + + + When overridden in a derived class, invokes the reflected method or constructor with the given parameters. + + The object on which to invoke the method or constructor. If a method is static, this argument is ignored. If a constructor is static, this argument must be null or an instance of the class that defines the constructor. + A bitmask that is a combination of 0 or more bit flags from . If is null, this parameter is assigned the value ; thus, whatever you pass in is ignored. + An object that enables the binding, coercion of argument types, invocation of members, and retrieval of MemberInfo objects via reflection. If is null, the default binder is used. + An argument list for the invoked method or constructor. This is an array of objects with the same number, order, and type as the parameters of the method or constructor to be invoked. If there are no parameters, this should be null.If the method or constructor represented by this instance takes a ByRef parameter, there is no special attribute required for that parameter in order to invoke the method or constructor using this function. Any object in this array that is not explicitly initialized with a value will contain the default value for that object type. For reference-type elements, this value is null. For value-type elements, this value is 0, 0.0, or false, depending on the specific element type. + An instance of CultureInfo used to govern the coercion of types. If this is null, the CultureInfo for the current thread is used. (This is necessary to convert a String that represents 1000 to a Double value, for example, since 1000 is represented differently by different cultures.) + + An Object containing the return value of the invoked method, or null in the case of a constructor, or null if the method's return type is void. Before calling the method or constructor, Invoke checks to see if the user has access permission and verifies that the parameters are valid.CautionElements of the array that represent parameters declared with the ref or out keyword may also be modified. + + + + + When overridden in a derived class, indicates whether one or more attributes of the specified type or of its derived types is applied to this member. + + The type of custom attribute to search for. The search includes derived types. + true to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + true if one or more instances of or any of its derived types is applied to this member; otherwise, false. + + + + + Provides a methods of representing imaginary properties which are unique to serialization. + + We aggregate the PropertyInfo associated with this member and return a mangled form of the name. + + + + + + The default fake name separator string. + + + + + Initializes a new instance of the class. + + The property to alias. + The name prefix to use. + + + + Initializes a new instance of the class. + + The property to alias. + The name prefix to use. + The separator string to use. + + + + The backing PropertyInfo that is being aliased. + + + + + Gets the module in which the type that declares the member represented by the current is defined. + + + + + Gets a value that identifies a metadata element. + + + + + Gets the name of the current member. + + + + + Gets the class that declares this member. + + + + + Gets the class object that was used to obtain this instance of MemberInfo. + + + + + Gets the type of the property. + + + The type of the property. + + + + + Gets the attributes. + + + The attributes. + + + + + Gets a value indicating whether this instance can read. + + + true if this instance can read; otherwise, false. + + + + + Gets a value indicating whether this instance can write. + + + true if this instance can write; otherwise, false. + + + + + When overridden in a derived class, returns an array of all custom attributes applied to this member. + + True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + An array that contains all the custom attributes applied to this member, or an array with zero elements if no attributes are defined. + + + + + When overridden in a derived class, returns an array of custom attributes applied to this member and identified by . + + The type of attribute to search for. Only attributes that are assignable to this type are returned. + True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + An array of custom attributes applied to this member, or an array with zero elements if no attributes assignable to have been applied. + + + + + When overridden in a derived class, indicates whether one or more attributes of the specified type or of its derived types is applied to this member. + + The type of custom attribute to search for. The search includes derived types. + True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + True if one or more instances of or any of its derived types is applied to this member; otherwise, false. + + + + + Returns an array whose elements reflect the public and, if specified, non-public get, set, and other accessors of the property reflected by the current instance. + + Indicates whether non-public methods should be returned in the MethodInfo array. true if non-public methods are to be included; otherwise, false. + + An array of objects whose elements reflect the get, set, and other accessors of the property reflected by the current instance. If is true, this array contains public and non-public get, set, and other accessors. If is false, this array contains only public get, set, and other accessors. If no accessors with the specified visibility are found, this method returns an array with zero (0) elements. + + + + + When overridden in a derived class, returns the public or non-public get accessor for this property. + + Indicates whether a non-public get accessor should be returned. true if a non-public accessor is to be returned; otherwise, false. + + A MethodInfo object representing the get accessor for this property, if is true. Returns null if is false and the get accessor is non-public, or if is true but no get accessors exist. + + + + + Gets the index parameters of the property. + + The index parameters of the property. + + + + When overridden in a derived class, returns the set accessor for this property. + + Indicates whether the accessor should be returned if it is non-public. true if a non-public accessor is to be returned; otherwise, false. + + Value Condition A object representing the Set method for this property. The set accessor is public.-or- is true and the set accessor is non-public. null is true, but the property is read-only.-or- is false and the set accessor is non-public.-or- There is no set accessor. + + + + + Gets the value of the property on the given instance. + + The object to invoke the getter on. + The to invoke with. + The binder to use. + The indices to use. + The culture to use. + The value of the property on the given instance. + + + + Sets the value of the property on the given instance. + + The object to set the value on. + The value to set. + The to invoke with. + The binder to use. + The indices to use. + The culture to use. + + + + Compares objects by reference only, ignoring equality operators completely. This is used by the property tree reference dictionaries to keep track of references. + + + + + A default, cached instance of this generic variant of the reference equality comparer. + + + + + Returns true if the object references are equal. + + + + + Returns the result of the object's own GetHashCode method. + + + + + Utility class indicating current Unity version. + + + + + Tests current Unity version is equal or greater. + + Minimum major version. + Minimum minor version. + true if the current Unity version is greater. Otherwise false. + + + + The current Unity version major. + + + + + The current Unity version minor. + + + + + Contains utilities for performing common unsafe operations. + + + + + Blindly creates an array of structs from an array of bytes via direct memory copy/blit. + + + + + Blindly creates an array of structs from an array of bytes via direct memory copy/blit. + + + + + Blindly copies an array of structs into an array of bytes via direct memory copy/blit. + + + + + Blindly copies an array of structs into an array of bytes via direct memory copy/blit. + + + + + Creates a new string from the contents of a given byte buffer. + + + + + Writes the contents of a string into a given byte buffer. + + + + + Blindly mem-copies a given number of bytes from the memory location of one object to another. WARNING: This method is ridiculously dangerous. Only use if you know what you're doing. + + + + + Provides basic functionality and overridable abstract methods for implementing a data reader. + + If you inherit this class, it is VERY IMPORTANT that you implement each abstract method to the *exact* specifications the documentation specifies. + + + + + + + Initializes a new instance of the class. + + The base stream of the reader. + The deserialization context to use. + The stream or context is null. + Cannot read from stream. + + + + Gets the current node id. If this is less than zero, the current node has no id. + + + The current node id. + + + + + Gets the current node depth. In other words, the current count of the node stack. + + + The current node depth. + + + + + Gets the name of the current node. + + + The name of the current node. + + + + + Gets or sets the base stream of the reader. + + + The base stream of the reader. + + value + Cannot read from stream + + + + Gets the deserialization context. + + + The deserialization context. + + + + + Tries to enter a node. This will succeed if the next entry is an . + + This call MUST (eventually) be followed by a corresponding call to + + This call will change the values of the , , and properties to the correct values for the current node. + + The type of the node. This value will be null if there was no metadata, or if the reader's serialization binder failed to resolve the type name. + true if entering a node succeeded, otherwise false + + + + Exits the current node. This method will keep skipping entries using until an is reached, or the end of the stream is reached. + + This call MUST have been preceded by a corresponding call to . + + This call will change the values of the , , and to the correct values for the node that was prior to the current node. + + true if the method exited a node, false if it reached the end of the stream. + + + + Tries to enters an array node. This will succeed if the next entry is an . + + This call MUST (eventually) be followed by a corresponding call to + + This call will change the values of the , , and properties to the correct values for the current array node. + + The length of the array that was entered. + true if an array was entered, otherwise false + + + + Exits the closest array. This method will keep skipping entries using until an is reached, or the end of the stream is reached. + + This call MUST have been preceded by a corresponding call to . + + This call will change the values of the , , and to the correct values for the node that was prior to the exited array node. + + true if the method exited an array, false if it reached the end of the stream. + + + + Reads a primitive array value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The element type of the primitive array. Valid element types can be determined using . + The resulting primitive array. + true if reading a primitive array succeeded, otherwise false + + + + Peeks ahead and returns the type of the next entry in the stream. + + The name of the next entry, if it has one. + The type of the next entry. + + + + Reads an internal reference id. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The internal reference id. + true if reading the value succeeded, otherwise false + + + + Reads an external reference index. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The external reference index. + true if reading the value succeeded, otherwise false + + + + Reads an external reference guid. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The external reference guid. + true if reading the value succeeded, otherwise false + + + + Reads an external reference string. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The external reference string. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the string of the entry is longer than 1 character, the first character of the string will be taken as the result. + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an or an . + + If the stored integer or floating point value is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an or an . + + If the stored integer or floating point value is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an or an . + + If the stored integer or floating point value is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a null value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + true if reading the value succeeded, otherwise false + + + + Skips the next entry value, unless it is an or an . If the next entry value is an or an , all of its contents will be processed, deserialized and registered in the deserialization context, so that internal reference values are not lost to entries further down the stream. + + + + + Disposes all resources and streams kept by the data reader. + + + + + Tells the reader that a new serialization session is about to begin, and that it should clear all cached values left over from any prior serialization sessions. + This method is only relevant when the same reader is used to deserialize several different, unrelated values. + + + + + Gets a dump of the data being read by the writer. The format of this dump varies, but should be useful for debugging purposes. + + + + + Peeks the current entry. + + The peeked entry. + + + + Consumes the current entry, and reads to the next one. + + The next entry. + + + + Implements functionality that is shared by both data readers and data writers. + + + + + Gets or sets the context's or writer's serialization binder. + + + The reader's or writer's serialization binder. + + + + + Gets a value indicating whether the reader or writer is in an array node. + + + true if the reader or writer is in an array node; otherwise, false. + + + + + Gets the current node depth. In other words, the current count of the node stack. + + + The current node depth. + + + + + Gets the current node, or if there is no current node. + + + The current node. + + + + + Pushes a node onto the node stack. + + The node to push. + + + + Pushes a node with the given name, id and type onto the node stack. + + The name of the node. + The id of the node. + The type of the node. + + + + Pushes an array node onto the node stack. This uses values from the current node to provide extra info about the array node. + + + + + Pops the current node off of the node stack. + + The name of the node to pop. + + There are no nodes to pop. + or + Tried to pop node with given name, but the current node's name was different. + + + + + Pops the current node if the current node is an array node. + + + + + Provides basic functionality and overridable abstract methods for implementing a data writer. + + If you inherit this class, it is VERY IMPORTANT that you implement each abstract method to the *exact* specifications the documentation specifies. + + + + + + + Initializes a new instance of the class. + + The base stream of the writer. + The serialization context to use. + The stream or context is null. + Cannot write to the stream. + + + + Gets or sets the base stream of the writer. + + + The base stream of the writer. + + value + Cannot write to stream + + + + Gets the serialization context. + + + The serialization context. + + + + + Flushes everything that has been written so far to the writer's base stream. + + + + + Writes the beginning of a reference node. + + This call MUST eventually be followed by a corresponding call to , with the same name. + + The name of the reference node. + The type of the reference node. If null, no type metadata will be written. + The id of the reference node. This id is acquired by calling . + + + + Begins a struct/value type node. This is essentially the same as a reference node, except it has no internal reference id. + + This call MUST eventually be followed by a corresponding call to , with the same name. + + The name of the struct node. + The type of the struct node. If null, no type metadata will be written. + + + + Ends the current node with the given name. If the current node has another name, an is thrown. + + The name of the node to end. This has to be the name of the current node. + + + + Begins an array node of the given length. + + The length of the array to come. + + + + Ends the current array node, if the current node is an array node. + + + + + Writes a primitive array to the stream. + + The element type of the primitive array. Valid element types can be determined using . + The primitive array to write. + + + + Writes a null value to the stream. + + The name of the value. If this is null, no name will be written. + + + + Writes an internal reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an external index reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an external guid reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an external string reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Disposes all resources and streams kept by the data writer. + + + + + Tells the writer that a new serialization session is about to begin, and that it should clear all cached values left over from any prior serialization sessions. + This method is only relevant when the same writer is used to serialize several different, unrelated values. + + + + + Gets a dump of the data currently written by the writer. The format of this dump varies, but should be useful for debugging purposes. + + + + + Reads data from a stream that has been written by a . + + + + + + Initializes a new instance of the class. + + The base stream of the reader. + The deserialization context to use. + + + + Disposes all resources kept by the data reader, except the stream, which can be reused later. + + + + + Peeks ahead and returns the type of the next entry in the stream. + + The name of the next entry, if it has one. + + The type of the next entry. + + + + + Tries to enters an array node. This will succeed if the next entry is an . + + This call MUST (eventually) be followed by a corresponding call to + This call will change the values of the , , and properties to the correct values for the current array node. + + The length of the array that was entered. + + true if an array was entered, otherwise false + + + + + Tries to enter a node. This will succeed if the next entry is an . + + This call MUST (eventually) be followed by a corresponding call to + This call will change the values of the , , and properties to the correct values for the current node. + + The type of the node. This value will be null if there was no metadata, or if the reader's serialization binder failed to resolve the type name. + + true if entering a node succeeded, otherwise false + + + + + Exits the closest array. This method will keep skipping entries using until an is reached, or the end of the stream is reached. + + This call MUST have been preceded by a corresponding call to . + + This call will change the values of the , , and to the correct values for the node that was prior to the exited array node. + + + true if the method exited an array, false if it reached the end of the stream. + + + + + Exits the current node. This method will keep skipping entries using until an is reached, or the end of the stream is reached. + + This call MUST have been preceded by a corresponding call to . + + This call will change the values of the , , and to the correct values for the node that was prior to the current node. + + + true if the method exited a node, false if it reached the end of the stream. + + + + + Reads a primitive array value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The element type of the primitive array. Valid element types can be determined using . + The resulting primitive array. + + true if reading a primitive array succeeded, otherwise false + + Type + typeof(T).Name + is not a valid primitive array type. + + + + Reads a value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the string of the entry is longer than 1 character, the first character of the string will be taken as the result. + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an or an . + + If the stored integer or floating point value is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an or an . + + If the stored integer or floating point value is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an or an . + + If the stored integer or floating point value is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an external reference guid. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The external reference guid. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an external reference index. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The external reference index. + + true if reading the value succeeded, otherwise false + + + + + Reads an external reference string. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The external reference string. + + true if reading the value succeeded, otherwise false + + + + + Reads a null value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + + true if reading the value succeeded, otherwise false + + + + + Reads an internal reference id. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The internal reference id. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Tells the reader that a new serialization session is about to begin, and that it should clear all cached values left over from any prior serialization sessions. + This method is only relevant when the same reader is used to deserialize several different, unrelated values. + + + + + Peeks the current entry. + + The peeked entry. + + + + Consumes the current entry, and reads to the next one. + + The next entry. + + + + Writes data to a stream that can be read by a . + + + + + + Initializes a new instance of the class. + + The base stream of the writer. + The serialization context to use. + + + + Begins an array node of the given length. + + The length of the array to come. + + + + Writes the beginning of a reference node. + + This call MUST eventually be followed by a corresponding call to , with the same name. + + The name of the reference node. + The type of the reference node. If null, no type metadata will be written. + The id of the reference node. This id is acquired by calling . + + + + Begins a struct/value type node. This is essentially the same as a reference node, except it has no internal reference id. + + This call MUST eventually be followed by a corresponding call to , with the same name. + + The name of the struct node. + The type of the struct node. If null, no type metadata will be written. + + + + Disposes all resources kept by the data writer, except the stream, which can be reused later. + + + + + Ends the current array node, if the current node is an array node. + + + + + Ends the current node with the given name. If the current node has another name, an is thrown. + + The name of the node to end. This has to be the name of the current node. + + + + Writes a primitive array to the stream. + + The element type of the primitive array. Valid element types can be determined using . + The primitive array to write. + Type + typeof(T).Name + is not a valid primitive array type. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an external guid reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an external index reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an external string reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a null value to the stream. + + The name of the value. If this is null, no name will be written. + + + + Writes an internal reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Tells the writer that a new serialization session is about to begin, and that it should clear all cached values left over from any prior serialization sessions. + This method is only relevant when the same writer is used to serialize several different, unrelated values. + + + + + Entry types in the binary format written by . + + + + + An invalid entry. + + + + + Entry denoting a named start of a reference node. + + + + + Entry denoting an unnamed start of a reference node. + + + + + Entry denoting a named start of a struct node. + + + + + Entry denoting an unnamed start of a struct node. + + + + + Entry denoting an end of node. + + + + + Entry denoting the start of an array. + + + + + Entry denoting the end of an array. + + + + + Entry denoting a primitive array. + + + + + Entry denoting a named internal reference. + + + + + Entry denoting an unnamed internal reference. + + + + + Entry denoting a named external reference by index. + + + + + Entry denoting an unnamed external reference by index. + + + + + Entry denoting a named external reference by guid. + + + + + Entry denoting an unnamed external reference by guid. + + + + + Entry denoting a named sbyte. + + + + + Entry denoting an unnamed sbyte. + + + + + Entry denoting a named byte. + + + + + Entry denoting an unnamed byte. + + + + + Entry denoting a named short. + + + + + Entry denoting an unnamed short. + + + + + Entry denoting a named ushort. + + + + + Entry denoting an unnamed ushort. + + + + + Entry denoting a named int. + + + + + Entry denoting an unnamed int. + + + + + Entry denoting a named uint. + + + + + Entry denoting an unnamed uint. + + + + + Entry denoting a named long. + + + + + Entry denoting an unnamed long. + + + + + Entry denoting a named ulong. + + + + + Entry denoting an unnamed ulong. + + + + + Entry denoting a named float. + + + + + Entry denoting an unnamed float. + + + + + Entry denoting a named double. + + + + + Entry denoting an unnamed double. + + + + + Entry denoting a named decimal. + + + + + Entry denoting an unnamed decimal. + + + + + Entry denoting a named char. + + + + + Entry denoting an unnamed char. + + + + + Entry denoting a named string. + + + + + Entry denoting an unnamed string. + + + + + Entry denoting a named guid. + + + + + Entry denoting an unnamed guid. + + + + + Entry denoting a named boolean. + + + + + Entry denoting an unnamed boolean. + + + + + Entry denoting a named null. + + + + + Entry denoting an unnamed null. + + + + + Entry denoting a type name. + + + + + Entry denoting a type id. + + + + + Entry denoting that the end of the stream has been reached. + + + + + Entry denoting a named external reference by string. + + + + + Entry denoting an unnamed external reference by string. + + + + + Provides a set of methods for reading data stored in a format written by a corresponding class. + + If you implement this interface, it is VERY IMPORTANT that you implement each method to the *exact* specifications the documentation specifies. + + It is strongly recommended to inherit from the class if you wish to implement a new data reader. + + + + + + Gets or sets the reader's serialization binder. + + + The reader's serialization binder. + + + + + Gets or sets the base stream of the reader. + + + The base stream of the reader. + + + + + Gets a value indicating whether the reader is in an array node. + + + true if the reader is in an array node; otherwise, false. + + + + + Gets the name of the current node. + + + The name of the current node. + + + + + Gets the current node id. If this is less than zero, the current node has no id. + + + The current node id. + + + + + Gets the current node depth. In other words, the current count of the node stack. + + + The current node depth. + + + + + Gets the deserialization context. + + + The deserialization context. + + + + + Gets a dump of the data being read by the writer. The format of this dump varies, but should be useful for debugging purposes. + + + + + Tries to enter a node. This will succeed if the next entry is an . + + This call MUST (eventually) be followed by a corresponding call to + + This call will change the values of the , , and properties to the correct values for the current node. + + The type of the node. This value will be null if there was no metadata, or if the reader's serialization binder failed to resolve the type name. + true if entering a node succeeded, otherwise false + + + + Exits the current node. This method will keep skipping entries using until an is reached, or the end of the stream is reached. + + This call MUST have been preceded by a corresponding call to . + + This call will change the values of the , , and to the correct values for the node that was prior to the current node. + + true if the method exited a node, false if it reached the end of the stream. + + + + Tries to enters an array node. This will succeed if the next entry is an . + + This call MUST (eventually) be followed by a corresponding call to + + This call will change the values of the , , and properties to the correct values for the current array node. + + The length of the array that was entered. + true if an array was entered, otherwise false + + + + Exits the closest array. This method will keep skipping entries using until an is reached, or the end of the stream is reached. + + This call MUST have been preceded by a corresponding call to . + + This call will change the values of the , , and to the correct values for the node that was prior to the exited array node. + + true if the method exited an array, false if it reached the end of the stream. + + + + Reads a primitive array value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The element type of the primitive array. Valid element types can be determined using . + The resulting primitive array. + true if reading a primitive array succeeded, otherwise false + + + + Peeks ahead and returns the type of the next entry in the stream. + + The name of the next entry, if it has one. + The type of the next entry. + + + + Reads an internal reference id. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The internal reference id. + true if reading the value succeeded, otherwise false + + + + Reads an external reference index. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The external reference index. + true if reading the value succeeded, otherwise false + + + + Reads an external reference guid. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The external reference guid. + true if reading the value succeeded, otherwise false + + + + Reads an external reference string. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The external reference string. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the string of the entry is longer than 1 character, the first character of the string will be taken as the result. + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an or an . + + If the stored integer or floating point value is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an or an . + + If the stored integer or floating point value is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an or an . + + If the stored integer or floating point value is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + true if reading the value succeeded, otherwise false + + + + Reads a null value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + true if reading the value succeeded, otherwise false + + + + Skips the next entry value, unless it is an or an . If the next entry value is an or an , all of its contents will be processed, deserialized and registered in the deserialization context, so that internal reference values are not lost to entries further down the stream. + + + + + Tells the reader that a new serialization session is about to begin, and that it should clear all cached values left over from any prior serialization sessions. + This method is only relevant when the same reader is used to deserialize several different, unrelated values. + + + + + Provides a set of methods for reading data stored in a format that can be read by a corresponding class. + + If you implement this interface, it is VERY IMPORTANT that you implement each method to the *exact* specifications the documentation specifies. + + It is strongly recommended to inherit from the class if you wish to implement a new data writer. + + + + + + Gets or sets the reader's serialization binder. + + + The reader's serialization binder. + + + + + Gets or sets the base stream of the writer. + + + The base stream of the writer. + + + + + Gets a value indicating whether the writer is in an array node. + + + true if the writer is in an array node; otherwise, false. + + + + + Gets the serialization context. + + + The serialization context. + + + + + Gets a dump of the data currently written by the writer. The format of this dump varies, but should be useful for debugging purposes. + + + + + Flushes everything that has been written so far to the writer's base stream. + + + + + Writes the beginning of a reference node. + + This call MUST eventually be followed by a corresponding call to , with the same name. + + The name of the reference node. + The type of the reference node. If null, no type metadata will be written. + The id of the reference node. This id is acquired by calling . + + + + Begins a struct/value type node. This is essentially the same as a reference node, except it has no internal reference id. + + This call MUST eventually be followed by a corresponding call to , with the same name. + + The name of the struct node. + The type of the struct node. If null, no type metadata will be written. + + + + Ends the current node with the given name. If the current node has another name, an is thrown. + + The name of the node to end. This has to be the name of the current node. + + + + Begins an array node of the given length. + + The length of the array to come. + + + + Ends the current array node, if the current node is an array node. + + + + + Writes a primitive array to the stream. + + The element type of the primitive array. Valid element types can be determined using . + The primitive array to write. + + + + Writes a null value to the stream. + + The name of the value. If this is null, no name will be written. + + + + Writes an internal reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an external index reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an external guid reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an external string reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Tells the writer that a new serialization session is about to begin, and that it should clear all cached values left over from any prior serialization sessions. + This method is only relevant when the same writer is used to serialize several different, unrelated values. + + + + + Contains various string constants used by the , and classes. + + + + + The named of a node id entry. + + + + + The name of a type entry. + + + + + The name of a regular array length entry. + + + + + The name of a primitive array length entry. + + + + + The name of a regular array content entry. + + + + + The name of a primitive array content entry. + + + + + The beginning of the content of an internal reference entry. + + + + + The beginning of the content of an external reference by index entry. + + + + + The beginning of the content of an external reference by guid entry. + + + + + The beginning of the content of an external reference by string entry. + + + + + Reads json data from a stream that has been written by a . + + + + + + Initializes a new instance of the class. + + The base stream of the reader. + The deserialization context to use. + + + + Gets or sets the base stream of the reader. + + + The base stream of the reader. + + + + + Disposes all resources kept by the data reader, except the stream, which can be reused later. + + + + + Peeks ahead and returns the type of the next entry in the stream. + + The name of the next entry, if it has one. + + The type of the next entry. + + + + + Tries to enter a node. This will succeed if the next entry is an . + + This call MUST (eventually) be followed by a corresponding call to + This call will change the values of the , , and properties to the correct values for the current node. + + The type of the node. This value will be null if there was no metadata, or if the reader's serialization binder failed to resolve the type name. + + true if entering a node succeeded, otherwise false + + + + + Exits the current node. This method will keep skipping entries using until an is reached, or the end of the stream is reached. + + This call MUST have been preceded by a corresponding call to . + + This call will change the values of the , , and to the correct values for the node that was prior to the current node. + + + true if the method exited a node, false if it reached the end of the stream. + + + + + Tries to enters an array node. This will succeed if the next entry is an . + + This call MUST (eventually) be followed by a corresponding call to + This call will change the values of the , , and properties to the correct values for the current array node. + + The length of the array that was entered. + + true if an array was entered, otherwise false + + + + + Exits the closest array. This method will keep skipping entries using until an is reached, or the end of the stream is reached. + + This call MUST have been preceded by a corresponding call to . + + This call will change the values of the , , and to the correct values for the node that was prior to the exited array node. + + + true if the method exited an array, false if it reached the end of the stream. + + + + + Reads a primitive array value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The element type of the primitive array. Valid element types can be determined using . + The resulting primitive array. + + true if reading a primitive array succeeded, otherwise false + + Type + typeof(T).Name + is not a valid primitive array type. + + + + Reads a value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an internal reference id. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The internal reference id. + + true if reading the value succeeded, otherwise false + + + + + Reads an external reference index. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The external reference index. + + true if reading the value succeeded, otherwise false + + + + + Reads an external reference guid. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The external reference guid. + + true if reading the value succeeded, otherwise false + + + + + Reads an external reference string. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The external reference string. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the string of the entry is longer than 1 character, the first character of the string will be taken as the result. + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads an value. This call will succeed if the next entry is an . + + If the value of the stored integer is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an or an . + + If the stored integer or floating point value is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an or an . + + If the stored integer or floating point value is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a value. This call will succeed if the next entry is an or an . + + If the stored integer or floating point value is smaller than or larger than , the result will be default(). + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The value that has been read. + + true if reading the value succeeded, otherwise false + + + + + Reads a null value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + + true if reading the value succeeded, otherwise false + + + + + Tells the reader that a new serialization session is about to begin, and that it should clear all cached values left over from any prior serialization sessions. + This method is only relevant when the same reader is used to deserialize several different, unrelated values. + + + + + Peeks the current entry. + + The peeked entry. + + + + Consumes the current entry, and reads to the next one. + + The next entry. + + + + Writes json data to a stream that can be read by a . + + + + + + Initializes a new instance of the class. + + The base stream of the writer. + The serialization context to use.> + Whether the json should be packed, or formatted as human-readable. + + + + Gets or sets a value indicating whether the json should be packed, or formatted as human-readable. + + + true if the json should be formatted as human-readable; otherwise, false. + + + + + Whether to enable an optimization that ensures any given type name is only written once into the json stream, and thereafter kept track of by ID. + + + + + Enable the "just started" flag, causing the writer to start a new "base" json object container. + + + + + Flushes everything that has been written so far to the writer's base stream. + + + + + Writes the beginning of a reference node. + + This call MUST eventually be followed by a corresponding call to , with the same name. + + The name of the reference node. + The type of the reference node. If null, no type metadata will be written. + The id of the reference node. This id is acquired by calling . + + + + Begins a struct/value type node. This is essentially the same as a reference node, except it has no internal reference id. + + This call MUST eventually be followed by a corresponding call to , with the same name. + + The name of the struct node. + The type of the struct node. If null, no type metadata will be written. + + + + Ends the current node with the given name. If the current node has another name, an is thrown. + + The name of the node to end. This has to be the name of the current node. + + + + Begins an array node of the given length. + + The length of the array to come. + + + + Ends the current array node, if the current node is an array node. + + + + + Writes a primitive array to the stream. + + The element type of the primitive array. Valid element types can be determined using . + The primitive array to write. + Type + typeof(T).Name + is not a valid primitive array type. + array + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a null value to the stream. + + The name of the value. If this is null, no name will be written. + + + + Writes an internal reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes a value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an external index reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an external guid reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an external string reference to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Writes an value to the stream. + + The name of the value. If this is null, no name will be written. + The value to write. + + + + Disposes all resources kept by the data writer, except the stream, which can be reused later. + + + + + Tells the writer that a new serialization session is about to begin, and that it should clear all cached values left over from any prior serialization sessions. + This method is only relevant when the same writer is used to serialize several different, unrelated values. + + + + + Parses json entries from a stream. + + + + + + The current deserialization context used by the text reader. + + + + + Initializes a new instance of the class. + + The stream to parse from. + The deserialization context to use. + The stream is null. + Cannot read from the stream. + + + + Resets the reader instance's currently peeked char and emergency playback queue. + + + + + Disposes all resources kept by the text reader, except the stream, which can be reused later. + + + + + Reads to (but not past) the beginning of the next json entry, and returns the entry name, contents and type. + + The name of the entry that was parsed. + The content of the entry that was parsed. + The type of the entry that was parsed. + + + + A serialization node as used by the format. + + + + + The name of the node. + + + + + The entry type of the node. + + + + + The data contained in the node. Depending on the entry type and name, as well as nodes encountered prior to this one, the format can vary wildly. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Tries to enters an array node. This will succeed if the next entry is an . + + This call MUST (eventually) be followed by a corresponding call to + This call will change the values of the , , and properties to the correct values for the current array node. + + The length of the array that was entered. + + true if an array was entered, otherwise false + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Reads a primitive array value. This call will succeed if the next entry is an . + + If the call fails (and returns false), it will skip the current entry value, unless that entry is an or an . + + The element type of the primitive array. Valid element types can be determined using . + The resulting primitive array. + + true if reading a primitive array succeeded, otherwise false + + Type + typeof(T).Name + is not a valid primitive array type. + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Peeks the current entry. + + The peeked entry. + + + + Consumes the current entry, and reads to the next one. + + The next entry. + + + + Shared config class for and . + + + + + The string to use to separate node id's from their names. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Begins an array node of the given length. + + The length of the array to come. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Formatter for all non-primitive one-dimensional arrays. + + The element type of the formatted array. + + + + + Returns null. + + + A null value. + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Custom formatter for the type . + + + + + + Returns null. + + + A null value. + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Provides common functionality for serializing and deserializing values of type , and provides automatic support for the following common serialization conventions: + + , , , , and . + + The type which can be serialized and deserialized by the formatter. + + + + + The on serializing callbacks for type . + + + + + The on serialized callbacks for type . + + + + + The on deserializing callbacks for type . + + + + + The on deserialized callbacks for type . + + + + + Whether the serialized value is a value type. + + + + + Gets the type that the formatter can serialize. + + + The type that the formatter can serialize. + + + + + Serializes a value using a specified . + + The value to serialize. + The writer to use. + + + + Deserializes a value using a specified . + + The reader to use. + + The deserialized value. + + + + + Deserializes a value of type using a specified . + + The reader to use. + + The deserialized value. + + + + + Serializes a value of type using a specified . + + The value to serialize. + The writer to use. + + + + Get an uninitialized object of type . WARNING: If you override this and return null, the object's ID will not be automatically registered and its OnDeserializing callbacks will not be automatically called, before deserialization begins. + You will have to call and immediately after creating the object yourself during deserialization. + + An uninitialized object of type . + + + + Registers the given object reference in the deserialization context. + + NOTE that this method only does anything if is not a value type. + + The value to register. + The reader which is currently being used. + + + + Invokes all methods on the object with the [OnDeserializing] attribute. + + WARNING: This method will not be called automatically if you override GetUninitializedObject and return null! You will have to call it manually after having created the object instance during deserialization. + + The value to invoke the callbacks on. + The deserialization context. + + + + Invokes all methods on the object with the [OnDeserializing] attribute. + + WARNING: This method will not be called automatically if you override GetUninitializedObject and return null! You will have to call it manually after having created the object instance during deserialization. + + The value to invoke the callbacks on. + The deserialization context. + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Formatter for all delegate types. + + This formatter can handle anything but delegates for dynamic methods. + + + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Get an uninitialized object of type . WARNING: If you override this and return null, the object's ID will not be automatically registered and its OnDeserializing callbacks will not be automatically called, before deserialization begins. + You will have to call and immediately after creating the object yourself during deserialization. + + + An uninitialized object of type . + + + + + Emergency hack class to support serialization of types derived from dictionary + + + + + Returns null. + + + A value of null. + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Custom generic formatter for the generic type definition . + + The type of the dictionary key. + The type of the dictionary value. + + + + + Creates a new instance of . + + + + + Returns null. + + + A value of null. + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Custom Odin serialization formatter for . + + Type of primary key. + Type of secondary key. + Type of value. + + + + Creates a new instance of . + + + + + Returns null. + + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides an easy way of implementing custom formatters. + + The type which can be serialized and deserialized by the formatter. + + + + Reads through all entries in the current node one at a time, and calls for each entry. + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Calls directly. + + The value to serialize. + The writer to serialize with. + + + + Reads a data entry into the value denoted by the entry name. + + The value to read into. + The name of the entry. + The type of the entry. + The reader currently used for deserialization. + + + + Write the serialized values of a value of type . + + The value to serialize. + The writer currently used for serialization. + + + + Indicates that this formatter type has been emitted. Never put this on a type! + + + + + A formatter for empty types. It writes no data, and skips all data that is to be read, deserializing a "default" value. + + + + + Skips the entry to read. + + + + + Does nothing at all. + + + + + Utility class for emitting formatters using the namespace. + + NOTE: Some platforms do not support emitting. Check whether you can emit on the current platform using . + + + + + The name of the pre-generated assembly that contains pre-emitted formatters for use on AOT platforms where emitting is not supported. Note that this assembly is not always present. + + + + + The name of the runtime-generated assembly that contains runtime-emitted formatters for use on non-AOT platforms where emitting is supported. Note that this assembly is not always present. + + + + + Base type for all AOT-emitted formatters. + + + + + Shortcut class that makes it easier to emit empty AOT formatters. + + + + + Skips the entry to read. + + + + + Does nothing at all. + + + + + Gets an emitted formatter for a given type. + + NOTE: Some platforms do not support emitting. On such platforms, this method logs an error and returns null. Check whether you can emit on the current platform using . + + The type to emit a formatter for. + The serialization policy to use to determine which members the emitted formatter should serialize. If null, is used. + The type of the emitted formatter. + The type argument is null. + + + + Emits a formatter for a given type into a given module builder, using a given serialization policy to determine which members to serialize. + + Type to create a formatter for. + The module builder to emit a formatter into. + The serialization policy to use for creating the formatter. + The fully constructed, emitted formatter type. + + + + Utility class for the class. + + + + + Determines whether the specified type can be formatted by a . + + The following criteria are checked: type implements , type is not abstract, type is not a generic type definition, type is not an interface, type has a public parameterless constructor. + + The collection type to check. + The element type of the collection. + true if the type can be formatted by a , otherwise false + The type argument is null. + + + + Formatter for all eligible types that implement the interface , and which have no other formatters specified. + + Eligibility for formatting by this class is determined by the method. + + The type of the collection. + The type of the element. + + + + Creates a new instance of . + + + + + Gets a new object of type . + + + A new object of type . + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Custom generic formatter for the generic type definition . + + The element type of the formatted list. + + + + + Returns null. + + + A null value. + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Serializes and deserializes a given type. + + NOTE that if you are implementing a custom formatter and registering it using the , it is not enough to implement - you have to implement . + + + + + Gets the type that the formatter can serialize. + + + The type that the formatter can serialize. + + + + + Serializes a value using a specified . + + The value to serialize. + The writer to use. + + + + Deserializes a value using a specified . + + The reader to use. + + The deserialized value. + + + + + Serializes and deserializes a given type T. + + The type which can be serialized and deserialized by the formatter. + + + + Serializes a value of type using a specified . + + The value to serialize. + The writer to use. + + + + Deserializes a value of type using a specified . + + The reader to use. + + The deserialized value. + + + + + Custom generic formatter for the generic type definition . + + The type of the key. + The type of the value. + + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Custom generic formatter for the generic type definition . + + The element type of the formatted list. + + + + + Returns null. + + + A null value. + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Minimal baseline formatter. Doesn't come with all the bells and whistles of any of the other BaseFormatter classes. + Common serialization conventions aren't automatically supported, and common deserialization callbacks are not automatically invoked. + + The type which can be serialized and deserialized by the formatter. + + + + Whether the serialized value is a value type. + + + + + Gets the type that the formatter can serialize. + + + The type that the formatter can serialize. + + + + + Deserializes a value of type using a specified . + + The reader to use. + + The deserialized value. + + + + + Serializes a value of type using a specified . + + The value to serialize. + The writer to use. + + + + Serializes a value using a specified . + + The value to serialize. + The writer to use. + + + + Deserializes a value using a specified . + + The reader to use. + + The deserialized value. + + + + + Get an uninitialized object of type . WARNING: If you override this and return null, the object's ID will not be automatically registered. + You will have to call immediately after creating the object yourself during deserialization. + + An uninitialized object of type . + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Registers the given object reference in the deserialization context. + + NOTE that this method only does anything if is not a value type. + + The value to register. + The reader which is currently being used. + + + + Formatter for all arrays with more than one dimension. + + The type of the formatted array. + The element type of the formatted array. + + + + + Returns null. + + + A null value. + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Formatter for all types. + + The type that is nullable. + + + + + Creates a new instance of . + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Formatter for all primitive one-dimensional arrays. + + The element type of the formatted array. This type must be an eligible primitive array type, as determined by . + + + + + Returns null. + + + A null value. + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Final fallback formatter for all types which have no other formatters. This formatter relies on reflection to work, and is thus comparatively slow and creates more garbage than a custom formatter. + + The type which can be serialized and deserialized by the formatter. + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Formatter for types that implement the interface. + + + + + + + Calls on the value to deserialize. + + + + + Calls on the value to deserialize. + + + + + Formatter for all types that implement the ISerializable interface. + + The type which can be serialized and deserialized by the formatter. + + + + + Get an uninitialized object of type . WARNING: If you override this and return null, the object's ID will not be automatically registered and its OnDeserializing callbacks will not be automatically called, before deserialization begins. + You will have to call and immediately after creating the object yourself during deserialization. + + + An uninitialized object of type . + + + + + Provides the actual implementation for deserializing a value of type . + + The uninitialized value to serialize into. This value will have been created earlier using . + The reader to deserialize with. + + + + Provides the actual implementation for serializing a value of type . + + The value to serialize. + The writer to serialize with. + + + + Creates and reads into a instance using a given reader and context. + + The reader to use. + + The which was read. + + + + + Writes the given using the given writer. + + The to write. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Formatter for the type which uses the reader/writer's to bind types. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Returns null. + + null. + + + + Helper class for quickly and easily implementing the interface. + + + + + Initializes a new instance of the class. + + The policy ID. + if set to true non serializable types will be allowed. + The delegate to use for determining whether members should be serialized. + + The id argument or the shouldSerializeFunc argument was null. + + + + + Gets the identifier of the policy. This can be stored in the serialization metadata, so the policy used to serialize it can be recovered without knowing the policy at runtime. This ID should preferably be unique. + + + The identifier of the policy. + + + + + Gets a value indicating whether to allow non serializable types. (Types which are not decorated with .) + + + true if serializable types are allowed; otherwise, false. + + + + + Gets a value indicating whether a given should be serialized or not. + + The member to check. + + true if the given member should be serialized, otherwise, false. + + + + + Use this attribute to specify that a type that implements the + interface should *always* format itself regardless of other formatters being specified. + + This means that the interface will be used to format all types derived from the type that + is decorated with this attribute, regardless of custom formatters for the derived types. + + + + + + Attribute indicating that a class which implements the interface somewhere in its hierarchy is a custom formatter for the type T. + + + + + + The priority of the formatter. Of all the available custom formatters, the formatter with the highest priority is always chosen. + + + + + Initializes a new instance of the class with priority 0. + + + + + Initializes a new instance of the class. + + The priority of the formatter. Of all the available custom formatters, the formatter with the highest priority is always chosen. + + + + Attribute indicating that a generic type definition class which implements the interface somewhere in its hierarchy is a custom formatter for *any variation* of the generic type definition T. + + The formatter's generic type parameters are mapped onto the serialized type's generic type parameters. + + For example, implements , where T is . + + + + + + The generic type definition of the serialized type. + + + + + Initializes a new instance of the class. + + The generic type definition of the serialized type. + The priority of the formatter. Of all the available custom formatters, the formatter with the highest priority is always chosen. + was null. + The type given in is not a generic type definition. + + + + An attribute that lets you help the DefaultSerializationBinder bind type names to types. This is useful if you're renaming a type, + that would result in data loss, and what to specify the new type name to avoid loss of data. + + + + + [assembly: OdinSerializer.BindTypeNameToType("Namespace.OldTypeName", typeof(Namespace.NewTypeName))] + //[assembly: OdinSerializer.BindTypeNameToType("Namespace.OldTypeName, OldFullAssemblyName", typeof(Namespace.NewTypeName))] + + namespace Namespace + { + public class SomeComponent : SerializedMonoBehaviour + { + public IInterface test; // Contains an instance of OldTypeName; + } + + public interface IInterface { } + + public class NewTypeName : IInterface { } + + //public class OldTypeName : IInterface { } + } + + + + + + Initializes a new instance of the class. + + Old old full type name. If it's moved to new a new assembly you must specify the old assembly name as well. See example code in the documentation. + The new type. + + + + Provides a default, catch-all implementation. This binder only includes assembly names, without versions and tokens, in order to increase compatibility. + + + + + + + Bind a type to a name. + + The type to bind. + The debug context to log to. + + The name that the type has been bound to. + + The type argument is null. + + + + Determines whether the specified type name is mapped. + + + + + Binds a name to type. + + The name of the type to bind. + The debug context to log to. + + The type that the name has been bound to, or null if the type could not be resolved. + + The typeName argument is null. + + + + The context of a given deserialization session. This class maintains all internal and external references during deserialization. + + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The streaming context to use. + + + + Initializes a new instance of the class. + + The formatter converter to use. + + + + Initializes a new instance of the class. + + The streaming context to use. + The formatter converter to use. + The formatterConverter parameter is null. + + + + Gets or sets the context's type binder. + + + The context's serialization binder. + + + + + Gets or sets the string reference resolver. + + + The string reference resolver. + + + + + Gets or sets the Guid reference resolver. + + + The Guid reference resolver. + + + + + Gets or sets the index reference resolver. + + + The index reference resolver. + + + + + Gets the streaming context. + + + The streaming context. + + + + + Gets the formatter converter. + + + The formatter converter. + + + + + Gets or sets the serialization configuration. + + + The serialization configuration. + + + + + Registers an internal reference to a given id. + + The id to register the reference with. + The reference to register. + + + + Gets an internal reference from a given id, or null if the id has not been registered. + + The id of the reference to get. + An internal reference from a given id, or null if the id has not been registered. + + + + Gets an external object reference by index, or null if the index could not be resolved. + + The index to resolve. + An external object reference by the given index, or null if the index could not be resolved. + + + + Gets an external object reference by guid, or null if the guid could not be resolved. + + The guid to resolve. + An external object reference by the given guid, or null if the guid could not be resolved. + + + + Gets an external object reference by an id string, or null if the id string could not be resolved. + + The id string to resolve. + An external object reference by an id string, or null if the id string could not be resolved. + + + + Resets the deserialization context completely to baseline status, as if its constructor has just been called. + This allows complete reuse of a deserialization context, with all of its internal reference buffers. + + + + + An entry type which is part of a stream being read by a . + + + + + Could not parse entry. + + + + + Entry is a primitive value of type string or char. + + + + + Entry is a primitive value of type guid. + + + + + Entry is a primitive value of type sbyte, byte, short, ushort, int, uint, long or ulong. + + + + + Entry is a primitive value of type float, double or decimal. + + + + + Entry is a primitive boolean value. + + + + + Entry is a null value. + + + + + Entry marks the start of a node, IE, a complex type that contains values of its own. + + + + + Entry marks the end of a node, IE, a complex type that contains values of its own. + + + + + Entry contains an ID that is a reference to a node defined previously in the stream. + + + + + Entry contains the index of an external object in the DeserializationContext. + + + + + Entry contains the guid of an external object in the DeserializationContext. + + + + + Entry marks the start of an array. + + + + + Entry marks the end of an array. + + + + + Entry marks a primitive array. + + + + + Entry indicating that the reader has reached the end of the data stream. + + + + + Entry contains the string id of an external object in the DeserializationContext. + + + + + + Causes Odin's inspector to completely ignore a given member, preventing it from even being included in an Odin PropertyTree, + and such will not cause any performance hits in the inspector. + + Note that Odin can still serialize an excluded member - it is merely ignored in the inspector itself. + + + + + Resolves external guid references to reference objects during serialization and deserialization. + + + + + Gets or sets the next resolver in the chain. + + + The next resolver in the chain. + + + + + Tries to resolve a reference from a given Guid. + + The Guid to resolve. + The resolved value. + true if the value was resolved; otherwise, false. + + + + Determines whether this resolver can reference the specified value with a Guid. + + The value to check. + The Guid which references the value. + true if the value can be referenced; otherwise, false. + + + + Resolves external index references to reference objects during serialization and deserialization. + + + + + Tries to resolve the given reference index to a reference value. + + The index to resolve. + The resolved value. + true if the index could be resolved to a value, otherwise false. + + + + Determines whether the specified value can be referenced externally via this resolver. + + The value to reference. + The index of the resolved value, if it can be referenced. + true if the reference can be resolved, otherwise false. + + + + Resolves external strings references to reference objects during serialization and deserialization. + + + + + Gets or sets the next resolver in the chain. + + + The next resolver in the chain. + + + + + Tries to resolve a reference from a given Guid. + + The to resolve. + The resolved value. + true if the value was resolved; otherwise, false. + + + + Determines whether this resolver can reference the specified value with a string. + + The value to check. + The string which references the value. + true if the value can be referenced; otherwise, false. + + + + Specifies that a type is capable of serializing itself using an and an + . + + The deserialized type instance will be created without a constructor call using the + + method if it is a reference type, otherwise it will be created using default(type). + + Use to specify that a class which implements this + interface should *always* format itself regardless of other formatters being specified. + + + + + Serializes the instance's data using the given writer. + + + + + Deserializes data into the instance using the given reader. + + + + + Defines which members to serialize and deserialize when there aren't any custom formatters for a type. + Usually, it governs the behaviour of the and classes. + + + + + Gets the identifier of the policy. This can be stored in the serialization metadata, so the policy used to serialize can be recovered upon deserialization without knowing the policy ahead of time. This ID should preferably be unique. + + + The identifier of the policy. + + + + + Gets a value indicating whether to allow non serializable types. (Types which are not decorated with .) + + + true if serializable types are allowed; otherwise, false. + + + + + Gets a value indicating whether a given should be serialized or not. + + The member to check. + true if the given member should be serialized, otherwise, false. + + + + Contains information about a node during deserialization and serialization. + + + + + An empty node. + + + + + The name of the node. + + + + + The id of the node, or -1 if the node has no id. + + + + + The type of the node, or null if the node has no type metadata. + + + + + Whether the node is an array or not. + + + + + Whether the node is an empty node. + + + + + Initializes a new instance of the struct. + + The name of the node. + The id of the node. + The type of the node. + If set to true the node is an array node. + + + + Implements the operator == between and . + + The first . + The second . + + true if the nodes were equal; otherwise, false. + + + + + Implements the operator != between and . + + The first . + The second . + + true if the nodes were not equal; otherwise, false. + + + + + Determines whether the specified , is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Indicates that an instance field or auto-property was previously serialized with a different name, so that values serialized with the old name will be properly deserialized into this member. + + This does the same as Unity's FormerlySerializedAs attribute, except it can also be applied to properties. + + + + + + The former name. + + + + + Initializes a new instance of the class. + + The former name. + + + + An exception thrown when the serialization system has encountered an issue so severe that serialization is being aborted. If this exception is caught in the serialization system somewhere, it should be rethrown. + + + + + Initializes a new instance of the class. + + The message. + + + + Initializes a new instance of the class. + + The message. + The inner exception. + + + + Defines the configuration during serialization and deserialization. This class is thread-safe. + + + + + Initializes a new instance of the class. + + + + + + Setting this member to true indicates that in the case where, when expecting to deserialize an instance of a certain type, + but encountering an incompatible, uncastable type in the data being read, the serializer should attempt to deserialize an + instance of the expected type using the stored, possibly invalid data. + + + This is equivalent to applying the attribute, except global + instead of specific to a single type. Note that if this member is set to false, individual types may still be deserialized + with invalid data if they are decorated with the attribute. + + + + + + Gets or sets the serialization policy. This value is never null; if set to null, it will default to . + + + The serialization policy. + + + + + Gets or sets the debug context. This value is never null; if set to null, a new default instance of will be created upon the next get. + + + The debug context. + + + + + Resets the configuration to a default configuration, as if the constructor had just been called. + + + + + Defines a context for debugging and logging during serialization and deserialization. This class is thread-safe. + + + + + The logger to use for logging messages. + + + + + The logging policy to use. + + + + + The error handling policy to use. + + + + + Log a warning. Depending on the logging policy and error handling policy, this message may be suppressed or result in an exception being thrown. + + + + + Log an error. Depending on the logging policy and error handling policy, this message may be suppressed or result in an exception being thrown. + + + + + Log an exception. Depending on the logging policy and error handling policy, this message may be suppressed or result in an exception being thrown. + + + + + The context of a given serialization session. This class maintains all internal and external references during serialization. + + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The streaming context to use. + + + + Initializes a new instance of the class. + + The formatter converter to use. + + + + Initializes a new instance of the class. + + The streaming context to use. + The formatter converter to use. + The formatterConverter parameter is null. + + + + Gets or sets the context's type binder. + + + The context's serialization binder. + + + + + Gets the streaming context. + + + The streaming context. + + + + + Gets the formatter converter. + + + The formatter converter. + + + + + Gets or sets the index reference resolver. + + + The index reference resolver. + + + + + Gets or sets the string reference resolver. + + + The string reference resolver. + + + + + Gets or sets the Guid reference resolver. + + + The Guid reference resolver. + + + + + Gets or sets the serialization configuration. + + + The serialization configuration. + + + + + Tries to get the id of an internally referenced object. + + The reference to get the id of. + The id that was found, or -1 if no id was found. + true if a reference was found, otherwise false. + + + + Tries to register an internal reference. Returns true if the reference was registered, otherwise, false when the reference has already been registered. + + The reference to register. + The id of the registered reference. + true if the reference was registered, otherwise, false when the reference has already been registered. + + + + Tries to register an external index reference. + + The object to reference. + The index of the referenced object. + true if the object could be referenced by index; otherwise, false. + + + + Tries to register an external guid reference. + + The object to reference. + The guid of the referenced object. + true if the object could be referenced by guid; otherwise, false. + + + + Tries to register an external string reference. + + The object to reference. + The id string of the referenced object. + true if the object could be referenced by string; otherwise, false. + + + + Resets the context's internal reference map. + + + + + Resets the serialization context completely to baseline status, as if its constructor has just been called. + This allows complete reuse of a serialization context, with all of its internal reference buffers. + + + + + Indicates that an instance field or auto-property should be serialized by Odin. + + + + + + Binds types to strings during serialization, and strings to types during deserialization. + + + + + Provides a default, catch-all implementation. This binder only includes assembly names, without versions and tokens, in order to increase compatibility. + + + + + Bind a type to a name. + + The type to bind. + The debug context to log to. + The name that the type has been bound to. + + + + Binds a name to a type. + + The name of the type to bind. + The debug context to log to. + The type that the name has been bound to, or null if the type could not be resolved. + + + + Determines whether the specified type name is mapped. + + + + + Contains a set of default implementations of the interface. + + NOTE: Policies are not necessarily compatible with each other in intuitive ways. + Data serialized with the policy + will for example fail to deserialize auto-properties with , + even if only strict data is needed. + It is best to ensure that you always use the same policy for serialization and deserialization. + + This class and all of its policies are thread-safe. + + + + + Tries to get a serialization policy by its id, in case a serialization graph has the policy used for serialization stored by name. + + + + + All fields not marked with are serialized. If a field is marked with both and , then the field will be serialized. + + + + + Public fields, as well as fields or auto-properties marked with or and not marked with , are serialized. + + There are two exceptions: + 1) All fields in tuples, as well as in private nested types marked as compiler generated (e.g. lambda capture classes) are also serialized. + 2) Virtual auto-properties are never serialized. Note that properties specified by an implemented interface are automatically marked virtual by the compiler. + + + + + Only fields and auto-properties marked with or and not marked with are serialized. + + There are two exceptions: + 1) All fields in private nested types marked as compiler generated (e.g. lambda capture classes) are also serialized. + 2) Virtual auto-properties are never serialized. Note that properties specified by an implemented interface are automatically marked virtual by the compiler. + + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for all complex types; IE, types which are not primitives as determined by the method. + + The type which the can serialize and deserialize. + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for all enums. + + The type of the enum to serialize and deserialize. + + + + + Reads an enum value of type . + + The reader to use. + + The value which has been read. + + + + + Writes an enum value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializes and deserializes a given type, and wraps serialization and deserialization with all the proper calls to free formatters from tedious boilerplate. + + Whenever serializing or deserializing anything, it is *strongly recommended* to use to get a proper wrapping serializer for that type. + + NOTE: This class should NOT be inherited from; it is hard-coded into the system. + + To extend the serialization system, instead create custom formatters, which are used by the class. + + + + + Editor-only event that fires whenever a serializer serializes a type. + + + + + Fires the event. + + + + + Gets a for the given value. If the value is null, it will be treated as a value of type . + + The value to get a for. + A for the given value. + + + + Gets a for type T. + + The type to get a for. + A for type T. + + + + Gets a for the given type. + + The type to get a for. + A for the given type. + The type argument is null. + + + + Reads a value weakly, casting it into object. Use this method if you don't know what type you're going to be working with at compile time. + + The reader to use. + The value which has been read. + + + + Writes a weakly typed value. Use this method if you don't know what type you're going to be working with at compile time. + + The value to write. + The writer to use. + + + + Writes a weakly typed value with a given name. Use this method if you don't know what type you're going to be working with at compile time. + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializes and deserializes the type , and wraps serialization and deserialization with all the proper calls to free formatters from tedious boilerplate. + + Whenever serializing or deserializing anything, it is *strongly recommended* to use to get a proper wrapping serializer for that type. + + NOTE: This class should NOT be inherited from; it is hard-coded into the system. + + To extend the serialization system, instead create custom formatters, which are used by the class. + + The type which the can serialize and deserialize. + + + + Reads a value of type weakly, casting it into object. Use this method if you don't know what type you're going to be working with at compile time. + + The reader to use. + + The value which has been read. + + + + + Writes a weakly typed value of type with a given name. Use this method if you don't know what type you're going to be working with at compile time. + + The name of the value to write. + The value to write. + The writer to use. + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The value to write. + The writer to use. + + + + Writes a value of type with a given name. + + The name of the value to write. + The value to write. + The writer to use. + + + + Fires the event with the T generic argument of the serializer. + + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Serializer for the type. + + + + + + Reads a value of type . + + The reader to use. + + The value which has been read. + + + + + Writes a value of type . + + The name of the value to write. + The value to write. + The writer to use. + + + + Custom formatter for the type. + + + + + + Returns null. + + + A null value. + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + + Custom formatter for the type. + This serializes nothing and always deserializes null, + and only exists to ensure that no coroutine instances + are ever created by the serialization system, since they + will in almost all cases be invalid instances. + + + Invalid coroutine instances crash Unity instantly when + they are garbage collected. + + + + + + Gets the type that the formatter can serialize. + + + The type that the formatter can serialize. + + + + + Returns null. + + + + + Returns null. + + + + + Does nothing. + + + + + Does nothing. + + + + + Not yet documented. + + Not yet documented. + + + + Not yet documented. + + + + + Not yet documented. + + Not yet documented. + Not yet documented. + + + + Not yet documented. + + Not yet documented. + Not yet documented. + + + + Not yet documented. + + Not yet documented. + Not yet documented. + Not yet documented. + + + + Not yet documented. + + + + + Gets the provider identifier. + + + + + Gets the path string from key. + + The key. + + + + Gets the key from path string. + + The path string. + + + + Compares the specified x. + + The x. + The y. + + + + Not yet documented. + + + + + Gets the path string from key. + + The key. + + + + Gets the key from path string. + + The path string. + + + + Compares the specified x. + + The x. + The y. + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Dictionary key path provider for + + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Indicates that an Odin-serialized Unity object controls its own serialization format. Every time it is serialized, it will be asked which format to use. + + + + + Gets the format to use for serialization. + + + + + Indicates that an Odin-serialized Unity object supports prefab serialization. + + + + + Gets or sets the serialization data of the object. + + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Unity serialized data struct that contains all data needed by Odin serialization. + + + + + The name of the field. + + + + + The name of the field. + + + + + The name of the field. + + + + + The data format used by the serializer. This field will be automatically set to the format specified in the global serialization config + when the Unity object gets serialized, unless the Unity object implements the interface. + + + + + The serialized data when serializing with the Binray format. + + + + + All serialized Unity references. + + + + + Whether the object contains any serialized data. + + + + + Gets a value indicating whether the struct contains any data. + If this is false, then it could mean that Unity has not yet deserialized the struct. + + + + + The serialized data when serializing with the JSON format. + + + + + The reference to the prefab this is only populated in prefab scene instances. + + + + + All serialized Unity references. + + + + + All Odin serialized prefab modifications. + + + + + The serialized data when serializing with the Nodes format. + + + + + Resets all data. + + + + + Custom generic formatter for the , , and types. + + The type of UnityEvent that this formatter can serialize and deserialize. + + + + + Get an uninitialized object of type . + + + An uninitialized object of type . + + + + + Resolves external index references to Unity objects. + + + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with a list of Unity objects. + + The referenced Unity objects. + + + + Gets the currently referenced Unity objects. + + A list of the currently referenced Unity objects. + + + + Sets the referenced Unity objects of the resolver to a given list, or a new list if the value is null. + + The referenced Unity objects to set, or null if a new list is required. + + + + Determines whether the specified value can be referenced externally via this resolver. + + The value to reference. + The index of the resolved value, if it can be referenced. + + true if the reference can be resolved, otherwise false. + + + + + Tries to resolve the given reference index to a reference value. + + The index to resolve. + The resolved value. + + true if the index could be resolved to a value, otherwise false. + + + + + Resets this instance. + + + + + Utility class which initializes the Sirenix serialization system to be compatible with Unity. + + + + + Initializes the Sirenix serialization system to be compatible with Unity. + + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Custom formatter for the type. + + + + + + Reads into the specified value using the specified reader. + + The value to read into. + The reader to use. + + + + Writes from the specified value using the specified writer. + + The value to write from. + The writer to use. + + + + Provides a way of claiming and releasing cached array buffers. + + The element type of the array to buffer. + + + + + Gets the total element count of the buffered array. This will always be a power of two. + + + The total element count of the buffered array. + + Cannot access a buffer while it is freed. + + + + Gets the buffered array. + + + The buffered array. + + Cannot access a buffer while it is freed. + + + + Gets a value indicating whether this buffer is free. + + + true if this buffer is free; otherwise, false. + + + + + Claims a buffer with the specified minimum capacity. Note: buffers always have a capacity equal to or larger than 256. + + The minimum capacity. + A buffer which has a capacity equal to or larger than the specified minimum capacity. + Requested size of buffer must be larger than 0. + + + + Frees the specified buffer. + + The buffer to free. + The buffer argument is null. + + + + Frees this buffer. + + + + + Frees this buffer. + + + + + Utility class for locating and caching formatters for all non-primitive types. + + + + + Editor-only event that fires whenever an emittable formatter has been located. + This event is used by the AOT formatter pre-emitter to locate types that need to have formatters pre-emitted. + + + + + Editor-only event that fires whenever a formatter has been located. + + + + + This event is invoked before everything else when a formatter is being resolved for a given type. If any invoked delegate returns a valid formatter, that formatter is used and the resolve process stops there. + + This can be used to hook into and extend the serialization system's formatter resolution logic. + + + + + Gets a formatter for the type . + + The type to get a formatter for. + The serialization policy to use if a formatter has to be emitted. If null, is used. + + A formatter for the type . + + + + + Gets a formatter for a given type. + + The type to get a formatter for. + The serialization policy to use if a formatter has to be emitted. If null, is used. + + A formatter for the given type. + + The type argument is null. + + + + Provides an array of utility methods which are commonly used by serialization formatters. + + + + + Gets a map of all serializable members on the given type. This will also properly map names extracted from and to their corresponding members. + + The type to get a map for. + The serialization policy to use. If null, is used. + A map of all serializable members on the given type. + + + + Gets an array of all serializable members on the given type. + + The type to get serializable members for. + The serialization policy to use. If null, is used. + An array of all serializable members on the given type. + + + + Creates a fake Unity null value of a given type, for the given -derived owning type. + + Unity uses these kinds of values to indicate missing object references. + + Type of the null value. + Type of the owning value. This is the value which changes the which you get. + A fake Unity null value of a given type. + The nullType or owningType parameter is null. + + The type given in the nullType parameter is not a Unity object. + or + The type given in the owningType parameter is not a Unity object. + + + + + Determines whether a given type is a primitive type to the serialization system. + + The following criteria are checked: type.IsPrimitive or type.IsEnum, or type is a , or . + + The type to check. + true if the given type is a primitive type; otherwise, false. + + + + Determines whether a given type is a primitive array type. Namely, arrays with primitive array types as elements are primitive arrays. + + The following types are primitive array types: , , , , , , , , , , , , and . + + The type to check. + true if the given type is a primitive array type; otherwise, false. + + + + Gets the type contained in the given . Currently only and is supported. + + The to get the contained type of. + The type contained in the given . + Can't get the contained type of the given type. + + + + Gets the value contained in a given . Currently only and is supported. + + The to get the value of. + The instance to get the value from. + The value contained in the given . + Can't get the value of the given type. + + + + Sets the value of a given MemberInfo. Currently only and is supported. + + The to set the value of. + The object to set the value on. + The value to set. + + Property has no setter + or + Can't set the value of the given type. + + + + + Gets an aliased version of a member, with the declaring type name included in the member name, so that there are no conflicts with private fields and properties with the same name in different classes in the same inheritance hierarchy. + + Marked internal in Odin because this method MUST NOT BE CALLED FROM ODIN'S INSPECTOR CODE. + Odin has its own version of this, and there must be no conflict. These aliases must not be + mixed into Odin's own. Use InspectorPropertyInfoUtility.GetPrivateMemberAlias instead. + + + + + Provides utility methods for handling dictionary keys in the prefab modification system. + + + + + A smart comparer for dictionary keys, that uses the most appropriate available comparison method for the given key types. + + + + + Not yet documented. + + Not yet documented. + Not yet documented. + Not yet documented. + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + An Odin-serialized prefab modification, containing all the information necessary to apply the modification. + + + + + The type of modification to be made. + + + + + The deep reflection path at which to make the modification. + + + + + A list of all deep reflection paths in the target object where the value referenced by this modification was also located. + + + + + The modified value to set. + + + + + The new list length to set. + + + + + The dictionary keys to add. + + + + + The dictionary keys to remove. + + + + + Applies the modification to the given Object. + + + + + Types of prefab modification that can be applied. + + + + + A value has been changed at a given path. + + + + + A list length has been changed at a given path. + + + + + A dictionary has been changed at a given path. + + + + + Corresponds to the .NET class, but works only with buffers and so never allocates garbage. + + This class always writes and reads bytes in a little endian format, regardless of system architecture. + + + + + Converts a byte array into a hexadecimal string. + + + + + Converts a hexadecimal string into a byte array. + + + + + Reads two bytes from a buffer and converts them into a value. + + The buffer to read from. + The index to start reading at. + The converted value. + + + + Reads two bytes from a buffer and converts them into a value. + + The buffer to read from. + The index to start reading at. + The converted value. + + + + Reads four bytes from a buffer and converts them into an value. + + The buffer to read from. + The index to start reading at. + The converted value. + + + + Reads four bytes from a buffer and converts them into an value. + + The buffer to read from. + The index to start reading at. + The converted value. + + + + Reads eight bytes from a buffer and converts them into a value. + + The buffer to read from. + The index to start reading at. + The converted value. + + + + Reads eight bytes from a buffer and converts them into an value. + + The buffer to read from. + The index to start reading at. + The converted value. + + + + Reads four bytes from a buffer and converts them into an value. + + The buffer to read from. + The index to start reading at. + The converted value. + + + + Reads eight bytes from a buffer and converts them into an value. + + The buffer to read from. + The index to start reading at. + The converted value. + + + + Reads sixteen bytes from a buffer and converts them into a value. + + The buffer to read from. + The index to start reading at. + The converted value. + + + + Reads sixteen bytes from a buffer and converts them into a value. + + The buffer to read from. + The index to start reading at. + The converted value. + + + + Turns a value into two bytes and writes those bytes to a given buffer. + + The buffer to write to. + The index to start writing at. + The value to write. + + + + Turns an value into two bytes and writes those bytes to a given buffer. + + The buffer to write to. + The index to start writing at. + The value to write. + + + + Turns an value into four bytes and writes those bytes to a given buffer. + + The buffer to write to. + The index to start writing at. + The value to write. + + + + Turns an value into four bytes and writes those bytes to a given buffer. + + The buffer to write to. + The index to start writing at. + The value to write. + + + + Turns a value into eight bytes and writes those bytes to a given buffer. + + The buffer to write to. + The index to start writing at. + The value to write. + + + + Turns an value into eight bytes and writes those bytes to a given buffer. + + The buffer to write to. + The index to start writing at. + The value to write. + + + + Turns a value into four bytes and writes those bytes to a given buffer. + + The buffer to write to. + The index to start writing at. + The value to write. + + + + Turns a value into eight bytes and writes those bytes to a given buffer. + + The buffer to write to. + The index to start writing at. + The value to write. + + + + Turns a value into sixteen bytes and writes those bytes to a given buffer. + + The buffer to write to. + The index to start writing at. + The value to write. + + + + Turns a value into sixteen bytes and writes those bytes to a given buffer. + + The buffer to write to. + The index to start writing at. + The value to write. + + + + Provides an array of utility wrapper methods for easy serialization and deserialization of objects of any type. + + + + + Creates an for a given format. + + The stream to write to. + The serialization context to use. + The format to write. + + An for a given format. + + + + + + Creates an for a given format. + + The stream to read from. + The deserialization context to use. + The format to read. + + An for a given format. + + + + + + Serializes the given value using the given writer. + + The value to serialize. + The writer to use. + + + + Serializes the given value, using the given writer. + + The value to serialize. + The writer to use. + A list of the Unity objects which were referenced during serialization. + + + + Serializes the given value using the given writer. + + The type of the value to serialize. + The value to serialize. + The writer to use. + + + + Serializes the given value, using the given writer. + + The type of the value to serialize. + The value to serialize. + The writer to use. + A list of the Unity objects which were referenced during serialization. + + + + Serializes the given value to a given stream in the specified format. + + The value to serialize. + The stream to serialize to. + The format to serialize in. + The context. + + + + Serializes the given value to a given stream in the specified format. + + The value to serialize. + The stream to serialize to. + The format to serialize in. + A list of the Unity objects which were referenced during serialization. + The context. + + + + Serializes the given value to a given stream in the specified format. + + The type of the value to serialize. + The value to serialize. + The stream to serialize to. + The format to serialize in. + The context. + + + + Serializes the given value to a given stream in the specified format. + + The type of the value to serialize. + The value to serialize. + The stream to serialize to. + The format to serialize in. + A list of the Unity objects which were referenced during serialization. + The context. + + + + Serializes the given value using the specified format, and returns the result as a byte array. + + The value to serialize. + The format to use. + The context. + A byte array containing the serialized value. + + + + Serializes the given value using the specified format, and returns the result as a byte array. + + The value to serialize. + The format to use. + A list of the Unity objects which were referenced during serialization. + A byte array containing the serialized value. + + + + Serializes the given value using the specified format, and returns the result as a byte array. + + The type of the value to serialize. + The value to serialize. + The format to use. + The context to use. + A byte array containing the serialized value. + + + + Serializes the given value using the specified format and returns the result as a byte array. + + The type of the value to serialize. + The value to serialize. + The format to use. + A list of the Unity objects which were referenced during serialization. + The context to use. + A byte array containing the serialized value. + + + + Deserializes a value from the given reader. This might fail with primitive values, as they don't come with metadata. + + The reader to use. + The deserialized value. + + + + Deserializes a value from the given reader, using the given list of Unity objects for external index reference resolution. This might fail with primitive values, as they don't come with type metadata. + + The reader to use. + The list of Unity objects to use for external index reference resolution. + + The deserialized value. + + + + + Deserializes a value from the given reader. + + The type to deserialize. + The reader to use. + The deserialized value. + + + + Deserializes a value of a given type from the given reader, using the given list of Unity objects for external index reference resolution. + + The type to deserialize. + The reader to use. + The list of Unity objects to use for external index reference resolution. + + The deserialized value. + + + + + Deserializes a value from the given stream in the given format. This might fail with primitive values, as they don't come with type metadata. + + The reader to use. + The format to read. + The context. + + The deserialized value. + + + + + Deserializes a value from the given stream in the given format, using the given list of Unity objects for external index reference resolution. This might fail with primitive values, as they don't come with type metadata. + + The stream to read from. + The format to read. + The list of Unity objects to use for external index reference resolution. + The context. + + The deserialized value. + + + + + Deserializes a value of a given type from the given stream in the given format. + + The type to deserialize. + The stream to read from. + The format to read. + The context. + + The deserialized value. + + + + + Deserializes a value of a given type from the given stream in the given format, using the given list of Unity objects for external index reference resolution. + + The type to deserialize. + The stream to read from. + The format to read. + The list of Unity objects to use for external index reference resolution. + The context. + + The deserialized value. + + + + + Deserializes a value from the given byte array in the given format. This might fail with primitive values, as they don't come with type metadata. + + The bytes to deserialize from. + The format to read. + The context. + + The deserialized value. + + + + + Deserializes a value from the given byte array in the given format, using the given list of Unity objects for external index reference resolution. This might fail with primitive values, as they don't come with type metadata. + + The bytes to deserialize from. + The format to read. + The list of Unity objects to use for external index reference resolution. + + The deserialized value. + + + + + Deserializes a value of a given type from the given byte array in the given format. + + The type to deserialize. + The bytes to deserialize from. + The format to read. + The context to use. + + The deserialized value. + + + + + Deserializes a value of a given type from the given byte array in the given format, using the given list of Unity objects for external index reference resolution. + + The type to deserialize. + The bytes to deserialize from. + The format to read. + The list of Unity objects to use for external index reference resolution. + The context to use. + + The deserialized value. + + + + + Creates a deep copy of an object. Returns null if null. All Unity objects references will remain the same - they will not get copied. + + + + + Provides an array of utility wrapper methods for easy serialization and deserialization of Unity objects of any type. + Note that, during serialization, it is always assumed that we are running on Unity's main thread. Deserialization can + happen on any thread, and all API's interacting with deserialization are thread-safe. + + Note that setting the IndexReferenceResolver on contexts passed into methods on this class will have no effect, as it will always + be set to a UnityReferenceResolver. + + + + + From the new scriptable build pipeline package + + + + + Note: it is assumed that code calling this is holding the DeserializePrefabCaches_LOCK lock, and will continue to hold it while the returned hashset is being modified + + + + + Whether to always force editor mode serialization. This member only exists in the editor. + + + + + Not yet documented. + + + + + Checks whether Odin will serialize a given member. + + The member to check. + Whether to allow serialization of members that will also be serialized by Unity. + The policy that Odin should be using for serialization of the given member. If this parameter is null, it defaults to . + True if Odin will serialize the member, otherwise false. + + + + Guesses whether or not Unity will serialize a given member. This is not completely accurate. + + The member to check. + True if it is guessed that Unity will serialize the member, otherwise false. + The parameter is null. + + + + Guesses whether or not Unity will serialize a given type. This is not completely accurate. + + The type to check. + True if it is guessed that Unity will serialize the type, otherwise false. + The parameter is null. + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Creates an object with default values initialized in the style of Unity; strings will be "", classes will be instantiated recursively with default values, and so on. + + + + + In 2020.1, Unity changed EditorApplication.delayCall from a field to an event, meaning + we now have to use reflection to access it consistently across all versions of Unity. + + + + + A Unity Behaviour which is serialized by the Sirenix serialization system. + + + + + Invoked after deserialization has taken place. + + + + + Invoked before serialization has taken place. + + + + + A Unity Component which is serialized by the Sirenix serialization system. + + + + + Invoked after deserialization has taken place. + + + + + Invoked before serialization has taken place. + + + + + A Unity MonoBehaviour which is serialized by the Sirenix serialization system. + + + + + Invoked after deserialization has taken place. + + + + + Invoked before serialization has taken place. + + + + + A Unity ScriptableObject which is serialized by the Sirenix serialization system. + + + + + Invoked after deserialization has taken place. + + + + + Invoked before serialization has taken place. + + + + + A Unity StateMachineBehaviour which is serialized by the Sirenix serialization system. + + + + + Invoked after deserialization has taken place. + + + + + Invoked before serialization has taken place. + + + + + A Unity ScriptableObject which is serialized by the Sirenix serialization system. + + + + + Invoked after deserialization has taken place. + + + + + Invoked before serialization has taken place. + + + + diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.xml.meta b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.xml.meta new file mode 100644 index 0000000..4e778e1 --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Serialization.xml.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5f3147f7af4c49739579b966c458096f +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.dll b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.dll new file mode 100644 index 0000000000000000000000000000000000000000..a6d05498124055b988fdb02fbe0fc5efd48aeaff GIT binary patch literal 542720 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
    >m^1bwuuTJ)$ug#}TYYC|t46eK}>&04P|7!_Zex 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 z%0A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 + + + Sirenix.Utilities.Editor + + + + + Icon for using in editor GUI. + + + + + Gets the raw input icon texture. + + + + + Gets the icon's highlighted texture. + + + + + Gets the icon's active texture. + + + + + Gets the icon's inactive texture. + + + + + Gets a GUIContent object with the active texture. + + + + + Gets a GUIContent object with the inactive texture. + + + + + Gets a GUIContent object with the highlighted texture. + + + + + Draws the icon in a square rect, with a custom shader that makes the icon look better when down-scaled. + This also handles mouseover effects, and linier color spacing. + + + + + Draws the icon in a square rect, with a custom shader that makes the icon look better when down-scaled. + This also handles mouseover effects, and linier color spacing. + + + + + Draws the icon in a square rect, with a custom shader that makes the icon look better when down-scaled. + This also handles mouseover effects, and linier color spacing. + + + + + Collection of EditorIcons for use in GUI drawing. + + + + + Gets an icon of an airplane symbol. + + + + + Gets an icon of an alert circle symbol. + + + + + Gets an icon of an alert triangle symbol. + + + + + Gets an icon of an arrow down symbol. + + + + + Gets an icon of an arrow left symbol. + + + + + Gets an icon of an arrow right symbol. + + + + + Gets an icon of an arrow up symbol. + + + + + Gets an icon of a bell symbol. + + + + + Gets an icon of a car symbol. + + + + + Gets an icon of a char1 symbol. + + + + + Gets an icon of a char2 symbol. + + + + + Gets an icon of a char3 symbol. + + + + + Gets an icon of a char graph symbol. + + + + + Gets an icon of a checkmark symbol. + + + + + Gets an icon of a clock symbol. + + + + + Gets an icon of a clouds symbol. + + + + + Gets an icon of a clouds rainy symbol. + + + + + Gets an icon of a clouds rainy sunny symbol. + + + + + Gets an icon of a clouds rainy thunder symbol. + + + + + Gets an icon of a clouds thunder symbol. + + + + + Gets an icon of a crosshair symbol. + + + + + Gets an icon of a cut symbol. + + + + + Gets an icon of a day calendar symbol. + + + + + Gets an icon of a download symbol. + + + + + Gets an icon of an eject symbol. + + + + + Gets an icon of an eye dropper symbol. + + + + + Gets an icon of a female symbol. + + + + + Gets an icon of a file symbol. + + + + + Gets an icon of a file cabinet symbol. + + + + + Gets an icon of a finnish banner symbol. + + + + + Gets an icon of a flag symbol. + + + + + Gets an icon of a flag finnish symbol. + + + + + Gets an icon of a folder symbol. + + + + + Gets an icon of a folder back symbol. + + + + + Gets an icon of a gKey symbol. + + + + + Gets an icon of a globe symbol. + + + + + Gets an icon of a grid blocks symbol. + + + + + Gets an icon of a grid image text symbol. + + + + + Gets an icon of a grid image text list symbol. + + + + + Gets an icon of a grid layout symbol. + + + + + Gets an icon of a hamburger menu symbol. + + + + + Gets an icon of a house symbol. + + + + + Gets an icon of an image symbol. + + + + + Gets an icon of an image collection symbol. + + + + + Gets an icon of an info symbol. + + + + + Gets an icon of a letter symbol. + + + + + Gets an icon of a light bulb symbol. + + + + + Gets an icon of a link symbol. + + + + + Gets an icon of a list symbol. + + + + + Gets an icon of a loading bar symbol. + + + + + Gets an icon of a lock locked symbol. + + + + + Gets an icon of a lock unlocked symbol. + + + + + Gets an icon of a lock unloacked symbol. + + + + + Gets an icon of a magnifying glass symbol. + + + + + Gets an icon of a male symbol. + + + + + Gets an icon of a marker symbol. + + + + + Gets an icon of a maximize symbol. + + + + + Gets an icon of a microphone symbol. + + + + + Gets an icon of a minimize symbol. + + + + + Gets an icon of a minus symbol. + + + + + Gets an icon of a mobile phone symbol. + + + + + Gets an icon of a money symbol. + + + + + Gets an icon of a move symbol. + + + + + Gets an icon of a multi user symbol. + + + + + Gets an icon of a next symbol. + + + + + Gets an icon of a pacman ghost symbol. + + + + + Gets an icon of a paperclip symbol. + + + + + Gets an icon of a pause symbol. + + + + + Gets an icon of a pen symbol. + + + + + Gets an icon of a pen add symbol. + + + + + Gets an icon of a pen minus symbol. + + + + + Gets an icon of a play symbol. + + + + + Gets an icon of a plus symbol. + + + + + Gets an icon of a podium symbol. + + + + + Gets an icon of a previous symbol. + + + + + Gets an icon of a reception signal symbol. + + + + + Gets an icon of a redo symbol. + + + + + Gets an icon of a refresh symbol. + + + + + Gets an icon of a rotate symbol. + + + + + Gets an icon of a ruler symbol. + + + + + Gets an icon of a ruler rect symbol. + + + + + Gets an icon of a settings cog symbol. + + + + + Gets an icon of a shopping basket symbol. + + + + + Gets an icon of a shopping cart symbol. + + + + + Gets an icon of a single user symbol. + + + + + Gets an icon of a smart phone symbol. + + + + + Gets an icon of a sound symbol. + + + + + Gets an icon of a speech bubble round symbol. + + + + + Gets an icon of a speech bubble square symbol. + + + + + Gets an icon of a speech bubbles round symbol. + + + + + Gets an icon of a speech bubbles square symbol. + + + + + Gets an icon of a star pointer symbol. + + + + + Gets an icon of a stop symbol. + + + + + Gets an icon of a stretch symbol. + + + + + Gets an icon of a table symbol. + + + + + Gets an icon of a tag symbol. + + + + + Gets an icon of a test tube symbol. + + + + + Gets an icon of a timer symbol. + + + + + Gets an icon of a traffic stop light symbol. + + + + + Gets an icon of a transparent symbol. + + + + + Gets an icon of a tree symbol. + + + + + Gets an icon of a triangle down symbol. + + + + + Gets an icon of a triangle left symbol. + + + + + Gets an icon of a triangle right symbol. + + + + + Gets an icon of a triangle up symbol. + + + + + Gets an icon of an undo symbol. + + + + + Gets an icon of an upload symbol. + + + + + Gets an icon of a wifi signal symbol. + + + + + Gets an icon of an x symbol. + + + + + Gets a texture of a test inconclusive symbol. + + + + + Gets a texture of a test failed symbol. + + + + + Gets a texture of a test normal symbol. + + + + + Gets a texture of a test passed symbol. + + + + + Gets a texture of a console info icon symbol. + + + + + Gets a texture of a console warnicon symbol. + + + + + Gets a texture of a console error icon symbol. + + + + + Gets a texture of an odin inspector logo symbol. + + + + + Gets a texture of a scene asset icon symbol. + + + + + Gets an icon representing a GameObject. + + + + + Gets an icon of a unity info icon. + + + + + Gets an icon of a unity warning icon. + + + + + Gets an icon of a unity error icon. + + + + + Gets an icon of a unity folder. + + + + + Lazy loading Editor Icon. + + + + + Loads an EditorIcon from the spritesheet. + + + + + Gets the icon's highlight texture. + + + + + Gets the icon's active texture. + + + + + Gets the icon's inactive texture. + + + + + Not yet documented. + + + + + Utility for parsing and emitting expression delegates. + + + + Parses an expression and tries to emit a delegate method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted delegate if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and tries to emit a delegate method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + The parameters of the expression delegate. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted delegate if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and tries to emit a delegate method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + The parameters of the expression delegate. + The names of the expression's parameters, for use with the named parameter syntax. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted delegate if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and tries to emit a delegate method. + The expression to parse. + The emit context. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted delegate if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and tries to emit a delegate of the specified type. + The expression to parse. + The emit context. + The type of the delegate to emit. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted delegate if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionFunc method. + The expression to parse. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionFunc if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionFunc method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionFunc if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionFunc method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionFunc if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionFunc method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionFunc if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionFunc method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionFunc if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionFunc method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionFunc if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionFunc method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionFunc if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionFunc method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionFunc if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionFunc method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionFunc if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionFunc method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionFunc if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionAction method. + The expression to parse. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionAction if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionAction method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionAction if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionAction method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionAction if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionAction method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionAction if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionAction method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionAction if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionAction method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionAction if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionAction method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionAction if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionAction method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionAction if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionAction method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionAction if the expression is compiled successfully. Otherwise, null. + + + Parses an expression and emits an ExpressionAction method. + The expression to parse. + Indicates if the expression should be static instead of instanced. + The context type for the execution of the expression. + Output for any errors that may occur. + If true then error message will be formatted with color tags. Otherwise, the error message will be formatted with text only. + Returns the emitted ExpressionAction if the expression is compiled successfully. Otherwise, null. + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Drag and drop utilities for both Unity and non-unity objects. + + + + + Gets the position from where the last drag started from in screen space. + + + + + Gets the delta position between the currrent mouse position and where the last drag originated from. + + + + + Gets the hovering accepted drop zone ID. + + + + + Gets a value indicating whether an instance is currently being dragged. + + + + + Gets the currently dragging identifier. + + + + + Gets the current hovering drop zone identifier. + + + + + Gets a more percistent id for drag and drop. + + + + + Draws a objectpicker button in the given rect. This one is designed to look good on top of DrawDropZone(). + + + + + Draws a objectpicker butter, in the given rect. This one is designed to look good on top of DrawDropZone(). + + + + + Draws the graphics for a DropZone. + + + + + A draggable zone for both Unity and non-unity objects. + + + + + A drop zone area for bot Unity and non-unity objects. + + + + + A drop zone area for bot Unity and non-unity objects. + + + + + A drop zone area for bot Unity and non-unity objects. + + + + + A drop zone area for bot Unity and non-unity objects. + + + + + A drop zone area for bot Unity and non-unity objects. + + + + + A drop zone area for bot Unity and non-unity objects. + + + + + A drop zone area for bot Unity and non-unity objects. + + + + + A drop zone area for bot Unity and non-unity objects. + + + + + Disalloweds the drop area for next drag zone. Follow this function call by a DragZone. + + + + + A draggable zone for both Unity and non-unity objects. + + + + + A draggable zone for both Unity and non-unity objects. + + + + + A draggable zone for both Unity and non-unity objects. + + + + + A draggable zone for both Unity and non-unity objects. + + + + + Collection of extension methods for . + + + + + Returns true when the user presses the specified mouse button. + + The . + The mouse button the user has to press. + If true then the method will call on the event. + true on mouse down events with the specified button. Otherwise false. + + + + Returns true when the user clicks a rect with the mouse. + + The event. + The rect the user can click on. + The button the user has to press. + If true then the method will call on the event. + true on mouse down events with the specified button. Otherwise false. + + + + Returns true when the user releases the specified mouse button. + + The . + The mouse button the user has to release. + If true then the method will call on the event. + true on mouse up events, with the specified button. Otherwise false. + + + + Returns true when the user releases the specified mouse button over the specified rect. + + The . + The rect the user has to release the mouse button over. + The mouse button the user has to release. + If true then the method will call on the event. + true on mouse up events, with the specified button and over the specified rect. Otherwise false. + + + + Returns true when the user left clicks a rect. + + The . + The rect the user can click. + If true then the method will call on the event. + true on left click events, on the specified rect. Otherwise false. + + + + Returns true when the user right clicks a rect. + + The . + The rect the user can right click. + If true then the method will call on the event. + true on context click events, on the specified rect. Otherwise false. + + + + Returns true when the user presses the specified key. + + The . + The key the user has to press. + If true then the method will call on the event. + true on key down events with the specified key code. Otherwise false. + + + + Returns true when the user releases the specified key. + + The . + The key the user has to release. + If true then the method will call on the event. + true on key up events with the specified key code. Otherwise false. + + + + Returns true whene the user moves or drags the mouse. + + The . + If true then the method will call on the event. + true on mouse move or mouse drag events. Otherwise false. + + + + Returns true when the user hovers the mouse over the specified rect. + + The . + The rect the user can hover. + true on any event where the mouse is hovering the specified rect. Otherwise false. + + + + Returns true on repaint events. + + The . + true on repaint events. Otherwise false. + + + + Returns true on layout events. + + The . + true on layout events. Otherwise false. + + + + Returns true on the specified event. + + The . + The required event type. + true on the specified event. Otherwise false. + + + + Collection of extension methods for . + + + + + Removes all menu items with a given name from the GenericMenu. + + The GenericMenu to remove items from. + The name of the items to remove. + True if any items were removed, otherwise false. + + + + Replaces the first found menu item with a given name with a new menu item, or if no such element is found, adds a new one. + + The GenericMenu to replace items in. + The name of the items to remove. + The func to replace or add. + The on value to set the new menu item with. + True if an item was replaced, otherwise false. + + + + Replaces the first found menu item with a given name with a new menu item, or if no such element is found, adds a new one. + + The GenericMenu to replace items in. + The name of the items to remove. + The on value to set the new menu item with. + The func to replace or add. + The user data. + + True if an item was replaced, otherwise false. + + + + + This class is due to undergo refactoring. + + + + + The value. + + + + + Performs an implicit conversion from to . + + + + + How the square object field should be aligned. + + + + + + Left aligned. + + + + + Centered. + + + + + Right aligned. + + + + + This class is due to undergo refactoring. Use the new DragAndDropUtilities instead. + + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + This class is due to undergo refactoring. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + This class is due to undergo refactoring. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + This class is due to undergo refactoring. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + This class is due to undergo refactoring. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + This class is due to undergo refactoring. + + + + + Emitted wrapper for the internal "UnityEngine.GUIClip" class. + + + + + Not yet documented. + + + + + Gets the top most clipped rect. + + + + + Gets the visible rect. + + + + + Gets the top rect. + + + + + Unclips the specified position. + + The position. + + + + + Unclips the specified rect. + + The rect. + + + + + A helper class to control paging of n number of elements in various situations. + + + + + Disables the paging, and show all elements. + + + + + Initializes a new instance of the class. + + + + + Updates all values based on and . + + + Call update right before using and in your for loop. + + The total number of elements to apply paging for. + + + + Gets or sets a value indicating whether this instance is enabled. + + + true if this instance is enabled; otherwise, false. + + + + + Gets a value indicating whether this instance is on the frist page. + + + true if this instance is on frist page; otherwise, false. + + + + + Gets a value indicating whether this instance is on the last page. + + + true if this instance is on last page; otherwise, false. + + + + + Gets or sets the number of items per page. + + + The number of items pr page. + + + + + Gets or sets the current page. + + + The current page. + + + + + Gets the start index. + + + The start index. + + + + + Gets the end index. + + + The end index. + + + + + Gets or sets the page count. + + + The page count. + + + + + Gets the total number of elements. + Use to change the value. + + + + + Draws right-aligned toolbar paging buttons. + + + + + A Utility class for creating tables in Unity's editor GUI. + A table can either be created from scratch using new GUITable(xCount,yCount), or created using one of the static GUITable.Create overloads. + See the online documentation, for examples and more information. + + + Creating a matrix table for a two-dimentional array. + + private GUITable table; + + private void Init() + { + bool[,] boolArr = new bool[20,20]; + + this.table = GUITable.Create( + twoDimArray: boolArr, + drawElement: (rect, x, y) => boolArr[x, y] = EditorGUI.Toggle(rect, boolArr[x, y]), + horizontalLabel: "Optional Horizontal Label", // horizontalLabel is optional and can be null. + columnLabels: (rect, x) => GUI.Label(rect, x.ToString()), // columnLabels is optional and can be null. + verticalLabel: "Optional Vertical Label", // verticalLabel is optional and can be null. + rowLabels: (rect, x) => GUI.Label(rect, x.ToString()) // rowLabels is optional and can be null. + ); + } + + private void OnGUI() + { + this.table.DrawTable(); + } + + + + Creating a table for a list. + + private GUITable table; + + private void Init() + { + Listt<SomeClasst> someList = new List<SomeClass>() { new SomeClass(), new SomeClass(), new SomeClass() }; + + this.table = GUITable.Create(someList, "Optional Title", + new GUITableColumn() + { + ColumnTitle = "A", + OnGUI = (rect, i) => someList[i].A = EditorGUI.TextField(rect, someList[i].A), + Width = 200, + MinWidth = 100, + }, + new GUITableColumn() + { + ColumnTitle = "B", + OnGUI = (rect, i) => someList[i].B = EditorGUI.IntField(rect, someList[i].B), + Resizable = false, + }, + new GUITableColumn() + { + ColumnTitle = "C", + OnGUI = (rect, i) => someList[i].C = EditorGUI.IntField(rect, someList[i].C), + SpanColumnTitle = true, + } + ); + } + + private void OnGUI() + { + this.table.DrawTable(); + } + + private class SomeClass + { + public string A; + public int B; + public int C; + public int D; + } + + + + Styling a cell. + Each has two events, OnGUI and OnGUIStyle. OnGUIStyle is called right before OnGUI, but only in repaint events. + + guiTable[x,y].GUIStyle += rect => EditorGUI.DrawRect(rect, Color.red); + + + + Row and column span. + A cell will span and cover all neighbour cells that are null. + + // Span horizontally: + guiTable[x - 2,y] = null; + guiTable[x - 1,y] = null; + guiTable[x,y].SpanX = true; + guiTable[x + 1,y] = null; + + // Span vertically: + guiTable[x,y - 2] = null; + guiTable[x,y - 1] = null; + guiTable[x,y].SpanY = true; + guiTable[x,y + 1] = null; + + + + + + + + The row count. + + + + + The column count. + + + + + The Table Rect. + + + + + Whether to respect the current GUI indent level. + + + + + Gets or sets a from the . + + + + + Initializes a new instance of the class. + + + + + Draws the table. + + + + + Recaluclates cell and column sizes in the next frame. + + + + + Recalculates the layout for the entire table. + This method gets called whenever the table is initialized, resized or adjusted. If you are manipulating + the width or height of individual table cells, remember to call this method when you're done. + + + + + Creates a table. + + + + + Creates a table. + + + + + Creates a table. + + + + + Creates a table. + + + + + A cell of a + + + + + The minimum width. + + + + + The width of the cell. Default is width is 0. + The width the column is determained by the widest cell in the column. + Width = 0 = auto. + + + + + The height of the cell. Default is height is 22. + The height the column is determained by the tallest cell in the row. + + + + + If true, the cell will expand vertically, covering all neighbour null cells. + + + + + If true, the cell will expand horizontally, covering all neighbour null cells. + + + + + The table column index. + + + + + The table row index. + + + + + The GUI style + + + + + Gets the rect. + + + + + GUITableColumns used creating a table list using GUITable.Create(). + + + + + + + Draws a cell at the given row index for this column. + + + + + The column title text. If there are is columns with a title, there we not be rendered an additional table row for column titles. + + + + + The minimum with of the column. + + + + + The width of the Column. + 0 = auto, and is also the default. + + + + + If true, the column becomes resiziable. + Default is true. + + + + + If true, the column title cell, will span horizontally to neighbour columns, which column titles are null. + Default is false. + + + + + The GUITabGroup is a utility class to draw animated tab groups. + + + + var tabGroup = SirenixEditorGUI.CreateAnimatedTabGroup(someKey); + // Register your tabs before starting BeginGroup. + var tab1 = tabGroup.RegisterTab("tab 1"); + var tab2 = tabGroup.RegisterTab("tab 2"); + + tabGroup.BeginGroup(drawToolbar: true); + { + if (tab1.BeginPage()) + { + // Draw GUI for the first tab page; + } + tab1.EndPage(); + + if (tab2.BeginPage()) + { + // Draw GUI for the second tab page; + } + tab2.EndPage(); + } + tabGroup.EndGroup(); + + // Control the animation speed. + tabGroup.AnimationSpeed = 0.2f; + + // If true, the tab group will have the height equal to the biggest page. Otherwise the tab group will animate in height as well when changing page. + tabGroup.FixedHeight = true; + + // You can change page by calling: + tabGroup.GoToNextPage(); + tabGroup.GoToPreviousPage(); + + + + + + + The animation speed (1 / s) + + + + + The animation speed + + + + + Gets the outer rect of the entire tab group. + + + + + The inner rect of the current tab page. + + + + + If true, the tab group will have the height equal to the biggest page. Otherwise the tab group will animate in height as well when changing page. + + + Sets the current page. + + The page to switch to. + + + + Gets the current page. + + + + + Gets the t. + + + + + The height of the tab buttons. + + + + + Registers the tab. + + + + + Begins the group. + + if set to true a tool-bar for changing pages is drawn. + The style. + + + + Ends the group. + + + + + Goes to page. + + + + + Goes to next page. + + + + + Goes to previous page. + + + + + Various helper function for GUI. + + + + + Gets the bold default font. + + + + + An alternative to GUI.FocusControl(null), which does not take focus away from the current GUI.Window. + + + + + Whether the inspector is currently in the progress of drawing a dictionary key. + + + + + Hides the following draw calls. Remember to call when done. + + + + + Unhides the following draw calls after having called . + + + + + Determines whether the specified EditorWindow is docked. + + The editor window. + true if the editor window is docked. Otherwise false. + + + + Not yet documented. + + + + + Opens a new inspector window for the specified object. + + The unity object. + unityObj + + + + Gets or sets a value indicating whether labels are currently bold. + + + true if this instance is bold label; otherwise, false. + + + + + Gets the size of the current window border. + + + The size of the current window border. + + + + + Gets the editor screen point offset. + + + The editor screen point offset. + + + + + Gets the current editor gui context width. Only set these if you know what it does. + Setting this has been removed. Use PushContextWidth and PopContextWidth instead. + + + + + Unity EditorGUIUtility.labelWidth only works reliablly in Repaint events. + BetterLabelWidth does a better job at giving you the correct LabelWidth in non-repaint events. + + + + + Odin will set this for you whenever an Odin property tree is drawn. + But if you're using BetterLabelWidth and BetterContextWidth without Odin, then + you need to set BetterContextWidth in the beginning of each GUIEvent. + + + + + Gets the current indent amount. + + + The current indent amount. + + + + + Gets the mouse screen position. + + + The mouse screen position. + + + + + Gets the current editor window. + + + The current editor window. + + + + + Gets a value indicating whether the current editor window is focused. + + + true if the current window has focus. Otherwise, false. + + + + + Gets the ID of the current editor window. + + + The ID of the current editor window. + + + + + Gets a value indicating whether a repaint has been requested. + + + true if repaint has been requested. Otherwise false. + + + + + Gets or sets the actual EditorGUIUtility.LabelWidth, regardless of the current hierarchy mode or context width. + + + + + Requests a repaint. + + + + + Requests a repaint. + + + + + Begins the layout measuring. Remember to end with . + + + + + Ends the layout measuring started by + + The measured rect. + + + + Gets the current layout rect. + + The current layout rect. + + + + Gets the current layout rect. + + The current layout rect. + + + + Gets the playmode color tint. + + The playmode color tint. + + + + Pushes a context width to the context width stack. + Remember to pop the value again with . + + The width to push. + + + + Pops a value pushed by . + + + + + Pushes a color to the GUI color stack. Remember to pop the color with . + + The color to push the GUI color.. + if set to true blend with alpha. + + + + Takes a screenshot of the GUI within the specified rect. + + The rect. + The screenshot as a render texture. + + + + Pops the GUI color pushed by . + + + + + Pushes a state to the GUI enabled stack. Remember to pop the state with . + + If set to true GUI will be enabled. Otherwise GUI will be disabled. + + + + Pops the GUI enabled pushed by + + + + + Pushes a state to the IsDrawingDictionaryKey stack. Remember to pop the state with . + + + + + Pops the state pushed by + + + + + Pushes the hierarchy mode to the stack. Remember to pop the state with . + + The hierachy mode state to push. + Changing hierachy mode also changes how label-widths are calcualted. By default, we try to keep the current label width. + + + + Pops the hierarchy mode pushed by . + + + + + Pushes bold label state to the stack. Remember to pop with . + + Value indicating if labels should be bold or not. + + + + Pops the bold label state pushed by . + + + + + Pushes the indent level to the stack. Remember to pop with . + + The indent level to push. + + + + Pops the indent level pushed by . + + + + + Pushes the content color to the stack. Remember to pop with . + + The content color to push.. + If set to true blend with alpha. + + + + Pops the content color pushed by . + + + + + Pushes the label color to the stack. Remember to pop with . + + The label color to push. + + + + Pops the label color pushed by . + + + + + Pushes the GUI position offset to the stack. Remember to pop with . + + The GUI offset. + + + + Pops the GUI position offset pushed by . + + + + + Pushes a GUI matrix to the stack. Remember to pop with . + + The GUI matrix to push. + + + + Pops the GUI matrix pushed by . + + + + + Ignores input on following GUI calls. Remember to end with . + + + + + Ends the ignore input started by . + + + + + Pushes the event type to the stack. Remember to pop with . + + The type of event to push. + + + + Pops the event type pushed by . + + + + + Pushes the width to the editor GUI label width to the stack. Remmeber to Pop with . + + The editor GUI label width to push. + + + + Pops editor gui label widths pushed by . + + + + + Pushes the value to the responsive vector component fields stack. Remeber to pop with . + + + + + Pops responsive vector component fields value pushed by . + + + + + Pushes the value to the fade group duration stack. Remeber to pop with . + + + + + Pops fade group duration value pushed by . + + + + + Pushes the value to the tab page slide animation duration stack. Remember to pop with . + + + + + + Pops tab page slide animation duration value pushed by . + + + + + Clears the repaint request. + + + + + Gets a temporary value context. + + The type of the config value. + The key for the config. + The name of the config. + GUIConfig for the specified key and name. + + + + Gets a temporary value context. + + The type of the value. + The key for the config. + The ID for the config. + GUIConfig for the specified key and ID. + + + + Gets a temporary value context. + + The type of the value. + The primary key. + The secondary key. + GUIConfig for the specified primary and secondary key. + + + + Gets a temporary value context. + + The type of the value. + The key for the context. + GUIConfig for the specified key. + + + + Gets a temporary nullable value context. + + Key for context. + Name for the context. + + + + Gets a temporary nullable value context. + + Key for context. + Id of the context. + + + + Gets a temporary nullable value context. + + Primary key for the context. + Secondary key for the context. + + + + Gets a temporary nullable value context. + + Key for the context. + + + + Gets a temporary context. + + Key for the context. + Name for the context. + Default value of the context. + + + + Gets a temporary context. + + Key for the context. + Id for the context. + Default value of the context. + + + + Gets a temporary context. + + Primary key for the context. + Secondary key for the context. + Default value of the context. + + + + Gets a temporary context. + + Key for the context. + Default value of the context. + + + + Gets a temporary GUIContent with the specified text. + + The text for the GUIContent. + Temporary GUIContent instance. + + + + Gets a temporary GUIContent with the specified text and tooltip. + + The text for the GUIContent. + The tooltip for the GUIContent. + Temporary GUIContent instance. + + + + Gets a temporary GUIContent with the specified image and tooltip. + + The image for the GUIContent. + The tooltip for the GUIContent. + Temporary GUIContent instance. + + + + Gets a temporary GUIContent with the specified text, image and tooltip. + + The text for the GUIContent. + The image for the GUIContent. + The tooltip for the GUIContent. + Temporary GUIContent instance. + + + + Indents the rect by the current indent amount. + + The rect to indent. + Indented rect. + + + + Indents the rect by the current indent amount. + + The rect to indent. + + + + Repaints the EditorWindow if a repaint has been requested. + + The window to repaint. + + + + Repaints the editor if a repaint has been requested. If the currently rendering window is not an InspectorWindow, Repaint() will be called on the current window as well. + + The editor to repaint. + + + + Gets the best thumbnail icon given the provided arguments provided. + + + + + + + + + Configuration for progress bar fields. + + + + + The height of the progress bar field. Default 12 pixel. + + + + + The foreground color of the progress bar field. + + + + + The background color of the progress bar field. + + + + + If true the progress bar field will draw a label ontop to show the current value. + + + + + Alignment of the progress bar field overlay. + + + + + Default configuration. + + + + + Creates a copy of the configuration. + + The configuration to copy. + + + + Creates a progress bar configuration. + + The height of the progress bar. + The foreground color of the progress bar. + The background color of the progress bar. + If true there will be drawn a overlay on top of the field. + The alignment of the text overlay. + + + + Draw mode of quaternion fields. + + + + + + + Draw the quaterion as euler angles. + + + + + Draw the quaterion in as an angle and an axis. + + + + + Draw the quaternion as raw x, y, z and w values. + + + + + Field drawing functions for various types. + + + + + The width of the X, Y and Z labels in structs. + + + + + When true the component labels, for vector fields, will be hidden when the field is too narrow. + + + + + Draws a regular Unity ObjectField, but supports labels being nulls, and also adds a small button that will open the object in a new inspector window. + + Position and size of the field. + The label to use, or null if no label should be used. + The Unity object. + The Unity object type. This supports inheritance. + Wheather or not to allow scene objects. + + + + Draws a regular Unity ObjectField, but supports labels being nulls, and also adds a small button that will open the object in a new inspector window. + + Position and size of the field. + The label to use, or null if no label should be used. + The Unity object. + The Unity object type. This supports inheritance. + Wheather or not to allow scene objects. + + + + Draws a regular Unity ObjectField, but supports labels being nulls, and also adds a small button that will open the object in a new inspector window. + + Position and size of the field. + The Unity object. + The Unity object type. This supports inheritance. + Wheather or not to allow scene objects. + + + + Draws a regular Unity ObjectField, but supports labels being nulls, and also adds a small button that will open the object in a new inspector window. + + The label to use, or null if no label should be used. + The Unity object. + The Unity object type. This supports inheritance. + Wheather or not to allow scene objects. + Layout options. + + + + Draws a regular Unity ObjectField, but supports labels being nulls, and also adds a small button that will open the object in a new inspector window. + + The label to use, or null if no label should be used. + The Unity object. + The Unity object type. This supports inheritance. + Wheather or not to allow scene objects. + Layout options. + + + + Draws a regular Unity ObjectField, but supports labels being nulls, and also adds a small button that will open the object in a new inspector window. + + The Unity object. + The Unity object type. This supports inheritance. + Wheather or not to allow scene objects. + Layout options. + + + + Draws a square ObjectField which renders a preview for UnityEngine.Object types. + This object field also adds support for drag and drop, dragging an object to another square object field, swaps the values. + If you hold down control while letting go it will replace the value, And you can control + click the object field to quickly delete the value it holds. + + + + + Draws a square ObjectField which renders a preview for UnityEngine.Object types. + This object field also adds support for drag and drop, dragging an object to another square object field, swaps the values. + If you hold down control while letting go it will replace the value, And you can control + click the object field to quickly delete the value it holds. + + + + + Draws a square ObjectField which renders a preview for UnityEngine.Object types. + This object field also adds support for drag and drop, dragging an object to another square object field, swaps the values. + If you hold down control while letting go it will replace the value, And you can control + click the object field to quickly delete the value it holds. + + + + + Draws a square ObjectField which renders a preview for UnityEngine.Object types. + This object field also adds support for drag and drop, dragging an object to another square object field, swaps the values. + If you hold down control while letting go it will replace the value, And you can control + click the object field to quickly delete the value it holds. + + + + + Draws a square ObjectField which renders a preview for UnityEngine.Object types. + This object field also adds support for drag and drop, dragging an object to another square object field, swaps the values. + If you hold down control while letting go it will replace the value, And you can control + click the object field to quickly delete the value it holds. + + Position and size of the field. + The label to use, or null if no label should be used. + The Unity object. + The Unity object type. This supports inheritance. + Wheather or not to allow scene objects. + How the square object field should be aligned. + + + + Draws a square ObjectField which renders a preview for UnityEngine.Object types. + This object field also adds support for drag and drop, dragging an object to another square object field, swaps the values. + If you hold down control while letting go it will replace the value, And you can control + click the object field to quickly delete the value it holds. + + Position and size of the field. + The label to use, or null if no label should be used. + The Unity object. + The Unity object type. This supports inheritance. + Wheather or not to allow scene objects. + How the square object field should be aligned. + + + + Draws a square ObjectField which renders a preview for UnityEngine.Object types. + This object field also adds support for drag and drop, dragging an object to another square object field, swaps the values. + If you hold down control while letting go it will replace the value, And you can control + click the object field to quickly delete the value it holds. + + Position and size of the field. + The Unity object. + The Unity object type. This supports inheritance. + Wheather or not to allow scene objects. + How the square object field should be aligned. + + + + Draws a square ObjectField which renders a preview for UnityEngine.Object types. + This object field also adds support for drag and drop, dragging an object to another square object field, swaps the values. + If you hold down control while letting go it will replace the value, And you can control + click the object field to quickly delete the value it holds. + + The label to use, or null if no label should be used. + The Unity object. + The Unity object type. This supports inheritance. + Wheather or not to allow scene objects. + The height or size of the square object field. + How the square object field should be aligned. + + + + Draws a square ObjectField which renders a preview for UnityEngine.Object types. + This object field also adds support for drag and drop, dragging an object to another square object field, swaps the values. + If you hold down control while letting go it will replace the value, And you can control + click the object field to quickly delete the value it holds. + + The label to use, or null if no label should be used. + The Unity object. + The Unity object type. This supports inheritance. + Wheather or not to allow scene objects. + The height or size of the square object field. + How the square object field should be aligned. + + + + Draws a square ObjectField which renders a preview for UnityEngine.Object types. + This object field also adds support for drag and drop, dragging an object to another square object field, swaps the values. + If you hold down control while letting go it will replace the value, And you can control + click the object field to quickly delete the value it holds. + + The Unity object. + The Unity object type. This supports inheritance. + Wheather or not to allow scene objects. + The height or size of the square object field. + How the square object field should be aligned. + + + + Draws a polymorphic ObjectField. + + The label to use, or null if no label should be used. + The value. + The object type. This supports inheritance. + Wheather or not to allow scene objects. + Layout options. + + + + Draws a polymorphic ObjectField. + + + + + Draws a polymorphic ObjectField. + + + + + Draws a polymorphic ObjectField. + + The label to use, or null if no label should be used. + The value. + The object type. This supports inheritance. + Wheather or not to allow scene objects. + Layout options. + + + + Draws a polymorphic ObjectField. + + The value. + The object type. This supports inheritance. + Wheather or not to allow scene objects. + Layout options. + + + + Draws a field for a layer mask. + + Position and size of the field. + The label to use, or null if no label should be used. + The layer mask to draw. + + + + Draws a field for a layer mask. + + Position and size of the field. + The label to use, or null if no label should be used. + The layer mask to draw. + + + + Draws a field for a layer mask. + + Position and size of the field. + The layer mask to draw. + + + + Draws a field for a layer mask. + + The label to use, or null if no label should be used. + The layer mask to draw. + Layout options. + + + + Draws a field for a layer mask. + + The label to use, or null if no label should be used. + The layer mask to draw. + Layout options. + + + + Draws a field for a layer mask. + + The layer mask to draw. + Layout options. + + + + Draws a Guid field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a Guid field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a Guid field. + + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a Guid field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a Guid field. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a Guid field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws an int field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws an int field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws an int field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws an int field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws an int field. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws an int field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws an int field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws an int field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed int field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a delayed int field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a delayed int field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a delayed int field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a delayed int field. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a delayed int field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed int field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed int field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a range field for ints. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Minimum value. + Maximum value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a range field for ints. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Minimum value. + Maximum value. + Value assigned to the field. + + + + Draws a range field for ints. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Minimum value. + Maximum value. + Value assigned to the field. + + + + Draws a range field for ints. + + Position and size of the field. + Current value. + Minimum value. + Maximum value. + Value assigned to the field. + + + + Drwas a range field for ints. + + Label of field. Set to null for no label. + Current value. + Minimum value. + Maximum value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a range field for ints. + + Label of field. Set to null for no label. + Current value. + Minimum value. + Maximum value. + Layout options. + Value assigned to the field. + + + + Draws a range field for ints. + + Label of field. Set to null for no label. + Current value. + Minimum value. + Maximum value. + Layout options. + Value assigned to the field. + + + + Draws a range field for ints. + + Current value. + Minimum value. + Maximum value. + Layout options. + Value assigned to the field. + + + + Draws a colored progress bar field. + + Position and size of the field. + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + Optional text for label to be drawn ontop of the progress bar. This value is only used if the DrawValueLabel option is enabled in the ProgressBarConfig. + + + + Draws a colored progress bar field. + + Position and size of the field. + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + + + + Draws a colored progress bar field. + + Position and size of the field. + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + + + + Draws a colored progress bar field. + + Position and size of the field. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + + + + Draws a colored progress bar field. + + Position and size of the field. + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + + + + Draws a colored progress bar field. + + Position and size of the field. + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + + + + Draws a colored progress bar field. + + Position and size of the field. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + + + + Draws a colored progress bar field. + + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + Layout options. + + + + Draws a colored progress bar field. + + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + Layout options. + + + + Draws a colored progress bar field. + + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + Layout options. + + + + Draws a colored progress bar field. + + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + Layout options. + + + + Draws a colored progress bar field. + + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + Layout options. + + + + Draws a colored progress bar field. + + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + Layout options. + + + + Draws a colored segmented progress bar field. + + Position and size of the field. + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + Optional text for label to be drawn ontop of the progress bar. This value is only used if the DrawValueLabel option is enabled in the ProgressBarConfig. + + + + Draws a colored segmented progress bar field. + + Position and size of the field. + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + + + + Draws a colored segmented progress bar field. + + Position and size of the field. + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + + + + Draws a colored segmented progress bar field. + + Position and size of the field. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + + + + Draws a colored segmented progress bar field. + + Position and size of the field. + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + + + + Draws a colored segmented progress bar field. + + Position and size of the field. + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + + + + Draws a colored segmented progress bar field. + + Position and size of the field. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + + + + Draws a colored segmented progress bar field. + + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + Layout options. + + + + Draws a colored segmented progress bar field. + + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + Layout options. + + + + Draws a colored segmented progress bar field. + + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + The configuration for the progress bar field. + Layout options. + + + + Draws a colored segmented progress bar field. + + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + Layout options. + + + + Draws a colored segmented progress bar field. + + The label to use, or null if no label should be used. + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + Layout options. + + + + Draws a colored segmented progress bar field. + + The current value of the progress bar. + The left hand side value of the progress bar. + The right hand side value of the progress bar. + Layout options. + + + + Draws an overlay on top of a progress bar field. + + The rect used to draw the progress bar field with. (Minus the Rect for the prefix label, if any.) + The label to draw ontop of the progress bar field. + The relative value of the progress bar, from 0 to 1. + The configuration used to draw the progress bar field. + + + + Draws an overlay on top of a progress bar field. + + The rect used to draw the progress bar field with. (Minus the Rect for the prefix label, if any.) + The label to draw ontop of the progress bar field. + The relative value of the progress bar, from 0 to 1. + The configuration used to draw the progress bar field. + + + + Draws an long field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws an long field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws an long field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws an long field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws an long field. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws an long field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws an long field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws an long field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed long field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a delayed long field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a delayed long field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a delayed long field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a delayed long field. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a delayed long field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed long field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed long field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a float field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a float field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a float field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a float field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a float field. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a float field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a float field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a float field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed float field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a delayed float field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a delayed float field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a delayed float field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a delayed float field. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a delayed float field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed float field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed float field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a range field for floats. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Minimum value. + Maximum value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a range field for floats. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Minimum value. + Maximum value. + Value assigned to the field. + + + + Draws a range field for floats. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Minimum value. + Maximum value. + Value assigned to the field. + + + + Draws a range field for floats. + + Position and size of the field. + Current value. + Minimum value. + Maximum value. + Value assigned to the field. + + + + Draws a range field for floats. + + Label of field. Set to null for no label. + Current value. + Minimum value. + Maximum value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a range field for floats. + + Label of field. Set to null for no label. + Current value. + Minimum value. + Maximum value. + Layout options. + Value assigned to the field. + + + + Draws a range field for floats. + + Label of field. Set to null for no label. + Current value. + Minimum value. + Maximum value. + Layout options. + Value assigned to the field. + + + + Draws a range field for floats. + + Current value. + Minimum value. + Maximum value. + Layout options. + Value assigned to the field. + + + + Draws a double field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a double field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a double field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a double field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a double field. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a double field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a double field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a double field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed double field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a delayed double field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a delayed double field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a delayed double field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a delayed double field. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a delayed double field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed double field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed double field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a decimal field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a decimal field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a decimal field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a decimal field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a decimal field. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a decimal field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a decimal field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a decimal field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a text field for strings. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a text field for strings. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a text field for strings. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a text field for strings. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a text field for strings. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a text field for strings. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a text field for strings. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a text field for strings. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed text field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a delayed text field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a delayed text field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a delayed text field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a delayed text field. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a delayed text field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed text field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a delayed text field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a field that lets the user select a path to a file. + + Position and size of the field. + Label of field. Set to null for no label. + The current value. + A parent path the path needs to be relative to. Use null for Unity project directory. + Comma separated list of allowed file extensions. Use null to allow any file extension. + If true the path will be absolute. Otherwise the path will be relative to parentPath or to the Unity project directory. + If true the path will be enforced to use backslashes. Otherwise the path will be enforced to use forward slashes. + A path to a file. + + + + Draws a field that lets the user select a path to a file. + + Position and size of the field. + The current value. + A parent path the path needs to be relative to. Use null for Unity project directory. + Comma separated list of allowed file extensions. Use null to allow any file extension. + If true the path will be absolute. Otherwise the path will be relative to parentPath or to the Unity project directory. + If true the path will be enforced to use backslashes. Otherwise the path will be enforced to use forward slashes. + A path to a file. + + + + Draws a field that lets the user select a path to a file. + + Label of field. Set to null for no label. + The current value. + A parent path the path needs to be relative to. Use null for Unity project directory. + Comma separated list of allowed file extensions. Use null to allow any file extension. + If true the path will be absolute. Otherwise the path will be relative to parentPath or to the Unity project directory. + If true the path will be enforced to use backslashes. Otherwise the path will be enforced to use forward slashes. + Layout options. + A path to a file. + + + + Draws a field that lets the user select a path to a file. + + The current value. + A parent path the path needs to be relative to. Use null for Unity project directory. + Comma separated list of allowed file extensions. Use null to allow any file extension. + If true the path will be absolute. Otherwise the path will be relative to parentPath or to the Unity project directory. + If true the path will be enforced to use backslashes. Otherwise the path will be enforced to use forward slashes. + Layout options. + A path to a file. + + + + Draws a field that lets the user select a path to a folder. + + Position and size of the field. + Label of field. Set to null for no label. + The current value. + A parent path the path needs to be relative to. Use null for Unity project directory. + If true the path will be absolute. Otherwise the path will be relative to parentPath or to the Unity project directory. + If true the path will be enforced to use backslashes. Otherwise the path will be enforced to use forward slashes. + A path to a folder. + + + + Draws a field that lets the user select a path to a folder. + + Position and size of the field. + The current value. + A parent path the path needs to be relative to. Use null for Unity project directory. + If true the path will be absolute. Otherwise the path will be relative to parentPath or to the Unity project directory. + If true the path will be enforced to use backslashes. Otherwise the path will be enforced to use forward slashes. + A path to a folder. + + + + Draws a field that lets the user select a path to a folder. + + Label of field. Set to null for no label. + The current value. + A parent path the path needs to be relative to. Use null for Unity project directory. + If true the path will be absolute. Otherwise the path will be relative to parentPath or to the Unity project directory. + If true the path will be enforced to use backslashes. Otherwise the path will be enforced to use forward slashes. + Layout options. + A path to a folder. + + + + Draws a field that lets the user select a path to a folder. + + The current value. + A parent path the path needs to be relative to. Use null for Unity project directory. + If true the path will be absolute. Otherwise the path will be relative to parentPath or to the Unity project directory. + If true the path will be enforced to use backslashes. Otherwise the path will be enforced to use forward slashes. + Layout options. + A path to a folder. + + + + Draws a prefix label for a vector field, that implements label dragging. + + + + + Draws a prefix label for a vector field, that implements label dragging. + + The position and total size of the field. + The label content. If null this function does nothing. + The value for the vector field. + The vector scaled by label dragging. + + + + Draws a prefix label for a vector field, that implements label dragging. + + The position and total size of the field. + The label content. If null this function does nothing. + The value for the vector field. + The vector scaled by label dragging. + + + + Draws a prefix label for a vector field, that implements label dragging. + + The label content. If null this function does nothing. + The value for the vector field. + The vector scaled by label dragging. + + + + Draws a prefix label for a vector field, that implements label dragging. + + The label content. If null this function does nothing. + The value for the vector field. + The vector scaled by label dragging. + + + + Draws a Vector2 field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a Vector2 field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a Vector2 field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a Vector2 field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a Vector2 field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a Vector2 field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a Vector3 field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a Vector3 field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a Vector3 field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a Vector3 field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a Vector3 field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a Vector3 field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a Vector4 field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a Vector4 field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a Vector4 field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a Vector4 field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a Vector4 field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a Vector4 field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a Color field. + + Position and size of the field. + Label of field. Set to null for no label. + + Value assigned to the field. + + + + Draws a Color field. + + Position and size of the field. + Label of field. Set to null for no label. + + Value assigned to the field. + + + + Draws a Color field. + + Position and size of the field. + + Value assigned to the field. + + + + Draws a Color field. + + Label of field. Set to null for no label. + + Layout options. + Value assigned to the field. + + + + Draws a Color field. + + Label of field. Set to null for no label. + + Layout options. + Value assigned to the field. + + + + Draws a Color field. + + + Layout options. + Value assigned to the field. + + + + Draws a slider for setting two values between a min and a max limit. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + The min and max limit for the value. + Show fields for min and max value. + A Vector2 with X set as min value, and Y to set as max value. + + + + Draws a slider for setting two values between a min and a max limit. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + The min and max limit for the value. + Show fields for min and max value. + A Vector2 with X set as min value, and Y to set as max value. + + + + Draws a slider for setting two values between a min and a max limit. + + Position and size of the field. + Current value. + The min and max limit for the value. + Show fields for min and max value. + A Vector2 with X set as min value, and Y to set as max value. + + + + Draws a slider for setting two values between a min and a max limit. + + Label of field. Set to null for no label. + Current value. + The min and max limit for the value. + Show fields for min and max value. + Layout options. + A Vector2 with X set as min value, and Y to set as max value. + + + + Draws a slider for setting two values between a min and a max limit. + + Label of field. Set to null for no label. + Current value. + The min and max limit for the value. + Show fields for min and max value. + Layout options. + A Vector2 with X set as min value, and Y to set as max value. + + + + Draws a slider for setting two values between a min and a max limit. + + Current value. + The min and max limit for the value. + Show fields for min and max value. + Layout options. + A Vector2 with X set as min value, and Y to set as max value. + + + + Draws a slider for setting two values between a min and a max limit. + + Position and size of the field. + Label of field. Set to null for no label. + Current min value. + Current max value. + The min limit for the value. + The max limit for the value. + Show fields for min and max value. + + + + Draws a slider for setting two values between a min and a max limit. + + Position and size of the field. + Label of field. Set to null for no label. + Current min value. + Current max value. + The min limit for the value. + The max limit for the value. + Show fields for min and max value. + + + + Draws a slider for setting two values between a min and a max limit. + + Position and size of the field. + Current min value. + Current max value. + The min limit for the value. + The max limit for the value. + Show fields for min and max value. + + + + Draws a slider for setting two values between a min and a max limit. + + Label of field. Set to null for no label. + Current min value. + Current max value. + The min limit for the value. + The max limit for the value. + Show fields for min and max value. + Layout options. + + + + Draws a slider for setting two values between a min and a max limit. + + Label of field. Set to null for no label. + Current min value. + Current max value. + The min limit for the value. + The max limit for the value. + Show fields for min and max value. + Layout options. + + + + Draws a slider for setting two values between a min and a max limit. + + Current min value. + Current max value. + The min limit for the value. + The max limit for the value. + Show fields for min and max value. + Layout options. + + + + Draws a rotation field for a quaternion. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Draw mode for rotation field. + Value assigned to the field. + + + + Draws a rotation field for a quaternion. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Draw mode for rotation field. + Value assigned to the field. + + + + Draws a rotation field for a quaternion. + + Position and size of the field. + Current value. + Draw mode for rotation field. + Value assigned to the field. + + + + Draws a rotation field for a quaternion. + + Label of field. Set to null for no label. + Current value. + Draw mode for rotation field. + Layout options. + Value assigned to the field. + + + + Draws a rotation field for a quaternion. + + Label of field. Set to null for no label. + Current value. + Draw mode for rotation field. + Layout options. + Value assigned to the field. + + + + Draws a rotation field for a quaternion. + + Current value. + Draw mode for rotation field. + Layout options. + Value assigned to the field. + + + + Draws an euler field for a quaternion. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws an euler field for a quaternion. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws an euler field for a quaternion. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws an euler field for a quaternion. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws an euler field for a quaternion. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws an euler field for a quaternion. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws an angle axis field for a quaternion. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws an angle axis field for a quaternion. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws an angle axis field for a quaternion. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws an angle axis field for a quaternion. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws an angle axis field for a quaternion. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws an angle axis field for a quaternion. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a quaternion field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a quaternion field. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a quaternion field. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a quaternion field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a quaternion field. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a quaternion field. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a dropdown. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Names of selectable items. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a dropdown. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Names of selectable items. + Value assigned to the field. + + + + Draws a dropdown. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Names of selectable items. + Value assigned to the field. + + + + Draws a dropdown. + + Position and size of the field. + Current value. + Names of selectable items. + Value assigned to the field. + + + + Draws a dropdown. + + Label of field. Set to null for no label. + Current value. + Names of selectable items. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a dropdown. + + Label of field. Set to null for no label. + Current value. + Names of selectable items. + Layout options. + Value assigned to the field. + + + + Draws a dropdown. + + Label of field. Set to null for no label. + Current value. + Names of selectable items. + Layout options. + Value assigned to the field. + + + + Draws a dropdown. + + Current value. + Names of selectable items. + Layout options. + Value assigned to the field. + + + + Draws a generic dropdown. + + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Selectable items. + Value assigned to the field. + + + + Draws a generic dropdown. + + + Label of field. Set to null for no label. + Current value. + Selectable items. + Value assigned to the field. + + + + Draws a generic dropdown. + + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Selectable items. + Names of selectable items. If null ToString() will be used instead. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a generic dropdown. + + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + + Names of selectable items. If null ToString() will be used instead. + Value assigned to the field. + + + + Draws a generic dropdown. + + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + + Names of selectable items. If null ToString() will be used instead. + Value assigned to the field. + + + + Draws a generic dropdown. + + + Position and size of the field. + Current value. + + Names of selectable items. If null ToString() will be used instead. + Value assigned to the field. + + + + Draws a generic dropdown. + + + Label of field. Set to null for no label. + Current value. + + Names of selectable items. If null ToString() will be used instead. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a generic dropdown. + + + Label of field. Set to null for no label. + Current value. + + Names of selectable items. If null ToString() will be used instead. + Layout options. + Value assigned to the field. + + + + Draws a generic dropdown. + + + Label of field. Set to null for no label. + Current value. + + Names of selectable items. If null ToString() will be used instead. + Layout options. + Value assigned to the field. + + + + Draws a generic dropdown. + + + Current value. + + Names of selectable items. If null ToString() will be used instead. + Layout options. + Value assigned to the field. + + + + Draws a dropdown for an enum or an enum mask. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a dropdown for an enum or an enum mask. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a dropdown for an enum or an enum mask. + + Position and size of the field. + Label of field. Set to null for no label. + Current value. + Value assigned to the field. + + + + Draws a dropdown for an enum or an enum mask. + + Position and size of the field. + Current value. + Value assigned to the field. + + + + Draws a dropdown for an enum or an enum mask. + + Label of field. Set to null for no label. + Current value. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a dropdown for an enum or an enum mask. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a dropdown for an enum or an enum mask. + + Label of field. Set to null for no label. + Current value. + Layout options. + Value assigned to the field. + + + + Draws a dropdown for an enum or an enum mask. + + Current value. + Layout options. + Value assigned to the field. + + + + Draws a dropdown. + + + Position and size of the field. + Label of field. Set to null for no label. + Current selection. + Avaible items in the dropdown. + If true then the user can select multiple items. Otherwise the user can only select one item. + true when the user has changed the selection. Otherwise false. + + + + Draws a dropdown. + + + Position and size of the field. + Label of field. Set to null for no label. + Current selection. + Avaible items in the dropdown. + If true then the user can select multiple items. Otherwise the user can only select one item. + true when the user has changed the selection. Otherwise false. + + + + Draws a dropdown. + + + Position and size of the field. + Current selection. + Avaible items in the dropdown. + If true then the user can select multiple items. Otherwise the user can only select one item. + true when the user has changed the selection. Otherwise false. + + + + Draws a dropdown. + + + Label of field. Set to null for no label. + Current selection. + Avaible items in the dropdown. + If true then the user can select multiple items. Otherwise the user can only select one item. + Layout options. + true when the user has changed the selection. Otherwise false. + + + + Draws a dropdown. + + + Label of field. Set to null for no label. + Current selection. + Avaible items in the dropdown. + If true then the user can select multiple items. Otherwise the user can only select one item. + Layout options. + true when the user has changed the selection. Otherwise false. + + + + Draws a dropdown. + + + Current selection. + Avaible items in the dropdown. + If true then the user can select multiple items. Otherwise the user can only select one item. + Layout options. + true when the user has changed the selection. Otherwise false. + + + + Draws a dropdown field for enum masks. + + Position and size of the field. + Label of field. Set to null for no label. + Current selection. + GUIStyle for drawing the field. Set to null for default. + Value assigned to the field. + + + + Draws a dropdown field for enum masks. + + Position and size of the field. + Label of field. Set to null for no label. + Current selection. + Value assigned to the field. + + + + Draws a dropdown field for enum masks. + + Position and size of the field. + Label of field. Set to null for no label. + Current selection. + Value assigned to the field. + + + + Draws a dropdown field for enum masks. + + Position and size of the field. + Current selection. + Value assigned to the field. + + + + Draws a dropdown field for enum masks. + + Label of field. Set to null for no label. + Current selection. + GUIStyle for drawing the field. Set to null for default. + Layout options. + Value assigned to the field. + + + + Draws a dropdown field for enum masks. + + Label of field. Set to null for no label. + Current selection. + Layout options. + Value assigned to the field. + + + + Draws a dropdown field for enum masks. + + Label of field. Set to null for no label. + Current selection. + Layout options. + Value assigned to the field. + + + + Draws a dropdown field for enum masks. + + Current selection. + Layout options. + Value assigned to the field. + + + + Collection of various editor GUI functions. + + + + + The mixed value dash character, to show when something has mixed values; + + + + + Default fade group animation duration. + + + + + Tab page slide animation duration. + + + + + Shaking animation duration. + + + + + Expand foldouts by default. + + + + + Show buttons results by default. + + + + + Draws a GUI field for objects. + + The rect to draw the field in. + The label of the field. + The value of the field. + The object type for the field. + If set to true then allow scene objects to be assigned to the field. + If set to true the field is readonly. + The object assigned to the field. + + + + Draws an GUI field for objects. + + The label for the field. + The value of the field. + The object type for the field. + If set to true then allow scene objects to be assigned to the field. + If set to true the field is readonly. + The object assigned to the field. + + + + Draws a GUI field for objects. + + The key for the field. + The type. + The label for the field. + The current value for the field. + If set to true then allow scene objects to be assigned to the field. + + The object assigned to the field. + + + + + Draws a nicely formatted title with an optinal sub-title and horizontal ruler. + + + + + Draws a GUI color field. + + The rect to draw the field in. + The color of the field. + If set to true then use alpha in the preview. + If set to true then show alpha bar in the preview. + The color assigned to the field. + + + + Draws a warning message box. + + + Also triggers a warning during validation checks done by + + The message. + If set to true the message box will be wide. + + + + Draws a thick horizontal seperator. + + + + + Draws a thick horizontal seperator. + + + + + Draws a thick horizontal seperator. + + + + + Draws a thick horizontal seperator. + + + + + Draws a horizontal line seperator. + + + + + Draws a vertical line seperator. + + + + + Draws an error message box. + + + Also triggers an error during validation checks done by + + The message. + If set to true the message box will be wide. + + + + Draws a info message box. + + The message. + If set to true the message box will be wide. + + + + Draws a message box. + + The message. + If set to true the message box will be wide. + + + + Draws a message box. + + The message. + Type of the message. + If set to true the message box will be wide. + + + + Draws a message box. + + The message. + Type of the message. + The style of the message box. + If set to true the message box will be wide. + + + + Draws a message box that can be expanded to show more details. + + The message of the message box. + The detailed message of the message box. + Type of the message box. + If set to true the detailed message is hidden. + If set to true the message box will be wide. + State of isFolded. + + + + Draws a horizontal line separator. + + Width of the line. + + + + Draws a horizontal line separator. + + The color of the line. + The size of the line. + + + + Draws a vertical line separator. + + Width of the line. + + + + Draws a vertical line separator. + + The color of the line. + Width of the line. + + + + Draws a GUI button with an icon. + + The editor icon for the button. + The width of the button. + The height of the button. + The tooltip of the button. + true if the button was pressed. Otherwise false. + + + + Draws a GUI button with an icon. + + The editor icon for the button. + The GUI style for the button. + The width of the button. + The height of the button. + The tooltip of the button. + true if the button was pressed. Otherwise false. + + + + Draws a GUI button with an icon. + + The rect to draw the button in. + The editor icon for the button. + true if the button was pressed. Otherwise false. + + + + Draws a GUI button with an icon. + + The rect to draw the button in. + The editor icon for the button. + The tooltip of the button. + true if the button was pressed. Otherwise false. + + + + Draws a GUI button with an icon. + + The rect to draw the button in. + The editor icon for the button. + The GUI style for the button. + The tooltip of the button. + true if the button was pressed. Otherwise false. + + + + Draws a GUI button with an icon. + + The rect to draw the button in. + The icon texture. + The tooltip for the button. + true when the button is pressed. + + + + Draws a GUI button with an icon. + + The rect to draw the button in. + The icon texture. + Style for the button. + The tooltip for the button. + true when the button is pressed. + + + + Draws a GUI button with an icon. + + The icon texture. + Width of the button in pixels. + Height of the button in pixels. + The tooltip for the button. + true when the button is pressed. + + + + Draws a GUI button with an icon. + + The icon texture. + Style for the button. + Width of the button in pixels. + Height of the button in pixels. + The tooltip for the button. + true when the button is pressed. + + + + Draws a repeating icon button. + + The icon for the button. + true while the button is active. Otherwise false. + + + + Draws a repeating icon button. + + The icon for the button. + The size. + true while the button is active. Otherwise false. + + + + Draws a repeating icon button. + + The icon for the button. + The width of the button. + The height of the button. + true while the button is active. Otherwise false. + + + + Draws a toolbar icon button. + + The icon for the button. + If true, the button clickable while GUI.enabled == false. + + true if the button was pressed. Otherwise false. + + + + + Draws a toolbar icon button. + + The GUI content for the button. + Whether the button state is selected or not + true if the button was pressed. Otherwise false. + + + + Draws a toolbar icon button. + + The label for the button. + Whether the button state is selected or not + true if the button was pressed. Otherwise false. + + + + Draws a toolbar toggle. + + Current state of the toggle. + The icon for the toggle. + The state of the toggle. + + + + Draws a toolbar toggle. + + Current state of the toggle. + The icon for the toggle. + The state of the toggle. + + + + Draws a toolbar toggle. + + Current state of the toggle. + The GUI content for the button. + The state of the toggle. + + + + Draws a toolbar toggle. + + Current state of the toggle. + The text for the toggle. + The state of the toggle. + + + + Draws a toolbar tab. + + If true the tab will be the active tab. + Name for the tab. + State of isActive. + + + + Draws a toolbar tab. + + If true the tab will be the active tab. + Label for the tab. + State of isActive. + + + + Draws a solid color rectangle. + + The rect. + The color. + If true applies the user's playmdoe tint to the rect in playmode. + + + + Draws a solid color rectangle. + + The width. + The height. + The color. + If true applies the user's playmdoe tint to the rect in playmode. + The rect created. + + + + Draws borders around a rect. + + The rect. + The width of the border on all sides. + If true applies the user's playmdoe tint to the rect in playmode. + + + + Draws borders around a rect. + + The rect. + The width of the border on all sides. + The color of the border. + If true applies the user's playmdoe tint to the rect in playmode. + + + + Draws borders around a rect. + + The rect. + The left size. + The right size. + The top size. + The bottom size. + If true applies the user's playmdoe tint to the rect in playmode. + + + + Draws borders around a rect. + + The rect. + The left size. + The right size. + The top size. + The bottom size. + The color of the borders. + If true applies the user's playmdoe tint to the rect in playmode. + + + + Draws a toolbar search field. + + The current search text. + If set to true the force focus on the field. + The left and right margin. + The current search text. + + + + Draws a search field. + + + + + Begins a horizontal toolbar. Remember to end with . + + The height of the toolbar. + Padding for the top of the toolbar. + The rect of the horizontal toolbar. + + + + Begins a horizontal toolbar. Remember to end with . + + The style for the toolbar. + The height of the toolbar. + The top padding. + + The rect of the horizontal toolbar. + + + + + Ends a horizontal toolbar started by . + + + + + Begins a horizontal indentation. Remember to end with . + + The GUI layout options. + + + + Begins a horizontal indentation. Remember to end with . + + The style of the indentation. + The GUI layout options. + + + + Ends a identation horizontal layout group started by . + + + + + Begins a vertical indentation. Remember to end with . + + The GUI layout options. + + + + Begins a vertical indentation. Remember to end with . + + The style of the indentation. + The GUI layout options. + + + + Ends a identation vertical layout group started by . + + + + + Indents by the current indent value, . + + + + + Draws a menu button. + + The indent of the button. + The text of the button. + The current state of the button. + The texture icon for the button. + The current state of the button. + + + + Begins a fade group. Remember to end with . + + The key for the fade group. + Current state of the fade group. + + + + Begins a fade group. Remember to end with . + + The key for the fade group. + Current state of the fade group. + A value between 0 and 1 indicating how expanded the fade group is. + + + + Begins a fade group. Remember to end with . + + The primary key for the fade group. + The secondly key for the fade group. + Current state of the fade group. + + + + Begins a fade group. Remember to end with . + + The key for the fade group. + The name of the fade group. + Current state of the fade group. + + + + Begins a fade group. Remember to end with . + + The key for the fade group. + Current state of the fade group. + The duration of fade in and out. + + + + Begins a fade group. Remember to end with . + + The key for the fade group. + Current state of the fade group. + A value between 0 and 1 indicating how expanded the fade group is. + The duration of fade in and out. + + + + Begins a fade group. Remember to end with . + + The primary key for the fade group. + The secondly key for the fade group. + Current state of the fade group. + The duration of fade in and out. + + + + Begins a fade group. Remember to end with . + + The key for the fade group. + The name of the fade group. + Current state of the fade group. + The duration of fade in and out. + + + + Begins a fade group. Remember to end with . + + The current fading value between 0 and 1. + + + + Ends a fade group started by any BeginFadeGroup. + + + + + Draws a foldout field where clicking on the label toggles to the foldout too. + + The current state of the foldout. + The label of the foldout. + The GUI style. + + The current state of the foldout. + + + + + Draws a foldout field where clicking on the label toggles to the foldout too. + + The current state of the foldout. + The label of the foldout. + The GUI style. + + + + Draws a foldout field where clicking on the label toggles to the foldout too. + + The current state of the foldout. + The label of the foldout. + The value rect. + The GUI style. + + + + Draws a foldout field where clicking on the label toggles to the foldout too. + + The rect to draw the foldout field in. + The current state of the foldout. + The label of the foldout. + The style. + + + + Begins drawing a box. Remember to end with . + + The label of the box. + If set to true then center label. + The GUI layout options. + + + + Begins drawing a box. Remember to end with . + + The label of the box. + If set to true then center label. + The GUI layout options. + The rect of the box. + + + + Begins drawing a box. Remember to end with . + + The GUI layout options. + + + + Ends drawing a box started by any BeginBox. + + + + + Begins drawing a box header. Remember to end with . + + + + + Ends drawing a box header started by , + + + + + Begins drawing a box with toolbar style header. Remember to end with . + + Label for box header. + If true the label will be drawn in the center of the box header. + GUILayout options. + The rect of the box. + + + + Begins drawing a box with toolbar style header. Remember to end with . + + Label for box header. + If true the label will be drawn in the center of the box header. + GUILayout options. + The rect of the box. + + + + Begins drawing a box with toolbar style header. Remember to end with . + + GUILayout options. + The rect of the box. + + + + Ends the drawing a box with a toolbar style header started by . + + + + + Begins drawing a toolbar style box header. Remember to end with . + + The rect of the box. + + + + Ends the drawing of a toolbar style box header started by . + + + + + Begins drawing a legend style box. Remember to end with . + + The label for the legend style box. + If true the label will be drawn in the center of the box. + GUILayout options. + The rect of the box. + + + + Begins drawing a legend style box. Remember to end with . + + The label for the legend style box. + If true the label will be drawn in the center of the box. + GUILayout options. + The rect of the box. + + + + Begins drawing a legend style box. Remember to end with . + + GUILayout options. + The rect of the box. + + + + Ends the drawing of a legend style box started by + + + + + Begins drawing an inline box. Remember to end with . + + The GUI layout options. + The rect of the box. + + + + Ends drawing an inline box started by any BeginInlineBox. + + + + + Starts the shaking animation of a shaking group. + + + + + Starts the shaking animation of a shaking group. + + + + + Begins a shakeable group. + + + + + Ends the shakeable group. + + + + + Begins drawing a vertical menu list. + + The key for the menu list. + The rect created. + + + + Begins drawing a menu list item. Remember to end with + + Value indicating whether the item is selected. + Value indicating if the mouse is pressed on the item. + If set to true the item is set as selected.. + The rect used for the item. + + + + Ends drawing a menu list item started by + + + + + Ends drawing a vertical menu list started by + + + + + Begins drawing a vertical list. + + If set to true borders will be drawn around the vertical list. + If set to true a dark background will be drawn. + The GUI layout options. + The rect used for the list. + + + + Ends drawing a vertical list started by . + + + + + Begins drawing a list item. + + If set to true the item can be hovered with the mouse. + The style for the vertical list item. + The GUI layout options. + The rect used for the item. + + + + Begins drawing a list item. + + If set to true the item can be hovered with the mouse. + The style for the vertical list item. + The GUI layout options. + The color for even elements. + The color for odd elements. + The color for even elements when hovered. + The color for odd elements when hovered. + The rect used for the item. + + + + Ends drawing a list item started by . + + + + + Creates a animated tab group. + + The key for the tab group.. + An animated tab group. + + + + Begins drawing a toggle group. Remember to end with . + + The key of the group. + Value indicating if the group is enabled. + Value indicating if the group is visible. + The title of the group. + Value indicating if the group is toggled. + + + + Begins drawing a toggle group. Remember to end with . + + The key of the group. + Value indicating if the group is enabled. + Value indicating if the group is visible. + The title of the group. + Duration of the animation. + Value indicating if the group is toggled. + + + + Ends drawing a toggle group started by . + + + + + Begins drawing a horizontal auto scroll box. Remember to end with . + + The for the field. + The GUILayout options. + The rect used for the field. + + + + Ends drawing a horizontal auto scroll box started by . + + + + + Creates a rect that can be grabbed and pulled to change a value up or down. + + The grabbable rect. + The control ID for the sliding. + The current value. + + The current value. + + + + + Creates a rect that can be grabbed and pulled to change a value up or down. + + The grabbable rect. + The control ID for the sliding. + The current value. + + The current value. + + + + + Creates a rect that can be grabbed and pulled to change a value up or down. + + The grabbable rect. + The control ID for the sliding. + The current value. + + The current value. + + + + + Creates a rect that can be grabbed and pulled to change a value up or down. + + The grabbable rect. + The control ID for the sliding. + The current value. + + The current value. + + + + + Creates a rect that can be grabbed and pulled + + The grabbable rect. + The cursor. + + The the mouse delta position. + + + + + Creates a rect that can be grabbed and pulled + + The position. + The grabbable rect. + + The the mouse delta position. + + + + + Draws a field for a value of type T - dynamically choosing an appropriate drawer for the type. + Currently supported are: char, string, sbyte, byte, short, ushort, int, uint, long, ulong, float, double, decimal, Guid and all enums. + + The type of the value to draw. + The label of the fields. + The value to draw. + The layout options. + The possibly changed value. + + + + Checks whether a given type can be drawn as a dynamic field by + + The type to check. + True if the type can be drawn, otherwise false. + + + + Gets the feature rich control rect. + + + + + Gets the feature rich control rect. + + + + + Creates a control ID that handles keyboard control, focused editor window, indentation and prefix label correctly. + + The rect to make a feature rich control for. + The label for the control. Leave null for no label. + The created control ID. + A value indicating whether or not the control has keyboard focus. + + + + Creates a control ID that handles keyboard control, focused editor window, indentation and prefix label correctly. + + The rect to make a feature rich control for. + The created control ID. + A value indicating whether or not the control has keyboard focus. + + + + Collection of GUIStyles used by Sirenix. + + + + + Border color. + + + + + Box background color. + + + + + Dark editor background color. + + + + + Editor window background color. + + + + + Menu background color. + + + + + Header box background color. + + + + + Highlighted Button Color. + + + + + Highlight text color. + + + + + Highlight property color. + + + + + List item hover color for every other item. + + + + + List item hover color for every other item. + + + + + List item drag background color. + + + + + List item drag background color. + + + + + Column title background colors. + + + + + List item background color for every other item. OBSOLETE: Use ListItemColorEven instead. + + + + + List item background color for every other item. OBSOLETE: Use ListItemColorOdd instead. + + + + + List item color for every other item. + + + + + List item color for every other item. + + + + + Menu button active background color. + + + + + Menu button border color. + + + + + Menu button color. + + + + + Menu button hover color. + + + + + A light border color. + + + + + Bold label style. + + + + + Tag Button style. + + + + + Bold label style. + + + + + Centered bold label style. + + + + + Box container style. + + + + + Popup style. + + + + + Box header style. + + + + + Left button style. + + + + + Left button selected style. + + + + + Left button style. + + + + + Left button selected style. + + + + + Mid button style. + + + + + Mid button selected style. + + + + + Right button style. + + + + + Right button selected style. + + + + + Pane Options Button + + + + + Left button style. + + + + + Left button selected style. + + + + + Left button style. + + + + + Left button selected style. + + + + + Mid button style. + + + + + Mid button selected style. + + + + + Right button style. + + + + + Right button selected style. + + + + + Color field background style. + + + + + Foldout style. + + + + + Icon button style. + + + + + Label style. + + + + + White label style. + + + + + Black label style. + + + + + Centered label style. + + + + + Left Aligned Centered Label + + + + + Left aligned grey mini label style. + + + + + Left aligned grey label style. + + + + + Centered grey mini label + + + + + Left right aligned white mini label style. + + + + + Centered white mini label style. + + + + + Centered black mini label style. + + + + + List item style. + + + + + Menu button background style. + + + + + No style. + + + + + Odin Editor Wrapper. + + + + + Padding less box style. + + + + + Content Padding + + + + + Property padding. + + + + + Property margin. + + + + + Rich text label style. + + + + + Right aligned grey mini label style. + + + + + Right aligned white mini label style. + + + + + Section header style. + + + + + Section header style. + + + + + Toggle group background style. + + + + + Toggle group checkbox style. + + + + + Toggle group padding style. + + + + + Toggle group title background style. + + + + + Toolbar background style. + + + + + Toolbar button style. + + + + + Toolbar button selected style. + + + + + Toolbar search cancel button style. + + + + + Toolbar search field style. + + + + + Toolbar tab style. + + + + + Title style. + + + + + Bold title style. + + + + + Centered bold title style. + + + + + Right aligned bold title style. + + + + + Centered title style. + + + + + Right aligned title style. + + + + + Subtitle style. + + + + + Centered sub-title style. + + + + + Right aligned sub-title style. + + + + + Message box style. + + + + + Detailed Message box style. + + + + + Multiline Label + + + + + Centered Multiline Label + + + + + Centered Text Field + + + + + Gets the bottom box padding. + + + + + Unitys PaneOptions GUIStyle. + + + + + Unitys ProjectBrowserTextureIconDropShadow GUIStyle. + + + + + Unitys TL SelectionButton PreDropGlow GUIStyle. + + + + + Unitys ShurikenModuleTitle GUIStyle. + + + + + Draw this one manually with: new Color(1, 1, 1, EditorGUIUtility.isProSkin ? 0.25f : 0.45f) + + + + + A tab page created by . + + + + + + Gets the title of the tab. + + + + + Gets the title of the tab. + + + + + Gets the rect of the page. + + + + + Begins the page. + + + + + Ends the page. + + + + + Whether to draw a draw scroll view. + + + + + The number of pixels before a scroll view appears. + + + + + The maximum scroll view height. + + + + + The scroll position + + + + + The cell style + + + + + Gets the rect containing all rows. + + + + + Gets the first visible row index. + + + + + Gets the last visible row index. + + + + + Gets the outer rect. The height of this <= .height. + + + + + Gets the row rect. + + + + + Begins the table. + + + + + Begins the column. + + + + + Begins the cell. + + + + + Ends the cell. + + + + + Ends the column. + + + + + Ends the table. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Utility functions for Unity assets. + + + + + Gets all assets of the specified type. + + + + + Gets all assets of the specified type. + + The type of assets to find. + The asset folder path. + + + + Gets all assets of the specified type. + + The type of assets to find. + The asset folder path. + + + + Asset search helper. + + + + + The asset object. + + + + + Current index. + + + + + Search result count. + + + + + Tests if an asset can be created from a type. + + The type to test. + true if an asset can be created. Otherwise false. + + + + Tests if an asset can be created from a type. + + The type to test. + The base asset type. + true if an asset can be created. Otherwise false. + + + + Gets project path to the specified asset. + + The asset object. + The path to the asset. + + + + Creates a new asset of the specified type. + + The type of the asset. + Project path to the new asset. + The name of the asset. + + + + Functions for accessing the clipboard. + + + + + Gets the current copy mode. + + + + + Copies the specified object. + + + The object. + The copy mode. + + + + Copies the specified object. + + + + + Clears this instance. + + + + + Determines whether this instance can paste the specified type. + + + + + Determines whether this instance can paste the specified type. + + + + + Determines whether or not the Clipboard contains any instance. + + + + + Tries the paste. + + + + + Copies or gets the current object in the clipboard. + + + + + Copies or gets the current object in the clipboard. + + + + + The various modes of copying an object to the clipboard. + + + + + Deep copy. + + + + + Shallow Copy. + + + + + Reference Copy. + + + + + A utility class for getting delta time for the GUI editor. + + + + + Gets an EditorTimeHelper instance for the current drawing window. + + + + + Initializes a new instance of the class. + + + + + Gets the delta time. + + + + + Updates the delta time. + + + + + Compare strings and produce a distance score between them. + + + + + Determines whether if the source is within the search. + + The source string. + The target string. + Should the algorithm ignore letter case?. + Should the algorithm attempt to search on an abbreviation of the source?. + Threshold for what is considered to be within the search. 0 will return everything and 1 will only return exact matches. + True if the source is within the search. Otherwise false. + + + + Compares the target to the source and returns a distance score. + + The source string. + The target string. + + + Distance score. 0 is no match, and 1 is exact match. + + + + A utility class for properly counting frames and helps determine when a frame has started in an editor window. + + + + + Gets the frame count. + + + + + Gets a value indicating whether this instance is new frame. + + + + + Updates the frame counter and returns itself. + + + + + Hides the ObjectMembers in Visual Studio IntelliSense + + + + + Determines whether the specified , is equal to this instance. + + + + + Returns a hash code for this instance. + + + + + Gets the type. + + + + + Returns a that represents this instance. + + + + + Collection of texture functions. + + + + + Loads an image from bytes with the specified width and height. Use this instead of someTexture.LoadImage() if you're compiling to an assembly. Unity has moved the method in 2017, + and Unity's assembly updater is not able to fix it for you. This searches for a proper LoadImage method in multiple locations, and also handles type name conflicts. + + + + + Crops a Texture2D into a new Texture2D. + + + + + Converts a Sprite to a Texture2D. + + + + + + + AssemblyTypeFlags is a bitmask used to filter types and assemblies related to Unity. + + + + + + Excludes all types. + + + + + UserTypes includes all custom user scripts that are not located in an editor or plugin folder. + + + + + PluginTypes includes all types located in the plugins folder and are not located in an editor folder. + + + + + UnityTypes includes all types depended on UnityEngine and from UnityEngine, except editor, plugin and user types. + + + + + UserEditorTypes includes all custom user scripts that are located in an editor folder but not in a plugins folder. + + + + + PluginEditorTypes includes all editor types located in the plugins folder. + + + + + UnityEditorTypes includes all editor types that are not user editor types nor plugin editor types. + + + + + OtherTypes includes all other types that are not depended on UnityEngine or UnityEditor. + + + + + CustomTypes includes includes all types manually added to the Unity project. + This includes UserTypes, UserEditorTypes, PluginTypes and PluginEditorTypes. + + + + + GameTypes includes all assemblies that are likely to be included in builds. + This includes UserTypes, PluginTypes, UnityTypes and OtherTypes. + + + + + EditorTypes includes UserEditorTypes, PluginEditorTypes and UnityEditorTypes. + + + + + All includes UserTypes, PluginTypes, UnityTypes, UserEditorTypes, PluginEditorTypes, UnityEditorTypes and OtherTypes. + + + + + A utility class for finding types in various asssembly. + + + + + Initializes the class. + + + + + Re-scans the entire AppDomain. + + + + + Gets an of all assemblies in the current . + + An of all assemblies in the current . + + + + Gets the for a given assembly. + + The assembly. + The for a given assembly. + is null. + + + + Gets the type. + + The full name of the type without any assembly information. + + + + Gets the type. + + + + + Determines whether an assembly is depended on another assembly. + + The assembly. + The other assembly. + + true if has a reference in or is the same as . + + is null. + is null. + + + + Determines whether the assembly module is a of type . + + The assembly. + + true if the specified assembly of type ; otherwise, false. + + assembly + + + + Gets the full file path to a given assembly. + + The assembly. + The full file path to a given assembly, or Null if no file path was found. + is Null. + + + + Gets the full directory path to a given assembly. + + The assembly. + The full directory path in which a given assembly is located, or Null if no file path was found. + + + + Get types from the current AppDomain with a specified filter. + + The filters. + Types from the current AppDomain with the specified filters. + + + + Find members of the given type, while providing good error messages based on the following search filters provided. + See for more information. + + + + + MemberFinder is obsolete, and has been replacted by and . + Use cases that do not fit those utlities should use manual reflection that is hand-optimized for the best performance in the given case. + + MemberFinder was a utility class often used by Odin drawers to find fields, methods, and + properties while providing good user-friendly error messages based on the search criteria. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Find members of the given type, while providing good error messages based on the following search filters provided. + + + + + Find members of the given type, while providing good error messages based on the following search filters provided. + + + + + Can be true for both fields, properties and methods. + + + + + + Exclude members found in base-types. + + + + + Only include methods with the following parameter. + Calling this will also exclude fields and properties. + Parameter type inheritance is supported. + + + + + Only include methods with the following parameters. + Calling this will also exclude fields and properties. + Parameter type inheritance is supported. + + + + + Only include methods with the following parameters. + Calling this will also exclude fields and properties. + Parameter type inheritance is supported. + + + + + Only include methods with the following parameters. + Calling this will also exclude fields and properties. + Parameter type inheritance is supported. + + + + + Only include methods with the following parameters. + Calling this will also exclude fields and properties. + Parameter type inheritance is supported. + + + + + Only include methods with the following parameters. + Calling this will also exclude fields and properties. + Parameter type inheritance is supported. + + + + + Only include methods with the following parameters. + Calling this will also exclude fields and properties. + Parameter type inheritance is supported. + + + + + Only include methods with the following parameters. + Calling this will also exclude fields and properties. + Parameter type inheritance is supported. + + + + + Determines whether [has return type] [the specified return type]. + + + + + Can be true for both fields, properties and methods. + + + + + Calls IsField() and IsProperty(). + + + + + Only include static members. By default, both static and non-static members are included. + + + + + Only include non-static members. By default, both static and non-static members are included. + + + + + Specify the name of the member. + + + + + Excludes fields and methods if nether IsField() or IsMethod() is called. Otherwise includes properties. + By default, all member types are included. + + + + + Excludes fields and properties if nether IsField() or IsProperty() is called. Otherwise includes methods. + By default, all member types are included. + + + + + Excludes properties and methods if nether IsProperty() or IsMethod() is called. Otherwise includes fields. + By default, all member types are included. + + + + + Excludes non-public members if IsNonPublic() has not yet been called. Otherwise includes public members. + By default, both public and non-public members are included. + + + + + Excludes public members if IsPublic() has not yet been called. Otherwise includes non-public members. + By default, both public and non-public members are included. + + + + + Excludes fields and properties, and only includes methods with a return type of void. + + + + + Gets the member based on the search filters provided + Returns null if no member was found. + + + + + Gets the member based on the search filters provided, and provides a proper error message if no members was found. + + + + + Gets the member based on the search filters provided, and provides a proper error message if no members was found. + + + + + Try gets the member based on the search filters provided, and provides a proper error message if no members was found. + + + + + Try gets the member based on the search filters provided, and provides a proper error message if no members was found. + + + + + Try gets all members based on the search filters provided, and provides a proper error message if no members was found. + + + + + Gets or sets the width of the col. + + + + + Gets or sets the minimum width. + + + + + Gets a value indicating whether the width should be preserved when the table itself gets resiszed. + + + + + Gets a value indicating whether this is resizable. + + + + + This class contains utility methods for subscribing to various UnityEditor events reliably and safely across all Odin-supported versions of Unity. + + + + + Sometimes, someone accidentally overrides a delay action subscription to + by setting the value instead of using the += operator as should be done, + which can be done because in many versions of Unity it is a field, and not an event. + (In some versions of Unity it is an event, though, and in this case, this method acts as a wrapper + to subscribe reliably, no matter the nature of the backing event.) + This method subscribes to a lot of different callbacks, in the hopes of catching at least one. + + As opposed to , this method is safe to call from any thread, and will + delay the actual subscription to a safe time. + + + + + Sometimes, an idiot overrides a delay action subscription to , + which can be done because the people at Unity didn't know what events were once upon a time. + This method subscribes to a lot of different callbacks, in the hopes of catching at least one. + + + + + In 2020.1, Unity changed EditorApplication.delayCall from a field to an event, meaning + we now have to use reflection to access it consistently across all versions of Unity. + + + + diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.xml.meta b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.xml.meta new file mode 100644 index 0000000..0d59bcc --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.xml.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5c65184932ff4fd48a343e236025096f +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll new file mode 100644 index 0000000000000000000000000000000000000000..4fd55c6ba91b8fbe9d9d25d0a9144aeaf3659bc0 GIT binary patch literal 154112 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�sXXj`5GIs-W=PYQOle$<0$VPXV7)gLr}*n(O%mc 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

    v5LQ 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


    |1gH-z^ zT1dEDGYMCyr&H<$_8(Oc+Y_)oH052nlBY!;GHle@j8={V-AHz~DY1&K^9xc7hHt*~ z;N?6YOD@D-gxsDKvBsE#!}%$BrJ-Zxtu#Ey-5)$7x6K>$uuR>ja7giSb+<5GrWT3{wM-nRvq!mdw^#$QgN;@c-ctwXl7fLc2YfEh=bRF-ct#~R|I`dyTYFRv5b z8v)TiUCqG}(oPujZ%8xjf)>2b0s}UR=1*)JgDuVvu-Irm;kE?~;ZfL2svjF>Fi18f z8FERye~=hI!7= zjjy+fbwJ)qUhK&&nUvb%gx& zg)jT9gzJS$*f%iegL_$FR_8{OPeK``ySTWUT$GZqrBgw9>9pfFa{0Fby_G@c89(ji zxV1Og)_Xg+*qyaP8TQ<5$By%;%L~4d>?po1%)M$|P#Bnw(g^1g7Cs$0)tlVz{X|W7 zN)g_Yrt~4neNy@;xy>j-1B&tWk5jcs9POml551kL7lo0NUmVQA0*|Eg@1fJ zIl1QDLX_k@kX)dapnGp;_jqM4jZ;r(ynMA>@a!Mt?jL{tMaqGaqHaGbDgTr|WqGnt z28|KYcJw{bmz^YajE#o#(Ap*rd*nEsh*>9l?U?VC3r=RdScdkbyw#4$au0J* zM16LE&nMQ*UfZV1u}sz6Q8wDJrgIWIQ@7AKx2|ptLo)ZnSWYARQF5vuy$tjza*xfO z`v7cI%Gqb}?Bn}Wa-u)I2=pnkx8%-#wv@g3OSgv3QvM?bP;z_#y#Ry(&tCF&NK2&L zHNocpYE6jwYC@O4CTx^tsy?r$L7m=Dk^4lg4z^k)F>eSeY7cZZhs3$@Sse|F!%Um2slK`V&6fuw?pWVq5mfK zQYH30L|ZqMZvR)YS1Pe@AX@fNI$+qp$$Om=dlsUt8b&w&tJs^B*jEtk`7rwKU&Y>` z#GXE!lFZ?BJrK^nJ4%OJ{N+=ILO8tpY(}lK#+hS88?1O)x6OC|CfoakYiK z9pK;~wIh2^4OJrC{CxZ)+}h&*jRxaX?%8x&j6`>j zqGzSFF=flqOawv73;Vt-FV*!vSk9}QN`z}!ZI-ht9^uxe_(p?Q@#Nxoqrn;Hps7>* zXiCyY)15$Q0Lt@$+OV#Gl~Qg$96E_k?j(-po>-;I&0l1@R;Z z#p>)F?Mr_+>^vyTGDwO5i35O zVjecOussW%z99EHsln8p3Z=LuK95Z8uy|96Cw1jkn(YUikO;+AapF+t=Npxirbj2U)*`H<|zk2l=E6B9*luRE_ zX8_@mD(MDinXZsngnF}SK%w;zZ5U5?@(_q#2-9_6A11i~*2VGk5|dDZ-7TzP*^LeA zWc3SXokC&-8WMq}BrWs`AqP*Oqb7VT0(`?PLMtm0#fj$F6t80Brk65*lLq4(E72oPb1L>6X^So>QY?NBYFR0C7rNZYZF3bNA5Em$ECT+ZQVb2`ZKqJuBud6lq7#5nDy=l|vc#Grqv32* z%k`yHE{F2c0;G`Gmxh>3{;UZWT8#KRC()BE85>d}F1j_3+@O0XUJ+~*9&3&BGvg>* z$=rfAW;nw_m_+AUNV<^JJBj$UC>MHx zQXZO2pG{`wRGKMXGAS%JWc5?{>J&<@O`-RJ&>v;zzO*@&d&VM&I1!KilsvC)sTSWP zCtkh1)+Y;#ZJ8Uv%nHMN8Q#e_Qe1%E+vgj>md1q#CR4IHneGK5@S91))W@jT^zDU_t8(1k$xQkD)EOXDV$ilwByJV(k)q?7|p(Ak0B zyXzY)DSZZMzD=P+r~bR7kLF1Fd`_kB`i8_M8plhCuRyA&rqU}PN<7yDGPmB>awLvL zfMyXxgl|%CgfTcclAC2*DkUpY=_a6jX8DWc69moRJ6Q6$GB5=PN3bj+q&yxY@uX=q zb=tqnV|R```bnp4lxjsGSRR(RB$kUMZUQgMab)mn8XYkG1Nr<#6~D`2s+}w!SI>pTahN~IN+~ME`-TLd zKCD)545nJJH3DZ7Fch#p3q}-gi}Popsm!9!fS7^)jed%OloM8LqK;t=USicexyPS9 zv(fHn(*biNTcF#1*cQ3^vuukTi%WH`aaVo}@vT2(y((wcyk;=0`km{}3%UZiKAuD0 zu+0BsLFeUajL&lBR)V*Ky!~+5TuLs_rFVh;YwH`8E6=Tl9L81JUd~~1&OCU-=Fy8l z?2pw4J0D`Y-i|%BCe5d0@_af4NS02Kqyc6wUkSmg`E)gt>vQi06$mj0TY}hz5cjPq zo9Vp!C@VOs;~mFF#BibxCY$7y$ynibp8XkAn3TJ(_w@{+ZUH>4?5NK@L$Jvd7-8+* zJHl$ji)Y<2=cR>DK&1%_=z;~%%!cGqCU;ko*9=r{IJuO;K}_C-Qs|XDZRd?*2w97} zzNP@yeeigQh&*rRP3RGFPfMq((*K9%NtHYGBOI{Gy?s?!+;7jTE(NxMiH_wkQThi= z^c-rf$e?>N{)gI4lPhnya6Dh-jd#$rbHA=so{y{H;QF3wV2-Ka%DWMPjp4ZYScHw_XL`5k)ccAcUeNm0`WA8h)vl1wMaS`8B6Fw#>aXx z90xP-PEBZci-qkKU@;jL9xT5&X&0ni`J;L;7R&9X_{zEyLP|#uFXPWia7XEB(%Bj#*RL~PHwoT_j1eAQ!NDH2zh`P~gFg51h*=7? z@S=>O1XNQWr{D2L;_k6cEVE#o@a_keRGx(6S3a5k1-qrmZ1d!J$I%YFGOD)dDjBY|b$Kvb) zf+827#;{B}GgGa=5dyEld*Iy9qz|}2sr?c}S5z#+5>DW7L4B zLcCv2hphl#AO+Z|j_$EIWXoGu&b>K#JJsMJtvHL~JzA5G)qM_2Bn`1wub_KaBKU*G zp}c6fz_`7F-pR}Fw~~_nE9n3rIea7!KM9P&^8ILpRceH@2zhfAee^dGwyF^lR>M29 zn$7_Fs~qsKl2zJ(kb73sqkj|Olp5gyLcU&22d??+9ImPnrXghd8oK;%B0Nwd97f1< zYv}dAiGXt&avA!sMW0?vCjg<;QWauzL025FmwGe*N%3V6Wv->`c?eW(aS?4F{9|Ao zUrSGD{ED1^4~+Y3=>v^lo%08+gUe|h9Rj4~ z0mb;6!Pv5nZq@kSoPP?8)9dINjbEShAA#|B9etwl8*%=y^^^=>Pe%apeo#V0he!I; z!I-h0&eZs=IDa)5Yu3}X8owRq9|q&ddU{mjcjEk8VBB6$?`V7+Dnpn6wSBhNU*a-YS2obAnq)NP zX}tmG&kgjgCP~>1al<8PH=W@q`Nf%UO-}*Uj*mU zMtWHjz}dkBufWOPNMCCL9GYQ*v70Cvw}~bK$(e7I1Pj1P-$XMs!7fR#4V>+p=nhT5 z&RQd>bKsocL@#K9Gm_vrI4?HQmzv;;Bp9`slF^$7y)G6bVJo`)Ryqnu z&V05cm<`UHt#qy?SRe^Dg0pEW-K+^#NP?5#oZ3oHYl4lE;1M{Fx6&t?V5cCp)8X4F z8L^GV1If7`l%k}8Giw{2tqHOOn#>el57vflbfYH0kjexnz&W{%p3(&8CBZ{*9&MwK zHNh20Fl;*pfbDbykevHXNiYMPncHcaCb%aF)`GKcJ6*2{9!r8OaE@)K$2GwVNpKIG z``hUQP4Gq%4Bml>#|}CaNX{I7DOQeDaHj2`(=`EmRRV%l;H=(3*JuLvdIJQ9!8x*n z9@PY+CBbcQ?(Cp@_ zF1kt+Y?TBD!8x>x9@YeS4ThQJCOEft(c7BffF$U*8w2oeIsiz{{J12T49=9@G+7hi zT{M=|GH^0?)8(4rh9uYr&i>u>fF^h-39f;2eK)3Z4bS!2@)m2pWwXR zL*HqFNs?gvUaa2t(uqKF?l`^8GG7GF;=OcO43X_R)))V7DZA0nW>P^pz$!APGkA$N0OSjs+s@9XfXPyXqS0FHeJNHicAI5)&bJ zv%9%Zpr4;xNqMKF5c1{sf??4n;J!A#KUs*fbxFy2NOb9by6uB$D{mD0wwKbb$J2Jp zojTu_`H`)E@~1xN00!>^bQ%yhTS+kzD`R)~EM+a6m};%_L@r3#{aq!mAlB6b^qLlV zEZaD6hm%r`@Awz-ryax=)?azQSPJ+1f+OJE{mrW~RRSpxV&(0V-KQ(&AvM9*k^ z)EUA*0^{)^`b6Wm=KNuYG5jB%c9$2-oY#Ob)E#JbOrXkh1hOPxjRM@Q&uE%n9x z{zfL7eiSx1N@oJeD!~hooXnoUrPhPF;V9jx$)rhHsZ-#bK1$DM0-SqhF&=~S z4W#POmzCDarNrR^RgV(LZOIYGSbe;_e88urP9ddhS@bze(3aS+8z`Hy6k*L!STl&~ zU|AbjRZl}y%g)R9?t3Y525w04is+b(qrNQN`Nyz2K1PoL;gq*i7hGl%Vl}bX!%XH- zY{wUpIBjF_>6F&|UK9ZtiO57J;^lTZ%Q$LFyQ|r577Z{{t``%~0X7KKBGh%jyU;>R zL8G7Pd4REv!9B&uU^!Ez|8Y!LkJEiXD54Nl4R=>|sYV4MxEd9Opz2g7bg52lgy8B_ zZ-aNkTE-K7oZW`4(C?q^6 z3NNMMHEU}?S2MH~4A$@{iBuM@-z(dSrNkw;WW|ShEJ|%hO7~9E=l>Vafpsqn&qD1&R%vawHG0?PSbNAjNmEdFbxp`-3Ph< z$|Af$$U$f5$TM6e^~{u9Gha$E*666k$C$vvXCUCpGjtORk9!J2!ozUX1~=eIM|;(_ zQ&XwZeLDKW&$(DfKJc7FtcPdlD;60W1-RKrGoqeDZn^Q9&onsa-tlz3i8y`7z1{JhzJ@gAO)+$*_Mf)|mNntT?$@GQ*&k}K#P zf9{tWdJaCrb96WmoZe_k_=pF;Zb-X%NYG0s<TPpx6MTmIN&Ng^IO(zA=2-`1&hr#S@$QCnZ3uhO%1Ph~el{JN9XdxJ{aXcv z&i_F}&;O#~mh*VDo~Pq3{38>>6U%A-wLtxe^rP((0=Mwy89{$VfRmJLLQO$fWV4jD>L*4+RN5f zvOBpXS4=ti@M8t}fR?9>dn+%A^`lvG&@rIwFjVDw$m0yxXCkIk?s&SJDk~!io-y>BHg*63?*fhK=BIUo2G=uK`u4)cVc0@T*m5i@ilboYjnx=e`E^Or)G+t zI@T<6n4;&WF$El6|6fe8_68iLH|V;XFvWj-NCZhup`84%sL)>e?b$x>Lju09j(+aW zMw3##|MWqz;}*Pox9IrW|47MP{ZHPRB>z}Ryvym=@xLf}2ii@(L)YGcl4xXnxFQva zuC(|CHW%)KReJPYtiuRKyh{&h{O>vc zIv6+Z(wiFJhx6Zp@$N2tuko93{`h-vf83)Jf#j_HIe#G-i|*0I8oxE??*L=xJ-SQd z|H%30!MJdbUex%VIsZ8rFYeKo8b6HlN8YDo)O|V{NX|Ew^JjxG=RTdQ@%wWA1~4|> zr<*iBya>z?$H6&qpPtkN6C}X{a30>Lk2FCVmU1l0&vR4?FdjXik2QWH&L8>^xj&@Cf#lr% zIDZ-#(;w0q8sDGuSAntmAzh>Kc}+MU0^{&QdPL*5=izUHaqA(yt?>gn|2-J}9?|}f z)O+y0pD&_qgKak&8A#mDrL zCaTF4bIAtd^<(-*<9l)b*eA&T2~7mz*}I7KIDbAE3!cz)jo*;-w}7$r3Eiggn{obW zFwQ)oXElBc&VLNXlPC14#^*KUGW;pL|4(T=ken~?D=ss@nE8~ZX?)&ST-JcG_9I&nOx2j1B~nGnRJ2T&94N{EVh(g6UF> zOmLPzqboE)h9uYz&Vgt2pe9%$39f^4;~BlF3ARXrci_B#M*BTiGe0B=CW15RIi0Kt zaFUm;f?bw?we&e%#w3mer=`NMe8*jd>{iprn4qX$(h)BQygw6y*BtmST~T(HLHb@J z{{Ra=Q(%L$?ChH*xM9i`OB=?+3ob0ARfmJ+HhAq_Z_iIb*gA+kFFp2>{#c9za4HlWU4ksWJ9L|6jKTbv`- zWw~RSF3o9@d~&_NZlD1XMvF0`ie*rXK{b4w_ZcGs0y+X23K(}Z3<6OIwRFJ;wVSM`%Poh_J@+-NL%7_J6%PF%Sj18~o z#=QJvU>tu%PjJ5SaKp}d8PN&jCX0CwqWiDt3nk{~Qi`9C%EtC%HXQ@R+oHms1IFBJ zI#1)vDSf^XtWDW;GnXiNITBr2Tu~i@tjeB(n|dd@da-|<<$sNS zuFiEV@disko92GdsNA^M*g1Ml_W&_B5Z)VPqkb-1;{nOiFyZY`ZTDx{iV!%%fW4|kVf3n!Og zu!YN_Aw;5`OjQ@{@fDu1YLa521N%{3{^2NEf~(;sx1qY!e zDqBbswf7Noz0D=Pk*F&t22md$=g+;on^bhJ=c+=c(#}Y+dm?JOd$$Sj=10le1k|Zhm%j;LNlbvcvWubI zMObg|pY-vcFd`+k_y7_6BAe=DVM7+txuX57_s%Ll$Z%kg0UA-)S?{nX^p36p;*Hi- zbZ6be^(+|Y-qG_KpFeqApMvr19evLEN|SXWIybR2i{}>qo|1(3bUYAG&kZw?KKz0O zw{-9_-qVGes3?!J6O3K&>2A(flC&eb^3oLwR@jbo8*0U(;dRA@1e`PaMIkQy@@Cp#}VW*zi*R9g>~VPe|{Fwh9+smtJvZ zxWA<8CyvZ$<;BMQ4$AW95axP6;QykvsnfWrlp_=Zx;xLCA(1G}MqZFjNz5p&jDX0YTFceaPc-R$|f_T^!q2cyLl^~uD#g!nQjwPfZ zp1Cfb!tN{YC@rVUhUzj=CVD8ubUHxpL#t@EEIgo6!_~KdrwM1}a4S^mvVcuzp1~_& zxlD}`my1QwqNJw}do!5bw!*HS!dt=kU|3;(0hM(9RCzI)26|ujYi{!PaUGQGCigPs zl_%*&sOr@#f{&N^baYm-yAs6Dhb#~VizMO@x`?%%^7B4Tgaf1~LRGKGc zmpdutRzNws(kvkd1PSm(Kj!m<@`um@{v05@8Hk2ZD;YO|Q7QCU)2N^-<#3Hod zZgh!bQy?xn=Wo3u3(=NE!7w4%+Q&t!KQJ>C?fGTDENO^!4!G=Bq0w4YH{K|@YHBH0 z$E8vn=i)tct9qT>UQqexh4MT5sEws?Gng=&sdoiXvXYmFx1T9F#q%f6pYS_R&D3(Q zq;^Gll7RZEWejK-;9Hd0?dWiUTpJ;bkB8lyNCAFQyAi$>B3&)0!;J+o_y!-opb{;e zmBu&tto(C@Y<^62@(=dyLTV$O^JcNJFBdKtbe8ZaydY>`iLi;c&b|O6)hV~m!IAxL zB%c}AIoe`-4KGQD=n859S#mZ`^cQ_0o{kAgsx$A=^33}&9U)WMG+TDt%oP-B27CLS z+jxOWEf$C3x(#LYQ`*0BFG4|>qL8ivJ}lJH*R&zU>>H42^zml@H1|t%E|%yYCtKRH zp&?*>LxXegSrz;|qXHEB`x@%4_wf^-AX6v706$`3{A=_{^l&ZV=i%XIboWX0^AuNe zF@?A}UcYfhZB!VMAdt+FLiR}127Ys;$(Q&tA0`7PpYdP`lST_<@@Qcu5XNrhp{9hz zT!V$KOcSi#S?F~Lwqvw#kcCzgtjoTKSBG}Q2a}5XB!R8F4f&nX!c!g$Dd4;uOWCdR`^qspOA8!GEN}L5xjz`sKIvd3P6z^ssg*yPYh?cYm!IjUK$GY(X**0D{ z0hCYqg>oK056P3q7&(uv|16Jb69h7Mg0L2d;4TsViAj+o^-Ylba#juGtB|JSi){iX z%A#5u26394t6HLE$X>M?s}5E2;j#{#D3Eazg+)O5%DProATlveS(mX~O-P&>6c-=- zT_*991d=#Om;;nA6F7xL>LAIjvT z_10gIGx>)m-IgqneaXTFppP|DoIK(tZ6SY}Zy~nm@;1^WCENdO(s?NYS(PGW0p)8z zJ7f)drsgr}0+#Kpe{RyHQw6eSs<0m@UnZO7OstdhWU@iYaHmvpf04lPF zz@X^@NtiCA0_8KPGLGiW;@RJ3!3?ctaT94joG$dA@o{thlVNnAn5SU5`usl_M)yL2 z(=&wUOpm-zQl&fQE$W24ndTayFDm0Jdth;M9-S$WGc$#IK>6}eM$x=^%>Vm5m_5}z zR;CGLW14Un=wr=O8AO%G(uW4o^?9?+ZBJG-wc+M2wNltAvoOV+CF}soS6F2b&0E-` zd2`L3v@*J?g-x3+ko4KY2B3U-e5}&0|9u|03_5g$i;hxw`(xy#ff-dKbjMW({nflQgcwLx_ zQfiyeknEee!pM0@9bKO%hcC?I^4>-KWS`?vNV4V$=Xd}tB^*UuDUFbhPr-RMPk62g za8|w#zG}pT3G)Rqa=tJMh|hy@5xOmpH6NS>^M!OxFwMXPTfx~jU)atB0+p}g64&t|Y{zj%T6DgZaXU1>EqeMzW1&%EoHYJ7?zNE`#90jBEG~|CF|*;a}dErSmJ= zMBDK`l6|>A7@m&Qby|6CLfMg8e6>Zs-cTnoR8K^rY>0t$y{y1kl}Zv0%hs6*N+-Jr zbvZ1P#Vpe-c#4aK*+jOEg|!gLK9a|;AbTIVB+Y3fe&PH$ZbLPUJ;F$q+J{0sNEfDO zD7B3QrK;G(e1XgP@ekJU*=%qefSuoAzkTEdNMYK7S$yI`flOK`Oa_u#4TA8+%X*fV z!3{r|3RoP~Gc?0La(&v;5u;f2i->n=p>UZ;SK6{0yN1jITNC(0Ag9zt@HsCM<^l0M zoJ4O;xDDLxi-aATupzY~q9K??y#)5|HGE(*#Q-!4+_>E*7q70_hz!r#ImIxmb9s3D!z6 zl9mW${1RaTkX+JDl3*b?iPN1ZqO@XPmh45O_hN}Kbm@Oc_SMIeU5WG#EEO)WWW^6?D}Rqf z$Z?Kd{!~DrZA=M|#g*Pm5sYp}s!YPw1T_KQVD}+oS7$*Pw?qwv~;9!sRe*8WJ zJh?)+^f%!#J(a@0LBOFag)uAtI{j5j_;dtZwNlvpH{r2;D5ZZE0dKAp9{o-DeMKxB9QshmT9rKN$h%t`?TC@KVh@ zq8JES)$9Xr|7ziYCVBx;Zzj3{-p$p*Ehb|3B%+Pf$AW?325L)ez>;JQ@jY6H+!BrV zj6U)O=4gBDD`MU*EW!S3&_C7)$v|j*a+jsj8!&mAU456a|Y zqe$!a8sP~`64&wMoG=ZOp9)?%5zsgdoayU?8BBn7t#4X_ka__8)b|4Z1%T4& z8PXvw!;1w4A0pKkFyg;MB1bha7bGCYyQosOw zm_gqjxFG@0$l=hK>#+N z^qqjc0oaJtX9AA_6bHQ^itp? zKsC^BflmUegKq5%9>4?iT;L%9Ptd!7*8^&RJ_mdZP!qJ^0-ZtE0$mcc6QDL|cVIWb zx1fC)27CuP5V#e<3v?WCIKUfp2JkdM9nfDGQ9pq1LDvGV0;mgmD)4YXJ<#Sdgt!9g zgT4j43D5v^ug?i-3Ge|u3U~;>7xW6?3_wHBdx5tC8i6icmXN2Q8-uP2x&ojH=$^ps z0r=jvek|}{Kr_%8z^MQ~(8*sw7k~-$3gCGFd?HzY2zV=?Ip~OT2m@#Vx*u>)Kugej zfYSl3K;Hzu0B8;RE$}k{zA>vW=8852z;|Eu6@kA1;8U#n`oOgS?Lhwk+#JvzbTqIT z@B?TZ@*sTx9YCi7Cjx#1y$U!T&=K@u;O&4w&^Lk41AYQc+@J&KPM}>t7XWky?Fsxf z;AhY+fa?Q-K!*Yc0=j_i3v2}hgPsVS00;rS1b7y}40;dn20$q2>%b=fVW4SwLY{zT zpFwj5T@ZjTiRnFozXJRM+8?++0N>%#_XdszSU}GOP6kARz5#q35CytQ1wzUIqCqzV z_5#F!4g_uuz}JxUR^V_zEa(xy{Qy?bGk_-o@Yx*wYT!ix_KBNAz&ilHg1!lS4$uSi zJK$%4o}i0=i7^1s3$#0MIlynAeSp6O^alMSa7#cR(A|K;0KbDC2K)yD(9?j&1Nwqq z37i4w2l@c;Hb8&S*MQFe27rD8{1`A0bdj$xRsjZq{u=mmz+lkzfNKJVfNl@$4;TtM z3OEEX4D?{&-hkntQ-H?-Mu5%)o)3rzy%%^hAOZAc;FExnpkDz$0E`0d^fks*z-Z7F zfL#D%K-U5G0E`740Ne~P4s--?5FiosaNwSRB+xb$(LO&aGeExpo)4G_x*!H!5s(JD0ok6z)tN=X=xHn)W=)=I<0johf;ej9k)`0#J*aff_bX(xY zfOViFfV%+JgYFO96R-hv2Jm#iM$lV<*8nzwJ_URTum$u3;Ol^`pmm;vyaBxpbZO9q z0oy@$0;_G1qCbM(1KJDp*MPmC<7=aS@W9#! zdM@Zmfc>Di0WSv}0Nv(WJYN6@L0f@;1{?yt@jH|ka2RwMFW3VONN(}DW~E`k>8As*;Up#K1E0bB|?01zn>7<{E%&p!Wi20Iq}n$p_;w;0EYq;NgIqpicwu0^9;!(ieRna2s@6V7x#} z?to4N?hm*N`UvnQz&+4i8xiuZAtCoc&jFnTcmVnu@KL}+(B&Fqegt>~`VZhPfXATk z0v`Z80d3b5ZL!5FdUI=&wdR#NiBLL4qF9x0ocmetd@Gihh(073^173l4@k84K zWP>&VHvqf_Jr8&g;0@>#zy|?;g0?jQgMJIT9O#mOcc8<80|D$#9S0m z7W7!)Zh$X97iopM0$mPtGUzaXD`=P2s1wj`px1-$3n&lzt2P)n02M&b1|9f^WaL~7aF9Lo6O@GGN06GG6Y0!lM7SJBR6#S z!$3a=z6Tf%x?nJ#BY+X0zXUD=hzIQpTnmr@`X}H3z(~-)0!IQyfgTM!1TY%(Jm6`7 zF`%~quLg_-eFpdlU>xYDz;^(NpdCZduK`J*%LBUr#)JMIxCUSX==Q+P0TV&T0EYo4 zfgSY8t@bbpf><#0+K?ov*jQ*&yLQVC4~g|G`^7e~wpt>Ihwgohe4MG?J*iq^8+&Y2`kD zef;|Uo`-YZ_dLJzp7(vvIX;{c{Uv{nMLPN+#|XVxU$0x?72Sus<5fM3Q}I_lna843 z&*e-k(Tn*-EY%y?SAIv9>HWMD%k>F9iofZ4;~net-*tkHMVX$?1F=F^b17Ep*grZK z(5v)Nos89bDo;YW&gWdbruXpc0bR$3@rJ&{=dnh|O|Xq&t?tb2u}=5nzF4pGcp^6F z5-!9>y`ER$O}&q|W0Q`X=yAkm-Id$pANpQS!4^G^e}@X4#p&3pU*h@rr(VNlsMLFS z8{X1wCOIz%mvy=xi?{V^e+9Nz8|~wG@gim z=>mQNdvpbtW3N8LALHM;-JcxSuul)+yYQ|q;4JLd7r6!pbX=PE8BnFyaTX5h-#p@+ z0`KVyT#0JE@KLYP@V*{7#dd=K=;W!a59ynxnSsk6=-%n>i_0JCk8~*x>)gj2-|&%M z#>J@7mAoDw>qERBNA+1gj#?d^5xMdL{1cs|TcJ+(=5F{@|AOzvXLaaPadsW_(> zaQMdAuk;Eo#d*DrH{)ylAy?tQ`YS$(Z*-FxUW?&^PUhD5pYFrA;9EVEQ*lv0%wup# z=kY9jrx$S{zSkRgHGa?scn2=)Q(TLPU((XxaktYx`iN?y<55rdm&Rgn&_|j6q@RonU;;KbVp7^j85TRXr>?FA-Gyk z;R(1#=W`C4>m^)_SY5$u5wFkAvR}uwx@)F=K3eEOoPw76_xxM5(m6aG*Xft|1+><0 za2XPG_;%N~&_~zR>TEp}?Q|8dL6UAc+i@)0IlLaMZ$q*k&!f;@XLANR z=*3)w8}ueF$B*>^-i;geIX;0-ddM8x41S_#@)Y=#F=`vHMi;#&*E(^N-k#@v;b#5) zT+2sSJ?|;=KzCivOVC3f;REQY>pyL~)<4w=Iu5;b5AKYg>HE1Kdh78#61VCnIRkz4 zD_n%W`b~Zfx9Nkt3%BdjT!%Y!%rmxeouWJHMEqQ*a4+1chw~8JrPFy5`sqT>Lw~)R zmtuh4!4(*&Yx#W)(wF!gQuVL%Jq{SA%Xv0N=-7Goi~1p*p>Ic;{(;wGh8|ns@j;H> z#m^#N|8lJo7nSg==c!(_y>oWZa&gqy1jt}8yx=5#@fe$k;awTH)s6X2t(Lx{Nmyx6g6nZY= zMm?TKqO+dO8R()*_&MCH*YhfL)BAWkdg#$FdVZs?-pU2&uk(w{4fp9PF2=8P^S?wQ zpXlMbm+l1LZyq&_2V#Vt!ecQ?=W`B5>m^)_F?tKH#W-Efdof<0;m_b#d_^@{Xg{ha z=_K6}ll86K4QYBP--AbW85dxx4sTf2>2y6#_eX}#<4ioRmvISZ>I1wJv-AnBMW!B9 zY`w_ROF0+WdMmHPY<-67Fh{q2+4B)OdNB7xuFmFZctV%+66EO`K8U%xS&4l=p44}6 z4?LwG^JA{mn8TOqG~r@y%AH*KD&EX7e2*J7;}7_19^=N>@E6>i zGc6>R8(2sj&*OMbu&`@+Ik({M7TS_GaVx&t!ms1~+?xMjB?)|%+wdGKOXOH9Ys-td z9p7T5NxYk{=h0T4%on&l=eQFcINF`KflIg}cXVfrCbE&kyf$-~R|SW8RdSfu+Z^V# zgTuUbbC}m&4)c1K!@R0E%&VHiybf`g*I^Fxs^KuNS`PF2l*7D^ahTUh4)Z$AVP0q1 z-^h9Ygn50#VP4;InAdk4=5?9Fyz049m{&s%^NQv$ucjR4)r`ZunsXAzbC_344)bcw SVP1(G=9R=@UhVnHy!ii2-1$NP literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll.mdb.meta b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll.mdb.meta new file mode 100644 index 0000000..2f90dc7 --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll.mdb.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4873f2a8bdae42baa0406e8a6136086f +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll.meta b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll.meta new file mode 100644 index 0000000..2dacfd7 --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: 4873f2a8bdae42baa0406e8a61366ca1 +timeCreated: 1488828285 +licenseType: Store +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + Any: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 0 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude N3DS: 1 + Exclude OSXIntel: 1 + Exclude OSXIntel64: 1 + Exclude OSXUniversal: 1 + Exclude PS4: 1 + Exclude PSM: 1 + Exclude PSP2: 1 + Exclude SamsungTV: 1 + Exclude Tizen: 1 + Exclude WebGL: 1 + Exclude WiiU: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude WindowsStoreApps: 1 + Exclude XboxOne: 1 + Exclude iOS: 1 + Exclude tvOS: 1 + Editor: + enabled: 1 + settings: + DefaultValueInitialized: true + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.xml b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.xml new file mode 100644 index 0000000..b665fac --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.xml @@ -0,0 +1,3658 @@ + + + + Sirenix.Utilities + + + + + Extension methods for the UnityEngine.Color type. + + + + + Lerps between multiple colors. + + The colors. + The t. + + + + + Moves the towards implementation for Color. + + From color. + To color. + The maximum delta. + + + + Tries to parse a string to a Color. The following formats are supported: + "new Color(0.4, 0, 0, 1)", "#FFEEBBFF", "#FFEECC", "FFEEBBFF", "FFEECC" + + The color string. + The color. + Returns true if the parse was a success. + + + + Converts a color to a string formatted to c# + + The color. + new Color(r, g, b, a) + + + + Pows the color with the specified factor. + + The color. + The factor. + + + + Normalizes the RGB values of the color ignoring the alpha value. + + The color. + + + + Delegate method extensions. + + + + + Memoizes the specified func - returns the memoized version + + + + + Memoizes the specified func - returns the memoized version + + + + + FieldInfo method extensions. + + + + + Determines whether the specified field is an alias. + + The field to check. + + true if the specified field is an alias; otherwise, false. + + + + + Returns the original, backing field of an alias field if the field is an alias. + + The field to check. + /// if set to true an exception will be thrown if the field is not aliased. + + The field was not aliased; this only occurs if throwOnNotAliased is true. + + + + Garbage free enumerator methods. + + + + + Garbage free enumerator for lists. + + + + + Garbage free enumerator for dictionaries. + + + + + Garbage free enumator for dictionary values. + + + + + Garbage free enumerator for hashsets. + + + + + List iterator. + + + + + Creates a list iterator. + + + + + Gets the enumerator. + + + + + Gets the current value. + + + + + Moves to the next value. + + + + + Disposes the iterator. + + + + + Hashset iterator. + + + + + Creates a hashset iterator. + + + + + Gets the enumerator. + + + + + Gets the current value. + + + + + Moves to the next value. + + + + + Disposes the iterator. + + + + + Dictionary iterator. + + + + + Creates a dictionary iterator. + + + + + Gets the enumerator. + + + + + Gets the current value. + + + + + Moves to the next value. + + + + + Disposes the iterator. + + + + + Dictionary value iterator. + + + + + Creates a dictionary value iterator. + + + + + Gets the enumerator. + + + + + Gets the current value. + + + + + Moves to the next value. + + + + + Disposes the iterator. + + + + + Various LinQ extensions. + + + + + Calls an action on each item before yielding them. + + The collection. + The action to call for each item. + + + + Perform an action on each item. + + The source. + The action to perform. + + + + Perform an action on each item. + + The source. + The action to perform. + + + + Convert each item in the collection. + + The collection. + Func to convert the items. + + + + Convert a colletion to a HashSet. + + + + + Convert a colletion to a HashSet. + + + + + Convert a collection to an immutable list. + + The collection. + + + + Add an item to the beginning of a collection. + + The collection. + Func to create the item to prepend. + + + + Add an item to the beginning of a collection. + + The collection. + The item to prepend. + + + + Add a collection to the beginning of another collection. + + The collection. + The collection to prepend. + + + + Add an item to the beginning of another collection, if a condition is met. + + The collection. + The condition. + Func to create the item to prepend. + + + + Add an item to the beginning of another collection, if a condition is met. + + The collection. + The condition. + The item to prepend. + + + + Add a collection to the beginning of another collection, if a condition is met. + + The collection. + The condition. + The collection to prepend. + + + + Add an item to the beginning of another collection, if a condition is met. + + The collection. + The condition. + Func to create the item to prepend. + + + + Add an item to the beginning of another collection, if a condition is met. + + The collection. + The condition. + The item to prepend. + + + + Add a collection to the beginning of another collection, if a condition is met. + + The collection. + The condition. + The collection to prepend. + + + + Add an item to the beginning of another collection, if a condition is met. + + The collection. + The condition. + Func to create the item to prepend. + + + + Add an item to the beginning of another collection, if a condition is met. + + The collection. + The condition. + The item to prepend. + + + + Add a collection to the beginning of another collection, if a condition is met. + + The collection. + The condition. + The collection to prepend. + + + + Add an item to the end of a collection. + + The collection. + Func to create the item to append. + + + + Add an item to the end of a collection. + + The collection. + The item to append. + + + + Add a collection to the end of another collection. + + The collection. + The collection to append. + + + + Add an item to the end of a collection if a condition is met. + + The collection. + The condition. + Func to create the item to append. + + + + Add an item to the end of a collection if a condition is met. + + The collection. + The condition. + The item to append. + + + + Add a collection to the end of another collection if a condition is met. + + The collection. + The condition. + The collection to append. + + + + Add an item to the end of a collection if a condition is met. + + The collection. + The condition. + Func to create the item to append. + + + + Add an item to the end of a collection if a condition is met. + + The collection. + The condition. + The item to append. + + + + Add a collection to the end of another collection if a condition is met. + + The collection. + The condition. + The collection to append. + + + + Returns and casts only the items of type . + + The collection. + + + + Adds a collection to a hashset. + + The hashset. + The collection. + + + + Returns true if the list is either null or empty. Otherwise false. + + The list. + + + + Sets all items in the list to the given value. + + The list. + The value. + + + + Adds the elements of the specified collection to the end of the IList<T>. + + + + + Sorts an IList + + + + + Sorts an IList + + + + + MemberInfo method extensions. + + + + + Returns true if the attribute whose type is specified by the generic argument is defined on this member + + + + + Returns true if the attribute whose type is specified by the generic argument is defined on this member + + + + + Returns the first found custom attribute of type T on this member + Returns null if none was found + + + + + Returns the first found non-inherited custom attribute of type T on this member + Returns null if none was found + + + + + Gets all attributes of the specified generic type. + + The member. + + + + Gets all attributes of the specified generic type. + + The member. + If true, specifies to also search the ancestors of element for custom attributes. + + + + Gets all attribute instances defined on a MemeberInfo. + + The member. + + + + Gets all attribute instances on a MemberInfo. + + The member. + If true, specifies to also search the ancestors of element for custom attributes. + + + + If this member is a method, returns the full method name (name + params) otherwise the member name paskal splitted + + + + + Determines whether a FieldInfo, PropertyInfo or MethodInfo is static. + + The member. + + true if the specified member is static; otherwise, false. + + + + + + Determines whether the specified member is an alias. + + The member to check. + + true if the specified member is an alias; otherwise, false. + + + + + Returns the original, backing member of an alias member if the member is an alias. + + The member to check. + /// if set to true an exception will be thrown if the member is not aliased. + + The member was not aliased; this only occurs if throwOnNotAliased is true. + + + + Various extensions for MethodInfo. + + + + + Returns the specified method's full name "methodName(argType1 arg1, argType2 arg2, etc)" + Uses the specified gauntlet to replaces type names, ex: "int" instead of "Int32" + + + + + Returns a string representing the passed method parameters names. Ex "int num, float damage, Transform target" + + + + + Returns the specified method's full name. + + + + + Tests if a method is an extension method. + + + + + Determines whether the specified method is an alias. + + The method to check. + + true if the specified method is an alias; otherwise, false. + + + + + Returns the original, backing method of an alias method if the method is an alias. + + The method to check. + /// if set to true an exception will be thrown if the method is not aliased. + + The method was not aliased; this only occurs if throwOnNotAliased is true. + + + + Determines the type of operator. + + + + + + The == operator. + + + + + The != operator. + + + + + The + operator. + + + + + The - operator. + + + + + The * operator. + + + + + The / operator. + + + + + The < operator. + + + + + The > operator. + + + + + The <= operator. + + + + + The >= operator. + + + + + The % operator. + + + + + The >> operator. + + + + + The << operator. + + + + + The & operator. + + + + + The | operator. + + + + + The ^ operator. + + + + + The ~ operator. + + + + + The && operator. + + + + + The || operator. + + + + + The ! operator. + + + + + DirectoryInfo method extensions. + + + + + Gets the name of the directory. Always returns forward slash seperators as opposed to Path.GetDirectoryName(). + + + + + Determines whether the directory has a given directory in its hierarchy of children. + + The parent directory. + The sub directory. + + + + Finds a parent directory with a given name, or null if no such parent directory exists. + + + + + Returns a value indicating whether or not a path can be made relative to another. + + The parent path. + The path to make relative to the parent path. + A value indicating if the path can be made relative to the parent path. + + + + Returns a path string to path that is relative to the parent path. + + The parent path. + The path to make relative to the parent path. + A relative path from parent path to path. + + + + Tries to make a path that is relative from parent path to path. + + The parent path. + The path to make relative to the parent path. + A relative path from parent path to path. null if no relative path could be made. + A value indicating if the method succeeded in making a relative path. + + + + Combines two paths, and replaces all backslases with forward slash. + + + + + PropertyInfo method extensions. + + + + + Determines whether a property is an auto property. + + + + + Determines whether the specified property is an alias. + + The property to check. + + true if the specified property is an alias; otherwise, false. + + + + + Returns the original, backing property of an alias property if the property is an alias. + + The property to check. + /// if set to true an exception will be thrown if the property is not aliased. + + The property was not aliased; this only occurs if throwOnNotAliased is true. + + + + Defines a collection of handy Rect transformation methods, that can chained together for complex behaviour. + Note that no method defined here changes the original Rect, but instead returns a new transformed Rect. + + + + + Returns a Rect with the specified width. + + The original Rect. + The desired width of the new Rect. + + + + Returns a Rect with the specified height. + + The original Rect. + The desired height of the new Rect. + + + + Returns a Rect with the specified size. + + The original Rect. + The desired width of the new Rect. + The desired height of the new Rect. + + + + Returns a Rect with the specified size. + + The original Rect. + The desired size of the new Rect. + + + + Returns a Rect that has been inserted by the specified amount on the X-axis. + + The original Rect. + The desired padding. + + + + Returns a Rect that has been inserted by the specified amount on the X-axis. + + The original Rect. + Desired padding on the left side. + Desired padding on the right side. + + + + Returns a Rect that has been inserted by the specified amount on the Y-axis. + + The original Rect. + The desired padding. + + + + Returns a Rect that has been inserted by the specified amount on the Y-axis. + + The original Rect. + The desired padding on the top. + The desired padding on the bottom. + + + + Returns a Rect that has been inserted by the specified amount. + + The original Rect. + The desired padding. + + + + Returns a Rect that has been inserted by the specified amount. + + The original Rect. + The desired horizontal padding. + The desired vertical padding. + + + + Returns a Rect that has been inserted by the specified amount. + + The original Rect. + The desired padding on the left. + The desired padding on the right. + The desired padding on the top. + The desired padding on the bottom. + + + + Returns a Rect, with the specified width, that has been aligned to the left of the original Rect. + + The original Rect. + The desired width of the new Rect. + + + + Returns a Rect, with the specified width, that has been aligned to horizontal center of the original Rect. + + The original Rect. + The desired width of the new Rect. + + + + Returns a Rect, with the specified width and height in the center of the provided rect. + + The original Rect. + The desired width of the new Rect. + The desired height of the new Rect. + + + + Returns a Rect, with the specified width, that has been aligned to the right of the original Rect. + + The original Rect. + The desired width of the new Rect. + + + + Returns a Rect, with the specified width, that has been aligned to the right of the original Rect. + + + + + Returns a Rect, with the specified height, that has been aligned to the top of the original Rect. + + The original Rect. + The desired height of the new Rect. + + + + Returns a Rect, with the specified height, that has been aligned to the vertical middle of the original Rect. + + The original Rect. + The desired height of the new Rect. + + + + Returns a Rect, with the specified height, that has been aligned to the bottom of the original Rect. + + The original Rect. + The desired height of the new Rect. + + + + Returns a Rect, with the specified width, that has been aligned horizontally to the center of the original rect. + + The original Rect. + The desired width of the new Rect. + + + + Returns a Rect, with the specified height, that has been aligned vertically to the center of the original rect. + + The original Rect. + The desired height of the new Rect. + + + + Returns a Rect, with the specified width and height, that has been aligned horizontally and vertically to the center of the original rect. + + The original Rect. + The desired width and height of the new Rect. + + + + Returns a Rect, with the specified width and height, that has been aligned horizontally and vertically to the center of the original rect. + + The original Rect. + The desired width of the new Rect. + The desired height of the new Rect. + + + + Returns a Rect that has been expanded by the specified amount. + + The original Rect. + The desired expansion. + + + + Returns a Rect that has been expanded by the specified amount. + + The original Rect. + The desired expansion on the X-axis. + The desired expansion on the Y-axis. + + + + Returns a Rect that has been expanded by the specified amount. + + The original Rect. + The desired expansion on the left. + The desired expansion on the right. + The desired expansion on the top. + The desired expansion on the bottom. + + + + Splits a Rect horizontally into the specified number of sub-rects, and returns a sub-rect for the specified index. + + The original Rect. + The index for the subrect. Includes 0, and excludes count. + The amount of subrects the Rect should be split into. + + + + Splits a Rect vertically into the specified number of sub-rects, and returns a sub-rect for the specified index. + + The original Rect. + The index for the subrect. Includes 0, and excludes count. + The amount of subrects the Rect should be split into. + + + + Splits a Rect into a grid from left to right and then down. + + The original rect. + The width of a grid cell. + The height of a grid cell. + The index of the grid cell. + + + + + Splits a Rect into a grid from left to right and then down. + + + + + Moves a Rect to the specified center X position. + + The original Rect. + The desired center x position. + + + + Moves a Rect to the specified center Y position. + + The desired original Rect. + The desired desired center y position. + + + + Moves a Rect to the specified center position. + + The original Rect. + The desired center X position. + The desired center Y position. + + + + Moves a Rect to the specified center position. + + The original Rect. + The desired center position. + + + + Moves a Rect to the specified position. + + The orignal Rect. + The desired position. + + + + Resets a Rect's position to zero. + + The original Rect. + + + + Moves a Rect's position by the specified amount. + + The original Rect. + The change in position. + + + + Moves a Rect's position by the specified amount. + + The original Rect. + The x. + The y. + + + + Sets a Rect's X position. + + The original Rect. + The desired X position. + + + + Adds to a Rect's X position. + + The original Rect. + The value to add. + + + + Subtracts from a Rect's X position. + + The original Rect. + The value to subtract. + + + + Sets a Rect's Y position. + + The original Rect. + The desired Y position. + + + + Adds to a Rect's Y position. + + The original Rect. + The value to add. + + + + Subtracts a Rect's Y position. + + The original Rect. + The value to subtract. + + + + Sets the min position of a Rect. + + The original Rect. + The desired min position. + + + + Adds to a Rect's min position. + + The original rect. + The value to add. + + + + Subtracts a Rect's min position. + + The original Rect. + The vlaue to subtract. + + + + Sets a Rect's max position. + + The original Rect. + The desired max position. + + + + Adds to a Rect's max position. + + The original Rect. + The value to add. + + + + Subtracts a Rect's max position. + + The original Rect. + The value to add. + + + + Sets a Rect's X min position. + + The original Rect. + The desired min X position. + + + + Adds to a Rect's X min position. + + The original Rect. + The value to add. + + + + Subtracts from a Rect's X min position. + + The original Rect. + The value to subtract. + + + + Sets a Rect's X max position. + + The original Rect. + The desired X max position. + + + + Adds to a Rect's X max position. + + The original Rect. + The value to add. + + + + Subtracts a Rect's X max position. + + The original Rect. + The value to subtract. + + + + Sets a Rect's Y min position. + + The original Rect. + The desired Y min. + + + + Adds to a Rect's Y min position. + + The original Rect. + The value to add. + + + + Subtracts a Rect's Y min position. + + The original Rect. + The value to subtract. + + + + + Sets a Rect's Y max position. + + The original Rect. + The desired Y max position. + + + + Adds to a Rect's Y max position. + + The original Rect. + The value to add. + + + + Subtracts from a Rect's Y max position. + + The original Rect. + The value to subtract. + + + + Sets a Rect's width, if it is less than the specified value. + + The original Rect. + The desired min width. + + + + Sets a Rect's width, if it is greater than the specified value. + + The original Rect. + The desired max width. + + + + Sets a Rect's height, if it is less than the specified value. + + The original Rect. + The desired min height. + + + + Sets a Rect's height, if it is greater than the specified value. + + The original Rect. + The desired max height. + + + + Expands a rect to contain a given position. + + The original Rect. + The position to expand the rect towards. + + + + String method extensions. + + + + + Eg MY_INT_VALUE => MyIntValue + + + + + Returns whether or not the specified string is contained with this string + + + + + Ex: "thisIsCamelCase" -> "This Is Camel Case" + + + + + Returns true if this string is null, empty, or contains only whitespace. + + The string to check. + true if this string is null, empty, or contains only whitespace; otherwise, false. + + + + Type method extensions. + + + + + Type name alias lookup. + TypeNameAlternatives["Single"] will give you "float", "UInt16" will give you "ushort", "Boolean[]" will give you "bool[]" etc.. + + + + + Checks whether a given string is a valid CSharp identifier name. This also checks full type names including namespaces. + + The identifier to check. + + + + Determines whether a type can be casted to another type. + + From. + To. + if set to true an implicit or explicit operator must be defined on the given type. + + + + If a type can be casted to another type, this provides a function to manually convert the type. + + From. + To. + if set to true an implicit or explicit operator must be defined on the given type. + + + + If a type can be casted to another type, this provides a function to manually convert the type. + + if set to true an implicit or explicit operator must be defined on the given type. + + + + If a type can be casted to another type, this provides the method info of the method in charge of converting the type. + + From. + To. + if set to true an implicit or explicit operator must be defined on the given type. + + + + Gets an equality comparer delegate used to compare the equality of values of a given type. In order, this will be: + + 1. The == operator, if one is defined on the type. + 2. A delegate that uses , if the type implements that interface. + 3. .NET's own + + + Note that in the special case of the type , a special equality comparer is returned that only checks whether all the Quaternion components are equal. + This is because, by default, Quaternion's equality operator is broken when operating on invalid quaternions; "default(Quaternion) == default(Quaternion)" evaluates to false, and this causes a multitude of problems. + Special delegates are also returned for float and double, that consider float.NaN to be equal to float.NaN, and double.NaN to be equal to double.NaN. + + + + + Gets the first attribute of type T. Returns null in the no attribute of type T was found. + + The type. + If true, specifies to also search the ancestors of element for custom attributes. + + + + Determines whether a type implements or inherits from another type. + + The type. + To. + + + + Determines whether a type implements an open generic interface or class such as IList<> or List<>. + + Type of the candidate. + Type of the open generic type. + + + + + Determines whether a type implements an open generic interface such as IList<>. + + Type of the candidate. + Type of the open generic interface. + + Type " + openGenericInterfaceType.Name + " is not a generic type definition and an interface. + + + + Determines whether a type implements an open generic class such as List<>. + + Type of the candidate. + Type of the open generic interface. + + + + Gets the generic arguments of an inherited open generic class or interface. + + Type of the candidate. + The open generic type to get the arguments of. + + + + Gets the generic arguments of an inherited open generic class. + + Type of the candidate. + Type of the open generic class. + + + + Gets the generic arguments of an inherited open generic interface. + + Type of the candidate. + Type of the open generic interface. + + + + Gets the MethodInfo of a specific operator kind, with the given left and right operands. This overload is *far* faster than any of the other GetOperatorMethod implementations, and should be used whenever possible. + + + + + Gets the MethodInfo of a specific operator type. + + + + + Gets the MethodInfo of a specific operator type. + + + + + Gets all members from a given type, including members from all base types if the flag isn't set. + + + + + Gets all members from a given type, including members from all base types. + + + + + Gets all members of a specific type from a type, including members from all base types, if the flag isn't set. + + + + + Gets the generic type definition of an open generic base type. + + + + + Gets the generic type definition of an open generic base type. + + + + + Returns a lazy enumerable of all the base types of this type including interfaces and classes + + + + + Returns a lazy enumerable of all the base classes of this type + + + + + Used to filter out unwanted type names. Ex "int" instead of "Int32" + + + + + Returns a nicely formatted name of a type. + + + + + Returns a nicely formatted full name of a type. + + + + + Gets the name of the compilable nice. + + The type. + + + + Gets the full name of the compilable nice. + + The type. + + + + Returns the first found custom attribute of type T on this type + Returns null if none was found + + + + + Returns the first found non-inherited custom attribute of type T on this type + Returns null if none was found + + + + + Gets all attributes of type T. + + The type. + + + + Gets all attributes of type T. + + The type + If true, specifies to also search the ancestors of element for custom attributes. + + + + Returns true if the attribute whose type is specified by the generic argument is defined on this type + + + + + Returns true if the attribute whose type is specified by the generic argument is defined on this type + + + + + Determines whether a type inherits or implements another type. Also include support for open generic base types such as List<>. + + + + + + Determines whether a type inherits or implements another type. Also include support for open generic base types such as List<>. + + + + + + + Gets the number of base types between given type and baseType. + + + + + Determines whether a method has the specified parameter types. + + + + + FieldInfo will return the fieldType, propertyInfo the PropertyType, MethodInfo the return type and EventInfo will return the EventHandlerType. + + The MemberInfo. + + + + Gets the value contained in a given . Currently only and is supported. + + The to get the value of. + The instance to get the value from. + The value contained in the given . + Can't get the value of the given type. + + + + Sets the value of a given MemberInfo. Currently only and is supported. + + The to set the value of. + The object to set the value on. + The value to set. + + Property has no setter + or + Can't set the value of the given type. + + + + // + Tries to infer a set of valid generic parameters for a generic type definition, given a subset of known parameters. + + The generic type definition to attempt to infer parameters for. + The inferred parameters, if inferral was successful. + The known parameters to infer from. + True if the parameters could be inferred, otherwise, false. + + genericTypeDefinition is null + or + knownParameters is null + + The genericTypeDefinition parameter must be a generic type definition. + + + + Checks whether an array of types satisfy the constraints of a given generic type definition. + If this method returns true, the given parameters can be safely used with with the given generic type definition. + + The generic type definition to check. + The parameters to check validity for. + + genericType is null + or + types is null + + The genericType parameter must be a generic type definition. + + + + Checks whether an array of types satisfy the constraints of a given generic method definition. + If this method returns true, the given parameters can be safely used with with the given generic method definition. + + The generic method definition to check. + The parameters to check validity for. + + genericType is null + or + types is null + + The genericMethod parameter must be a generic method definition. + + + + Before calling this method we must ALWAYS hold a lock on the GenericConstraintsSatisfaction_LOCK object, as that is an implicit assumption it works with. + + + + + Not yet documented. + + + + + Formats a string with the specified generic parameter constraints on any given type. Example output: where T : class + + + + + Determines whether a generic type contains the specified generic argument constraints. + + The type. + The generic argument types. + + + + Determines whether a type is a fully constructed generic type. + + + + + Determines whether a type is nullable by ensuring the type is neither a PrimitiveType, ValueType or an Enum. + + + + + Gets the enum bitmask in a ulong. + + enumType + + + + Gets a value indicating if the string is a reserved C# keyword. + + The identifier to check. + true if the string is a C# keyword. Otherwise false. + + + + Extends various Unity classes. + + + + + Determines whether a Unity object is null or "fake null", + without ever calling Unity's own equality operators. + This method is useful for checking if a Unity object is + null, destroyed or missing at times when it is not allowed + to call Unity's own equality operators, for example when + not running on the main thread. + + The Unity object to check. + True if the object is null, missing or destroyed; otherwise false. + + + + Contains utilities for operating on arrays. + + + + + Creates a new array with an added element. + + The element type of the array. + The array. + The value to add. + The new array. + The given array was null. + + + + Creates a new array with an element inserted at a given index. + + The element type of the array. + The array. + The index to insert at. + The value to insert. + The given array was null. + The index to insert at was out of range. + + + + Creates a new array with an element removed. + + The element type of the array. + The array. + The index to remove an element at. + + The given array was null. + The given index to remove an element at was out of range. + + + + Utility class for asset Guid script + + + + + Tries to update the Guid of a specified asset with the Guid from a specified script type. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Provides utilities for using the namespace. + + This class is due for refactoring. Use at your own peril. + + + + + Gets a value indicating whether emitting is supported on the current platform. + + + true if the current platform can emit; otherwise, false. + + + + + Creates a delegate which gets the value of a field. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The type of the field to get a value from. + The instance describing the field to create a getter for. + A delegate which gets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which gets the value of a field. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The instance describing the field to create a getter for. + A delegate which gets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which sets the value of a field. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + The type of the field to set a value to. + The instance describing the field to create a setter for. + A delegate which sets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which sets the value of a field. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + The instance describing the field to create a setter for. + A delegate which sets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which gets the value of a field. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The type of the instance to get a value from. + The type of the field to get a value from. + The instance describing the field to create a getter for. + A delegate which gets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which gets the value of a field from a weakly typed instance of a given type. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The type of the field to get a value from. + The of the instance to get a value from. + The instance describing the field to create a getter for. + A delegate which gets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which gets the weakly typed value of a field from a weakly typed instance of a given type. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The of the instance to get a value from. + The instance describing the field to create a getter for. + A delegate which gets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which sets the value of a field. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + The type of the instance to set a value on. + The type of the field to set a value to. + The instance describing the field to create a setter for. + A delegate which sets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which sets the value of a field on a weakly typed instance of a given type. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + The type of the field to set a value to. + Type of the instance. + The instance describing the field to create a setter for. + + A delegate which sets the value of the given field. + + The fieldInfo parameter is null. + Field cannot be static. + + + + Creates a delegate which sets the weakly typed value of a field on a weakly typed instance of a given type. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + Type of the instance. + The instance describing the field to create a setter for. + + A delegate which sets the value of the given field. + + The fieldInfo parameter is null. + Field cannot be static. + + + + Creates a delegate which gets the weakly typed value of a field from a weakly typed instance of a given type. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The of the instance to get a value from. + The instance describing the field to create a getter for. + A delegate which gets the value of the given field. + The fieldInfo parameter is null. + + + + Creates a delegate which sets the weakly typed value of a property on a weakly typed instance of a given type. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + Type of the instance. + The instance describing the property to create a setter for. + + A delegate which sets the value of the given field. + + The fieldInfo parameter is null. + Property cannot be static. + + + + Creates a delegate which sets the value of a property. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + The type of the property to set a value to. + The instance describing the property to create a setter for. + A delegate which sets the value of the given property. + The propertyInfo parameter is null. + + + + Creates a delegate which gets the value of a property. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The type of the property to get a value from. + The instance describing the property to create a getter for. + A delegate which gets the value of the given property. + The propertyInfo parameter is null. + + + + Creates a delegate which sets the value of a property. If emitting is not supported on the current platform, the delegate will use reflection to set the value. + + The type of the instance to set a value on. + The type of the property to set a value to. + The instance describing the property to create a setter for. + A delegate which sets the value of the given property. + The propertyInfo parameter is null. + + + + Creates a delegate which gets the value of a property. If emitting is not supported on the current platform, the delegate will use reflection to get the value. + + The type of the instance to get a value from. + The type of the property to get a value from. + The instance describing the property to create a getter for. + A delegate which gets the value of the given property. + The propertyInfo parameter is null. + + + + Creates a fast delegate method which calls a given parameterless instance method and returns the result. + + The type of the class which the method is on. + The type which is returned by the given method info. + The method info instance which is used. + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + + + Creates a fast delegate method which calls a given parameterless static method. + + The method info instance which is used. + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + + + Creates a fast delegate method which calls a given parameterless weakly typed instance method. + + The method info instance which is used. + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + + + Not yet documented. + + + + + Creates a fast delegate method which calls a given weakly typed instance method with one argument and returns a value. + + The type of the result. + The type of the first argument. + The method info instance which is used. + + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + methodInfo + + Given method ' + methodInfo.Name + ' is static when it has to be an instance method. + or + Given method ' + methodInfo.Name + ' must return type + typeof(TResult) + . + or + Given method ' + methodInfo.Name + ' must have exactly one parameter. + or + The first parameter of the method ' + methodInfo.Name + ' must be of type + typeof(TArg1) + . + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Creates a fast delegate method which calls a given parameterless instance method. + + The type of the class which the method is on. + The method info instance which is used. + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + + + Creates a fast delegate method which calls a given instance method with a given argument. + + The type of the class which the method is on. + The type of the argument with which to call the method. + The method info instance which is used. + A delegate which calls the method and returns the result, except it's hundreds of times faster than MethodInfo.Invoke. + + + + This class encapsulates common combinations. + + + + + Search criteria encompassing all public and non-public members, including base members. + Note that you also need to specify either the Instance or Static flag. + + + + + Search criteria encompassing all public instance members, including base members. + + + + + Search criteria encompassing all non-public instance members, including base members. + + + + + Search criteria encompassing all public and non-public instance members, including base members. + + + + + Search criteria encompassing all public static members, including base members. + + + + + Search criteria encompassing all non-public static members, including base members. + + + + + Search criteria encompassing all public and non-public static members, including base members. + + + + + Search criteria encompassing all public instance members, excluding base members. + + + + + Search criteria encompassing all non-public instance members, excluding base members. + + + + + Search criteria encompassing all public and non-public instance members, excluding base members. + + + + + Search criteria encompassing all public static members, excluding base members. + + + + + Search criteria encompassing all non-public static members, excluding base members. + + + + + Search criteria encompassing all public and non-public static members, excluding base members. + + + + + Search criteria encompassing all members, including base and static members. + + + + + Search criteria encompassing all members (public and non-public, instance and static), including base members. + + + + + + A GlobalConfig singleton, automatically created and saved as a ScriptableObject in the project at the specified path. + This only happens if the UnityEditor is present. If it's not, a non-persistent ScriptableObject is created at run-time. + + + Remember to locate the path within a resources folder if you want the config file to be loaded at runtime without the Unity editor being present. + + + The asset path is specified by defining a . If no attribute is defined it will be saved in the root assets folder. + + + + + [GlobalConfig("Assets/Resources/MyConfigFiles/")] + public class MyGlobalConfig : GlobalConfig<MyGlobalConfig> + { + public int MyGlobalVariable; + } + + void SomeMethod() + { + int value = MyGlobalConfig.Instance.MyGlobalVariable; + } + + + + + + Gets a value indicating whether this instance has instance loaded. + + + + + Gets the singleton instance. + + + + + Tries to load the singleton instance. + + + + + Opens the config in a editor window. This is currently only used internally by the Sirenix.OdinInspector.Editor assembly. + + + + + This attribute is used by classes deriving from GlobalConfig and specifies the asset path for the generated config file. + + + + + + + Gets the full asset path including Application.dataPath. Only relevant if IsInResourcesFolder is false. + + + + + Gets the relative asset path. Only relevant if IsInResourcesFolder is false. + + + + + Gets the resources path. Only relevant if IsInResourcesFolder is true. + + + + + Whether the config should be associated with an asset in the project. If false, no config asset will be generated or loaded, and a new "temporary" config instance will be created for every reload. This is true by default. + + + + + Gets a value indicating whether this asset is located within a resource folder. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The relative asset. Remember to locate the path within a resources folder if you want the config file to be loaded at runtime without the Unity Editor. + + + + + GUILayoutOptions is a handy utility that provides cached GUILayoutOpion arrays based on the wanted parameters. + + + + + Most GUILayout and EditorGUILayout methods takes an optional "params GUILayoutOption[]" parameter. + Each time you call this, an array is allocated generating garbage. + + + // Generates garbage: + GUILayout.Label(label, GUILayout.Label(label, GUILayout.Width(20), GUILayout.ExpandHeight(), GUILayout.MaxWidth(300))); + + // Does not generate garbage: + GUILayout.Label(label, GUILayout.Label(label, GUILayoutOptions.Width(20).ExpandHeight().MaxWidth(300))); + + + + + + An EmptyGUIOption[] array with a length of 0. + + + + + A GUILayoutOptions instance with an implicit operator to be converted to a GUILayoutOption[] array. + + + + + + Gets or creates the cached GUILayoutOption array based on the layout options specified. + + + + + Option passed to a control to give it an absolute width. + + + + + Option passed to a control to give it an absolute height. + + + + + Option passed to a control to specify a maximum height. + + + + + Option passed to a control to specify a maximum width. + + + + + Option passed to a control to specify a minimum height. + + + + + Option passed to a control to specify a minimum width. + + + + + Option passed to a control to allow or disallow vertical expansion. + + + + + Option passed to a control to allow or disallow horizontal expansion. + + + + + Determines whether the instance is equals another instance. + + + + + Returns a hash code for this instance. + + + + + Option passed to a control to give it an absolute width. + + + + + Option passed to a control to give it an absolute height. + + + + + Option passed to a control to specify a maximum height. + + + + + Option passed to a control to specify a maximum width. + + + + + Option passed to a control to specify a minimum width. + + + + + Option passed to a control to specify a minimum height. + + + + + Option passed to a control to allow or disallow vertical expansion. + + + + + Option passed to a control to allow or disallow horizontal expansion. + + + + + Immutable hashset wraps another hashset, and allows for reading the inner hashset, without the ability to change it. + + + + + Creates an immutable hashset around another hashset. + + + + + Returns true if the item is contained in the list. + + The item's value. + + + + Gets the enumerator. + + + + + Gets the enumerator. + + + + + Interface for immutable list. + + + + + Interface for generic immutable list. + + + + + Index accessor. + + + + + Immutable list wraps another list, and allows for reading the inner list, without the ability to change it. + + + + + Creates an immutable list around another list. + + + + + Number of items in the list. + + + + + Immutable list cannot be changed directly, so it's size is always fixed. + + + + + Immutable list are always readonly. + + + + + Returns true if the inner list is synchronized. + + + + + Gets the sync root object. + + + + + Index accessor. + + Index. + + + + Returns true if the item is contained in the list. + + The item's value. + + + + Copy the list to an array, + + Target array. + Index. + + + + Copy the list to an array, + + Target array. + Index. + + + + Gets an enumerator. + + + + + Get the index of a value. + + The item's value. + + + + Immutable list cannot be edited. + + Index. + + + + Immutable list cannot be edited. + + Index. + Item. + + + + Immutable list cannot be edited. + + Item. + + + + Immutable list cannot be edited. + + + + + Immutable list cannot be edited. + + Item. + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Immutable list wraps another list, and allows for reading the inner list, without the ability to change it. + + + + + Creates an immutable list around another list. + + + + + Number of items in the list. + + + + + Immutable list are always readonly. + + + + + Index accessor. + + Index. + + + + Returns true if the item is contained in the list. + + + + + Copies the list to an array. + + + + + Gets an enumerator. + + + + + Gets the index of an item. + + + + + Various list extension methods. + + + + + Increases or decrease the number of items in the list to the specified count. + + The list. + The new length. + + + + Increases or decrease the number of items in the list to the specified count. + + The list. + The new length. + Value of new elements. + + + + Increases or decrease the number of items in the list to the specified count. + + The list. + The new length. + + + + Increases or decrease the number of items in the list to the specified count. + + The list. + The new length. + Value of new elements. + + + + Collection of math function. + + + + + Distance from a point to a line. + + + + + Returns a smooth value between start and end based on t. + + First point. + Second point. + Position between 0 and 1. + + + + Returns a smooth value between start and end based on t. + + First point. + Second point. + Position between 0 and 1. + Number of interpolations to make. + + + + Returns the fractional of the value. + + The value to get the fractional of. + + + + Returns the fractional of the value. + + The value to get the fractional of. + + + + Returns the fractional of the value. + + The value to get the fractional of. + + + + Returns a value based on t, that bounces faster and faster. + + The value to bounce. + + + + Returns a smooth value between 0 and 1 based on t. + + Position between 0 and 1. + + + + Returns a smooth value between 0 and 1 based on t. + + Position between 0 and 1. + Number of interpolations to make. + + + + Returns an unclamped linear interpolation of two vectors. + + The first vector. + The second vector. + The interpolation factor. + + + + Returns an unclamped linear interpolation of two vectors. + + The first vector. + The second vector. + The interpolation factor. + + + + Returns a value that bounces between 0 and 1 based on value. + + The value to bounce. + + + + Returns a value that eases in elasticly. + + The value to ease in elasticly. + The amplitude. + The length. + + + + Pows each element of the vector. + + The vector. + The power. + + + + Returns a Vector2 with each element set to their respective sign. + + The vector to sign. + + + + Returns a Vector3 with each element set to their respective sign. + + The vector to sign. + + + + Returns a value that eases out elasticly. + + The value to ease out elasticly. + The amplitude. + The length. + + + + Returns a smooth value betweeen that peaks at t=0.5 and then comes back down again. + + A value between 0 and 1. + + + + Clamps the value of a Vector3. + + The vector to clamp. + The min value. + The max value. + + + + Clamps the value of a Vector2. + + The vector to clamp. + The min value. + The max value. + + + + Computes a hash for a byte array. + + The byte array. + + + + Gives a smooth path between a collection of points. + + The collection of point. + The current position in the path. 0 is at the start of the path, 1 is at the end of the path. + + + + Checks if two given lines intersect with one another and returns the intersection point (if + any) in an out parameter. + Source: http://stackoverflow.com/questions/3746274/line-intersection-with-aabb-rectangle. + Edited to implement Cohen-Sutherland type pruning for efficiency. + + Starting point of line a. + Ending point of line a. + Starting point of line b. + Ending point of line b. + + The out parameter which contains the intersection point if there was any. + + True if the two lines intersect, otherwise false. + + + + Returns the collision point between two infinite lines. + + + + + Distance from line to plane. + + Position of the plane. + Surface normal of the plane. + Origin of the line. + Line direction normal. + + + + Distance from ray to plane. + + The ray. + The plane. + + + + Rotates a Vector2 by an angle. + + The point to rotate. + The angle to rotate. + + + + Rotates a Vector2 around a point by an angle.. + + The point to rotate. + The point to rotate around. + The angle to rotate. + + + + Interpolates t between a and b to a value between 0 and 1 using a Hermite polynomial. + + The first value. + The second value. + The position value. + A smoothed value between 0 and 1. + + + + Interpolates t between a and b to a value between 0 and 1. + + The first value. + The second value. + The position value. + Linear value between 0 and 1. + + + + Wraps a value between min and max. + + The value to wrap. + The minimum value. + The maximum value. + + + + Wraps a value between min and max. + + The value to wrap. + The minimum value. + The maximum value. + + + + Wraps a value between min and max. + + The value to wrap. + The minimum value. + The maximum value. + + + + Rounds a number based on a mininum difference. + + The value to round. + The min difference. + The rounded value. + + + + Discards the least significant demicals. + + The value of insignificant decimals. + Value with significant decimals. + + + + Clamps and wraps an angle between two values. + + + + + Contains utilities for operating on arrays multi-dimentional arrays. + + + + + Inserts one column left of the specified column index. + + The type of the element. + Index of the column. + The array. + + + + Inserts one column right of the specified column index. + + The type of the element. + Index of the column. + The arr. + + + + Inserts one row above the specified row index. + + The type of the element. + The array. + The row index. + + + + Inserts one row below the specified row index. + + The type of the element. + The array. + Index of the row. + + + + Duplicates the column. + + The type of the element. + Index of the column. + The array. + + + + Duplicates the row. + + The type of the element. + The array. + Index of the row. + + + + Moves a column. + + The type of the element. + The array. + From column. + To column. + + + + Moves a row. + + The type of the element. + The array. + From row. + To row. + + + + Deletes a column. + + The type of the element. + The array. + Index of the column. + + + + Deletes the row. + + The type of the element. + The array. + Index of the row. + + + + Indicates a persistent assembly. + + + + + Provides a methods of representing imaginary fields which are unique to serialization. + + We aggregate the FieldInfo associated with this member and return a mangled form of the name. + + + + + + The default fake name separator string. + + + + + Initializes a new instance of the class. + + The field to alias. + The name prefix to use. + + + + Initializes a new instance of the class. + + The field to alias. + The name prefix to use. + The separator string to use. + + + + Gets the aliased field. + + + The aliased field. + + + + + Gets the module in which the type that declares the member represented by the current is defined. + + + + + Gets a value that identifies a metadata element. + + + + + Gets the name of the current member. + + + + + Gets the class that declares this member. + + + + + Gets the class object that was used to obtain this instance of MemberInfo. + + + + + Gets the type of the field. + + + The type of the field. + + + + + Gets a RuntimeFieldHandle, which is a handle to the internal metadata representation of a field. + + + + + Gets the attributes. + + + The attributes. + + + + + When overridden in a derived class, returns an array of all custom attributes applied to this member. + + True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + An array that contains all the custom attributes applied to this member, or an array with zero elements if no attributes are defined. + + + + + When overridden in a derived class, returns an array of custom attributes applied to this member and identified by . + + The type of attribute to search for. Only attributes that are assignable to this type are returned. + True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + An array of custom attributes applied to this member, or an array with zero elements if no attributes assignable to have been applied. + + + + + When overridden in a derived class, indicates whether one or more attributes of the specified type or of its derived types is applied to this member. + + The type of custom attribute to search for. The search includes derived types. + True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + True if one or more instances of or any of its derived types is applied to this member; otherwise, false. + + + + + Gets the value of the field. + + The object instance to get the value from. + The value of the field. + + + + When overridden in a derived class, sets the value of the field supported by the given object. + + The object whose field value will be set. + The value to assign to the field. + A field of Binder that specifies the type of binding that is desired (for example, Binder.CreateInstance or Binder.ExactBinding). + A set of properties that enables the binding, coercion of argument types, and invocation of members through reflection. If is null, then Binder.DefaultBinding is used. + The software preferences of a particular culture. + + + + Provides a methods of representing aliased methods. + + In this case, what we're representing is a method on a parent class with the same name. + + We aggregate the MethodInfo associated with this member and return a mangled form of the name. + The name that we return is "parentname+methodName". + + + + + + The default fake name separator string. + + + + + Initializes a new instance of the class. + + The method to alias. + The name prefix to use. + + + + Initializes a new instance of the class. + + The method to alias. + The name prefix to use. + The separator string to use. + + + + Gets the aliased method. + + + The aliased method. + + + + + Gets the custom attributes for the return type. + + + + + Gets a handle to the internal metadata representation of a method. + + + + + Gets the attributes associated with this method. + + + + + Gets the class that declares this member. + + + + + Gets the name of the current member. + + + + + Gets the class object that was used to obtain this instance of MemberInfo. + + + + + When overridden in a derived class, returns the MethodInfo object for the method on the direct or indirect base class in which the method represented by this instance was first declared. + + + A MethodInfo object for the first implementation of this method. + + + + + When overridden in a derived class, returns an array of all custom attributes applied to this member. + + true to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + An array that contains all the custom attributes applied to this member, or an array with zero elements if no attributes are defined. + + + + + When overridden in a derived class, returns an array of custom attributes applied to this member and identified by . + + The type of attribute to search for. Only attributes that are assignable to this type are returned. + true to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + An array of custom attributes applied to this member, or an array with zero elements if no attributes assignable to have been applied. + + + + + When overridden in a derived class, returns the flags. + + + The MethodImplAttributes flags. + + + + + When overridden in a derived class, gets the parameters of the specified method or constructor. + + + An array of type ParameterInfo containing information that matches the signature of the method (or constructor) reflected by this MethodBase instance. + + + + + When overridden in a derived class, invokes the reflected method or constructor with the given parameters. + + The object on which to invoke the method or constructor. If a method is static, this argument is ignored. If a constructor is static, this argument must be null or an instance of the class that defines the constructor. + A bitmask that is a combination of 0 or more bit flags from . If is null, this parameter is assigned the value ; thus, whatever you pass in is ignored. + An object that enables the binding, coercion of argument types, invocation of members, and retrieval of MemberInfo objects via reflection. If is null, the default binder is used. + An argument list for the invoked method or constructor. This is an array of objects with the same number, order, and type as the parameters of the method or constructor to be invoked. If there are no parameters, this should be null.If the method or constructor represented by this instance takes a ByRef parameter, there is no special attribute required for that parameter in order to invoke the method or constructor using this function. Any object in this array that is not explicitly initialized with a value will contain the default value for that object type. For reference-type elements, this value is null. For value-type elements, this value is 0, 0.0, or false, depending on the specific element type. + An instance of CultureInfo used to govern the coercion of types. If this is null, the CultureInfo for the current thread is used. (This is necessary to convert a String that represents 1000 to a Double value, for example, since 1000 is represented differently by different cultures.) + + An Object containing the return value of the invoked method, or null in the case of a constructor, or null if the method's return type is void. Before calling the method or constructor, Invoke checks to see if the user has access permission and verifies that the parameters are valid.CautionElements of the array that represent parameters declared with the ref or out keyword may also be modified. + + + + + When overridden in a derived class, indicates whether one or more attributes of the specified type or of its derived types is applied to this member. + + The type of custom attribute to search for. The search includes derived types. + true to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + true if one or more instances of or any of its derived types is applied to this member; otherwise, false. + + + + + Provides a methods of representing imaginary properties which are unique to serialization. + + We aggregate the PropertyInfo associated with this member and return a mangled form of the name. + + + + + + The default fake name separator string. + + + + + Initializes a new instance of the class. + + The property to alias. + The name prefix to use. + + + + Initializes a new instance of the class. + + The property to alias. + The name prefix to use. + The separator string to use. + + + + Not yet documented. + + + + + Gets the module in which the type that declares the member represented by the current is defined. + + + + + Gets a value that identifies a metadata element. + + + + + Gets the name of the current member. + + + + + Gets the class that declares this member. + + + + + Gets the class object that was used to obtain this instance of MemberInfo. + + + + + Gets the type of the property. + + + The type of the property. + + + + + Gets the attributes. + + + The attributes. + + + + + Gets a value indicating whether this instance can read. + + + true if this instance can read; otherwise, false. + + + + + Gets a value indicating whether this instance can write. + + + true if this instance can write; otherwise, false. + + + + + When overridden in a derived class, returns an array of all custom attributes applied to this member. + + True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + An array that contains all the custom attributes applied to this member, or an array with zero elements if no attributes are defined. + + + + + When overridden in a derived class, returns an array of custom attributes applied to this member and identified by . + + The type of attribute to search for. Only attributes that are assignable to this type are returned. + True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + An array of custom attributes applied to this member, or an array with zero elements if no attributes assignable to have been applied. + + + + + When overridden in a derived class, indicates whether one or more attributes of the specified type or of its derived types is applied to this member. + + The type of custom attribute to search for. The search includes derived types. + True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. + + True if one or more instances of or any of its derived types is applied to this member; otherwise, false. + + + + + Returns an array whose elements reflect the public and, if specified, non-public get, set, and other accessors of the property reflected by the current instance. + + Indicates whether non-public methods should be returned in the MethodInfo array. true if non-public methods are to be included; otherwise, false. + + An array of objects whose elements reflect the get, set, and other accessors of the property reflected by the current instance. If is true, this array contains public and non-public get, set, and other accessors. If is false, this array contains only public get, set, and other accessors. If no accessors with the specified visibility are found, this method returns an array with zero (0) elements. + + + + + When overridden in a derived class, returns the public or non-public get accessor for this property. + + Indicates whether a non-public get accessor should be returned. true if a non-public accessor is to be returned; otherwise, false. + + A MethodInfo object representing the get accessor for this property, if is true. Returns null if is false and the get accessor is non-public, or if is true but no get accessors exist. + + + + + Gets the index parameters of the property. + + The index parameters of the property. + + + + When overridden in a derived class, returns the set accessor for this property. + + Indicates whether the accessor should be returned if it is non-public. true if a non-public accessor is to be returned; otherwise, false. + + Value Condition A object representing the Set method for this property. The set accessor is public.-or- is true and the set accessor is non-public. null is true, but the property is read-only.-or- is false and the set accessor is non-public.-or- There is no set accessor. + + + + + Gets the value of the property on the given instance. + + The object to invoke the getter on. + The to invoke with. + The binder to use. + The indices to use. + The culture to use. + The value of the property on the given instance. + + + + Sets the value of the property on the given instance. + + The object to set the value on. + The value to set. + The to invoke with. + The binder to use. + The indices to use. + The culture to use. + + + + Paths to Sirenix assets. + + + + + Path to Odin Inspector folder. + + + + + Path to Sirenix assets folder. + + + + + Path to Sirenix folder. + + + + + Path to Sirenix assemblies. + + + + + Path to Odin Inspector resources folder. + + + + + Path to Odin Inspector configuration folder. + + + + + Path to Odin Inspector resources configuration folder. + + + + + Path to Odin Inspector temporary folder. + + + + + This attribute is used by classes deriving from GlobalConfig and specifies the menu item path for the preference window and the asset path for the generated config file. + The scriptable object created will be located at the OdinEditorConfigs path unless other is specified. + Classes implementing this attribute will be part of the Odin Preferences window. + + + + + + Initializes a new instance of the class. + + + + + This attribute is used by classes deriving from GlobalConfig and specifies the menu item path for the preference window and the asset path for the generated config file. + The scriptable object created will be located at the OdinResourcesConigs path unless other is specified. + Classes implementing this attribute will be part of the Odin Preferences window. + + + + + + Initializes a new instance of the class. + + + + + Not yet documented. + + + + + Not yet documented. + + Not yet documented. + Not yet documented. + Not yet documented. + + + + Compares two strings in a number-aware manner, IE, "[2] Foo" is considered to come before "[10] Bar". + + + + + Utility class indicating current Unity version. + + + + + Tests current Unity version is equal or greater. + + Minimum major version. + Minimum minor version. + true if the current Unity version is greater. Otherwise false. + + + + The current Unity version major. + + + + + The current Unity version minor. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Not yet documented. + + + + + Compares objects by reference only, ignoring equality operators completely. This is used by the property tree reference dictionaries to keep track of references. + + + + + A default, cached instance of this generic variant of the reference equality comparer. + + + + + Returns true if the object references are equal. + + + + + Returns the result of the object's own GetHashCode method. + + + + diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.xml.meta b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.xml.meta new file mode 100644 index 0000000..63d3480 --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/Sirenix.Utilities.xml.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4873f2a8bdae42baa0406e8a6136096f +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/link.xml b/Assets/Plugins/Sirenix/Assemblies/link.xml new file mode 100644 index 0000000..1df8f84 --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/link.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Assemblies/link.xml.meta b/Assets/Plugins/Sirenix/Assemblies/link.xml.meta new file mode 100644 index 0000000..4dfefc6 --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/link.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2373d9909155cae468605be57f69461c +timeCreated: 1613046886 +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Demos.meta b/Assets/Plugins/Sirenix/Demos.meta new file mode 100644 index 0000000..6ea179b --- /dev/null +++ b/Assets/Plugins/Sirenix/Demos.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ea9123c061588dc47b848832fb85817b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Demos/Custom Attribute Processors.unitypackage.meta b/Assets/Plugins/Sirenix/Demos/Custom Attribute Processors.unitypackage.meta new file mode 100644 index 0000000..8dd2946 --- /dev/null +++ b/Assets/Plugins/Sirenix/Demos/Custom Attribute Processors.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f597f19f656ba56eae4f6a3a7cc528f4 +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Demos/Custom Drawers.unitypackage.meta b/Assets/Plugins/Sirenix/Demos/Custom Drawers.unitypackage.meta new file mode 100644 index 0000000..35418d0 --- /dev/null +++ b/Assets/Plugins/Sirenix/Demos/Custom Drawers.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 48e08dc33330d11e9d4a1b246c52e4f6 +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Demos/Editor Windows.unitypackage.meta b/Assets/Plugins/Sirenix/Demos/Editor Windows.unitypackage.meta new file mode 100644 index 0000000..cb0b40f --- /dev/null +++ b/Assets/Plugins/Sirenix/Demos/Editor Windows.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ed09910c0094cb27be8f3ca264680da3 +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Demos/Sample - RPG Editor.unitypackage.meta b/Assets/Plugins/Sirenix/Demos/Sample - RPG Editor.unitypackage.meta new file mode 100644 index 0000000..8a58328 --- /dev/null +++ b/Assets/Plugins/Sirenix/Demos/Sample - RPG Editor.unitypackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cc355dd4cf1e6173beaeb22c2858cbe1 +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector.meta b/Assets/Plugins/Sirenix/Odin Inspector.meta new file mode 100644 index 0000000..0213108 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: abce34fc4c84f7e40a26a9d11d1c578a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Assets.meta b/Assets/Plugins/Sirenix/Odin Inspector/Assets.meta new file mode 100644 index 0000000..f022e79 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Assets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3d38ee25ee419b24f8af63a1c81d4b5e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor.meta b/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor.meta new file mode 100644 index 0000000..676eecc --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 00f94164baa814b40a7ec8a589114511 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/ConfigData.bytes b/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/ConfigData.bytes new file mode 100644 index 0000000000000000000000000000000000000000..1a63707e7ca56f06d78c7833892fa8f566cc1767 GIT binary patch literal 1616 zcmd^^*A+Nv^!if*S%+8Fp!UhR0z+pHDN8|gt0j(S% zIYDAaQ(awMTV3_nUvqXA`FB!0L3tO4*vA~7;wy5F7Z(NAiewO6 z=#X>tSeuwQDbbe{MZbpAZ4A+3Yq8esR{#040}pZ7fX+6(Th!`>x)2k=^wj|hwE zz*^!}#py}$lr~(&m$-@7am&#m?&3N=$H&yX8vTo)gZ6Yw`QttYI~pd}YJ=!Vxe zrzCpx8H?72D^06>aMOC?54@7ZxRRkxw8tj>lgo1%DktP-b7DXEv~rUjb>aX0hY z*U41R36rsY&+#3H$CEK}x-PyWO>9ajNs5YKCTQ64R}ovR8?5@t%OQE?q{atN#=r7G i?5Mc|c0Wc|EN^nv(s|~c@UX2FSU5Z)C!3T^==o0pUZ?f| literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/ConfigData.bytes.meta b/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/ConfigData.bytes.meta new file mode 100644 index 0000000..6ad740b --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/ConfigData.bytes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 90eaa0dc28c1934408dc1c02e13a507f +timeCreated: 1628274352 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/Odin Inspector Logo.png b/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/Odin Inspector Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4b639dfc4ef48db0350fe94d7628ab7e656013df GIT binary patch literal 23267 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ℑaC!j zgdvd4tsO6QV>DU7#KsY2O0!e&oU+q9uP>drmAa5qwiZM|9ml=Fm3@nW7mx4m^9kdM zMiL;K`b=eNc5DA5M$-b&h%uA7&(E}OP<9?kKkM{jOB zRW9rz!~9y>`?V&0#LYl0#23wpvO(2mWR6kJbM09PUX@=od~Ir+OQB_qf?H|JpN`jG zbjYVqebLbrsIi?t>7SHw7rT-Q38v>2_-<1r<$f7>5gV#0_vp1ny_|uU)qPRAqe1-o zn&WW7@hO6!qiFNx0MTCjZ22eb$)|<<9U^8r2Qa*AE>P1 z!2X3xBSPDW)7?gv!_@g`ob&kYatdd)ba&WG3_(`~VYIe9;W4~nG(zzzUGO=h_R|_l z@cOwFu`)01e!8j_GCUe%w!CLMjXmiKryY1VB9ADc@A`oVdBC~iy_4q^6Dy!Vzyduz z`&YBL`~m@WQdi1YA}ijz10|>%Dm1Jm+Gwrum&s|B9~jkx*10e}v}@sWo8brp(;IY! zm=}Idy`i5ew|qa|H8i!-+!}qHR#1yy^jfyIhwjF@L53Ag!E8igN;d3NgM?Ly_NL5w zdAaI_n=u+RWh!oQ%weRwO{`J?n3*FQDeG1>P;+IAPCU83*$@6AC(zMG1}L`Cj9r@w zktCkJ^vBn2_mC4;K2q0PVQ=4|&{>frGEqoSPfdk+kT~AsiQ2UAbD`mFBF9s1%;)J< znsTN}>5(lBx)@(mXC!VgUg|)1pq<4W6mRwAHZN}#3bwFa<9+)6{0opLNw}M2RM0y4 zVCB7u_*<^Yv4#Ze&5@G`iCq#*?Gfs3s4#Xux~+-<7M8GxExvWvfAihycr_L&n} z#A(GOK*akMIWJA+Fkg|fHp|?ZOS?L8UIUZ<$(nR@&W1DfCyUKtyX6-AX^`uEc*zwNO7GLy6&QU`@a-r3Cgk*%MG{ zuzV%#lu9AmI%5Z|1$b66zM*1-WkAK^@|F5Hv(Js6t1NOcizZhl%|A=@SW(M>)AcSs z`FK*z%5hs##-iozd((K#yYdqLf}*`A+@hDEiDi;+KokLc;*=LpjaRJ7%rx+gc+~-e hJp#S8q8m$q`8~1-zGwD9`@a>asdiqqP}w@@{{ZG&FJAxv literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/Odin Inspector Logo.png.meta b/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/Odin Inspector Logo.png.meta new file mode 100644 index 0000000..0d68b07 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/Odin Inspector Logo.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: a78bffbeb81b48ae9ec71ad7969613e5 +timeCreated: 1493397482 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 1 + correctGamma: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 1 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: 1 + aniso: 16 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + 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 + alphaIsTransparency: 1 + textureType: 5 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/OdinPathLookup.asset b/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/OdinPathLookup.asset new file mode 100644 index 0000000..5cbffd2 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/OdinPathLookup.asset @@ -0,0 +1,13 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -262940062, guid: a4865f1ab4504ed8a368670db22f409c, type: 3} + m_Name: OdinPathLookup + m_EditorClassIdentifier: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/OdinPathLookup.asset.meta b/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/OdinPathLookup.asset.meta new file mode 100644 index 0000000..4d528eb --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Assets/Editor/OdinPathLookup.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 08379ccefc05200459f90a1c0711a340 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Config.meta b/Assets/Plugins/Sirenix/Odin Inspector/Config.meta new file mode 100644 index 0000000..5cdebee --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Config.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a49ca321538a06f4aa8096210e50c67c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor.meta b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor.meta new file mode 100644 index 0000000..a696ac6 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c727a747a1fbbd447a86e1f6415be2de +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/GeneralDrawerConfig.asset b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/GeneralDrawerConfig.asset new file mode 100644 index 0000000..5119601 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/GeneralDrawerConfig.asset @@ -0,0 +1,14 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -645759843, guid: a4865f1ab4504ed8a368670db22f409c, type: 3} + m_Name: GeneralDrawerConfig + m_EditorClassIdentifier: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/GeneralDrawerConfig.asset.meta b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/GeneralDrawerConfig.asset.meta new file mode 100644 index 0000000..375ff68 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/GeneralDrawerConfig.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e0b2ebefefe8fb04495b9eba25d8d397 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/InspectorConfig.asset b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/InspectorConfig.asset new file mode 100644 index 0000000..5b65043 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/InspectorConfig.asset @@ -0,0 +1,19 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1137305049, guid: a4865f1ab4504ed8a368670db22f409c, type: 3} + m_Name: InspectorConfig + m_EditorClassIdentifier: + enableOdinInInspector: 1 + defaultEditorBehaviour: 11 + processMouseMoveInInspector: 1 + drawingConfig: + configs: [] diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/InspectorConfig.asset.meta b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/InspectorConfig.asset.meta new file mode 100644 index 0000000..2adc4f6 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/InspectorConfig.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d136afd15b1958b40ae2fc477882aeb8 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/OdinModuleConfig.asset b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/OdinModuleConfig.asset new file mode 100644 index 0000000..f09018b --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/OdinModuleConfig.asset @@ -0,0 +1,19 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -228747253, guid: a4865f1ab4504ed8a368670db22f409c, type: 3} + m_Name: OdinModuleConfig + m_EditorClassIdentifier: + configurations: + - ID: Unity.Mathematics + ActivationSettings: 0 + ModuleTogglingSettings: 1 + ModuleUpdateSettings: 0 diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/OdinModuleConfig.asset.meta b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/OdinModuleConfig.asset.meta new file mode 100644 index 0000000..2d60005 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Config/Editor/OdinModuleConfig.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fbe7b659c52fece48b1fee750082614c +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Modules.meta b/Assets/Plugins/Sirenix/Odin Inspector/Modules.meta new file mode 100644 index 0000000..debdfc7 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Modules.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 15c43f6258d5e2744a11580fe86101e6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Entities.data b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Entities.data new file mode 100644 index 0000000000000000000000000000000000000000..abe322d83cb594eedb0f19c624816260ebaa4ab7 GIT binary patch literal 41801 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 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Entities.data.meta b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Entities.data.meta new file mode 100644 index 0000000..965c525 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Entities.data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 728df0e3465c1a148b83053a3f31d489 +timeCreated: 1573836981 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.data b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.data new file mode 100644 index 0000000000000000000000000000000000000000..03629ac6c85d01e0780c26cbef0cf12fbd02f678 GIT binary patch literal 46862 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 r-aWa!<-mt+j&9v@Mt4?McHt_YU-93s#o literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.data.meta b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.data.meta new file mode 100644 index 0000000..ee5dc74 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4866e740a22eb1e49b1603b051e4d92c +timeCreated: 1573836980 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.meta b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.meta new file mode 100644 index 0000000..b30442a --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b77d3360914db0246aea3600c395ea65 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/MathematicsDrawers.cs b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/MathematicsDrawers.cs new file mode 100644 index 0000000..47a1db4 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/MathematicsDrawers.cs @@ -0,0 +1,883 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +namespace Sirenix.OdinInspector.Modules.UnityMathematics.Editor +{ +#if UNITY_EDITOR + using System; + using System.Collections.Generic; + using System.Reflection; + using Sirenix.OdinInspector.Editor; + using Sirenix.Utilities; + using Sirenix.Utilities.Editor; + using Unity.Mathematics; + using UnityEditor; + using UnityEngine; + + public sealed class MatrixFloat2x2Processor : MatrixProcessor { } + public sealed class MatrixFloat3x2Processor : MatrixProcessor { } + public sealed class MatrixFloat4x2Processor : MatrixProcessor { } + public sealed class MatrixFloat2x3Processor : MatrixProcessor { } + public sealed class MatrixFloat3x3Processor : MatrixProcessor { } + public sealed class MatrixFloat4x3Processor : MatrixProcessor { } + public sealed class MatrixFloat2x4Processor : MatrixProcessor { } + public sealed class MatrixFloat3x4Processor : MatrixProcessor { } + public sealed class MatrixFloat4x4Processor : MatrixProcessor { } + + public sealed class MatrixDouble2x2Processor : MatrixProcessor { } + public sealed class MatrixDouble3x2Processor : MatrixProcessor { } + public sealed class MatrixDouble4x2Processor : MatrixProcessor { } + public sealed class MatrixDouble2x3Processor : MatrixProcessor { } + public sealed class MatrixDouble3x3Processor : MatrixProcessor { } + public sealed class MatrixDouble4x3Processor : MatrixProcessor { } + public sealed class MatrixDouble2x4Processor : MatrixProcessor { } + public sealed class MatrixDouble3x4Processor : MatrixProcessor { } + public sealed class MatrixDouble4x4Processor : MatrixProcessor { } + + public sealed class MatrixBool2x2Processor : MatrixProcessor { } + public sealed class MatrixBool3x2Processor : MatrixProcessor { } + public sealed class MatrixBool4x2Processor : MatrixProcessor { } + public sealed class MatrixBool2x3Processor : MatrixProcessor { } + public sealed class MatrixBool3x3Processor : MatrixProcessor { } + public sealed class MatrixBool4x3Processor : MatrixProcessor { } + public sealed class MatrixBool2x4Processor : MatrixProcessor { } + public sealed class MatrixBool3x4Processor : MatrixProcessor { } + public sealed class MatrixBool4x4Processor : MatrixProcessor { } + + public sealed class MatrixInt2x2Processor : MatrixProcessor { } + public sealed class MatrixInt3x2Processor : MatrixProcessor { } + public sealed class MatrixInt4x2Processor : MatrixProcessor { } + public sealed class MatrixInt2x3Processor : MatrixProcessor { } + public sealed class MatrixInt3x3Processor : MatrixProcessor { } + public sealed class MatrixInt4x3Processor : MatrixProcessor { } + public sealed class MatrixInt2x4Processor : MatrixProcessor { } + public sealed class MatrixInt3x4Processor : MatrixProcessor { } + public sealed class MatrixInt4x4Processor : MatrixProcessor { } + + public sealed class MatrixUInt2x2Processor : MatrixProcessor { } + public sealed class MatrixUInt3x2Processor : MatrixProcessor { } + public sealed class MatrixUInt4x2Processor : MatrixProcessor { } + public sealed class MatrixUInt2x3Processor : MatrixProcessor { } + public sealed class MatrixUInt3x3Processor : MatrixProcessor { } + public sealed class MatrixUInt4x3Processor : MatrixProcessor { } + public sealed class MatrixUInt2x4Processor : MatrixProcessor { } + public sealed class MatrixUInt3x4Processor : MatrixProcessor { } + public sealed class MatrixUInt4x4Processor : MatrixProcessor { } + + public sealed class DisableUnityMatrixDrawerAttribute : Attribute { } + + public abstract class MatrixProcessor : OdinAttributeProcessor + { + public override void ProcessSelfAttributes(InspectorProperty property, List attributes) + { + attributes.GetOrAddAttribute(); + attributes.GetOrAddAttribute(); + } + + public override void ProcessChildMemberAttributes(InspectorProperty parentProperty, MemberInfo member, List attributes) + { + attributes.Add(new HideLabelAttribute()); + attributes.Add(new MatrixChildAttribute()); + } + } + + public class DisableUnityMatrixDrawerAttributeDrawer : OdinAttributeDrawer + { + protected override void Initialize() + { + this.SkipWhenDrawing = true; + var chain = this.Property.GetActiveDrawerChain().BakedDrawerArray; + + for (int i = 0; i < chain.Length; i++) + { + var type = chain[i].GetType(); + + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(UnityPropertyDrawer<,>) && type.GetGenericArguments()[0].Name == "MatrixDrawer") + { + chain[i].SkipWhenDrawing = true; + break; + } + } + } + } + + public class MatrixChildAttribute : Attribute { } + + public class Bool2Drawer : OdinValueDrawer + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 100; + + if (label != null) + { + GUILayout.Space(3); // Ugh, better than nothing + } + + var options = GUILayoutOptions.Height(EditorGUIUtility.singleLineHeight); + + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + EditorGUILayout.BeginVertical(options); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical(options); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + EditorGUILayout.EndVertical(); + GUIHelper.PopLabelWidth(); + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + } + + public class Bool3Drawer : OdinValueDrawer + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 100; + + if (label != null) + { + GUILayout.Space(3); // Ugh, better than nothing + } + + var options = GUILayoutOptions.Height(EditorGUIUtility.singleLineHeight); + + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + EditorGUILayout.BeginVertical(options); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical(options); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical(options); + this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null); + EditorGUILayout.EndVertical(); + GUIHelper.PopLabelWidth(); + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + } + + public class Bool4Drawer : OdinValueDrawer + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 100; + + if (label != null) + { + GUILayout.Space(3); // Ugh, better than nothing + } + + var options = GUILayoutOptions.Height(EditorGUIUtility.singleLineHeight); + + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + EditorGUILayout.BeginVertical(options); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical(options); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical(options); + this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null); + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical(options); + this.ValueEntry.Property.Children[3].Draw(showLabels ? GUIHelper.TempContent("W") : null); + EditorGUILayout.EndVertical(); + GUIHelper.PopLabelWidth(); + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + } + + public class Float2Drawer : OdinValueDrawer, IDefinesGenericMenuItems + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + // Slide rect + { + var val = this.ValueEntry.SmartValue; + EditorGUI.BeginChangeCheck(); + var vec = SirenixEditorFields.VectorPrefixSlideRect(labelRect, new Vector2(val.x, val.y)); + val = new float2(vec.x, vec.y); + if (EditorGUI.EndChangeCheck()) + { + this.ValueEntry.SmartValue = val; + } + } + + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + + /// + /// Populates the generic menu for the property. + /// + public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu) + { + float2 value = (float2)property.ValueEntry.WeakSmartValue; + var vec = new Vector2(value.x, value.y); + + if (genericMenu.GetItemCount() > 0) + { + genericMenu.AddSeparator(""); + } + genericMenu.AddItem(new GUIContent("Normalize"), Mathf.Approximately(vec.magnitude, 1f), () => NormalizeEntries(property)); + genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0)"), vec == Vector2.zero, () => SetVector(property, Vector2.zero)); + genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1)"), vec == Vector2.one, () => SetVector(property, Vector2.one)); + genericMenu.AddSeparator(""); + genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0)"), vec == Vector2.right, () => SetVector(property, Vector2.right)); + genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0)"), vec == Vector2.left, () => SetVector(property, Vector2.left)); + genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1)"), vec == Vector2.up, () => SetVector(property, Vector2.up)); + genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1)"), vec == Vector2.down, () => SetVector(property, Vector2.down)); + } + + private void SetVector(InspectorProperty property, Vector2 value) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = new float2(value.x, value.y); + } + }); + } + + private void NormalizeEntries(InspectorProperty property) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = math.normalizesafe((float2)property.ValueEntry.WeakValues[i]); + } + }); + } + } + + public class Float3Drawer : OdinValueDrawer, IDefinesGenericMenuItems + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + // Slide rect + { + var val = this.ValueEntry.SmartValue; + EditorGUI.BeginChangeCheck(); + var vec = SirenixEditorFields.VectorPrefixSlideRect(labelRect, new Vector3(val.x, val.y, val.z)); + val = new float3(vec.x, vec.y, vec.z); + if (EditorGUI.EndChangeCheck()) + { + this.ValueEntry.SmartValue = val; + } + } + + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + + /// + /// Populates the generic menu for the property. + /// + public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu) + { + float3 value = (float3)property.ValueEntry.WeakSmartValue; + var vec = new Vector3(value.x, value.y, value.z); + + if (genericMenu.GetItemCount() > 0) + { + genericMenu.AddSeparator(""); + } + genericMenu.AddItem(new GUIContent("Normalize"), Mathf.Approximately(vec.magnitude, 1f), () => NormalizeEntries(property)); + genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0, 0)"), vec == Vector3.zero, () => SetVector(property, Vector3.zero)); + genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1, 1)"), vec == Vector3.one, () => SetVector(property, Vector3.one)); + genericMenu.AddSeparator(""); + genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0, 0)"), vec == Vector3.right, () => SetVector(property, Vector3.right)); + genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0, 0)"), vec == Vector3.left, () => SetVector(property, Vector3.left)); + genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1, 0)"), vec == Vector3.up, () => SetVector(property, Vector3.up)); + genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1, 0)"), vec == Vector3.down, () => SetVector(property, Vector3.down)); + genericMenu.AddItem(new GUIContent("Forward", "Set the vector property to (0, 0, 1)"), vec == Vector3.forward, () => SetVector(property, Vector3.forward)); + genericMenu.AddItem(new GUIContent("Back", "Set the vector property to (0, 0, -1)"), vec == Vector3.back, () => SetVector(property, Vector3.back)); + } + + private void SetVector(InspectorProperty property, Vector3 value) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = new float3(value.x, value.y, value.z); + } + }); + } + + private void NormalizeEntries(InspectorProperty property) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = math.normalizesafe((float3)property.ValueEntry.WeakValues[i]); + } + }); + } + } + + public class Float4Drawer : OdinValueDrawer, IDefinesGenericMenuItems + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + // Slide rect + { + var val = this.ValueEntry.SmartValue; + EditorGUI.BeginChangeCheck(); + var vec = SirenixEditorFields.VectorPrefixSlideRect(labelRect, new Vector4(val.x, val.y, val.z, val.w)); + val = new float4(vec.x, vec.y, vec.z, vec.w); + if (EditorGUI.EndChangeCheck()) + { + this.ValueEntry.SmartValue = val; + } + } + + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null); + this.ValueEntry.Property.Children[3].Draw(showLabels ? GUIHelper.TempContent("W") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + + /// + /// Populates the generic menu for the property. + /// + public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu) + { + float4 value = (float4)property.ValueEntry.WeakSmartValue; + var vec = new Vector4(value.x, value.y, value.z, value.w); + + if (genericMenu.GetItemCount() > 0) + { + genericMenu.AddSeparator(""); + } + genericMenu.AddItem(new GUIContent("Normalize"), Mathf.Approximately(vec.magnitude, 1f), () => NormalizeEntries(property)); + genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0, 0, 0)"), vec == Vector4.zero, () => SetVector(property, Vector3.zero)); + genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1, 1, 1)"), vec == Vector4.one, () => SetVector(property, Vector4.one)); + genericMenu.AddSeparator(""); + genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0, 0, 0)"), (Vector3)vec == Vector3.right, () => SetVector(property, Vector3.right)); + genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0, 0, 0)"), (Vector3)vec == Vector3.left, () => SetVector(property, Vector3.left)); + genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1, 0, 0)"), (Vector3)vec == Vector3.up, () => SetVector(property, Vector3.up)); + genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1, 0, 0)"), (Vector3)vec == Vector3.down, () => SetVector(property, Vector3.down)); + genericMenu.AddItem(new GUIContent("Forward", "Set the vector property to (0, 0, 1, 0)"), (Vector3)vec == Vector3.forward, () => SetVector(property, Vector3.forward)); + genericMenu.AddItem(new GUIContent("Back", "Set the vector property to (0, 0, -1, 0)"), (Vector3)vec == Vector3.back, () => SetVector(property, Vector3.back)); + } + + private void SetVector(InspectorProperty property, Vector4 value) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = new float4(value.x, value.y, value.z, value.w); + } + }); + } + + private void NormalizeEntries(InspectorProperty property) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = math.normalizesafe((float4)property.ValueEntry.WeakValues[i]); + } + }); + } + } + + + public class Double2Drawer : OdinValueDrawer, IDefinesGenericMenuItems + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + // Slide rect + { + var val = this.ValueEntry.SmartValue; + EditorGUI.BeginChangeCheck(); + var vec = SirenixEditorFields.VectorPrefixSlideRect(labelRect, new Vector2((float)val.x, (float)val.y)); + val = new double2(vec.x, vec.y); + if (EditorGUI.EndChangeCheck()) + { + this.ValueEntry.SmartValue = val; + } + } + + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + + /// + /// Populates the generic menu for the property. + /// + public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu) + { + double2 value = (double2)property.ValueEntry.WeakSmartValue; + var vec = new Vector2((float)value.x, (float)value.y); + + if (genericMenu.GetItemCount() > 0) + { + genericMenu.AddSeparator(""); + } + genericMenu.AddItem(new GUIContent("Normalize"), Mathf.Approximately(vec.magnitude, 1f), () => NormalizeEntries(property)); + genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0)"), vec == Vector2.zero, () => SetVector(property, Vector2.zero)); + genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1)"), vec == Vector2.one, () => SetVector(property, Vector2.one)); + genericMenu.AddSeparator(""); + genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0)"), vec == Vector2.right, () => SetVector(property, Vector2.right)); + genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0)"), vec == Vector2.left, () => SetVector(property, Vector2.left)); + genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1)"), vec == Vector2.up, () => SetVector(property, Vector2.up)); + genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1)"), vec == Vector2.down, () => SetVector(property, Vector2.down)); + } + + private void SetVector(InspectorProperty property, Vector2 value) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = new double2(value.x, value.y); + } + }); + } + + private void NormalizeEntries(InspectorProperty property) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = math.normalizesafe((double2)property.ValueEntry.WeakValues[i]); + } + }); + } + } + + public class Double3Drawer : OdinValueDrawer, IDefinesGenericMenuItems + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + // Slide rect + { + var val = this.ValueEntry.SmartValue; + EditorGUI.BeginChangeCheck(); + var vec = SirenixEditorFields.VectorPrefixSlideRect(labelRect, new Vector3((float)val.x, (float)val.y, (float)val.z)); + val = new double3(vec.x, vec.y, vec.z); + if (EditorGUI.EndChangeCheck()) + { + this.ValueEntry.SmartValue = val; + } + } + + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + + /// + /// Populates the generic menu for the property. + /// + public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu) + { + double3 value = (double3)property.ValueEntry.WeakSmartValue; + var vec = new Vector3((float)value.x, (float)value.y, (float)value.z); + + if (genericMenu.GetItemCount() > 0) + { + genericMenu.AddSeparator(""); + } + genericMenu.AddItem(new GUIContent("Normalize"), Mathf.Approximately(vec.magnitude, 1f), () => NormalizeEntries(property)); + genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0, 0)"), vec == Vector3.zero, () => SetVector(property, Vector3.zero)); + genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1, 1)"), vec == Vector3.one, () => SetVector(property, Vector3.one)); + genericMenu.AddSeparator(""); + genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0, 0)"), vec == Vector3.right, () => SetVector(property, Vector3.right)); + genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0, 0)"), vec == Vector3.left, () => SetVector(property, Vector3.left)); + genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1, 0)"), vec == Vector3.up, () => SetVector(property, Vector3.up)); + genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1, 0)"), vec == Vector3.down, () => SetVector(property, Vector3.down)); + genericMenu.AddItem(new GUIContent("Forward", "Set the vector property to (0, 0, 1)"), vec == Vector3.forward, () => SetVector(property, Vector3.forward)); + genericMenu.AddItem(new GUIContent("Back", "Set the vector property to (0, 0, -1)"), vec == Vector3.back, () => SetVector(property, Vector3.back)); + } + + private void SetVector(InspectorProperty property, Vector3 value) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = new double3(value.x, value.y, value.z); + } + }); + } + + private void NormalizeEntries(InspectorProperty property) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = math.normalizesafe((double3)property.ValueEntry.WeakValues[i]); + } + }); + } + } + + public class Double4Drawer : OdinValueDrawer, IDefinesGenericMenuItems + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + // Slide rect + { + var val = this.ValueEntry.SmartValue; + EditorGUI.BeginChangeCheck(); + var vec = SirenixEditorFields.VectorPrefixSlideRect(labelRect, new Vector4((float)val.x, (float)val.y, (float)val.z, (float)val.w)); + val = new double4(vec.x, vec.y, vec.z, vec.w); + if (EditorGUI.EndChangeCheck()) + { + this.ValueEntry.SmartValue = val; + } + } + + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null); + this.ValueEntry.Property.Children[3].Draw(showLabels ? GUIHelper.TempContent("W") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + + /// + /// Populates the generic menu for the property. + /// + public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu) + { + double4 value = (double4)property.ValueEntry.WeakSmartValue; + var vec = new Vector4((float)value.x, (float)value.y, (float)value.z, (float)value.w); + + if (genericMenu.GetItemCount() > 0) + { + genericMenu.AddSeparator(""); + } + genericMenu.AddItem(new GUIContent("Normalize"), Mathf.Approximately(vec.magnitude, 1f), () => NormalizeEntries(property)); + genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0, 0, 0)"), vec == Vector4.zero, () => SetVector(property, Vector3.zero)); + genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1, 1, 1)"), vec == Vector4.one, () => SetVector(property, Vector4.one)); + genericMenu.AddSeparator(""); + genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0, 0, 0)"), (Vector3)vec == Vector3.right, () => SetVector(property, Vector3.right)); + genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0, 0, 0)"), (Vector3)vec == Vector3.left, () => SetVector(property, Vector3.left)); + genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1, 0, 0)"), (Vector3)vec == Vector3.up, () => SetVector(property, Vector3.up)); + genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1, 0, 0)"), (Vector3)vec == Vector3.down, () => SetVector(property, Vector3.down)); + genericMenu.AddItem(new GUIContent("Forward", "Set the vector property to (0, 0, 1, 0)"), (Vector3)vec == Vector3.forward, () => SetVector(property, Vector3.forward)); + genericMenu.AddItem(new GUIContent("Back", "Set the vector property to (0, 0, -1, 0)"), (Vector3)vec == Vector3.back, () => SetVector(property, Vector3.back)); + } + + private void SetVector(InspectorProperty property, Vector4 value) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = new double4(value.x, value.y, value.z, value.w); + } + }); + } + + private void NormalizeEntries(InspectorProperty property) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = math.normalizesafe((double4)property.ValueEntry.WeakValues[i]); + } + }); + } + } + + public class Int2Drawer : OdinValueDrawer + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + } + + public class Int3Drawer : OdinValueDrawer + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + } + + public class Int4Drawer : OdinValueDrawer + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null); + this.ValueEntry.Property.Children[3].Draw(showLabels ? GUIHelper.TempContent("W") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + } + + public class UInt2Drawer : OdinValueDrawer + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + } + + public class UInt3Drawer : OdinValueDrawer + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + } + + public class UInt4Drawer : OdinValueDrawer + { + private bool isMatrixChild; + + protected override void Initialize() + { + this.isMatrixChild = this.Property.GetAttribute() != null; + } + + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null); + this.ValueEntry.Property.Children[3].Draw(showLabels ? GUIHelper.TempContent("W") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + } +#endif +} \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/MathematicsDrawers.cs.meta b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/MathematicsDrawers.cs.meta new file mode 100644 index 0000000..95a3319 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/MathematicsDrawers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 74718b273a32d874a9dc3c58269c36b3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/Sirenix.OdinInspector.Modules.UnityMathematics.asmdef b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/Sirenix.OdinInspector.Modules.UnityMathematics.asmdef new file mode 100644 index 0000000..613c7ac --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/Sirenix.OdinInspector.Modules.UnityMathematics.asmdef @@ -0,0 +1,11 @@ +{ + "name": "Sirenix.OdinInspector.Modules.UnityMathematics", + "references": [ "Unity.Mathematics", "Sirenix.OdinInspector.Attributes", "Sirenix.OdinInspector.Editor", "Sirenix.Utilities", "Sirenix.Utilities.Editor" ], + "includePlatforms": [ "Editor" ], + "excludePlatforms": [], + "allowUnsafeCode": true, + "autoReferenced": true, + "overrideReferences": false, + "precompiledReferences": [ "Sirenix.Utilities.dll", "Sirenix.Utilities.Editor.dll", "Sirenix.OdinInspector.Attributes.dll", "Sirenix.OdinInspector.Editor.dll", "Sirenix.Serialization.dll" ], + "defineConstraints": [] +} \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/Sirenix.OdinInspector.Modules.UnityMathematics.asmdef.meta b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/Sirenix.OdinInspector.Modules.UnityMathematics.asmdef.meta new file mode 100644 index 0000000..791fd52 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/Sirenix.OdinInspector.Modules.UnityMathematics.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ad968d605628d06499b62cdc30f11cf8 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/manifest.txt b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/manifest.txt new file mode 100644 index 0000000..bc4189a --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/manifest.txt @@ -0,0 +1,8 @@ +ManifestVersion: 1 +ModuleID: Unity.Mathematics +ModuleVersion: 1.0.1.0 +ModuleFiles: + MathematicsDrawers.cs + MathematicsDrawers.cs.meta + Sirenix.OdinInspector.Modules.UnityMathematics.asmdef + Sirenix.OdinInspector.Modules.UnityMathematics.asmdef.meta diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/manifest.txt.meta b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/manifest.txt.meta new file mode 100644 index 0000000..12572fe --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics/manifest.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ec6185a268f83de4bb16c1c6ab37e831 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts.meta new file mode 100644 index 0000000..09e96bb --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8517088b338a89e48a32261e3ebbb7a0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor.meta new file mode 100644 index 0000000..7f92ac2 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9438ede469a708a41975622dac3d5cd5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/AssemblyImportSettingsAutomation.cs b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/AssemblyImportSettingsAutomation.cs new file mode 100644 index 0000000..0a40989 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/AssemblyImportSettingsAutomation.cs @@ -0,0 +1,134 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +#if UNITY_EDITOR && UNITY_5_6_OR_NEWER + +namespace Sirenix.OdinInspector.Editor +{ + using System.IO; + using System.Collections.Generic; + using Sirenix.Serialization.Utilities.Editor; + using Sirenix.Utilities; + using UnityEditor; + using UnityEditor.Build; + +#if UNITY_2018_1_OR_NEWER + using UnityEditor.Build.Reporting; +#endif + + public class AssemblyImportSettingsAutomation : +#if UNITY_2018_1_OR_NEWER + IPreprocessBuildWithReport +#else + IPreprocessBuild +#endif + { + + public int callbackOrder { get { return -1500; } } + + private static void ConfigureImportSettings() + { + if (EditorOnlyModeConfig.Instance.IsEditorOnlyModeEnabled() || ImportSettingsConfig.Instance.AutomateBeforeBuild == false) + { + return; + } + + var assemblyDir = new DirectoryInfo(SirenixAssetPaths.SirenixAssembliesPath).FullName; + var projectAssetsPath = Directory.GetCurrentDirectory().TrimEnd('\\', '/'); + + var isPackage = PathUtilities.HasSubDirectory(new DirectoryInfo(projectAssetsPath), new DirectoryInfo(assemblyDir)) == false; + + var aotDirPath = assemblyDir + "NoEmitAndNoEditor/"; + var jitDirPath = assemblyDir + "NoEditor/"; + + var aotDir = new DirectoryInfo(aotDirPath); + var jitDir = new DirectoryInfo(jitDirPath); + + var aotAssemblies = new List(); + var jitAssemblies = new List(); + + foreach (var file in aotDir.GetFiles("*.dll")) + { + string path = file.FullName; + if (isPackage) + { + path = SirenixAssetPaths.SirenixAssembliesPath.TrimEnd('\\', '/') + "/" + path.Substring(assemblyDir.Length); + } + else + { + path = path.Substring(projectAssetsPath.Length + 1); + } + + aotAssemblies.Add(path); + } + + foreach (var file in jitDir.GetFiles("*.dll")) + { + string path = file.FullName; + if (isPackage) + { + path = SirenixAssetPaths.SirenixAssembliesPath.TrimEnd('\\', '/') + "/" + path.Substring(assemblyDir.Length); + } + else + { + path = path.Substring(projectAssetsPath.Length + 1); + } + + jitAssemblies.Add(path); + } + + AssetDatabase.StartAssetEditing(); + try + { + var platform = EditorUserBuildSettings.activeBuildTarget; + + if (AssemblyImportSettingsUtilities.IsJITSupported( + platform, + AssemblyImportSettingsUtilities.GetCurrentScriptingBackend(), + AssemblyImportSettingsUtilities.GetCurrentApiCompatibilityLevel())) + { + ApplyImportSettings(platform, aotAssemblies.ToArray(), OdinAssemblyImportSettings.ExcludeFromAll); + ApplyImportSettings(platform, jitAssemblies.ToArray(), OdinAssemblyImportSettings.IncludeInBuildOnly); + } + else + { + ApplyImportSettings(platform, aotAssemblies.ToArray(), OdinAssemblyImportSettings.IncludeInBuildOnly); + ApplyImportSettings(platform, jitAssemblies.ToArray(), OdinAssemblyImportSettings.ExcludeFromAll); + } + } + finally + { + AssetDatabase.StopAssetEditing(); + } + } + + private static void ApplyImportSettings(BuildTarget platform, string[] assemblyPaths, OdinAssemblyImportSettings importSettings) + { + for (int i = 0; i < assemblyPaths.Length; i++) + { + AssemblyImportSettingsUtilities.SetAssemblyImportSettings(platform, assemblyPaths[i], importSettings); + } + } + +#if UNITY_2018_1_OR_NEWER + + void IPreprocessBuildWithReport.OnPreprocessBuild(BuildReport report) + { + ConfigureImportSettings(); + } + +#else + + void IPreprocessBuild.OnPreprocessBuild(BuildTarget target, string path) + { + ConfigureImportSettings(); + } + +#endif + } +} + +#endif // UNITY_EDITOR && UNITY_5_6_OR_NEWER \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/AssemblyImportSettingsAutomation.cs.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/AssemblyImportSettingsAutomation.cs.meta new file mode 100644 index 0000000..f0c0967 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/AssemblyImportSettingsAutomation.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d4d815a2bfd253342bfd6542c08315fb +timeCreated: 1533296750 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/BuildAOTAutomation.cs b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/BuildAOTAutomation.cs new file mode 100644 index 0000000..88b438b --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/BuildAOTAutomation.cs @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +#if UNITY_EDITOR && UNITY_5_6_OR_NEWER + +namespace Sirenix.Serialization.Internal +{ + using Sirenix.Serialization; + using UnityEditor; + using UnityEditor.Build; + using System.IO; + using System; + +#if UNITY_2018_1_OR_NEWER + + using UnityEditor.Build.Reporting; + +#endif + +#if UNITY_2018_1_OR_NEWER + public class PreBuildAOTAutomation : IPreprocessBuildWithReport +#else + public class PreBuildAOTAutomation : IPreprocessBuild +#endif + { + public int callbackOrder { get { return -1000; } } + + public void OnPreprocessBuild(BuildTarget target, string path) + { + if (AOTGenerationConfig.Instance.ShouldAutomationGeneration(target)) + { + AOTGenerationConfig.Instance.ScanProject(); + AOTGenerationConfig.Instance.GenerateDLL(); + } + } + +#if UNITY_2018_1_OR_NEWER + + public void OnPreprocessBuild(BuildReport report) + { + this.OnPreprocessBuild(report.summary.platform, report.summary.outputPath); + } + +#endif + } + +#if UNITY_2018_1_OR_NEWER + public class PostBuildAOTAutomation : IPostprocessBuildWithReport +#else + public class PostBuildAOTAutomation : IPostprocessBuild +#endif + { + public int callbackOrder { get { return -1000; } } + + public void OnPostprocessBuild(BuildTarget target, string path) + { + if (AOTGenerationConfig.Instance.DeleteDllAfterBuilds && AOTGenerationConfig.Instance.ShouldAutomationGeneration(target)) + { + Directory.Delete(AOTGenerationConfig.Instance.AOTFolderPath, true); + File.Delete(AOTGenerationConfig.Instance.AOTFolderPath.TrimEnd('/', '\\') + ".meta"); + AssetDatabase.Refresh(); + } + } + +#if UNITY_2018_1_OR_NEWER + + public void OnPostprocessBuild(BuildReport report) + { + this.OnPostprocessBuild(report.summary.platform, report.summary.outputPath); + } + +#endif + } +} + +#endif // UNITY_EDITOR && UNITY_5_6_OR_NEWER \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/BuildAOTAutomation.cs.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/BuildAOTAutomation.cs.meta new file mode 100644 index 0000000..cf0c388 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/BuildAOTAutomation.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: dd3672808cdf76541aa3d383c87a5616 +timeCreated: 1514538277 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/EnsureOdinInspectorDefine.cs b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/EnsureOdinInspectorDefine.cs new file mode 100644 index 0000000..bb77c1c --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/EnsureOdinInspectorDefine.cs @@ -0,0 +1,121 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +#if UNITY_EDITOR + +namespace Sirenix.Utilities +{ + using System; + using System.Linq; + using UnityEditor; + + /// + /// Defines the ODIN_INSPECTOR symbol. + /// + internal static class EnsureOdinInspectorDefine + { + private static readonly string[] DEFINES = new string[] { "ODIN_INSPECTOR", "ODIN_INSPECTOR_3" }; + + [InitializeOnLoadMethod] + private static void EnsureScriptingDefineSymbol() + { + var currentTarget = EditorUserBuildSettings.selectedBuildTargetGroup; + + if (currentTarget == BuildTargetGroup.Unknown) + { + return; + } + + var definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(currentTarget).Trim(); + var defines = definesString.Split(';'); + + bool changed = false; + + foreach (var define in DEFINES) + { + if (defines.Contains(define) == false) + { + if (definesString.EndsWith(";", StringComparison.InvariantCulture) == false) + { + definesString += ";"; + } + + definesString += define; + changed = true; + } + } + + if (changed) + { + PlayerSettings.SetScriptingDefineSymbolsForGroup(currentTarget, definesString); + } + } + } + + // + // If you have a project where only some users have Odin, and you want to utilize the ODIN_INSPECTOR + // define symbol. Then, in order to only define the symbol for those with Odin, you can delete this script, + // which prevent ODIN_INSPECTOR from being added to the Unity's player settings. + // + // And instead automatically add the ODIN_INSPECTOR define to an mcs.rsp file if Odin exists using the script below. + // You can then ignore the mcs.rsp file in source control. + // + // Remember to manually remove the ODIN_INSPECTOR define symbol in player settings after removing this script. + // + // static class AddOdinInspectorDefineIfOdinExist + // { + // private const string ODIN_MCS_DEFINE = "-define:ODIN_INSPECTOR"; + // + // [InitializeOnLoadMethod] + // private static void AddOrRemoveOdinDefine() + // { + // var addDefine = AppDomain.CurrentDomain.GetAssemblies().Any(x => x.FullName.StartsWith("Sirenix.OdinInspector.Editor")); + // + // #if ODIN_INSPECTOR + // var hasDefine = true; + // #else + // var hasDefine = false; + // #endif + // + // if (addDefine == hasDefine) + // { + // return; + // } + // + // var mcsPath = Path.Combine(Application.dataPath, "mcs.rsp"); + // var hasMcsFile = File.Exists(mcsPath); + // + // if (addDefine) + // { + // var lines = hasMcsFile ? File.ReadAllLines(mcsPath).ToList() : new List(); + // if (!lines.Any(x => x.Trim() == ODIN_MCS_DEFINE)) + // { + // lines.Add(ODIN_MCS_DEFINE); + // File.WriteAllLines(mcsPath, lines.ToArray()); + // AssetDatabase.Refresh(); + // } + // } + // else if (hasMcsFile) + // { + // var linesWithoutOdinDefine = File.ReadAllLines(mcsPath).Where(x => x.Trim() != ODIN_MCS_DEFINE).ToArray(); + // + // if (linesWithoutOdinDefine.Length == 0) + // { + // // Optional - Remove the mcs file instead if it doesn't contain any lines. + // File.Delete(mcsPath); + // } + // else + // { + // File.WriteAllLines(mcsPath, linesWithoutOdinDefine); + // } + // + // AssetDatabase.Refresh(); + // } + // } + // } +} + +#endif // UNITY_EDITOR \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/EnsureOdinInspectorDefine.cs.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/EnsureOdinInspectorDefine.cs.meta new file mode 100644 index 0000000..4619d98 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/EnsureOdinInspectorDefine.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d9763cb398cf6e146b74d6b7bac2fe50 +timeCreated: 1519909294 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs new file mode 100644 index 0000000..cf30f7d --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs @@ -0,0 +1,208 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +#if UNITY_EDITOR && UNITY_2018_3_OR_NEWER +#pragma warning disable + +namespace Sirenix.OdinInspector.Editor.Drawers +{ + using Sirenix.OdinInspector; + using Sirenix.OdinInspector.Editor; + using Sirenix.Utilities; + using Sirenix.Utilities.Editor; + using System.Linq; + using UnityEditor; + using UnityEngine; + + [DrawerPriority(0.001, 0, 0)] + public class FixBrokenUnityObjectWrapperDrawer : OdinValueDrawer, IDefinesGenericMenuItems + where T : UnityEngine.Component + { + private const string AUTO_FIX_PREFS_KEY = "TemporarilyBrokenUnityObjectWrapperDrawer.autoFix"; + + private bool isBroken = false; + private T realWrapperInstance; + private bool allowSceneViewObjects; + private static bool autoFix; + + protected override void Initialize() + { + this.allowSceneViewObjects = this.ValueEntry.Property.GetAttribute() == null; + autoFix = EditorPrefs.HasKey(AUTO_FIX_PREFS_KEY); + } + + protected override void DrawPropertyLayout(GUIContent label) + { + if (!(this.ValueEntry.ValueState == PropertyValueState.NullReference || this.ValueEntry.ValueState == PropertyValueState.ReferenceValueConflict)) + { + this.CallNextDrawer(label); + return; + } + + if (Event.current.type == EventType.Layout) + { + this.isBroken = false; + var count = this.ValueEntry.ValueCount; + for (int i = 0; i < count; i++) + { + var component = this.ValueEntry.Values[i]; + + if (ComponentIsBroken(component, ref this.realWrapperInstance)) + { + this.isBroken = true; + break; + } + } + + if (this.isBroken && autoFix) + { + this.isBroken = false; + + for (int i = 0; i < this.ValueEntry.ValueCount; i++) + { + T fixedComponent = null; + if (ComponentIsBroken(this.ValueEntry.Values[i], ref fixedComponent) && fixedComponent) + { + (this.ValueEntry as IValueEntryActualValueSetter).SetActualValue(i, fixedComponent); + } + } + + this.ValueEntry.Update(); + } + } + + if (!this.isBroken) + { + this.CallNextDrawer(label); + return; + } + + var rect = EditorGUILayout.GetControlRect(label != null); + var btnRect = rect.AlignRight(20); + var controlRect = rect.SetXMax(btnRect.xMin - 5); + + object newInstance = null; + + EditorGUI.BeginChangeCheck(); + { + if (this.ValueEntry.BaseValueType.IsInterface) + { + newInstance = SirenixEditorFields.PolymorphicObjectField(controlRect, + label, + this.realWrapperInstance, + this.ValueEntry.BaseValueType, + this.allowSceneViewObjects); + } + else + { + newInstance = SirenixEditorFields.UnityObjectField( + controlRect, + label, + this.realWrapperInstance, + this.ValueEntry.BaseValueType, + this.allowSceneViewObjects) as Component; + } + } + if (EditorGUI.EndChangeCheck()) + { + this.ValueEntry.WeakSmartValue = newInstance; + } + + if (GUI.Button(btnRect, " ", EditorStyles.miniButton)) + { + var popup = new FixBrokenUnityObjectWrapperPopup(this.ValueEntry); + OdinEditorWindow.InspectObjectInDropDown(popup, 300); + } + + if (Event.current.type == EventType.Repaint) + { + GUI.DrawTexture(btnRect, EditorIcons.ConsoleWarnicon, ScaleMode.ScaleToFit); + } + } + + private static bool ComponentIsBroken(T component, ref T realInstance) + { + var uObj = component; + var oObj = (object)uObj; + + if (oObj != null && uObj == null) + { + var instanceId = uObj.GetInstanceID(); + if (AssetDatabase.Contains(instanceId)) + { + var path = AssetDatabase.GetAssetPath(instanceId); + var realWrapper = AssetDatabase.LoadAllAssetsAtPath(path).FirstOrDefault(n => n.GetInstanceID() == instanceId) as T; + if (realWrapper) + { + realInstance = realWrapper; + return true; + } + } + } + + return false; + } + + public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu) + { + if (EditorPrefs.HasKey(AUTO_FIX_PREFS_KEY)) + { + genericMenu.AddItem(new GUIContent("Disable auto-fix of broken prefab instance references"), false, (x) => + { + EditorPrefs.DeleteKey(AUTO_FIX_PREFS_KEY); + autoFix = false; + }, null); + } + } + + [TypeInfoBox("This asset reference is temporarily broken until the next reload, because of an error in Unity where the C# wrapper object of a prefab asset is destroyed when changes are made to that prefab asset. This error has been reported to Unity.\n\nMeanwhile, Odin can fix this for you by getting a new, valid wrapper object from the asset database and replacing the broken wrapper instance with the new one.")] + private class FixBrokenUnityObjectWrapperPopup + { + private IPropertyValueEntry valueEntry; + + public FixBrokenUnityObjectWrapperPopup(IPropertyValueEntry valueEntry) + { + this.valueEntry = valueEntry; + } + + [HorizontalGroup, Button(ButtonSizes.Large)] + public void FixItThisTime() + { + for (int i = 0; i < this.valueEntry.ValueCount; i++) + { + var localI = i; + T fixedComponent = null; + if (ComponentIsBroken(this.valueEntry.Values[i], ref fixedComponent) && fixedComponent) + { + this.valueEntry.Property.Tree.DelayActionUntilRepaint(() => + { + (this.valueEntry as IValueEntryActualValueSetter).SetActualValue(localI, fixedComponent); + }); + } + } + + if (GUIHelper.CurrentWindow) + { + EditorApplication.delayCall += GUIHelper.CurrentWindow.Close; + } + } + + [HorizontalGroup, Button(ButtonSizes.Large)] + public void FixItAlways() + { + EditorPrefs.SetBool(AUTO_FIX_PREFS_KEY, true); + autoFix = true; + + if (GUIHelper.CurrentWindow) + { + EditorApplication.delayCall += GUIHelper.CurrentWindow.Close; + } + } + } + } +} + +#endif \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs.meta new file mode 100644 index 0000000..ae85733 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 903c11a9cf3ba6f4e8c653443c6893a0 +timeCreated: 1546967292 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Sirenix.OdinInspector.CompatibilityLayer.Editor.asmdef b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Sirenix.OdinInspector.CompatibilityLayer.Editor.asmdef new file mode 100644 index 0000000..0de0c97 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Sirenix.OdinInspector.CompatibilityLayer.Editor.asmdef @@ -0,0 +1,15 @@ +{ + "name": "Sirenix.OdinInspector.CompatibilityLayer.Editor", + "references": [ + "Sirenix.OdinInspector.CompatibilityLayer" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": true, + "autoReferenced": true, + "overrideReferences": false, + "precompiledReferences": [], + "defineConstraints": [] +} \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Sirenix.OdinInspector.CompatibilityLayer.Editor.asmdef.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Sirenix.OdinInspector.CompatibilityLayer.Editor.asmdef.meta new file mode 100644 index 0000000..189de6c --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Sirenix.OdinInspector.CompatibilityLayer.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4db1229c02f3f629bdd928353859c2b3 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncListDrawer.cs b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncListDrawer.cs new file mode 100644 index 0000000..f629440 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncListDrawer.cs @@ -0,0 +1,88 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +#if UNITY_EDITOR && !UNITY_2019_1_OR_NEWER +#pragma warning disable 0618 + +namespace Sirenix.OdinInspector.Editor.Drawers +{ + using Sirenix.Utilities.Editor; + using UnityEditor; + using UnityEngine; + using UnityEngine.Networking; + + /// + /// SyncList property drawer. + /// + [DrawerPriority(0, 0, 2)] + public class SyncListDrawer : OdinValueDrawer where TList : SyncList + { + private LocalPersistentContext visible; + + protected override void Initialize() + { + this.visible = this.Property.Context.GetPersistent(this, "expanded", GeneralDrawerConfig.Instance.OpenListsByDefault); + } + + /// + /// Draws the property. + /// + protected override void DrawPropertyLayout(GUIContent label) + { + var entry = this.ValueEntry; + var property = entry.Property; + int minCount = int.MaxValue; + int maxCount = 0; + + for (int i = 0; i < entry.ValueCount; i++) + { + if (entry.Values[i].Count > maxCount) + { + maxCount = entry.Values[i].Count; + } + + if (entry.Values[i].Count < minCount) + { + minCount = entry.Values[i].Count; + } + } + + SirenixEditorGUI.BeginHorizontalToolbar(); + this.visible.Value = SirenixEditorGUI.Foldout(this.visible.Value, GUIHelper.TempContent("SyncList " + label.text + " [" + typeof(TList).Name + "]")); + EditorGUILayout.LabelField(GUIHelper.TempContent(minCount == maxCount ? (minCount == 0 ? "Empty" : minCount + " items") : minCount + " (" + maxCount + ") items"), SirenixGUIStyles.RightAlignedGreyMiniLabel); + SirenixEditorGUI.EndHorizontalToolbar(); + + if (SirenixEditorGUI.BeginFadeGroup(this.visible, this.visible.Value)) + { + GUIHelper.PushGUIEnabled(false); + SirenixEditorGUI.BeginVerticalList(); + { + var elementLabel = new GUIContent(); + for (int i = 0; i < maxCount; i++) + { + SirenixEditorGUI.BeginListItem(); + elementLabel.text = "Item " + i; + + if (i < minCount) + { + property.Children[i].Draw(elementLabel); + } + else + { + EditorGUILayout.LabelField(elementLabel, SirenixEditorGUI.MixedValueDashChar); + } + SirenixEditorGUI.EndListItem(); + } + } + SirenixEditorGUI.EndVerticalList(); + GUIHelper.PopGUIEnabled(); + } + SirenixEditorGUI.EndFadeGroup(); + } + } +} + +#endif // UNITY_EDITOR && !UNITY_2019_1_OR_NEWER \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncListDrawer.cs.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncListDrawer.cs.meta new file mode 100644 index 0000000..0fe8235 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncListDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 047c7e4af9c032a428c12b7c564a6593 +timeCreated: 1545410615 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncVarAttributeDrawer.cs b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncVarAttributeDrawer.cs new file mode 100644 index 0000000..34be37f --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncVarAttributeDrawer.cs @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +#if UNITY_EDITOR && !UNITY_2019_1_OR_NEWER +#pragma warning disable 0618 + +namespace Sirenix.OdinInspector.Editor.Drawers +{ + using Sirenix.Utilities; + using UnityEditor; + using UnityEngine; + using UnityEngine.Networking; + + /// + /// SyncVar attribute drawer. + /// + public class SyncVarAttributeDrawer : OdinAttributeDrawer + { + /// + /// Draws the property. + /// + protected override void DrawPropertyLayout(GUIContent label) + { + GUILayout.BeginHorizontal(); + { + GUILayout.BeginVertical(); + { + this.CallNextDrawer(label); + } + GUILayout.EndVertical(); + + GUILayout.Label("SyncVar", EditorStyles.miniLabel, GUILayoutOptions.Width(52f)); + } + GUILayout.EndHorizontal(); + } + } +} + +#endif // UNITY_EDITOR && !UNITY_2019_1_OR_NEWER \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncVarAttributeDrawer.cs.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncVarAttributeDrawer.cs.meta new file mode 100644 index 0000000..8ddc41f --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/SyncVarAttributeDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bda5b631304c8cb4485d60ef8bda618b +timeCreated: 1545410615 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Vector2IntMinMaxAttributeDrawer.cs b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Vector2IntMinMaxAttributeDrawer.cs new file mode 100644 index 0000000..089f90d --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Vector2IntMinMaxAttributeDrawer.cs @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +#if UNITY_EDITOR && UNITY_2017_2_OR_NEWER + +namespace Sirenix.OdinInspector.Editor.Drawers +{ + using Sirenix.OdinInspector; + using Sirenix.OdinInspector.Editor; + using Sirenix.OdinInspector.Editor.ValueResolvers; + using Sirenix.Utilities; + using Sirenix.Utilities.Editor; + using System.Reflection; + using UnityEditor; + using UnityEngine; + + /// + /// Draws Vector2Int properties marked with . + /// + public class Vector2IntMinMaxAttributeDrawer : OdinAttributeDrawer + { + private ValueResolver minGetter; + private ValueResolver maxGetter; + private ValueResolver vector2IntMinMaxGetter; + + /// + /// Initializes the drawer by resolving any optional references to members for min/max value. + /// + protected override void Initialize() + { + // Min member reference. + this.minGetter = ValueResolver.Get(this.Property, this.Attribute.MinValueGetter, this.Attribute.MinValue); + this.maxGetter = ValueResolver.Get(this.Property, this.Attribute.MaxValueGetter, this.Attribute.MaxValue); + + // Min max member reference. + if (this.Attribute.MinMaxValueGetter != null) + { + this.vector2IntMinMaxGetter = ValueResolver.Get(this.Property, this.Attribute.MinMaxValueGetter); + } + } + + /// + /// Draws the property. + /// + protected override void DrawPropertyLayout(GUIContent label) + { + ValueResolver.DrawErrors(this.minGetter, this.maxGetter, this.vector2IntMinMaxGetter); + + // Get the range of the slider from the attribute or from member references. + Vector2 range; + if (this.vector2IntMinMaxGetter != null && !this.vector2IntMinMaxGetter.HasError) + { + range = (Vector2)this.vector2IntMinMaxGetter.GetValue(); + } + else + { + range.x = this.minGetter.GetValue(); + range.y = this.maxGetter.GetValue(); + } + + EditorGUI.BeginChangeCheck(); + Vector2 value = SirenixEditorFields.MinMaxSlider(label, (Vector2)this.ValueEntry.SmartValue, range, this.Attribute.ShowFields); + if (EditorGUI.EndChangeCheck()) + { + this.ValueEntry.SmartValue = new Vector2Int((int)value.x, (int)value.y); + } + } + } +} +#endif // UNITY_EDITOR && UNITY_2017_2_OR_NEWER \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Vector2IntMinMaxAttributeDrawer.cs.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Vector2IntMinMaxAttributeDrawer.cs.meta new file mode 100644 index 0000000..67aec2c --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/Vector2IntMinMaxAttributeDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 30393ed590c8fb64da0612e8a2fad8a4 +timeCreated: 1532688697 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntDrawers.cs b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntDrawers.cs new file mode 100644 index 0000000..795bf89 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntDrawers.cs @@ -0,0 +1,141 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +#if UNITY_EDITOR && UNITY_2017_2_OR_NEWER + +namespace Sirenix.OdinInspector.Editor.Drawers +{ + using Utilities.Editor; + using UnityEditor; + using UnityEngine; + + /// + /// Vector2Int proprety drawer. + /// + public sealed class Vector2IntDrawer : OdinValueDrawer, IDefinesGenericMenuItems + { + /// + /// Draws the property. + /// + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + var contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + EditorGUI.BeginChangeCheck(); + var val = SirenixEditorFields.VectorPrefixSlideRect(labelRect, (Vector2)this.ValueEntry.SmartValue); + if (EditorGUI.EndChangeCheck()) + { + this.ValueEntry.SmartValue = new Vector2Int((int)val.x, (int)val.y); + } + + var showLabels = SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + + /// + /// Populates the generic menu for the property. + /// + public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu) + { + Vector2Int value = (Vector2Int)property.ValueEntry.WeakSmartValue; + + if (genericMenu.GetItemCount() > 0) + { + genericMenu.AddSeparator(""); + } + genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0)"), value == Vector2Int.zero, () => SetVector(property, Vector2Int.zero)); + genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1)"), value == Vector2Int.one, () => SetVector(property, Vector2Int.one)); + genericMenu.AddSeparator(""); + genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0)"), value == Vector2Int.right, () => SetVector(property, Vector2Int.right)); + genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0)"), value == Vector2Int.left, () => SetVector(property, Vector2Int.left)); + genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1)"), value == Vector2Int.up, () => SetVector(property, Vector2Int.up)); + genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1)"), value == Vector2Int.down, () => SetVector(property, Vector2Int.down)); + } + + private void SetVector(InspectorProperty property, Vector2Int value) + { + property.Tree.DelayActionUntilRepaint(() => + { + for (int i = 0; i < property.ValueEntry.ValueCount; i++) + { + property.ValueEntry.WeakValues[i] = value; + } + }); + } + } + + /// + /// Vector3Int property drawer. + /// + public sealed class Vector3IntDrawer : OdinValueDrawer, IDefinesGenericMenuItems + { + /// + /// Draws the property. + /// + protected override void DrawPropertyLayout(GUIContent label) + { + Rect labelRect; + var contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect); + { + EditorGUI.BeginChangeCheck(); + var val = SirenixEditorFields.VectorPrefixSlideRect(labelRect, (Vector3)this.ValueEntry.SmartValue); + if (EditorGUI.EndChangeCheck()) + { + this.ValueEntry.SmartValue = new Vector3Int((int)val.x, (int)val.y, (int)val.z); + } + + var showLabels = SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185; + GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth); + this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null); + this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null); + this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null); + GUIHelper.PopLabelWidth(); + + } + SirenixEditorGUI.EndHorizontalPropertyLayout(); + } + + /// + /// Populates the generic menu for the property. + /// + public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu) + { + Vector3Int value = (Vector3Int)property.ValueEntry.WeakSmartValue; + + if (genericMenu.GetItemCount() > 0) + { + genericMenu.AddSeparator(""); + } + + genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0, 0)"), value == Vector3Int.zero, () => SetVector(property, Vector3Int.zero)); + genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1, 1)"), value == Vector3Int.one, () => SetVector(property, Vector3Int.one)); + genericMenu.AddSeparator(""); + genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0, 0)"), value == Vector3Int.right, () => SetVector(property, Vector3Int.right)); + genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0, 0)"), value == Vector3Int.left, () => SetVector(property, Vector3Int.left)); + genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1, 0)"), value == Vector3Int.up, () => SetVector(property, Vector3Int.up)); + genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1, 0)"), value == Vector3Int.down, () => SetVector(property, Vector3Int.down)); + genericMenu.AddItem(new GUIContent("Forward", "Set the vector property to (0, 0, 1)"), value == new Vector3Int(0, 0, 1), () => SetVector(property, new Vector3Int(0, 0, 1))); + genericMenu.AddItem(new GUIContent("Back", "Set the vector property to (0, 0, -1)"), value == new Vector3Int(0, 0, -1), () => SetVector(property, new Vector3Int(0, 0, -1))); + } + + private void SetVector(InspectorProperty property, Vector3Int value) + { + property.Tree.DelayActionUntilRepaint(() => + { + property.ValueEntry.WeakSmartValue = value; + }); + } + } +} + +#endif // UNITY_EDITOR && UNITY_2017_2_OR_NEWER \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntDrawers.cs.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntDrawers.cs.meta new file mode 100644 index 0000000..079096c --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntDrawers.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2fc48d59edff00f49b8ae717c776ff45 +timeCreated: 1520596090 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntPropertyResolvers.cs b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntPropertyResolvers.cs new file mode 100644 index 0000000..c62f2e5 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntPropertyResolvers.cs @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +#if UNITY_EDITOR && UNITY_2017_2_OR_NEWER + +namespace Sirenix.OdinInspector.Editor.Drawers +{ + using UnityEngine; + + public sealed class Vector2IntResolver : BaseMemberPropertyResolver + { + protected override InspectorPropertyInfo[] GetPropertyInfos() + { + return new InspectorPropertyInfo[] + { + InspectorPropertyInfo.CreateValue("x", 0, this.Property.ValueEntry.SerializationBackend, + new GetterSetter( + getter: (ref Vector2Int vec) => vec.x, + setter: (ref Vector2Int vec, int value) => vec.x = value)), + InspectorPropertyInfo.CreateValue("y", 0, this.Property.ValueEntry.SerializationBackend, + new GetterSetter( + getter: (ref Vector2Int vec) => vec.y, + setter: (ref Vector2Int vec, int value) => vec.y = value)), + }; + } + } + + public sealed class Vector3IntResolver : BaseMemberPropertyResolver + { + protected override InspectorPropertyInfo[] GetPropertyInfos() + { + return new InspectorPropertyInfo[] + { + InspectorPropertyInfo.CreateValue("x", 0, this.Property.ValueEntry.SerializationBackend, + new GetterSetter( + getter: (ref Vector3Int vec) => vec.x, + setter: (ref Vector3Int vec, int value) => vec.x = value)), + InspectorPropertyInfo.CreateValue("y", 0, this.Property.ValueEntry.SerializationBackend, + new GetterSetter( + getter: (ref Vector3Int vec) => vec.y, + setter: (ref Vector3Int vec, int value) => vec.y = value)), + InspectorPropertyInfo.CreateValue("z", 0, this.Property.ValueEntry.SerializationBackend, + new GetterSetter( + getter: (ref Vector3Int vec) => vec.z, + setter: (ref Vector3Int vec, int value) => vec.z = value)), + }; + } + } +} + +#endif // UNITY_EDITOR && UNITY_2017_2_OR_NEWER \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntPropertyResolvers.cs.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntPropertyResolvers.cs.meta new file mode 100644 index 0000000..b008adb --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/VectorIntPropertyResolvers.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 435323e396d85494daeb5278528fe138 +timeCreated: 1539340561 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/SerializedNetworkBehaviour.cs b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/SerializedNetworkBehaviour.cs new file mode 100644 index 0000000..84ae8e6 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/SerializedNetworkBehaviour.cs @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +#if !UNITY_2019_1_OR_NEWER +#pragma warning disable 0618 + +namespace Sirenix.OdinInspector +{ + using Sirenix.Serialization; + using UnityEngine; + using UnityEngine.Networking; + + /// + /// A Unity NetworkBehaviour which is serialized by the Sirenix serialization system. + /// Please note that Odin's custom serialization only works for non-synced variables - [SyncVar] and SyncLists still have the same limitations. + /// + [ShowOdinSerializedPropertiesInInspector] + public abstract class SerializedNetworkBehaviour : NetworkBehaviour, ISerializationCallbackReceiver, ISupportsPrefabSerialization + { + [SerializeField, HideInInspector] + private SerializationData serializationData; + + SerializationData ISupportsPrefabSerialization.SerializationData { get { return this.serializationData; } set { this.serializationData = value; } } + + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + UnitySerializationUtility.DeserializeUnityObject(this, ref this.serializationData); + this.OnAfterDeserialize(); + } + + void ISerializationCallbackReceiver.OnBeforeSerialize() + { + UnitySerializationUtility.SerializeUnityObject(this, ref this.serializationData); + this.OnBeforeSerialize(); + } + + /// + /// Invoked after deserialization has taken place. + /// + protected virtual void OnAfterDeserialize() + { + } + + /// + /// Invoked before serialization has taken place. + /// + protected virtual void OnBeforeSerialize() + { + } + +#if UNITY_EDITOR + + [HideInTables] + [OnInspectorGUI, PropertyOrder(int.MinValue)] + private void InternalOnInspectorGUI() + { + EditorOnlyModeConfigUtility.InternalOnInspectorGUI(this); + } + +#endif + } +} + +#endif // UNITY_2019_1_OR_NEWER \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/SerializedNetworkBehaviour.cs.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/SerializedNetworkBehaviour.cs.meta new file mode 100644 index 0000000..3c81a9a --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/SerializedNetworkBehaviour.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5d496f720527c984b8acc75a238bbd79 +timeCreated: 1545412221 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Sirenix.OdinInspector.CompatibilityLayer.asmdef b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Sirenix.OdinInspector.CompatibilityLayer.asmdef new file mode 100644 index 0000000..0d79168 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Sirenix.OdinInspector.CompatibilityLayer.asmdef @@ -0,0 +1,11 @@ +{ + "name": "Sirenix.OdinInspector.CompatibilityLayer", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "autoReferenced": true, + "overrideReferences": false, + "precompiledReferences": [], + "defineConstraints": [] +} \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Sirenix.OdinInspector.CompatibilityLayer.asmdef.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Sirenix.OdinInspector.CompatibilityLayer.asmdef.meta new file mode 100644 index 0000000..d6566a7 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Sirenix.OdinInspector.CompatibilityLayer.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e048eeec9bdb9d30448017b829deb3f6 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/VectorIntFormatters.cs b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/VectorIntFormatters.cs new file mode 100644 index 0000000..65c1036 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/VectorIntFormatters.cs @@ -0,0 +1,80 @@ +#if UNITY_2017_2_OR_NEWER + +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +[assembly: Sirenix.Serialization.RegisterFormatter(typeof(Sirenix.Serialization.Vector2IntFormatter))] +[assembly: Sirenix.Serialization.RegisterFormatter(typeof(Sirenix.Serialization.Vector3IntFormatter))] +namespace Sirenix.Serialization +{ + using UnityEngine; + + /// + /// Custom formatter for the type. + /// + /// + public class Vector2IntFormatter : MinimalBaseFormatter + { + private static readonly Serializer Serializer = Serialization.Serializer.Get(); + + /// + /// Reads into the specified value using the specified reader. + /// + /// The value to read into. + /// The reader to use. + protected override void Read(ref Vector2Int value, IDataReader reader) + { + value.x = Vector2IntFormatter.Serializer.ReadValue(reader); + value.y = Vector2IntFormatter.Serializer.ReadValue(reader); + } + + /// + /// Writes from the specified value using the specified writer. + /// + /// The value to write from. + /// The writer to use. + protected override void Write(ref Vector2Int value, IDataWriter writer) + { + Vector2IntFormatter.Serializer.WriteValue(value.x, writer); + Vector2IntFormatter.Serializer.WriteValue(value.y, writer); + } + } + + /// + /// Custom formatter for the type. + /// + /// + public class Vector3IntFormatter : MinimalBaseFormatter + { + private static readonly Serializer Serializer = Serialization.Serializer.Get(); + + /// + /// Reads into the specified value using the specified reader. + /// + /// The value to read into. + /// The reader to use. + protected override void Read(ref Vector3Int value, IDataReader reader) + { + value.x = Vector3IntFormatter.Serializer.ReadValue(reader); + value.y = Vector3IntFormatter.Serializer.ReadValue(reader); + value.z = Vector3IntFormatter.Serializer.ReadValue(reader); + } + + /// + /// Writes from the specified value using the specified writer. + /// + /// The value to write from. + /// The writer to use. + protected override void Write(ref Vector3Int value, IDataWriter writer) + { + Vector3IntFormatter.Serializer.WriteValue(value.x, writer); + Vector3IntFormatter.Serializer.WriteValue(value.y, writer); + Vector3IntFormatter.Serializer.WriteValue(value.z, writer); + } + } +} + +#endif \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/VectorIntFormatters.cs.meta b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/VectorIntFormatters.cs.meta new file mode 100644 index 0000000..f1e500e --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/VectorIntFormatters.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a2f1c424a60dfbd4fa331449baeac351 +timeCreated: 1520596090 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Readme.txt b/Assets/Plugins/Sirenix/Readme.txt new file mode 100644 index 0000000..c39dd1c --- /dev/null +++ b/Assets/Plugins/Sirenix/Readme.txt @@ -0,0 +1,35 @@ +------------------------------------ Getting Started ------------------------------------ + +Open up the Getting Started guide from "Tools > Odin Inspector > Getting Started." + + +------------------------------------- Helpful Links ------------------------------------- + +Tutorials: https://odininspector.com/tutorials +API Documentaion: https://odininspector.com/documentation +Roadmap: https://odininspector.com/roadmap +Release Notes: https://odininspector.com/patch-notes +Issue Tracker: https://bitbucket.org/sirenix/odin-inspector + + +--------------------------------- Community and Support --------------------------------- + +If you have any issues, suggestions or want advice, then you're more than welcome +to join us on Discord, or reach out to us by any other means. + +Support: https://odininspector.com/support +Community Addons: https://odininspector.com/community-tools +Discord: https://discord.gg/AgDmStu + + +-------------------------------------- Thank you! --------------------------------------- + +We really hope you like using Odin. Be sure to leave a review on the Asset Store, +that helps us out a lot! + +Leave a review: https://assetstore.unity.com/packages/tools/utilities/odin-inspector-and-serializer-89041 + + +Odin Inspector is published and developed by Sirenix. + +Sirenix: Https://sirenix.net \ No newline at end of file diff --git a/Assets/Plugins/Sirenix/Readme.txt.meta b/Assets/Plugins/Sirenix/Readme.txt.meta new file mode 100644 index 0000000..71cef77 --- /dev/null +++ b/Assets/Plugins/Sirenix/Readme.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e957a9e8b4f4bce4b8a34e504a8c39d7 +timeCreated: 1533815770 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources.meta b/Assets/Resources.meta new file mode 100644 index 0000000..cd5a4d6 --- /dev/null +++ b/Assets/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cadb47b6195e91b42a2d8db5ab4bf310 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/DOTweenSettings.asset b/Assets/Resources/DOTweenSettings.asset new file mode 100644 index 0000000..a2aadc5 --- /dev/null +++ b/Assets/Resources/DOTweenSettings.asset @@ -0,0 +1,53 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 16995157, guid: a811bde74b26b53498b4f6d872b09b6d, type: 3} + m_Name: DOTweenSettings + m_EditorClassIdentifier: + useSafeMode: 1 + safeModeOptions: + logBehaviour: 2 + nestedTweenFailureBehaviour: 0 + timeScale: 1 + useSmoothDeltaTime: 0 + maxSmoothUnscaledTime: 0.15 + rewindCallbackMode: 0 + showUnityEditorReport: 0 + logBehaviour: 0 + drawGizmos: 1 + defaultRecyclable: 0 + defaultAutoPlay: 3 + defaultUpdateType: 0 + defaultTimeScaleIndependent: 0 + defaultEaseType: 6 + defaultEaseOvershootOrAmplitude: 1.70158 + defaultEasePeriod: 0 + defaultAutoKill: 1 + defaultLoopType: 0 + debugMode: 0 + debugStoreTargetId: 1 + showPreviewPanel: 1 + storeSettingsLocation: 0 + modules: + showPanel: 0 + audioEnabled: 1 + physicsEnabled: 1 + physics2DEnabled: 1 + spriteEnabled: 1 + uiEnabled: 1 + textMeshProEnabled: 0 + tk2DEnabled: 0 + deAudioEnabled: 0 + deUnityExtendedEnabled: 0 + epoOutlineEnabled: 0 + createASMDEF: 0 + showPlayingTweens: 0 + showPausedTweens: 0 diff --git a/Assets/Resources/DOTweenSettings.asset.meta b/Assets/Resources/DOTweenSettings.asset.meta new file mode 100644 index 0000000..a5947e4 --- /dev/null +++ b/Assets/Resources/DOTweenSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f6c56f206447d814b9ae07c0474c71f0 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniversalRenderPipelineGlobalSettings.asset b/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset similarity index 100% rename from Assets/UniversalRenderPipelineGlobalSettings.asset rename to Assets/Settings/UniversalRenderPipelineGlobalSettings.asset diff --git a/Assets/UniversalRenderPipelineGlobalSettings.asset.meta b/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset.meta similarity index 100% rename from Assets/UniversalRenderPipelineGlobalSettings.asset.meta rename to Assets/Settings/UniversalRenderPipelineGlobalSettings.asset.meta diff --git a/Assets/勍.meta b/Assets/勍.meta new file mode 100644 index 0000000..6504c7e --- /dev/null +++ b/Assets/勍.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b45caa05d3d09324abeb4c7e1a777904 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/勍/场景.meta b/Assets/勍/场景.meta new file mode 100644 index 0000000..494c269 --- /dev/null +++ b/Assets/勍/场景.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b3f68c973c239d947af3b160a245827f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/SampleScene.unity b/Assets/勍/场景/骨骼测试场景.unity similarity index 66% rename from Assets/Scenes/SampleScene.unity rename to Assets/勍/场景/骨骼测试场景.unity index 7b420f6..5262e97 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/勍/场景/骨骼测试场景.unity @@ -172,6 +172,7 @@ MonoBehaviour: serializedVersion: 2 m_Bits: 1 m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 m_RenderPostProcessing: 0 m_Antialiasing: 0 m_AntialiasingQuality: 2 @@ -350,3 +351,129 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &1084903714 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 1555915082} + m_Modifications: + - target: {fileID: 951836818, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalRotation.w + value: 0.99922603 + objectReference: {fileID: 0} + - target: {fileID: 951836818, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalRotation.z + value: 0.03933591 + objectReference: {fileID: 0} + - target: {fileID: 2110753430, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalPosition.x + value: 2.3447857 + objectReference: {fileID: 0} + - target: {fileID: 2110753430, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalPosition.y + value: -0.13307858 + objectReference: {fileID: 0} + - target: {fileID: 50099845796739461, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_RootOrder + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 50099845796739461, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalPosition.x + value: -2.12 + objectReference: {fileID: 0} + - target: {fileID: 50099845796739461, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalPosition.y + value: -4.61 + objectReference: {fileID: 0} + - target: {fileID: 50099845796739461, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalPosition.z + value: -1.0228372 + objectReference: {fileID: 0} + - target: {fileID: 50099845796739461, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 50099845796739461, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 50099845796739461, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 50099845796739461, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 50099845796739461, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 50099845796739461, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 50099845796739461, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5709595267743773255, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalRotation.w + value: 0.7260015 + objectReference: {fileID: 0} + - target: {fileID: 5709595267743773255, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalRotation.z + value: -0.6876931 + objectReference: {fileID: 0} + - target: {fileID: 8522599996288171628, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalRotation.w + value: 0.99998426 + objectReference: {fileID: 0} + - target: {fileID: 8522599996288171628, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_LocalRotation.z + value: 0.0056176935 + objectReference: {fileID: 0} + - target: {fileID: 8765724049729688277, guid: c63483674e2db904197c6beaca347645, type: 3} + propertyPath: m_Name + value: "\u9A6C\u554A" + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: c63483674e2db904197c6beaca347645, type: 3} +--- !u!4 &1084903715 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 50099845796739461, guid: c63483674e2db904197c6beaca347645, type: 3} + m_PrefabInstance: {fileID: 1084903714} + m_PrefabAsset: {fileID: 0} +--- !u!1 &1555915081 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1555915082} + m_Layer: 0 + m_Name: "\u9A6C" + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1555915082 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1555915081} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.7172437, y: 0.7393208, z: 1.0228372} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1084903715} + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/Scenes/SampleScene.unity.meta b/Assets/勍/场景/骨骼测试场景.unity.meta similarity index 100% rename from Assets/Scenes/SampleScene.unity.meta rename to Assets/勍/场景/骨骼测试场景.unity.meta diff --git a/Assets/勍/美术资源.meta b/Assets/勍/美术资源.meta new file mode 100644 index 0000000..22bec73 --- /dev/null +++ b/Assets/勍/美术资源.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cc2cb915b76caf8418a6c82a9e63406b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/勍/美术资源/马啊PSD.psb b/Assets/勍/美术资源/马啊PSD.psb new file mode 100644 index 0000000000000000000000000000000000000000..251bee0da6403eb10102853b817b9ee3ed1adcf9 GIT binary patch literal 686353 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

    Xc5O9mejKWg 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

    fZl4SLTRV!CNYweG~aRsh?v>dyWZrJ;Y*PU8y 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

    XIr+t-A`RXJ#PxA< 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", + "ignore": false, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + "newSceneOverride": 0 +} \ No newline at end of file diff --git a/UserSettings/EditorUserSettings.asset b/UserSettings/EditorUserSettings.asset index 245f11f..d3cea84 100644 --- a/UserSettings/EditorUserSettings.asset +++ b/UserSettings/EditorUserSettings.asset @@ -6,8 +6,20 @@ EditorUserSettings: serializedVersion: 4 m_ConfigSettings: RecentlyUsedSceneGuid-0: + value: 515250075c0c595e5f5a5e71122159444e4e4a2f7a7d7f602f284d66b4b76661 + flags: 0 + RecentlyUsedSceneGuid-1: value: 5b520d0503545b0d0c0c0a2715770748154f4d2c7d7d7e627a7d4a35b4e1646a flags: 0 + RecentlyUsedSceneGuid-2: + value: 5550060701065c085e5c5924162609444f4f4b297e70226674284564b1b8326d + flags: 0 + RecentlyUsedSceneGuid-3: + value: 0204525104005f5f5e5d5526117b0b44424e4073752d2536747c1b31e7b3673c + flags: 0 + RecentlyUsedSceneGuid-4: + value: 02020157070050580c5b582340215c44464f4b297f7d7e64792d1c62b1e16269 + flags: 0 vcSharedLogLevel: value: 0d5e400f0650 flags: 0 diff --git a/UserSettings/Layouts/default-2021.dwlt b/UserSettings/Layouts/default-2021.dwlt index 6a0b8ed..bf65704 100644 --- a/UserSettings/Layouts/default-2021.dwlt +++ b/UserSettings/Layouts/default-2021.dwlt @@ -14,121 +14,17 @@ MonoBehaviour: m_EditorClassIdentifier: m_PixelRect: serializedVersion: 2 - x: 2249 - y: 302.5 - width: 1206 - height: 715 + x: 0 + y: 43.2 + width: 1536 + height: 772.8 m_ShowMode: 4 - m_Title: - m_RootView: {fileID: 6} + m_Title: "\u5C42\u7EA7" + m_RootView: {fileID: 2} m_MinSize: {x: 875, y: 300} m_MaxSize: {x: 10000, y: 10000} - m_Maximized: 0 + m_Maximized: 1 --- !u!114 &2 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: - - {fileID: 9} - - {fileID: 3} - m_Position: - serializedVersion: 2 - x: 0 - y: 30 - width: 1206 - height: 665 - m_MinSize: {x: 679, y: 492} - m_MaxSize: {x: 14002, y: 14042} - vertical: 0 - controlID: 119 ---- !u!114 &3 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 921 - y: 0 - width: 285 - height: 665 - m_MinSize: {x: 276, y: 71} - m_MaxSize: {x: 4001, y: 4021} - m_ActualView: {fileID: 13} - m_Panes: - - {fileID: 13} - m_Selected: 0 - m_LastSelected: 0 ---- !u!114 &4 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 0 - y: 0 - width: 228 - height: 394 - m_MinSize: {x: 201, y: 221} - m_MaxSize: {x: 4001, y: 4021} - m_ActualView: {fileID: 14} - m_Panes: - - {fileID: 14} - m_Selected: 0 - m_LastSelected: 0 ---- !u!114 &5 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: ProjectBrowser - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 0 - y: 394 - width: 921 - height: 271 - m_MinSize: {x: 231, y: 271} - m_MaxSize: {x: 10001, y: 10021} - m_ActualView: {fileID: 12} - m_Panes: - - {fileID: 12} - - {fileID: 17} - m_Selected: 0 - m_LastSelected: 1 ---- !u!114 &6 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -141,18 +37,22 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Children: - - {fileID: 7} - - {fileID: 2} - - {fileID: 8} + - {fileID: 3} + - {fileID: 4} + - {fileID: 5} m_Position: serializedVersion: 2 x: 0 y: 0 - width: 1206 - height: 715 + width: 1536 + height: 772.8 m_MinSize: {x: 875, y: 300} m_MaxSize: {x: 10000, y: 10000} ---- !u!114 &7 + m_UseTopView: 1 + m_TopViewHeight: 30 + m_UseBottomView: 1 + m_BottomViewHeight: 20 +--- !u!114 &3 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -169,14 +69,39 @@ MonoBehaviour: serializedVersion: 2 x: 0 y: 0 - width: 1206 + width: 1536 height: 30 m_MinSize: {x: 0, y: 0} m_MaxSize: {x: 0, y: 0} - m_LoadedToolbars: [] - m_MainToolbar: {fileID: 18} - m_LastLoadedLayoutName: Default ---- !u!114 &8 + m_LastLoadedLayoutName: +--- !u!114 &4 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: + - {fileID: 6} + - {fileID: 7} + - {fileID: 8} + - {fileID: 9} + m_Position: + serializedVersion: 2 + x: 0 + y: 30 + width: 1536 + height: 722.8 + m_MinSize: {x: 400, y: 200} + m_MaxSize: {x: 32384, y: 16192} + vertical: 0 + controlID: 79 +--- !u!114 &5 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -192,12 +117,12 @@ MonoBehaviour: m_Position: serializedVersion: 2 x: 0 - y: 695 - width: 1206 + y: 752.8 + width: 1536 height: 20 m_MinSize: {x: 0, y: 0} m_MaxSize: {x: 0, y: 0} ---- !u!114 &9 +--- !u!114 &6 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -211,17 +136,95 @@ MonoBehaviour: m_EditorClassIdentifier: m_Children: - {fileID: 10} - - {fileID: 5} + - {fileID: 11} m_Position: serializedVersion: 2 x: 0 y: 0 - width: 921 - height: 665 - m_MinSize: {x: 403, y: 492} - m_MaxSize: {x: 10001, y: 14042} + width: 697.6 + height: 722.8 + m_MinSize: {x: 100, y: 200} + m_MaxSize: {x: 8096, y: 16192} vertical: 1 - controlID: 92 + controlID: 119 +--- !u!114 &7 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 697.6 + y: 0 + width: 194.40002 + height: 722.8 + m_MinSize: {x: 202, y: 221} + m_MaxSize: {x: 4002, y: 4021} + m_ActualView: {fileID: 12} + m_Panes: + - {fileID: 12} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &8 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 892 + y: 0 + width: 300.80005 + height: 722.8 + m_MinSize: {x: 232, y: 271} + m_MaxSize: {x: 10002, y: 10021} + m_ActualView: {fileID: 14} + m_Panes: + - {fileID: 14} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &9 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 1192.8 + y: 0 + width: 343.19995 + height: 722.8 + m_MinSize: {x: 276, y: 71} + m_MaxSize: {x: 4001, y: 4021} + m_ActualView: {fileID: 13} + m_Panes: + - {fileID: 13} + m_Selected: 0 + m_LastSelected: 0 --- !u!114 &10 MonoBehaviour: m_ObjectHideFlags: 52 @@ -231,22 +234,23 @@ MonoBehaviour: m_GameObject: {fileID: 0} m_Enabled: 1 m_EditorHideFlags: 1 - m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} m_Name: m_EditorClassIdentifier: - m_Children: - - {fileID: 4} - - {fileID: 11} + m_Children: [] m_Position: serializedVersion: 2 x: 0 y: 0 - width: 921 - height: 394 - m_MinSize: {x: 403, y: 221} - m_MaxSize: {x: 8003, y: 4021} - vertical: 0 - controlID: 93 + width: 697.6 + height: 622.4 + m_MinSize: {x: 201, y: 221} + m_MaxSize: {x: 4001, y: 4021} + m_ActualView: {fileID: 16} + m_Panes: + - {fileID: 16} + m_Selected: 0 + m_LastSelected: 0 --- !u!114 &11 MonoBehaviour: m_ObjectHideFlags: 52 @@ -262,19 +266,116 @@ MonoBehaviour: m_Children: [] m_Position: serializedVersion: 2 - x: 228 - y: 0 - width: 693 - height: 394 - m_MinSize: {x: 202, y: 221} - m_MaxSize: {x: 4002, y: 4021} + x: 0 + y: 622.4 + width: 697.6 + height: 100.39996 + m_MinSize: {x: 200, y: 200} + m_MaxSize: {x: 4000, y: 4000} m_ActualView: {fileID: 15} m_Panes: - {fileID: 15} - - {fileID: 16} m_Selected: 0 - m_LastSelected: 1 + m_LastSelected: 0 --- !u!114 &12 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12061, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_MinSize: {x: 200, y: 200} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: "\u5C42\u7EA7" + m_Image: {fileID: -3734745235275155857, guid: 0000000000000000d000000000000000, type: 0} + m_Tooltip: + m_Pos: + serializedVersion: 2 + x: 697.60004 + y: 73.6 + width: 192.40002 + height: 701.8 + m_ViewDataDictionary: {fileID: 0} + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: [] + m_SceneHierarchy: + m_TreeViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: 76ecffff82ecffff88ecffff78f0ffff0efbffff + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 7} + m_SearchString: + m_ExpandedScenes: [] + m_CurrenRootInstanceID: 0 + m_LockTracker: + m_IsLocked: 0 + m_CurrentSortingName: TransformSorting + m_WindowGUID: 2e41307eb01faed4e87abe86bae87f81 +--- !u!114 &13 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12019, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_MinSize: {x: 275, y: 50} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: "\u68C0\u67E5\u5668" + m_Image: {fileID: -440750813802333266, guid: 0000000000000000d000000000000000, type: 0} + m_Tooltip: + m_Pos: + serializedVersion: 2 + x: 1192.8 + y: 73.6 + width: 342.19995 + height: 701.8 + m_ViewDataDictionary: {fileID: 0} + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: [] + m_ObjectsLockedBeforeSerialization: [] + m_InstanceIDsLockedBeforeSerialization: + m_PreviewResizer: + m_CachedPref: -160 + m_ControlHash: -371814159 + m_PrefName: Preview_InspectorPreview + m_LastInspectedObjectInstanceID: -1 + m_LastVerticalScrollValue: 0 + m_GlobalObjectId: + m_InspectorMode: 0 + m_LockTracker: + m_IsLocked: 0 + m_PreviewWindow: {fileID: 0} +--- !u!114 &14 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -289,16 +390,19 @@ MonoBehaviour: m_MinSize: {x: 230, y: 250} m_MaxSize: {x: 10000, y: 10000} m_TitleContent: - m_Text: Project - m_Image: {fileID: -5467254957812901981, guid: 0000000000000000d000000000000000, type: 0} + m_Text: "\u9879\u76EE" + m_Image: {fileID: -5179483145760003458, guid: 0000000000000000d000000000000000, type: 0} m_Tooltip: m_Pos: serializedVersion: 2 - x: 2249 - y: 726.5 - width: 920 - height: 250 + x: 892 + y: 73.6 + width: 298.80005 + height: 701.8 m_ViewDataDictionary: {fileID: 0} + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: [] m_SearchFilter: m_NameFilter: m_ClassNames: [] @@ -312,21 +416,22 @@ MonoBehaviour: m_SkipHidden: 0 m_SearchArea: 1 m_Folders: - - Assets + - Assets/AmplifyShaderEditor m_Globs: [] + m_OriginalText: m_ViewMode: 1 m_StartGridSize: 64 m_LastFolders: - - Assets + - Assets/AmplifyShaderEditor m_LastFoldersGridSize: -1 - m_LastProjectPath: U:\layout + m_LastProjectPath: "C:\\Users\\13259\\Desktop\\\u8D5B\u9A6C" m_LockTracker: m_IsLocked: 0 m_FolderTreeState: scrollPos: {x: 0, y: 0} - m_SelectedIDs: f4350000 - m_LastClickedID: 13812 - m_ExpandedIDs: 00000000f435000000ca9a3b + m_SelectedIDs: ea7e0000 + m_LastClickedID: 32490 + m_ExpandedIDs: 000000008a6e00008c6e00008e6e0000906e0000 m_RenameOverlay: m_UserAcceptedRename: 0 m_Name: @@ -354,7 +459,7 @@ MonoBehaviour: scrollPos: {x: 0, y: 0} m_SelectedIDs: m_LastClickedID: 0 - m_ExpandedIDs: 00000000f4350000 + m_ExpandedIDs: 000000008a6e00008c6e00008e6e0000906e0000 m_RenameOverlay: m_UserAcceptedRename: 0 m_Name: @@ -382,7 +487,7 @@ MonoBehaviour: m_SelectedInstanceIDs: m_LastClickedInstanceID: 0 m_HadKeyboardFocusLastEvent: 0 - m_ExpandedInstanceIDs: c6230000 + m_ExpandedInstanceIDs: m_RenameOverlay: m_UserAcceptedRename: 0 m_Name: @@ -398,7 +503,7 @@ MonoBehaviour: m_IsRenaming: 0 m_OriginalEventType: 11 m_IsRenamingFilename: 1 - m_ClientGUIView: {fileID: 0} + m_ClientGUIView: {fileID: 8} m_CreateAssetUtility: m_EndAction: {fileID: 0} m_InstanceID: 0 @@ -409,215 +514,8 @@ MonoBehaviour: m_ScrollPosition: {x: 0, y: 0} m_GridSize: 64 m_SkipHiddenPackages: 0 - m_DirectoriesAreaWidth: 207 ---- !u!114 &13 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12019, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_MinSize: {x: 275, y: 50} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Inspector - m_Image: {fileID: -2667387946076563598, guid: 0000000000000000d000000000000000, type: 0} - m_Tooltip: - m_Pos: - serializedVersion: 2 - x: 3170 - y: 332.5 - width: 284 - height: 644 - m_ViewDataDictionary: {fileID: 0} - m_ObjectsLockedBeforeSerialization: [] - m_InstanceIDsLockedBeforeSerialization: - m_PreviewResizer: - m_CachedPref: 160 - m_ControlHash: -371814159 - m_PrefName: Preview_InspectorPreview - m_LastInspectedObjectInstanceID: -1 - m_LastVerticalScrollValue: 0 - m_AssetGUID: - m_InstanceID: 0 - m_LockTracker: - m_IsLocked: 0 - m_PreviewWindow: {fileID: 0} ---- !u!114 &14 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12061, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_MinSize: {x: 200, y: 200} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Hierarchy - m_Image: {fileID: 7966133145522015247, guid: 0000000000000000d000000000000000, type: 0} - m_Tooltip: - m_Pos: - serializedVersion: 2 - x: 2249 - y: 332.5 - width: 227 - height: 373 - m_ViewDataDictionary: {fileID: 0} - m_SceneHierarchy: - m_TreeViewState: - scrollPos: {x: 0, y: 0} - m_SelectedIDs: - m_LastClickedID: 0 - m_ExpandedIDs: 42fbffff - m_RenameOverlay: - m_UserAcceptedRename: 0 - m_Name: - m_OriginalName: - m_EditFieldRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 0 - height: 0 - m_UserData: 0 - m_IsWaitingForDelay: 0 - m_IsRenaming: 0 - m_OriginalEventType: 11 - m_IsRenamingFilename: 0 - m_ClientGUIView: {fileID: 0} - m_SearchString: - m_ExpandedScenes: [] - m_CurrenRootInstanceID: 0 - m_LockTracker: - m_IsLocked: 0 - m_CurrentSortingName: TransformSorting - m_WindowGUID: 4c969a2b90040154d917609493e03593 + m_DirectoriesAreaWidth: 105 --- !u!114 &15 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12013, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_MinSize: {x: 200, y: 200} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Scene - m_Image: {fileID: 2593428753322112591, guid: 0000000000000000d000000000000000, type: 0} - m_Tooltip: - m_Pos: - serializedVersion: 2 - x: 2477 - y: 332.5 - width: 691 - height: 373 - m_ViewDataDictionary: {fileID: 0} - m_ShowContextualTools: 0 - m_WindowGUID: cc27987af1a868c49b0894db9c0f5429 - m_Gizmos: 1 - m_OverrideSceneCullingMask: 6917529027641081856 - m_SceneIsLit: 1 - m_SceneLighting: 1 - m_2DMode: 0 - m_isRotationLocked: 0 - m_PlayAudio: 0 - m_AudioPlay: 0 - m_Position: - m_Target: {x: 0, y: 0, z: 0} - speed: 2 - m_Value: {x: 0, y: 0, z: 0} - m_RenderMode: 0 - m_CameraMode: - drawMode: 0 - name: Shaded - section: Shading Mode - m_ValidateTrueMetals: 0 - m_DoValidateTrueMetals: 0 - m_ExposureSliderValue: 0 - m_SceneViewState: - showFog: 1 - showMaterialUpdate: 0 - showSkybox: 1 - showFlares: 1 - showImageEffects: 1 - showParticleSystems: 1 - showVisualEffectGraphs: 1 - m_Grid: - xGrid: - m_Fade: - m_Target: 0 - speed: 2 - m_Value: 0 - m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} - m_Pivot: {x: 0, y: 0, z: 0} - m_Size: {x: 0, y: 0} - yGrid: - m_Fade: - m_Target: 1 - speed: 2 - m_Value: 1 - m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} - m_Pivot: {x: 0, y: 0, z: 0} - m_Size: {x: 1, y: 1} - zGrid: - m_Fade: - m_Target: 0 - speed: 2 - m_Value: 0 - m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} - m_Pivot: {x: 0, y: 0, z: 0} - m_Size: {x: 0, y: 0} - m_ShowGrid: 1 - m_GridAxis: 1 - m_gridOpacity: 0.5 - m_Rotation: - m_Target: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226} - speed: 2 - m_Value: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226} - m_Size: - m_Target: 10 - speed: 2 - m_Value: 10 - m_Ortho: - m_Target: 0 - speed: 2 - m_Value: 0 - m_CameraSettings: - m_Speed: 1 - m_SpeedNormalized: 0.5 - m_SpeedMin: 0.001 - m_SpeedMax: 2 - m_EasingEnabled: 1 - m_EasingDuration: 0.4 - m_AccelerationEnabled: 1 - m_FieldOfView: 90 - m_NearClip: 0.03 - m_FarClip: 10000 - m_DynamicClip: 1 - m_OcclusionCulling: 0 - m_LastSceneViewRotation: {x: 0, y: 0, z: 0, w: 0} - m_LastSceneViewOrtho: 0 - m_ReplacementShader: {fileID: 0} - m_ReplacementString: - m_SceneVisActive: 1 - m_LastLockedObject: {fileID: 0} - m_ViewIsLockedToObject: 0 ---- !u!114 &16 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -632,27 +530,30 @@ MonoBehaviour: m_MinSize: {x: 200, y: 200} m_MaxSize: {x: 4000, y: 4000} m_TitleContent: - m_Text: Game - m_Image: {fileID: -6423792434712278376, guid: 0000000000000000d000000000000000, type: 0} + m_Text: "\u6E38\u620F" + m_Image: {fileID: 4621777727084837110, guid: 0000000000000000d000000000000000, type: 0} m_Tooltip: m_Pos: serializedVersion: 2 - x: 507 - y: 94 - width: 1532 - height: 790 + x: 0 + y: 696 + width: 696.6 + height: 79.39996 m_ViewDataDictionary: {fileID: 0} - m_SerializedViewsNames: [] - m_SerializedViewsValues: [] + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: [] + m_SerializedViewNames: [] + m_SerializedViewValues: [] m_PlayModeViewName: GameView m_ShowGizmos: 0 m_TargetDisplay: 0 m_ClearColor: {r: 0, g: 0, b: 0, a: 0} - m_TargetSize: {x: 640, y: 480} + m_TargetSize: {x: 870.75, y: 72.999954} m_TextureFilterMode: 0 m_TextureHideFlags: 61 - m_RenderIMGUI: 0 - m_MaximizeOnPlay: 0 + m_RenderIMGUI: 1 + m_EnterPlayModeBehavior: 0 m_UseMipMap: 0 m_VSyncEnabled: 0 m_Gizmos: 0 @@ -663,10 +564,10 @@ MonoBehaviour: m_VRangeLocked: 0 hZoomLockedByDefault: 0 vZoomLockedByDefault: 0 - m_HBaseRangeMin: -766 - m_HBaseRangeMax: 766 - m_VBaseRangeMin: -395 - m_VBaseRangeMax: 395 + m_HBaseRangeMin: -348.30002 + m_HBaseRangeMax: 348.30002 + m_VBaseRangeMin: -29.199982 + m_VBaseRangeMax: 29.199982 m_HAllowExceedBaseRangeMin: 1 m_HAllowExceedBaseRangeMax: 1 m_VAllowExceedBaseRangeMin: 1 @@ -683,30 +584,30 @@ MonoBehaviour: m_DrawArea: serializedVersion: 2 x: 0 - y: 0 - width: 1532 - height: 790 - m_Scale: {x: 1, y: 1} - m_Translation: {x: 766, y: 395} + y: 21 + width: 696.6 + height: 58.399963 + m_Scale: {x: 0.99999994, y: 0.99999994} + m_Translation: {x: 348.3, y: 29.199982} m_MarginLeft: 0 m_MarginRight: 0 m_MarginTop: 0 m_MarginBottom: 0 m_LastShownAreaInsideMargins: serializedVersion: 2 - x: -766 - y: -395 - width: 1532 - height: 790 + x: -348.30002 + y: -29.199984 + width: 696.60004 + height: 58.399967 m_MinimalGUI: 1 - m_defaultScale: 1 - m_LastWindowPixelSize: {x: 1532, y: 790} + m_defaultScale: 0.99999994 + m_LastWindowPixelSize: {x: 870.75, y: 99.249954} m_ClearInEditMode: 1 m_NoCameraWarning: 1 - m_LowResolutionForAspectRatios: 01000000000000000000 + m_LowResolutionForAspectRatios: 00000000000000000000 m_XRRenderMode: 0 m_RenderTexture: {fileID: 0} ---- !u!114 &17 +--- !u!114 &16 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -715,32 +616,321 @@ MonoBehaviour: m_GameObject: {fileID: 0} m_Enabled: 1 m_EditorHideFlags: 1 - m_Script: {fileID: 12003, guid: 0000000000000000e000000000000000, type: 0} + m_Script: {fileID: 12013, guid: 0000000000000000e000000000000000, type: 0} m_Name: m_EditorClassIdentifier: - m_MinSize: {x: 100, y: 100} + m_MinSize: {x: 200, y: 200} m_MaxSize: {x: 4000, y: 4000} m_TitleContent: - m_Text: Console - m_Image: {fileID: -4327648978806127646, guid: 0000000000000000d000000000000000, type: 0} + m_Text: "\u573A\u666F" + m_Image: {fileID: 8634526014445323508, guid: 0000000000000000d000000000000000, type: 0} m_Tooltip: m_Pos: serializedVersion: 2 - x: 2249 - y: 726.5 - width: 920 - height: 250 + x: 0 + y: 73.6 + width: 696.6 + height: 601.4 m_ViewDataDictionary: {fileID: 0} ---- !u!114 &18 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 13963, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_DontSaveToLayout: 0 + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: + - dockPosition: 0 + containerId: overlay-toolbar__top + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: -100, y: -25.599976} + snapCorner: 3 + id: Tool Settings + index: 0 + layout: 1 + - dockPosition: 0 + containerId: overlay-toolbar__top + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: -141, y: 149} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 1 + id: unity-grid-and-snap-toolbar + index: 1 + layout: 1 + - dockPosition: 1 + containerId: overlay-toolbar__top + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: unity-scene-view-toolbar + index: 0 + layout: 1 + - dockPosition: 1 + containerId: overlay-toolbar__top + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 1 + id: unity-search-toolbar + index: 1 + layout: 1 + - dockPosition: 1 + containerId: overlay-toolbar__top + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Open Tile Palette + index: 2 + layout: 4 + - dockPosition: 1 + containerId: overlay-toolbar__top + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Tilemap Focus + index: 3 + layout: 4 + - dockPosition: 0 + containerId: overlay-container--left + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: unity-transform-toolbar + index: 0 + layout: 2 + - dockPosition: 0 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: 67.5, y: 86} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Orientation + index: 0 + layout: 4 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Light Settings + index: 0 + layout: 4 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Camera + index: 1 + layout: 4 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Cloth Constraints + index: 2 + layout: 4 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Cloth Collisions + index: 3 + layout: 4 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Navmesh Display + index: 4 + layout: 4 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Agent Display + index: 5 + layout: 4 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Obstacle Display + index: 6 + layout: 4 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Occlusion Culling + index: 7 + layout: 4 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Physics Debugger + index: 8 + layout: 4 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Scene Visibility + index: 9 + layout: 4 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Particles + index: 10 + layout: 4 + m_WindowGUID: 932fa420110f25f488f2a7bbcd1fb02a + m_Gizmos: 1 + m_OverrideSceneCullingMask: 6917529027641081856 + m_SceneIsLit: 1 + m_SceneLighting: 1 + m_2DMode: 1 + m_isRotationLocked: 0 + m_PlayAudio: 0 + m_AudioPlay: 0 + m_Position: + m_Target: {x: -2.27013, y: -0.4219437, z: 1.007452} + speed: 2 + m_Value: {x: -2.27013, y: -0.4219437, z: 1.007452} + m_RenderMode: 0 + m_CameraMode: + drawMode: 0 + name: Shaded + section: Shading Mode + m_ValidateTrueMetals: 0 + m_DoValidateTrueMetals: 0 + m_ExposureSliderValue: 0 + m_SceneViewState: + m_AlwaysRefresh: 0 + showFog: 1 + showSkybox: 1 + showFlares: 1 + showImageEffects: 1 + showParticleSystems: 1 + showVisualEffectGraphs: 1 + m_FxEnabled: 1 + m_Grid: + xGrid: + m_Fade: + m_Target: 0 + speed: 2 + m_Value: 0 + m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} + m_Pivot: {x: 0, y: 0, z: 0} + m_Size: {x: 0, y: 0} + yGrid: + m_Fade: + m_Target: 0 + speed: 2 + m_Value: 0 + m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} + m_Pivot: {x: 0, y: 0, z: 0} + m_Size: {x: 1, y: 1} + zGrid: + m_Fade: + m_Target: 1 + speed: 2 + m_Value: 1 + m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} + m_Pivot: {x: 0, y: 0, z: 0} + m_Size: {x: 1, y: 1} + m_ShowGrid: 1 + m_GridAxis: 1 + m_gridOpacity: 0.5 + m_Rotation: + m_Target: {x: 0, y: 0, z: 0, w: 1} + speed: 2 + m_Value: {x: 0, y: 0, z: 0, w: 1} + m_Size: + m_Target: 6.943548 + speed: 2 + m_Value: 6.943548 + m_Ortho: + m_Target: 1 + speed: 2 + m_Value: 1 + m_CameraSettings: + m_Speed: 1 + m_SpeedNormalized: 0.5 + m_SpeedMin: 0.01 + m_SpeedMax: 2 + m_EasingEnabled: 1 + m_EasingDuration: 0.4 + m_AccelerationEnabled: 1 + m_FieldOfViewHorizontalOrVertical: 60 + m_NearClip: 0.03 + m_FarClip: 10000 + m_DynamicClip: 1 + m_OcclusionCulling: 0 + m_LastSceneViewRotation: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226} + m_LastSceneViewOrtho: 0 + m_ReplacementShader: {fileID: 0} + m_ReplacementString: + m_SceneVisActive: 1 + m_LastLockedObject: {fileID: 0} + m_ViewIsLockedToObject: 0

  • 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 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll.mdb b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll.mdb new file mode 100644 index 0000000000000000000000000000000000000000..4c4e357e95cd02c4e87e4a859e35ee19381a553d GIT binary patch literal 119893 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 Ub4E_$Ogw_K@kq|Wqc{)$Kdp5xdH?_b literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll.mdb.meta b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll.mdb.meta new file mode 100644 index 0000000..d20c08e --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll.mdb.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d2a8f0021d6b47c5923d8972dfb8086f +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll.meta b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll.meta new file mode 100644 index 0000000..275aad1 --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Serialization.dll.meta @@ -0,0 +1,77 @@ +fileFormatVersion: 2 +guid: d2a8f0021d6b47c5923d8972dfb81ef1 +timeCreated: 1488828285 +licenseType: Store +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + Android: + enabled: 1 + settings: {} + Any: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 1 + Exclude Linux: 0 + Exclude Linux64: 0 + Exclude LinuxUniversal: 0 + Exclude N3DS: 1 + Exclude OSXIntel: 0 + Exclude OSXIntel64: 0 + Exclude OSXUniversal: 0 + Exclude PS4: 1 + Exclude PSM: 1 + Exclude PSP2: 1 + Exclude SamsungTV: 1 + Exclude Tizen: 1 + Exclude WebGL: 1 + Exclude WiiU: 1 + Exclude Win: 0 + Exclude Win64: 0 + Exclude WindowsStoreApps: 1 + Exclude XboxOne: 1 + Exclude iOS: 1 + Exclude tvOS: 1 + Editor: + enabled: 0 + settings: + DefaultValueInitialized: true + Linux: + enabled: 1 + settings: {} + Linux64: + enabled: 1 + settings: {} + LinuxUniversal: + enabled: 1 + settings: {} + OSXIntel: + enabled: 1 + settings: {} + OSXIntel64: + enabled: 1 + settings: {} + OSXUniversal: + enabled: 1 + settings: {} + PSM: + enabled: 0 + settings: {} + Win: + enabled: 1 + settings: {} + Win64: + enabled: 1 + settings: {} + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Utilities.dll b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Utilities.dll new file mode 100644 index 0000000000000000000000000000000000000000..3c25dd04fdac34c205f7447f032f6c5917412eb1 GIT binary patch literal 142336 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 z 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 a$_de4$=93G;86o)MuDQTo3t21ZwUFgqh|si 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 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Utilities.dll.mdb.meta b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Utilities.dll.mdb.meta new file mode 100644 index 0000000..e8f89f3 --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Utilities.dll.mdb.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1e0a9643dc0d4b46bf2321f72c4e086f +timeCreated: 1488828285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Utilities.dll.meta b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Utilities.dll.meta new file mode 100644 index 0000000..2cee0ca --- /dev/null +++ b/Assets/Plugins/Sirenix/Assemblies/NoEmitAndNoEditor/Sirenix.Utilities.dll.meta @@ -0,0 +1,77 @@ +fileFormatVersion: 2 +guid: 1e0a9643dc0d4b46bf2321f72c4e503e +timeCreated: 1488828285 +licenseType: Store +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + Android: + enabled: 1 + settings: {} + Any: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 1 + Exclude Linux: 0 + Exclude Linux64: 0 + Exclude LinuxUniversal: 0 + Exclude N3DS: 1 + Exclude OSXIntel: 0 + Exclude OSXIntel64: 0 + Exclude OSXUniversal: 0 + Exclude PS4: 1 + Exclude PSM: 1 + Exclude PSP2: 1 + Exclude SamsungTV: 1 + Exclude Tizen: 1 + Exclude WebGL: 1 + Exclude WiiU: 1 + Exclude Win: 0 + Exclude Win64: 0 + Exclude WindowsStoreApps: 1 + Exclude XboxOne: 1 + Exclude iOS: 1 + Exclude tvOS: 1 + Editor: + enabled: 0 + settings: + DefaultValueInitialized: true + Linux: + enabled: 1 + settings: {} + Linux64: + enabled: 1 + settings: {} + LinuxUniversal: + enabled: 1 + settings: {} + OSXIntel: + enabled: 1 + settings: {} + OSXIntel64: + enabled: 1 + settings: {} + OSXUniversal: + enabled: 1 + settings: {} + PSM: + enabled: 0 + settings: {} + Win: + enabled: 1 + settings: {} + Win64: + enabled: 1 + settings: {} + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.dll b/Assets/Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.dll new file mode 100644 index 0000000000000000000000000000000000000000..038cb3578ea38a390bf23e9c7986220ca55228f0 GIT binary patch literal 38400 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 + + + Sirenix.OdinInspector.Attributes + + + +